如今所有的Opening,只要有点底气,都会要求candidate有OOD的能力、熟练运用各种设计模式。然而在笔试及面试中,却只能通过形如,“列举GoF书中你知道的设计模式”,“画出strategy模式的UML图”之类的问题来进行测试,在如今实习生都把GoF书翻烂的年代,这样的问题如同,“请说出final, finally, finalize的区别”一样,只能浪费双方的时间。综观面试经验,对于“阐述一下你对OOD的看法”的回答,无非两类:“封装、多态、继承”或者“GoF的模式”,这样的回答恰恰代表了候选人对OOD理解的层次。

在OOD这个domain里面,类比数学公理,我认为Robert.C.Martin的OOD Principles已经说的非常清楚,当中最为核心的一条,就是SRP。所有其他的编程原则如同在五大Principles中的OCP、DIP更多的是基于SRP的一些推论,更不必说DRY原则等等一系列五花八门,变化多端的buzz word。我认为所有的程序设计工作,其实最终的目标都是为了达到隔离关注,将特定的需求交给专门的组件去完成。这里的组件在不同的上下文中含义不同,小至在单个系统模块内部,组件指的可能就是完成特定功能的Class/Function,大至SOA(另外一个buzz word)中,组件指的可能就是某个业务域服务系统。当明确了SRP是终极目标之后,OCP说的,只不过是“部分特定条件下的情况已经被本组件解决完毕并隔离,如需要处理其他特殊逻辑,请通过扩展的方式在特定的地方完成”;DIP则说“本实现所依赖的组件的具体实现选择过程应该由专门的选择策略组件完成,本类的主要关注是利用这些依赖完成本类所标称需要解决的问题”;至于那个DRY原则,则更显浅易懂了,本来就已经有特定的组件把特定的关注解决掉了,还有必要重新解决一次么?
那么所谓的封装、多态、继承,甚至是GoF的各种模式,到底是什么呢?同样的,类比数学中的概念,它们就是一些基于数学公理的推论,虽然我们可以通过公理一步一步的将所有的定理推论都推理出来,但极少数人会在实际运用计算的时候这么做,因为太慢了。同样的,这些类似Best practice的东西的价值也仅仅在于,解决某一特定前提下的某一特定问题,这样,你就明白为什么我深恶痛绝模式驱动编程:模式是为了解决特定问题而产生的,但这帮人的做法是为了运用某种模式,而去创造该模式所符合的问题,这让我想起那个关于数学家的笑话。然而我经历的团队中,这样的情况屡屡发生,成为过度工程的头号原因。
之前经常有人问,如何锻炼设计能力?我就会建议他们看一下那几个principles,每天读,读通读透,让它们成为你的条件反射。在做设计和review设计的时候,不停的问自己,我一共有多少个问题?正在考虑的这个组件要解决什么问题?在它所处的粒度来看,它是否只有单一职责?等到每个问题的答案都是Yes的时候,我认为这个设计至少不差。我之前看到过很多这样的设计,大多数情况下,它们不会有一些fancy的设计模式名称在里头,但却渗透着一股身经百战的老练,比如JQuery的core
同样的,有一种显而易见的bad smell:当你的代码库中充斥着大量的设计模式名称,而实现代码却看起来极其幼稚(我认为至少得读过Implementation Patterns或者Clean code),那么百分百的,你的团队中就至少有着一个急于想证明自己却又适得其反的成员,该是时候找他谈谈他的定位和成长计划了。