如图所示,返回当前周签到记录:
{
"data": {
"2022-01-02": true,
"2022-01-03": false,
"2022-01-04": false,
"2022-01-05": false,
"2022-01-06": false,
"2022-01-07": false,
"2022-01-08": false
}
}
true代表签到 false代表未签到
复制代码
面向过程代码实现
func (ctr *User) Signs(c *gin.Context) {
now := time.Now()
index := int(now.Weekday())
dates := make([]string, 7)
for i := 0; i < 7; i++ {
day := now.AddDate(0, 0, i - index).Format("2006-01-02")
dates[i] = day
}
// dates [2022-01-02 2022-01-03 2022-01-04 2022-01-05 2022-01-06 2022-01-07 2022-01-08]
signs := ctr.repo.Signs(c.Request.Context(), dates)
// signs [&{Id:1 UserId:1 Date:2022-01-02 00:00:00 +0800 CST}]
response := make(map[string]bool)
for _, s := range signs {
k := s.Date.Format("2006-01-02")
response[k] = true
}
// response [2022-01-02:true]
for i := 0; i < 7; i++ {
k := dates[i]
if _, ok := response[k]; ok {
continue
}
response[k] = false
}
c.JSON(http.StatusOK, gin.H{"data": response})
}
复制代码
思考:如果现在是codeReview阶段,需要代码评审,这段代码都有什么问题?
检视代码
在检视代码之前,先和大家讲个故事,前段时间家里跳闸停电了,家里电器较多,不太可能一个个地试,幸运的是现在的总闸旁边还有一系列的“功能电闸”,我先把所有的电闸关了,再将大厅的推上去,发现没问题,然后把主卧、侧卧一一推上去,都没问题,推到厨房时,又跳闸了,最后找到是厨房里的电热水壶漏电了,整个过程就只需要几分钟时间,而如果家里只有一个总闸,只能把所有的电器插头先拔了,然后把家里的电器接通电源挨个试,想想都头大。
听完故事,我们回头再检视一下我们的代码,首先,这段代码因为将参数整理、数据获取、数据转换、格式调整、输出等功能全部耦合在一起,一但出现生产问题,我们要紧急排查时,我们将不得不把整个方法都看一遍,也就像我们在检查电路时,将整个房子里的电器全部检查一遍,这个就是可阅读性差。
此外,如果我们希望对厨房的线路进行改造时我们只需要关闭厨房的电闸即可,但若只有一个总电闸,我们将不得不将总闸关闭,整个屋子断电了才能整改,例如需要现在的“年月天”日期修改成只需要“天”,我们需要从头阅读代码,定位所有跟日期有关的变量和日期key代码片段,理清代码片段上下文逻辑,然后才能确定是否需要修改,这个就是可维护性差。
另一方面,当我们需要在此基础上再增加一个新的日期范围,比如月签到,季度签到时,成本也会越来越高,每次修改都要改动原有的代码(所有功能都在一个方法中)。此外,当我们增加或修改功能时&#x