March 22
原则,你懂不
最近看了《疯狂的赛车》,里面那两个杀手,抑或是贼,也许又是毒贩,或者说他们是全才,反正他们的台词相当搞笑,“干一行爱一行”,“多行不义必自毙”,“不专业啊”,其中还有一句话就是“原则,你懂不”。
其实我不怎么懂原则,我说的原则是软件设计中的原则,每次当我问那些有经验的前辈们,怎么设计才算是一个合理的设计方案,一般都会得到的回答就是,经验,当经历的项目多了,自然就会有一套自己设计的套路。这种回答也实在是无可奈何,毕竟软件设计没有一套验证合理性的数学模型,所以对于一个设计方案,我遇到很多设计评审就是,合理就可以,但没有人可以肯定,这个设计不会造成一些后果。尤其是对于我这种菜鸟来说,设计一个模块都让我战战兢兢,如履薄冰。所以嘛,不知道点原则,那么做出来的事情肯定就不专业了。虽然现在的经验不能保证我能够吃透这些原则,但完全不知道原则,那就像是拿着菜刀去和鬼子搏斗一般,也许一转身,发现还有AK47,迫击炮,火箭筒之类的,虽然现在不会用,但也得学,虽说有时候杀鸡用牛刀,偏偏用牛刀可以把鸡杀了,但反过来杀牛用鸡刀,只怕是牛占据格斗的优势。
废话到此,先看伟大的wiki上对软件设计7条原则的描述:
1.开闭原则(Open/closed principle)
这个是最常提到的,当年我面试的时候,也被问过这个问题,简单的说,就是在面向对象的编程中,软件实体应该可以自由扩展,而不能被修改(software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification),也就是说,在要增加软件的功能,或者是要做其它方面的改进时,不能对原有的代码进行改动,而只能在原来的代码上进行添加。如果说你不得不修改原有的代码来改进一个模块的某些功能,那么只能说这个模块设计得不合理。
2.里氏代换原则(Liskov Substitution Principle,常缩写为.LSP)
这条原则是继承复用的基石。(Let q(x) be a property provable about objects x of type T. Then q(y) should be true for objects y of type S where S is a subtype of T.)如果q(x)是对象x的属性,属于T类型,那么如果q(y)是y对象的属性,属于类型S,且S是T的子类型。换言之,一个软件实体如果是用的一个基类的话,那么一定适用于其子类,但是反之不然,基类无法完成子类的某些功能。
由这条原则引申出了“基于契约设计”(Design By Constarct):类的编写者显式地规定针对该类的契约。客户代码的编写者可以通过该契约获悉可以依赖的行为方式。契约是通过每个方法声明的前置条件 (preconditions)和后置条件(postconditions)来指定的。要使一个方法得以执行,前置条件必须为真。执行完毕后,该方法要保证后置条件为真.就是说,在重新声明派生类中的例程(routine)时,只能使用相等或者更弱的前置条件来替换原始的前置条件,只能使用相等或者更强的后置条件来替换原始的后置条件。
3.依赖倒置原则(Dependence Inversion Principle)
这个原则也叫做控制翻转(Inverse of Control),该原则寻求颠覆传统看法,软件的高级模块应该依赖于软件的低级模块,取而代之的,软件的的高级和低级模块都应该依赖于公共的抽象。
此条原则的有点在于,在软件开发中,开发者不需要在开发高级模块之前完成低级模块的开发,这就使得自顶向下的模式在设计和开发中都成为可能。
具体而言,此条原则对我来说还很模糊,也许从Springs框架中的IOC,以及依赖注入可以体会到一些灵感。
4.接口隔离原则(Interface Segregation Principle, ISP)
一个类对另外一个类的依赖是建立在最小的接口上。
多个专门的接口比使用一个单一的总接口好,可以根据客户程序的需要,配置不同的接口,而不需要千篇一律的使用大的总接口。
也就是说,接口的粒度要尽可能的小……至于怎么小,具体情况具体分析了。
5.合成/聚合复用原则(Composite/Aggregate Reuse Principle,CARP)
在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分。新的对象通过这些向对象的委派达到复用已有功能的目的。这个设计原则有另一个简短的表述:要尽量使用合成/聚合,尽量不要使用继承。
其实这个原则我总觉得有些霸王,通过继承也能完成复用,而且有的时候继承更加能反映真实世界的关系……也许有的时候,考虑到软件对象抽象和现实的映射关系,继承的抽象是不是更能够容易理解。等过一段时间,看下自己是不是对这条原则有新的认识。
6.迪米特法则(Law of Demeter LoD)又叫做最少知识原则(Least Knowledge Principle,LKP)
其基本观念是,对于给定的对象,他应该尽可能少的了解其它组件的结构和属性。就是说,两个类如果要发生通信,那么最好不要直接直接发生作用,可以通过第三者转发……
其实这个理由很扯淡,通过第三者进行转发,那么不就是了解了第三者一些信息吗?抑或用一种特定的机制进行转发,搞不懂额。
7.单一职责原则(Simple responsibility principle SRP)
也就是说,一个类应该仅有一个引起它变化的原因,如果这个类有多个职责,那么就应该创建新的类去完成这些职责。
恩~说了这些原则,不过很多原则还必须通过实际项目去加深理解,原则为何在设计中起着作用,以及原则和具体的设计模式直接有什么联系,我还要慢慢体会。如果不知道这些原则,那么就是做软件不专业……多行不义必自毙。(满嘴顺口溜,你考研啊)