大家有没有看过这样的代码?就是一个方法里面,整个就是一个if
语句。然后这个if语句非常长长长长。。。一屏都放不下,你都不知道这个if
语句会在哪里结束。
fun runRule()
if (rulesEnabled) {
var maxConsecutiveCount = 0
var currentConsecutiveCount = 0
var previousReceiver = ""
expression.children.forEach {
if (it is KtBinaryExpression) {
val currentReceiver = getReceiver(it)
if (currentReceiver == previousReceiver) {
currentConsecutiveCount ++
} else {
currentConsecutiveCount = 1
previousReceiver = currentReceiver
}
maxConsecutiveCount = max(maxConsecutiveCount, currentConsecutiveCount)
} else {
currentConsecutiveCount = 0
previousReceiver = ""
}
}
if (maxConsecutiveCount >= threshold) {
report(CodeSmell(issue, Entity.from(expression), "This condition is too complex."))
}
val binaryExpressions = condition?.collectByType<KtBinaryExpression>()?.toList()
if (binaryExpressions != null && binaryExpressions.size > 1) {
val longestBinExpr = binaryExpressions.reduce { acc, binExpr ->
if (binExpr.text.length > acc.text.length) binExpr else acc
}
val conditionString = longestBinExpr.text
val count = frequency(conditionString, "&&") + frequency(conditionString, "||") + 1
if (count >= threshold) {
report(ThresholdedCodeSmell(issue,
Entity.from(condition),
Metric("SIZE", count, threshold),
"This condition is too complex."))
}
}
}
}
这种代码的缺点是,只要if
语句一长,你就很难分清后面的代码哪些是在if
里面,哪些不在 if
里面的。此外,这种写法也很容易导致下面的代码太多层的嵌套。嵌套太深的缺点,相信大家都有体会,在这里就不多说了。
像这种代码,有一个好用的技巧,就是使用guard clause。简单说就是,如果if
里面的条件不满足,就直接return
fun runRule() {
if (!rulesEnabled) return
var maxConsecutiveCount = 0
var currentConsecutiveCount = 0
var previousReceiver = ""
expression.children.forEach {
if (it is KtBinaryExpression) {
val currentReceiver = getReceiver(it)
if (currentReceiver == previousReceiver) {
currentConsecutiveCount ++
} else {
currentConsecutiveCount = 1
previousReceiver = currentReceiver
}
maxConsecutiveCount = max(maxConsecutiveCount, currentConsecutiveCount)
} else {
currentConsecutiveCount = 0
previousReceiver = ""
}
}
if (maxConsecutiveCount >= threshold) {
report(CodeSmell(issue, Entity.from(expression), "This condition is too complex."))
}
val binaryExpressions = condition?.collectByType<KtBinaryExpression>()?.toList()
if (binaryExpressions != null && binaryExpressions.size > 1) {
val longestBinExpr = binaryExpressions.reduce { acc, binExpr ->
if (binExpr.text.length > acc.text.length) binExpr else acc
}
val conditionString = longestBinExpr.text
val count = frequency(conditionString, "&&") + frequency(conditionString, "||") + 1
if (count >= threshold) {
report(ThresholdedCodeSmell(issue,
Entity.from(condition),
Metric("SIZE", count, threshold),
"This condition is too complex."))
}
}
}
这样一来,看代码的人只要看到方法开头,就知道下面的代码全部是满足 rulesEnabled
的这个条件的。
不要觉得这个东西无所谓,要知道,swift 语言里面有一个 guard 关键字,专门用来做这件事情。
func runRules() {
guard rulesEnabled else { return }
//run rules
}
如果一门语言把某一种写法集成到它的特性里面,可想而知这种写法的好处是特别大的。具体的话,大家下次看到这样的代码,自己去体会就好。