[toc]
如何寫出不好的代碼
這是一個從各個項目整理出來的代碼,具有一定代表性。壞代碼的產(chǎn)生,本篇暫時不深究原則,僅挑選在開發(fā)中遇到的代碼。
變量命名讓人感到疑惑
ismd5 := false
這個 ismd5 從名字上看,似乎是表明是不是md5值,但實際上代碼里面是表示imei是不是md5值,看下面的實際代碼
srcImei := imei //原始imei
if ismd5 == false {
has := md5.Sum([]byte(imei))
imei = hex.EncodeToString(has[:])
}
實際上 ismd5 這個值出現(xiàn)的地方非常早,但用到這個變量值是在另一個文件的另一個方法里面,初始看代碼的人可能對這個 ismd5 變量名一頭霧水。
推薦命名規(guī)范
- 具體可參考 google開源項目風(fēng)格指南
過多if else分支
直接看代碼示例
var priorBountyDistance string
if priorBountyInfo.Rank == 0 {
priorBountyDistance = "現(xiàn)在處在第xx名,請繼續(xù)保持"
} else {
priorInviters, err := bir.dao.GetInviters(priorBountyInfo.Rank, priorBountyInfo.Rank)
if err != nil {
return nil, err
}
if len(priorInviters) == 1 {
priorInviter := priorInviters[0]
inviteCount := int(math.Ceil(float64(priorInviter.StepCount+1-myself.StepCount) / float64(irc.StepCountPerInvitee)))
if priorBountyInfo.FullBounty == 0 {
if myBountyInfo.FullBounty == 0 {
priorBountyDistance = fmt.Sprintf("距離獲得$%.0f$xx僅需邀請$%d$人", float64(priorBountyInfo.Bounty)/100, inviteCount)
} else {
priorBountyDistance = fmt.Sprintf("距離第$%d$名僅需邀請$%d$人", priorBountyInfo.Rank, inviteCount)
}
} else {
priorBountyDistance = fmt.Sprintf("距離前$%.0f%%$僅需邀請$%d$人", priorBountyInfo.RelRank*100, inviteCount)
}
}
}
推薦做法
- 提前取反,快速失敗
- 運用策略模式,構(gòu)建分支
查詢和修改不分離
func checkIsRepeatImei(imei, channelID string) (bool, error) {
num, err := redis.AddClientReportImei(imei)
if err != nil {
log.Error("redis.AddClientReportImei(%v) error(%v)", imei, err)
return true, err
}
if num == 0 {
log.Error("Repeat IMEI(%v) from cache, ChannelID(%v).", imei, channelID)
return true, nil
}
return false,nil
}
這個checkIsRepeatImei是一個檢查imei是否是重復(fù)的方法,但是里面是通過向redis添加一個記錄來實現(xiàn),這個方法有副作用,也就是你本來是不存在的,調(diào)用一下就存在了。一個查詢方法居然會修改數(shù)據(jù)。
推薦做法
- 將查詢和修改分離
超長方法
- 一個方法代碼長度達到1000行方法,可能有的人覺得這怎么會發(fā)生。但事實上我們的代碼里面經(jīng)常出現(xiàn)。最常出現(xiàn)的場景是,這個方法是之前的人寫的,我只是添加一點點邏輯,然后隨著后面的迭代,換一個人又來加一些邏輯,越加越多。
- 此處就不貼代碼了