Keep It Simple and Stupid 这个原则听起来比较简单,重点是理解什么样的代码是简单的,代码行数少就是简单的代码吗???还是说当程序的逻辑十分复杂不容易理解时就是一个复杂的代码呢???
下面就让我们来看看怎么样判断简单。
代码就不展示了,其实懂的都懂,代码行数是一定不能作为判断依据的,因为很多代码行数少的代码,其实是采用了一些高级语法特性的。如正则表达式、位运算符等。
如果盲目的采用这些特性,会影响代码的可读性,因为这种运算法为了减少代码行数,会采用很多方式来规定一些特性,这些特性有时会不好理解。例如用位运算符来代替算数运算,这样虽然会提高代码性能和减少行数,但也不是 KISS 原则下的指导产物,其违反了代码的可读性。
那代码的逻辑复杂可以作为判断依据吗?其实也是懂的都懂,代码也不展示了(因为太复杂了,所以不展示了-v-),为什么逻辑复杂不能作为判断依据呢???
因为有些代码他就是逻辑复杂的,如果不信的话,直接打开算法相关实现,找到一个看不懂的,那么其就是我们的目标了。
因此如果没办法,在特定场景下,只能采用该算法的实现,那么使用这种复杂逻辑就不是违反 KISS 原则了,因为没办法。
综上,我们该如何写出符合 KISS 原则的代码呢,具体来说,还是需要 结合业务发展和技术团队能力。
在实际场景下,我们尽量做到以下几点就可以了。
不要去设计当前用不到的功能,不要去写当前用不到的代码。
该原则是作为一个指导思想来做的,其作用就是防止过度设计,但需要注意的是其是让你不做,但需要有可能要做的意识,提前留好拓展点,这样如果要做的时候,也可以快速跟上。 **
后续会有一篇文章,来专门讲解如何在软件设计中,防止过度设计,但对对应该优化,该留好优化点如何实现。
英语解释为:Dont repeat yourself,可以理解为不要写重复的代码,要做好代码的可复用性。但该规则跟 KISS 原则一样,听起来可能比较简单,但是在实际使用中,却要注重的一个原则。
因为在该原则中,有一个很关键的点,什么样的代码是重复的代码,只是简单的代码一样就是违反该原则了吗?下面就让我们来根据以下几种场景来判断什么是重复的代码。
public boolean validUsername(String username) {
if (StrUtil.isEmpty(username)) {
return false;
}
if (username.contains("77777")) {
return false;
}
return true;
}
public boolean validNickname(String nickname) {
if (StrUtil.isEmpty(nickname)) {
return false;
}
if (nickname.contains("77777")) {
return false;
}
return true;
}
我们来看一下,这一段代码是重复的吗?
明显能看出,两个方法的执行逻辑是一模一样的,那么我们可以说其是重复的,而将其合为一个方法吗?
答案是不行的,首先如果合成一个就违反了单一职责原则,一个方法做了多件事,此外,现在两个参数的校验逻辑是一样的,因此看着重复,后面如果 nickname 的校验逻辑改了呢?那就需要侵入式的修改代码,需要在所有使用该方法的代码中进行修改,依据 nickname 来特定的进行判断,从而违反了开闭原则。
因此,实现逻辑重复,不能构成代码重复的条件。
public boolean checkPasswordByRegex(String password) {
String regex = "123456";
boolean matches = Pattern.matches(regex, password);
return matches;
}
public boolean checkPasswordByStr(String password) {
boolean matches = StrUtil.equals(password, "123456");
return matches;
}
我们来看一下,上述两段代码是否构成重复?
答案是这两段代码是重复的代码,虽然这两段代码的实现逻辑不一致,代码编写也不一致,但其仍然违反了 DRY 原则,因为这两段代码所实现的点是一样的,下面我们来看一下这样重复的代码会带来什么隐患。
这样的设计可能会导致以下问题,
// 代码执行重复
public boolean validContainsA(String temp) {
if (StrUtil.isNotEmpty(temp) && temp.contains("A")) {
return true;
}
return false;
}
public boolean validTemp(String temp) {
if (StrUtil.isNotEmpty(temp) && temp.contains("A")) {
return true;
}
return validContainsA(temp);
}
上述代码因为举的例子比较简单,应该能很简单的看出有一段代码被执行了两次,那么这样的设计违反了 DRY 原则吗?
我们认为其也是违反的,这里放的只是一个简单的逻辑判断,所以看不出来什么,如果这里是放了一个耗时操作呢,例如读取数据库、文件等。那么进行重复的执行,则会影响整个程序的对外性能。
因此,判断如何一个代码是否是重复的,需要结合具体场景来做判断,在这里,我们可以看到代码实现方式一样不能作为判断依据,因此其实现的语义是不同的,这就是功能语义的判断范畴,而对于重复执行,我们在代码里需要做到尽量避免,因为如果重复执行费时操作,则会导致代码整体对外的性能下降。
迪米特原则是用来指导设计高内聚、低耦合代码的原则,因此我们先看一下什么是高内聚、低耦合。
看到想要完成的目标,现在再来看一下什么是迪米特原则。
其概念是:每个类或模块只需要了解与他关系密切即紧密关联的类或模块。再换句话说: