[1]动机、原则与模式——OO设计之我见
2014年8月,我应内训经理的要求,做一次技术分享。我认为在公司的IT开发中,对面向对象的设计和实现没有得到足够的重视,宣贯做的不够,大部分软件工程师在这方面的素养也有待提高。另外由于我的专业和长时间的实践,始终想对面向对象设计做一个自己的阐述。我觉得这是特别好的一次机会,所以就这个问题做了题为《动机、原则与模式——OO设计之我见》的讲座,反响较好。这篇文章就是脱胎于这次分享,并在文字上更规范了一些。
编程是什么?
说到面向对象的设计和开发,我就想到上学的时候Pascal老师问过的问题:编程是什么?经过这么多年的实践,我觉得当时老师给出的答案是本质上的。编程就是数据结构加算法。这里先谈谈我对算法的理解。
算法就是解决问题的步骤,我认为是一种对软件工程的动态表述。关于算法,我有一个好消息和一个坏消息。好消息是,作为社会科学的范畴,大到国家强盛,民族复兴,小到家庭和谐,自我实现。往往都很难用1234的步骤来描述;而作为自然科学的计算机技术,大多数的问题都可以用某种算法的表述十分精确的定义。这就是为什么让我们觉得科学家比社会学家更靠谱;坏消息是即使有明确的步骤,很多算法还是很难。探其缘由,算法的难度来源于与数学的不解之缘。因为很多算法问题都是可以通过数学来进行建模,进而变成一个数学问题来求解。
讨论完算法,再说数据结构,数据结构是数据的组织方式,是软件工程的静态表述,数据结构是一种静态的美。作为一个普通的程序员,你可能不会设计很高深的算法,但你会经常遇到设计数据结构的问题,OO设计,本质上就是设计数据结构。从现在业界的技术人员构成,你会发现,真正研究狭义的算法的程序员是金字塔的塔尖,他们在大型科研单位和BAT这种巨型互联网企业中。而大量的软件工程师和高级软件工程师其实都在做数据结构,只是在解决数据结构问题的过程中,涉及解决问题的步骤,即广义的算法。而且好的数据结构设计,会从根本上简化解决问题的步骤。
程序员的境界
我在这里提到了两个典型的员工,他们可能不是具体的两个人,但绝对代表了两类人。老李,10年以上工龄的老程序员,习惯了开发过程中不费脑子的Ctrl+c,v大法,鲜有拿得出手的OO设计方案;小王,科班出身但经验缺乏,遇到问题善于思考和总结,即使很小的设计,也能看出OO设计的影子。我对他们的看法是,老李是典型的“一年进步,N年循环”的程序员,而小王终将“从优秀到卓越”。为什么造成了这种不同?境界的不同!
这时我又想起了《大腕》这部电影,其中一个桥段就是葛优给Lucy讲解境界的含义。它是一种眼光,境界越高的人,看的就越远。我给出了这样一张slide和一个结论。就OO设计而言,普通的程序员,优秀的程序员,伟大的程序员和佛,境界就是这么大的区别,而在我们修炼内功的道路上,提升OO设计能力,就是提升境界。
ood.jpg动机、原则与模式
我认为,软件设计可以分为三个重要的层次,面向对象的思想和软件(构件)复用的动机是最高层次的,面向对象的设计原则是对以上内容的具体化和衔接,而设计模式才是更具体到实际问题的解决方案,即接”地气“的部分。所以一个好的软件系统设计师,首先应该有面向对象的思想,然后掌握面向对象的设计原则,最后才是具体问题具体分析,应用模式来解决实际问题。这样才会设计出比较合理的系统,以及降低滥用和错用设计模式的几率。
动机是指一个人想要干某件事情而在心里上形成的思维途径。同时也是一个人在做某种决定所产生的念头。说到动机,可以比较两种程序员,分别是懒程序员和“懒”程序员。前者,不深入思考系统的结构,不会用面向对象的方法设计整个系统,停留在面向过程的思维模式,简单的复制粘贴;后者,不是真的懒,而是不愿意在后期维护更多的代码,愿意在设计阶段投入更多的精力,专注于解耦和封装,磨刀不误砍柴工。
我把真正的OO设计的动机总结为三点,首先是真实的反应客观世界,也就是建立模型;其次是把正确的算法,即解决问题的步骤放到正确的结构中;最后是拥抱变化,为产品,也为自己的未来考虑。
有些人认为,学习OO设计就是学习设计模式。但我更认为,OO设计的原则重于设计模式。《Java与模式》是一部描述设计模式的出了名的大部头,一共1024页(好有计算机科学的感觉)。尽管你可以想象他用超过90%的篇幅描述各种设计模式,但是你可能不会想到,他在第二部分就写了这么一段话:
在目前的软件界,学习和应用设计模式正在形成风气。的确,通过学习和应用设计模式,可以更加深入地理解面向对象的设计理念,从而帮助设计师改善自己的系统设计。但是,设计模式并不能提供具有普遍性的设计指导原则。在读者经过一段时间的对设计模式的学习和使用之后,就会觉得这些孤立的设计模式的背后应当还有一些更为深层的、更具有普遍性的、共同的思想原则。
可见本书的作者,希望读者在进入设计模式这个绚丽世界前,先要掌握OO设计原则这个指南针,才不会在随后的学习中迷失方向,才能掌握“大巧若拙,大辩若讷”的OO设计精髓。那么OO设计原则都有哪些呢?我又怎样对它们进行解读呢?请看本文章的第二部分。