“我又写了一堆烂代码!”
这句话我经常对自己说,目的是为了督促自己不断地思考所写的代码是否足够可靠。
不要觉得代码通过了 QA 的测试就万事大吉了,如果你为了实现某个功能,而破坏了原有系统的规则,或者让代码变得耦合,那么这就是一件糟糕的事情。
我通常在实现某个功能后,我都会问自己几个问题。
第1个问题:我刚刚做的工作是让整个系统更容易改变还是更难改变?
优秀的代码设计都满足一个原则:ETC原则。即 Easier To Change,更容易变更。
我们学过的任何其他设计原则,其实都是 ETC 的一个特例。
为什么解耦很好?因为通过隔离关注焦点,可以让每一部分都容易变更——此谓ETC。
为什么单一职责原则很有用?因为一个需求变化仅体现为某个单一模块上的一个对应变化——此谓ETC。
为什么命名很重要?因为好的命名可以使代码更容易阅读,而你需要通过阅读来变更代码——此谓ETC!
当你在思考自己写的代码是否可靠时,ETC 就是一个很好的向导。
如果需求变更,你的代码是否能轻易的做出改变,以适应这种变化,甚至是可以被替代。如果不能,那么你的代码就成了一种障碍。
所以,ETC 它更像是一种价值观念,能够帮你在不同的方案中,选出正确的那一个。同时,也能让你的代码不断进化。
第2个问题:有没有为了偷懒,写了很多重复的表达?
要让项目更容易理解和维护,唯一的方法是遵循这条原则:系统中的每一部分,都必须有一个单一的、明确的、权威的代表。
这个原则被称为 DRY 原则(Don't repeat yourself 不要重复你自己)。也可以叫 OAOO(Once and only once 一次且仅一次)。
来看一个违反 DRY 原则的例子:
void calculate(int money){
if (money >= 400) {
print('打折后的价格为¥:${money*0.7} RMB');
}else if(money >= 300){
print('打折后的价格为¥:${money*0.8} RMB');
}else if(money >= 200){
print('打折后的价格为¥:${money*0.9} RMB');
}else{
print('打折后的价格为¥:${money} RMB');
}
}
这个例子就是典型的重复。
假如价格的单位变更了,改成卢布,或者其他货币,那一共需要修改 4 处 RMB。
再比如,'打折后的价格为¥' 这个文案有调整,改为 '折后价',那么也需要修改 4 处的内容。
所以,平时写代码时,一定要避免这样的写法。
第3个问题:我写的代码有没有破坏正交性?
“正交性”是几何学中的概念。若两条直线相交后构成直角,它们就是正交的。
“正交性”在计算科学中,表示独立性或解耦性。
对于两个或多个事物,其中一个的改变不影响其他任何一个,则这些事物是正交的。
举个例子,在项目中,如果你改动了 UI 相关的代码,而不影响其他业务逻辑(比如数据库操作,网络访问逻辑等等),那么这样的系统,就属于设计良好的系统。
相反,如果你发现自己改动其中一处的代码,会影响很多地方,那么你就得思考一下,是否需要重构代码了。
一般来说,保持代码的正交性有以下几个实用的方法:
- 使用最少知识原则(迪米特法则)来保持代码的解耦性。
- 避免全局数据。只要代码引用了全局数据,就会将自己绑定到共享该数据的其他组件上。
希望你也养成不断质疑代码的习惯。只要有机会就重新组织、改善其结构和正交性(重构)。