刚开始编程的时候是在高中,那个时候计算机课上老师教的是pascal。一种典型的面相过程的语言。那个时候懵懵懂懂的认为:程序还是一个蛮神奇的东西,敲几个英文字符进去,就能够有反馈。即使这个反馈只是非常简单的输出了一个“Hello World!”。
而大学开始比较系统的学习计算机这个东西。但是现在回想起来,貌似没有系统的学过程序设计这个东西啊。即使上了很多叫做《XXX程序设计》的课程之后,对于程序设计这个东西还是有种雾里看花的感觉。而且学的都是像汇编了,C了这样的一些比较底层的语言。主要是语法吧,设计层面的东西真的很少。造成很长一段时间内,我对程序设计的认知停留在高中pascal的水平,程序设计就是你输入个东西,然后设计一系列串行的逻辑,然后等着输出。
后来上了一个叫做《C++面向对象设计》的课,在上课之前以为这是一个高大上的课程,结果到最后老师把c++讲成了一个好用的c,比c优秀的地方主要就是在加了一些支持面向对象的语法。现在回想一下,那些叫做《XXX程序设计》的课程,基本上都是一些语言课程,貌似和程序“设计”这个东西有点不着边际。而也未能让我,对于“面向对象”或者“面相过程”构建起基本的概念。
写程序的时候,更多还是停留在pascal那个层次中。串行的逻辑。那个时候的梦想就是能够读完knuth四卷本的《The Art of program》还有他为这本书写的辅导书《基本数学》。因为大家在程序=数据结构+算法的世界观中,这几本书如同圣经。最后花了大概四五年吧,只读了第一卷的300多页。好吧,貌似我不是一个很虔诚的信徒。
有幸的是,大二开始跟着一个老师给他们当码农,敲代码。就这样稀里糊涂,断断续续的以一个码农的角色在他们的项目中敲敲打打。那时作为一个新手,得到最多的就是“埋汰”。他们看着你写的c或者c++代码,说这个太不优雅了。当时,我就想:靠,就是一串代码,又不是什么画,还能用优雅来形容啊。之后,他们开始说一些设计模式了之类如同天书的东西。大三下班学期的时候,有个哥们在搞magic linux的安装程序的重构。我就听着他天天在和我白活写第一版安装程序的是如何如何牛逼哄哄的。模块划分的多么多么清晰,模块间通信竟然都是用的xml。设计的可扩展性多么多么好,模块间高耦合地内聚了。。。。当时就觉得,靠,真的很牛逼啊。用现在的一个词就是:不觉明历。不过当然,得向牛逼的人学习。于是买了本c++版的《设计模式》,就是最经典的那本。记得那个时候,读起来,略觉生涩。很多概念都是囫囵吞枣的咽下去了。在以后的编程中,也能偶尔用用什么观察者了,单例了之类的模式。偶尔,能够针对一些问题提出一些看似非常符合设计模式的“设计”。
在接触到设计模式并能够稍微懂点的时间内,以为面向对象这个东西的主要内容就是“设计模式”了吧。你看用了设计模式之后,腿也不酸了,要也不疼了,一口气能上十层楼了。写代码也开始有点那种玄乎的“优雅”的感觉了。切以为自己在码农这个职业上已经算是入门了。直到有一天看了一本叫做《敏捷开发》的书,才猛然间惊醒。他妈的,在设计模式之上还有六大原则:单一职责、里氏替换、开闭原则、迪米特法则、接口隔离原则、依赖倒置原则。原来设计模式被设计出来的时候也是按照一定的指导原则的,那就是六大原则。好吧,现在我的面向对象程序设计的思想库中又多了一批非常不错的概念:六大原则。而且惊喜的发现,随着对这六个原则尤其是单一职责原则的深入理解。自己开始,能够慢慢跳出原先那种刻意去使用设计模式的牢笼。开始去关注程序设计本身,或者说具体情况相关的东西。而不是为了设计去设计。这个时候,才开始慢慢的体会到其实程序设计这个东西真的并不是简单的逻辑罗列,而是思想的结晶。是必须经过深思熟虑之后,才能完成的事情。不再一听到别人高谈阔论高内聚低耦合,就不觉明历,开始尝试着去思考他们所谓的高内聚低耦合到底是个什么东西,用这个标准来评判一个面相对象的设计是否合适。这个面相过程的遗留品在面向对象的设计范畴内到底能够发挥多大的作用。渐渐的发现,其实高内聚低耦合和单一职责与迪米特法则是那么的貌离神合。讲的都是我们一段代码的职责一定要纯粹,而且越纯粹越好。不要染指其他代码的职责。登陆的代码就负责登陆,不需要管界面上的事情。界面上的代码就负责展示内容就好,不要负责业务逻辑。当能够清晰的指出系统中每个模块,每个类,甚至是每个函数那“单纯”的职责的时候,那么整个系统应该说是优雅的了吧。
而这个时候,进行分析与设计的时候总是有种捉襟见肘的感觉,一个类的设计,甚至一个方法的定义与实现没有什么规矩可言。有些时候从上面说的六大原则和设计模式入手,大概构想出了软件的模样。但是到了一些编码细节上的时候,总是有种力不从心的感觉。简而言之,就是看手气写代码。最终是否能够真实的还原自己的设计,完全是个靠经验吃饭的事情。而比较悲剧的是,作为一个编程经验没有十年二十年的人来说,这似乎有点不太靠谱。作为一个数学系的学生,那种定理情节油然而生。难道就没有类似与定理一样的东西能够帮助我有效的还原设计,定义一个类,定义一个方法。于是又开始了狂看书的路程。
c++之父Bjarne Stroustrup的《The Design and Evolution Of C++》中一句话给了我方向:c++语言在众多语言的角逐中能够胜出,本质上是一种哲学思想的胜利。乍一看可能认为是面向对象在实践中战胜了面相过程开始主导软件开发语言。但是,当去仔细品味的时候,发现这种哲学思想是一种实用主义的思想。他以目标为导向,以最终效果为评判标准。中间所做的一切努力,都是为了达到最后的目标。就像面向对象诞生的时候,正是软件规模不断扩大,软件复杂性已经超出了人类可控制的范围。人们急需要一种能够合理的控制整个软件复杂性的方法,于是就有了面向对象。而复杂性控制这个概念是来自于软件工程的东西。顿时你就觉得脑海中的很多概念开始高度重合面相对象、软件工程、复杂性控制、面相过程。。。。。。。定理没找到,反倒是炖了一锅佛跳墙。七荤八素里面什么都有。
偶然的机会在WIKI上看到了一个词——工具理性。才有点开始懵懵懂懂的觉得看到了一点曙光。原来一个Code Monkey废了半天劲塞进脑瓜里的所有东西,都是工具而已。编程语言是工具;面向对象设计是工具;敏捷工程是工具。。。。我们只是合适的使用这些工具来完成目标而已。恍然大悟,其实根本就没必要纠结于在编码的时候用的是面向对象还是什么,没有必要纠结用没用设计模式,没有必要纠结开发过程到底敏捷不敏捷。。。只要能够实现最终的目标就好了。只是实现目标的这个过程还是依旧曲折。如何选择工具,并且如何有效的使用工具依旧是一个很重要的问题。但是已经有了一个大概的能够指引以后学习方向的思想——了解目标、了解工具,懂得如何合理而且有效的使用工具,并且Keep it simple。发现在程序设计这个事情上,真正难的不是你写出了些什么东西,而是你没有写什么东西。难的不是你进行复杂的设计与编码,而是尽可能少的设计和尽可能少的编码。这有点像国画中的留白,那些真正简单的东西才是最复杂的东西。能够把设计最到最简才是真正的功力。一个Redis才几千行代码,sqlite也不过3w行左右的代码。这两个东西做的事情不可为不复杂,但是设计的人之功力可见一斑。
最后用一幅画与大家共勉:
|