1.不要重复自己:当我们在两个或多个地方的时候发现一些相似的代码的时候,我们需要把他们的共性抽象出来形一个唯一的新方法,并且改变现有的地方的代码让他们以一些合适的参数调用这个新的方法。
2.面向接口而不是实现,组合优先于继承
3.查询和命令分离:
查询:当一个方法返回一个值来回应一个问题的时候,它就具有查询的性质;
命令:当一个方法要改变对象的状态的时候,它就具有命令的性质;
通常,一个方法可能是纯的Command模式或者是纯的Query模式,或者是两者的混合体。在设计接口时,如果可能,应该尽量使接口单一化,保证方法的行为严格的是命令或者是查询,这样查询方法不会改变对象的状态,没有副作用,而会改变对象的状态的方法不可能有返回值。也就是说:如果我们要问一个问题,那么就不应该影响到它的答案。
4.不要和陌生人说话,
在《Clean Code》一书中,有一段Apache framework中的一段违反了LoD的代码:
final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();
这么长的一串对其它对象的细节,以及细节的细节,细节的细节的细节……的调用,增加了耦合,使得代码结构复杂、僵化,难以扩展和维护。
5.面向对象的SOLID原则
职责单一原则(Single Responsibility Principle):一个类,只做一件事,并把这件事做好,其只有一个引起它变化的原因。单一职责原则可以看作是低耦合、高内聚在面向对象原则上的引申,将职责定义为引起变化的原因,以提高内聚性来减少引起变化的原因。职责过多,可能引起它变化的原因就越多,这将导致职责依赖,相互之间就产生影响,从而极大的损伤其内聚性,增加耦合度。单一职责,通常意味着单一的功能,因此不要为一个类实现过多的功能点。
开闭原则(Open/Closed Principle)::模块是可扩展的,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。
里氏代换原则(Liskov substitution principle):也就是,子类必须能够替换成它们的基类。即:子类应该可以替换任何基类能够出现的地方,并且经过替换以后,代码还能正常工作。
接口隔离原则(Interface Segregation Principle):接口隔离原则意思是把功能实现在接口中,而不是类中,使用多个专门的接口比使用单一的总接口要好。
依赖倒置原则(Dependency Inversion Principle ):高层模块不应该依赖于低层模块的实现,而是依赖于高层抽象。也就是说高层不要直接调用底层的实现,而是通过接口和底层交互。而接口是一个通用的标准。就好像浏览器并不依赖于后面的web服务器,其只依赖于HTTP协议。生活中的一个例子,例如一个人参加职称评审,评审机构会通知被评审人某个时间到某个地方参加评审。而不会要求被评审人如何到达评审地点,也就是说,不管被评审人自己开车过去,还是打车过去,还是坐公交过去,如果指定了具体实现,例如要求自己开车过去,就会有很多麻烦,很不灵活,被评审人没有车怎么办,没有驾照怎么办。对于参加评审的委员也是一样,只会要求参加的委员人数和委员的技术水平,而不会制定具体某些专家参加,如果具体到某个专家,评审时,这个专家无法到场怎么办。只提标准,不要求具体,就会非常灵活,被评审人只要达到要求就行,在指定的时间到达指定的地点,无论自己开车过去还是打车过去,评审专家A没有时间可以从专家库选择B,只要两个专家水平相当。
6.好莱坞法则:好莱坞原则就是一句话——“don’t call us, we’ll call you.”。意思是,好莱坞的经纪人们不希望你去联系他们,而是他们会在需要的时候来联系你。也就是说,所有的组件都是被动的,所有的组件初始化和调用都由容器负责。
简单的来讲,就是由容器控制程序之间的关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:
1.不创建对象,而是描述创建对象的方式。
2.在代码中,对象与服务没有直接联系,而是容器负责将这些联系在一起。
控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。
好莱坞原则就是IoC(Inversion of Control)或DI(Dependency Injection )的基础原则。这个原则很像依赖倒置原则,依赖接口,而不是实例,但是这个原则要解决的是怎么把这个实例传入调用类中?你可能把其声明成成员,你可以通过构造函数,你可以通过函数参数。但是 IoC可以让你通过配置文件,一个由Service Container 读取的配置文件来产生实际配置的类。但是程序也有可能变得不易读了,程序的性能也有可能还会下降。
7.关注点分离:这个原则,就是在软件开发中,通过各种手段,将问题的各个关注点分开。如果一个问题能分解为独立且较小的问题,就是相对较易解决的。问题太过于复杂,要解决问题需要关注的点太多,而程序员的能力是有限的,不能同时关注于问题的各个方面。正如程序员的记忆力相对于计算机知识来说那么有限一样,程序员解决问题的能力相对于要解决的问题的复杂性也是一样的非常有限。在我们分析问题的时候,如果我们把所有的东西混在一起讨论,那么就只会有一个结果——乱。