1.3 简单的追求
软件开发,尤其是企业应用软件开发,最根本的原则是简单化。简单可以使表达准确、思路清晰,可以实质性地、最大限度地降低软件开发成本。简单化不是天方夜谭,它是可以实现的。
在讨论软件开发中的简单化原则之前,我们不妨先来认识两个人。他们是中国近现代哲学史上的两位大家——金岳霖和冯友兰。很有趣,这两个人在表述哲学观点时,风格截然不同。金先生总是喜欢把简单的事情表述得很复杂,而冯先生呢,总是能把复杂的事情表述得很简单。我们来欣赏两段文字。
金先生在《论道》的“第8章——无极而太极”中写道:
道无始。所谓无始就是说无论把任何有量时间以为底始,总有此时间之前的道;或者说从任何现在算起,把有量时间往上推,推得无论如何的久,总推不到最初有道的时候。可是,道既然无始,为什么又有极呢?如果有极,那极岂不就是道底始!这极是极限的极,是达不到的极。它虽然是达不到的,然而如果我们用某种方法推上去,无量地推上去,它就是理论上推无可再推的极限,道虽无有量的始,而有无量地推上去的极限。我们把这个极限叫做无极。
冯先生在《中国哲学简史》中论述自己对于哲学的看法:
哲学,和其他各门知识一样,必须以经验为出发点。但是哲学,特别是形上学,又与其他各门知识不同,不同之处在于,哲学的发展使它最终达到超越经验的“某物”。在这个“某物”中,存在着从逻辑上说不可感只可思的东西。例如,方桌可感,而“方”不可感。这不是因为我们的感官发展不完全,而是因为“方”是一“理”,从逻辑上说,“理”只可思而不可感。
在这个“某物”中,也有既不可感,而且严格说来,亦不可思者。在第一章中,我说哲学是对于人生有系统的反思的思想。由于它的反思的性质,它最终必须思想从逻辑上说不可能成为思想的对象的“某物”。例如,宇宙,由于它是一切存在的全体,从逻辑上说,不可能成为思想的对象。我们在第十九章已经知道,“天”字有时候在这种全体的意义上使用,如郭象说:“天者,万物之总名也。”由于宇宙是一切存在的全体,所以一个人思及宇宙时,他是在反思地思,因为这个思和思的人也一定都包括在这个全体之内。但是当他思及这个全体,这个全体就在他的思之内而不包括这个思的本身。因为它是思的对象,所以与思相对而立。所以他思及的全体,实际上并不是一切存在的全体。可是他仍须思及全体,才能认识到全体不可思。人需要思,才能知道不可思者;正如有时候人需要声音才能知道静默。人必须思及不可思者,可是刚一要这么做,它就立即溜掉了。这正是哲学的最迷人而又最恼人的地方。
从逻辑上说,不可感者,超越经验;既不可感又不可思者,超越理智。关于超越经验和理智者,人不可能说得很多。所以哲学,至少是形上学,在它的性质上,一定是简单的,否则它又变成了简直是坏的科学。它虽然只有些简单的观念,也足够完成它的任务。
我本人偏好冯先生的那种简单表述。不过,哲学家的工作,是一种个人的行为。岳先生的文字尽管复杂晦涩,但读者有充裕的时间去揣摩他的观点。从这个角度来看,复杂性没有太大的问题。可是,在软件开发的过程中,复杂形式的思想交流就有点不可思议了。我们总是希望接触到最直白的常识。
要想用最直白的常识来交流,把握事物的本质是关键。而为了把握本质,我们首先需要认识事物。
一般来说,人们认识事物从简单开始,经过简单认识的不断堆积,然后在混乱复杂中摸索,最后又回归简单的认识。这样的认识过程同样适用于软件开发领域。
因此,在软件开发实践中,我们应该有意识地向认识的最高形式——简单化——靠拢。事实上,简单与否,常常可以成为衡量我们对事物认识程度的一个标准。我们不妨按照简单的标准来认识一下企业应用软件。
在我看来,企业应用软件很简单。它主要包括三个部分:一个领域模型,一组基于领域模型的计算,以及用来和用户交互的界面。这是一个基本的思路。
任何时候都不要轻易丢弃一个非常简单的原则性想法,同时,在任何时候都不要固执于一个具体的想法细节。
不过,当我们把这个基本思路应用到软件开发实践中去的时候,可能会发现,还有一些相关的工作要做。例如,领域模型在工作时会涉及信息的使用和存储。因为存储的需要,所以要了解数据库(现在的ORMapping工具使你不用更多地了解它)。
老实说,为了恪守简单的原则,我们应该逐渐进入细节。在这个例子中,思考领域模型的时候不要立即开始考虑数据库的因素。可以做到吗?
答案是,很多软件开发人员都做不到。他们总是忍不住会立即去考虑效率、领域模型中各元素的关系如何在数据库中的表达、ORMapping工具在使用中的一些限制等。
忍不住的结果就是,他们停留在一个点上,想了很多方法来解决他们担心的事情。因为这样的事情总是有很多,所以简单的原则总是被违背,而复杂性总是不期而至。
具有讽刺意味的是,在软件开发实践中,很多设计人员提出的针对性能的解决方案往往是性能的最大瓶颈。
假设我们恪守了简单化原则,同时有了一个满意的领域模型,接下来的事情就是基于领域模型的计算。
在系统工作期间,领域模型会产生很多的实例,这些实例拥有自己的数据。企业应用软件的主要工作内容基本上就是围绕这些数据做些加加减减的工作。
当然,除了加加减减,我们还需要了解一些相关的知识。
第一,业界有很多的平台和框架支持加加减减,例如JavaEE、Spring、Seam等。而这些平台和框架又提供了一些服务,例如,分布式计算、事务服务、连接池、状态服务(各种上下文)等。我们了解并运用这些平台和框架,可以减少自己的工作内容。
第二,除了平台和框架之外,我们可能还需要了解一些支持开发的工具。这些工具可以通过向导生成各种类型的项目,可以集成各种服务器,可以帮助我们开发程序、调试代码、发布应用等。
第三,如果还要延伸,那我们可能需要看看业界的一些流行的概念,比方说SOA。
SOA可以帮助企业来进行系统集成,同时它也可以帮助企业用一种全新的、面向服务的思想来构建系统。
我们不断地延伸知识,听上去似乎有点复杂了。但是,这些延伸的知识不是问题的本质。我们需要记住的应该只是那个简单的原则;我们需要做的其实只有一件事——基于领域模型的计算。
想想看,我们需要关注的只是如何把加加减减做得精到。所以,在陷入各种细节性的讨论之前,我们应该从思想上来把握问题的本质。
本质的就是简单的。所以,我们的目标是要让事情都变得简单。这有很多的工作要做,比方说如何让软件如何与平台框架的耦合性降到最低,如何让软件的可移植性和可扩展性最好等。事实上,这些让事情变得简单的工作,才是我们思考和努力的方向。相反,在简单的事物上,寻求局部的、复杂的解决方案是一种风险极高的做法。
认识上需要追求简单,实践中也该同样如此。
的确,软件开发实践存在一定的复杂性。这是因为,实践中遇到的背景知识是广泛的。这些背景知识,通常不会在一本或几本参考书中找到答案。例如,当你需要开发一个Linux版本的通信系统的时候,需要具备很多相关的知识。否则,会遇到很多困难。
我有过类似的经历。当时接到了一个任务:
我们要准备一个运行在VMWARE中的应用系统DEMO。这个DEMO将被部署在WAS(已部署WPS)上,系统运行时调用部署在WPS上的业务流程接口,业务流程的节点上会调用公司的规则引擎,规则引擎被封装成EJB部署在WAS上。所有的部署过程使用自动化脚本。
整个任务的时间是一周。如果你不了解VMWARE、WAS、WPS、规则引擎、EJB、SHELL SCRIPT、JACL和应用系统本身等,你该怎么做?没有答案。估计只能像我们一样瞎蒙吧。
相关背景知识的积累需要一个长期的过程。在这个过程中,主要的工作就是收集信息。
收集信息是一项艰巨复杂的任务。但是,对软件开发来说,这项任务是过程性的任务,而不是我们的目标任务。
可是,我总是很遗憾地发现,很多软件开发人员都被这个过程性的任务蒙蔽了双眼。他们中的一部分,始终徘徊在信息收集的门外(因为无法掌握足够的信息而无力解决问题),他们中的另一部分,在积累了丰富的信息之后,尽管已经不自觉地站到了一个更高的层次(可以用思想来指导行动)上,但是主观上,他们仍然把信息收集的过程当作了软件开发的本质内容。
之所以在这里谈论一些看似微不足道的差异,是因为我非常在乎思想观念上的差异。在我看来,出发点的不同,导致的结果可能完全两样。
这也是我不断强调在软件开发思想上要坚持简单化原则的原因。
其实,信息量的多寡,根本不能反映软件开发能力的本质差异。我们说必要的知识积累是软件开发的起点,但是软件开发的本质在于创造,所以运用信息的能力才是关键。
从这个角度来看,很多软件开发组织对软件开发技能的认识其实都是错误的。这些组织看重信息量,而忽视信息的使用方法。这也是我们为什么总是遇到复杂混乱的软件架构的原因之一。
如果你的企业正在招聘人才,请关注应聘者解决问题的思路和看待问题的层次。信息量既不是生产好软件的前提,也不是生产好软件的必要条件。以后的章节中,我还会进一步论述这个观点。
让我们再回到简单化的话题。简单化有什么好处呢?
越简单越准确。
用例的撰写就是一个明证:不需要修饰语,不需要副词,不需要语气词和助动词。有效的用例只保留主谓宾,没有任何内涵和外延干扰意思的表达。用例简单到只有常识和术语,几乎不可能带来歧义。
对于团队特征更明显的企业应用软件开发来说,简单化还是准确沟通的最好保证。
越简单思路越清晰。
我曾经看过这样的系统,它包含了很多概念和分层。一次调用会涉及数不清的接口,跨越数不清的框架、模块、公共组件和“小发明”。一定需要这样的结构吗?不需要。这样的结构只会使后期的演化和维护变得异常困难,由此带来了巨大的隐形开发成本。虽然我们不差资源和智慧,但能简单为啥不简单呢?
理想中的简单化是仅保留所有必须保留的,使通过简单化建立的一切,最有利于知识共享和持续演化。这两个目标看似容易,其实不容易。它需要成熟的简单化思想,需要持之以恒地恪守原则,需要简单化技能的训练。
还有一个问题。
在软件开发实践中,初始状态通常都是简单的。但是,随着时间的推移,软件开发开始变得复杂和混乱。这是为什么呢?很简单,这是因为软件开发人员丢弃了简单化思想和恪守简单化原则的精神。
很有趣。如果你曾经在生产企业应用软件的企业中呆过,那么,你总是会发现这样的丢弃行为。
回忆一下,你曾经经历过轻率决策吗?你曾经经历过非技术型妥协吗?你曾经经历过无责任参与吗?如果你曾经经历过,那么告诉你,那些都是打破简单化原则的“最好”方法,也是使软件开发变得复杂和混乱的根本原因之一。