简单之美:软件开发实践者的思考
上QQ阅读APP看书,第一时间看更新

1.2 本质的把握

把握软件和软件开发的本质,可以使知识和技能的积累变得更加高效,而把握认知方法的本质,可以使知识和技能的积累总是走在正确的道路上。

什么是软件的本质?在前一节中,我给出了自己对于软件本质的理解,那就是二进制和与或非逻辑。

我不认为二进制和与或非逻辑是对软件本质的唯一解释,事实上,每个人对软件的本质都有着自己的理解。人们在自己的思想长廊中往前追溯,然后会在一个地方停下来。他们认为,在这个地方,一切都是常识性的知识,虽然可以继续分解和往上追溯,但是已经没有必要。我把这种状态下对软件的认识称作软件的本质。

而软件开发的本质是什么呢?

软件开发是一项具有艺术性的科学工作。一方面,因为软件是逻辑学和数学的应用,所以软件开发是科学性的工作;另一方面,因为软件的实现有无限种结构形式,而且每一种结构形式都富含人类的创造和想象,所以软件开发是艺术性的工作。

有些人还可能会从心理学和管理学角度来阐释软件开发的本质。我不赞同这个观点,但这不是重点。

重点是什么呢?

重点是我们需要形成一个自己的、系统而且完整的观念。这种观念,一定会与你所有的认知融合在一起。它来自经验和实践,反复验证之后会成为你思想的一部分。很显然,要排斥一种观念是容易的。可是,没有自己的思想体系,就更加容易陷入一种迷惘的状态。

如果你尝试建立有体系的观念,你会用自己的观念解释一切,你也会不断地在失败中修正观念,那么你最终会在自己观念的带领下走向成功。举个例子,在现实世界中,苹果会从树上掉下来,你不会怀疑这一点,这就是你的世界观的一部分。可是,在微观世界里,你的观念会遭到重大打击。你需要调整世界观,用更复杂的方法来解释世界。你不断调整,最终得到真谛。这种有体系的观念,我称作思想体系。

思想体系的建立是很有用的。我们不妨以学习为例。你知道吗?最有效的学习方法就是用自己的思想体系来接纳外部知识。这也可以说明一个问题,你看,在计算机书店,有很多大师级的作品,他们的知识向所有人开放,可是很多人从中得到的收获总是非常有限的,为什么?因为思想体系还没有建立,很多人还无法对书中的知识进行有意识地提炼和抽象,所以总是会有很多疑惑和不解。

其实,只要经过足够长的时间,每一位软件开发人员都会不自觉地形成自己的软件开发思想,这和过日子是一样的。

不过,有很大一部分软件开发人员在经历短暂的思想积累以后,却偏离了软件开发的方向。很多软件开发人员,热衷于转向另一个更加不成熟的领域——软件开发管理。糟糕的是,这些不成熟的软件开发管理人员,在不自觉中为其他软件开发人员设置了更多通向成熟的障碍,最终破坏了软件开发的整体环境。

在以后的章节中,我们会详细讨论与软件开发管理相关的问题。这里我想先简单表达一个观点——管理,其实是软件开发中的辅助性工作,它很重要,但不是必需的。好的管理是高效的燃油添加剂,但是,我已经看过太多糟糕的管理,它们对软件开发的负面影响远大于软件开发人员自身。

软件开发思想难以形成体系,除了浮躁和放弃,还有一个原因。

在我们这个时代,很多软件开发人员都比较年轻,他们正在进入一个眼花缭乱的世界。与二十年前的软件开发人员相比,他们面临着更多的选择。而要想做出正确的选择,需要时刻保持清醒的认识和精准的判断。在软件领域中,充满了丰富的创造成果和层出不穷的新概念,毫无目标的追逐会使有限的积累能力稀释,从而使知识和技能的提升变得低效,甚至走向错误的道路上。

我在软件开发生涯中同样走了很多弯路。比方说,我曾经如饥似渴地阅读了大量自己不太理解的软件书籍,可是收效甚微。当我回头反思自己的软件开发生涯时,一方面认识到自己不是一个具有软件开发天赋的人,另一方面也为自己没有幸运地得到正确的指点而深感遗憾。哪方面的指点呢?不是如何使用某一款开发工具,也不是如何实现某一个精妙的算法,而是积累知识和技能的方法。

方法是我们一生中最有价值的知识财富。

谈到这里,我想到一个有趣的社会现象。

很多软件开发人员都接受了4年的大学高等教育,但是他们中的大多数人并不为自己在这期间取得的成绩而骄傲,有些人甚至还抱怨自己没有学到任何有用的知识。这种认识是不够全面和客观的。其实,我们在这4年里学到了最重要的知识——做人和做事的方法。在那段时间里,我们开始独立生活和思考,开始与一些和自己的成长环境不同、但知识和思想层次与自己接近的年轻人互相接触和相互影响,开始独立地为自己的生活和学习做决策等。与这些相比,学科内容本身并不是那么重要。

总之,如果思想体系没有建立,找不到建立思想体系的方法,以及不会应用思想体系来解决问题,我们就无法把握事物的本质。

在进入企业应用领域的这些年,我接触了很多新的概念:包括客户端、服务端、Web服务器、应用服务器、服务端容器、应用框架、远程方法调用、WebService、SOA、ESBESB(Enterprise Service Bus,企业服务总线),是指由中间件基础设施产品技术实现的、通过事件驱动和基于XML消息引擎,为更复杂的面向服务的架构提供的软件架构的构造物。企业服务总线通常在企业消息系统上提供一个抽象层,使得集成架构师能够不用编码而是利用消息的价值完成集成工作。、BPMSBPMS(Business Process Management System,业务流程管理系统)的思想以一种统一、中性的表示方法描述业务流程模型,使业务流程模型从实现逻辑中抽取出来,被各个企业应用程序所使用,从而灵活地构建基于流程的信息系统。等。每个概念都有数量庞大的衍生内容。对于新进入这个领域的开发人员来说,一下子面对这么多的概念会有点无所适从。

按照我们前面的说法,建立一个思想体系是最重要的。也就是说,只有在一个完整的上下文中思考才能真正解决问题。所以,我尝试用一条线索把上面的概念串联起来。

在1.1节中,我们提到了编程语言的发展。编程语言是软件开发必须使用的计算工具。在企业应用中,计算工具仍然是这些编程语言,只是计算的平台被推广到了网络上。

很多计算机连接在一起组成一个网络。连接的含义是指,计算机之间可以进行开关信号的传递(有线或者无线),为了保证连接和那些开关信号是有意义的,业界制定了一些标准协议。例如,TCP/IP协议。若想了解网络协议,可以参考相关的书籍。

在企业应用中,网络连接很重要,一方面是因为它能满足基本的信息传递的需求,另一方面还可以通过网络连接来使用其他计算机的计算能力。计算机的价格与计算能力通常存在一个指数关系,所以企业必须充分使用那些昂贵的计算能力。

提供计算能力的计算机就是服务器,而请求利用这些计算能力的计算机就是客户端。

我不认为软件开发人员充分认识了这一点。当系统面临着计算性能问题时候,很多软件开发组织甚至还没有意识到分布计算的重要性。

如何利用服务器的计算能力呢?有很多种方式。这些年,业界最流行的是Web服务模式。在这种服务模式中,客户端变成了浏览器(甚至屏蔽了计算机的概念),服务端则是遵循Web协议的任意实现。换句话说,采用这种服务模式的企业应用,只是借用了Web服务与客户端交互,位于延伸空间中的各种概念与创造并不依赖于Web服务。

通常情况下,应用服务器是Web服务器之后的第一个延伸。Web服务器对客户端请求信息(URL)进行分拣,具有指定特征的信息交由应用服务器来处理。

为什么需要应用服务器,而不是直接面对应用程序?这是因为很多有价值的公共任务需要应用服务器来处理。以JavaEE应用服务器为例,应用服务器负责建立一个企业应用程序空间,把JSP页面编译成Servlet,管理服务线程,维护各种寄居于容器中的组件生命周期,提供事务服务、安全服务和消息服务,还有像配置管理、外部资源连接、数据库连接池等。应用服务器的作用是很大的。

我们提到了服务端容器,这又是个有趣的概念。我们知道,为了使用应用服务器提供的各项服务,你必须按照容器定义的接口来开发组件。这些组件往往无法独立存在,甚至连生命周期也掌握在容器的手中。这有点类似于回调函数,但是比回调函数的想象丰富多了。

很多软件开发人员毫无节制地开发容器组件,程序中到处散布着和容器相关的参数。这种做法是不对的。尽管容器提供了丰富的功能,但仍然要尽量使应用程序和容器隔离,经过这样隔离的应用程序才具有良好的移植性。实际上,应用程序应该与任何第三方的框架和平台隔离。

对于企业应用来说,有了应用服务器和服务端容器还不够,有很多第三方的应用框架对应用服务器的功能做了一些补充。例如,Struts使用MVC模式为页面与后台应用之间建立了一种新的联系方式,Spring如果你有兴趣通过研究Spring的源码来理解Spring的架构、设计和实现原理,从而更好地应用Spring进行开发,推荐阅读《Spring技术内幕——深入解析Spring架构与设计原理》一书。提供了一个轻量级的容器实现等。这些第三方应用框架中的优点正在被缓慢地引入到应用服务器的标准中。

为了更好地使用服务端的计算能力,我们要用到服务端的分布式计算。事实上,应用服务器早就支持了这种计算模式。服务端的分布式计算是高性能企业应用的基础,而远程方法调用则是分布式计算的基础。

远程方法调用使分布式应用与单机应用从程序代码这个级别看上去变得没有什么不同。当然,远程方法调用有一些额外的工作要做,例如,对于RMI(Remote Method Invocation,远程方法调用)来说,需要使用RMI注册服务器来获取远程方法的引用。

RMI的问题在于,首先它是Java特有的(虽然可以与其他语言进行映射);其次它使用了特定的服务协议。于是,业界提出了WebService的概念。这使远程方法调用被提到一个新的高度。与RMI这类的实现截然相反,WebService独立于任何平台。它可以附加在HTTP这类最普遍使用的协议上,完成异构平台间程序代码级别的整合。

在Web Service出现的头几年,业界并没有找到使用它的最佳场景。直到某一天,它悄然成为SOA的一块重要基石。

我们正处在SOA概念泛滥的年代,有些人拥抱它,有些人排斥它。其实SOA一点也不神秘,它只是远程方法调用的变体。不过,这种变体是革命性的,它改变的不仅仅是一种技术实现,它改变的是构架企业应用软件的思想。

为什么呢?

企业应用软件传统的构建方法是,首先进行数据或对象建模,然后基于这些模型来完成业务功能。这个过程不是一次就能成功的。

因此,在分析和实现业务功能的时候,要时时对数据或对象模型进行修改。修改的工作比较烦人,涉及大量遗留的应用。MDAMDA(Model Driven Architecture,模型驱动架构)是由OMG定义的一个软件开发框架。它是一种基于UML以及其他工业标准的框架,支持软件设计和模型的可视化、存储和交换。与UML相比,MDA能够创建出机器可读和高度抽象的模型,这些模型独立于实现技术,以标准化的方式储存。MDA把建模语言用作一种编程语言而不仅仅是设计语言。希望完成模型到业务功能的自动化,从而尽量减少烦人的修订工作。

当然,传统的构建方法也不是刻板的,在数据或对象建模前,通常会尽早地使用用例来描述业务功能。即便如此,传统方法的首要目标仍然是数据或对象模型。

而与传统方法不同,SOA面向服务来建模。它更偏重于用例中的行为,而不是实体。之所以关注行为,是因为SOA有一项特殊的使命,那就是整合企业中的所有应用,包括新规划的系统和已有的系统。

对于已有的系统(软件资产),考虑数据和对象模型意义不大,考虑如何利用已有系统的功能才是关键。所以,如何快速有效地抽取已有系统的功能,是首先要考虑的事情。

由于WebService的发展和普及,抽取功能已经是一件很容易的事情了。这为SOA的推广铺平了道路。

对于新规划的系统,使用传统构建方法更好。很多软件开发组织,总在追寻解决问题的银弹。其实,没有打中目标,通常不是弓箭不好,而是你还没有掌握使用弓箭的技能。

因为SOA的普及,ESB也变得引人注目。注意到了SOA的特殊使命了吗?企业服务总线就是用来整合企业的所有应用的,它支持异构的系统在一个共同的契约下发生关系。就这么简单。

与之类似,BPMS也应运而生。SOA确立了整合系统的思想,ESB提供了准备就绪的服务,业务流程管理系统就是使用这些服务的工具和平台。

好了,以上就是我对那些概念的思考。

我把那些概念串成了一条线索。现在,线索中的每一个节点,都有了一个合理的解释。我不认为自己的解释和线索是唯一的,甚至也许有些还不够准确。但重要的是,我现在有一个体系来接纳新的概念了。

根据以往的经验,思考新的概念,经过解释、修正、再解释,最后把这些新概念转化成为思想体系的一部分。这应该就是认知方法的本质了。