用管理的思维编写程序

2014-04-22

在20世纪90年代,面向对象的编程思想已经逐步代替了面向过程编程思想。特别在当前的大型企业应用项目中,使用面向对象的程序设计思想进行软件设计,可以构造出较稳定、易扩展、易维护的软件。

面向对象的程序设计思想发展到今天,已经有20多年的历史了。然而在一些使用面向对象技术(如JAVA)编写的软件程序中,仍然可以看到很大篇幅的过程式代码,这使得软件在稳定性、可读性上都大打折扣。要想解决这一问题,需要掌握面向对象的原则以及实现面向对象的方法。
程序员朋友都听说过,面向对象有以下几大基本原则:

开闭原则

对扩展开放,对修改关闭。通俗点说,一个软件或一个模块,在需要增加新的功能时,如果通过增加新的代码或修改现有代码的外围代码(非核心代码)即可实现,那么我们可以说,这个软件或模块满足了开闭原则。

依赖倒转原则

依赖抽象而不是依赖具体。通俗点说,程序只依赖抽象类或接口,不依赖具体类。具体类的修改(改名称、改方法实现)不会影响其它类的代码。

里氏代换原则

父类可以出现的地方,子类就一定可以出现。因此子类在覆盖父类方法时,方法的实现与父类相比在“量”上可以不同,在“方向”上要一致。举个简单例子:父类有一个逻辑验证方法,当验证通过时返回true,未通过时返回false。现在子类将该方法覆盖为通过时返回false,未通过时返回true,这显然会造成软件逻辑上的错误。

接口隔离原则

使用多个专门的接口比使用单一的总接口要好。废话,一个类做完全部事情,你受得了?

 迪米特法则

一个类与另一个类(或一个模块与另一个模块、一个软件系统与另一个软件系统)之间的通信要尽可能少,换句话说彼此了解得越少越安全(你知道得太多了J)

上述几个原则即是面向对象开发时要注意的几个基本原则,还有一些其它原则,本文不一一列举。

有了这几个原则作为面向对象开发软件的衡量标准,可以多多测量自己所编写代码的水平。每当写完一个方法、一个类、一个模块时,不妨用上述几个原则来考量一下。脑海中时常多问自己1个问题:当今后增加XX功能时,我现有的代码要如何修改?如果你自己的答案是勿须修改现有的核心代码(这些代码可能是你冥思苦想、绞尽脑汁的心血),只须增加代码,加点配置文件什么的,那恭喜你,你的程序具有很强的可扩展性。

如果你的答案是可能要改自己的核心代码,那估计到时候就悲剧了,传说中的牵一发而动全身就是说的你这种软件。新功能一增加,bug到处乱窜,为了解决这一问题,你可能采取另一个办法,就是不修改现有核心代码,将这份代码复制一份到另外一个地方,然后去修改复制出来的代码,这样一来,你就会陷入一个代码泥潭,越陷越深最终不能自拔。

为了使自己编写的软件满足面向对象的这些原则,我们在程序开发时,不妨使用管理的思维来编写程序。

当你收到某一个功能需求时,在以前也许会直接联想到该用哪些API来实现,该用几个循环,什么条件下使用什么样的if判断等。如果你真是这样想的,那么即使你是使用的java之类的面向对象语言,你编写出的代码仍然是面向过程的。也许你不自觉的就在一个方法中,用几百行代码实现了这个功能需求。其中,循环套循环、if嵌if,这样的代码也许你自己隔个三两天来看,都不容易看懂,如果换一个人来维护这样的代码,估计要吐血。在这样的代码海洋中,如果在不起眼的角落里,有一个字符输入错误,估计你会花很大的力气才检查得出来。

如果你用管理的思维来编写程序,那就不一样了。则在编写代码前,你会想象,实现这个功能需求,需要一系列的类,就好象要做一件事情,不是一个人去完成它,而是一个团队去完成。这个团队有自己的部门组织机构(package包),每个部门下面都有多个员工(class类)。各个部门有自己的职责(包的分类),各个员工也有自己的职责(抽象类或接口)。员工与员工之间如何沟通,部门与部门之间如何通信,这些都可以参考现实中大型企业的管理来实现。当你将这些部门和员工的职责设计好,相当于程序中的包和类以及类中的方法就设计好了,最后来实现这些方法,相信是游刃有余的了。在这种系统中,每个类的职责都很清晰,每个方法的代码都不多,如果有某个字符输入错误,会很容易的发现它。这也正是很多人推崇的一个方法只做一件事情的原因。

在使用管理的思维来编写程序时,因为程序中的类的方法签名会对应到管理体系中的员工职责,因此,要善于区分这些职责的重要性,将核心职责放在核心类中实现,业务职责放在业务类中实现。核心职责是系统中长期不变的(相对的长期),要放在抽象类中,业务职责根据业务的变化会相应的变化,因此要放在具体实现类中。区分核心和业务的目的是为了提高系统的稳定性,正是所谓的要善于区分变和不变的部分。

现在我们用管理的思维再来验证一下面向对象的几大原则!

开闭原则

当新功能需要增加时,相当于一个团队有新的业务需要开展(这个新业务与老业务在性质上是一样的,不会是完全不同的领域),现实中当然是新增一两个业务员,或者新增一个业务部门即可,对团队的核心组织架构当然不会有影响。

依赖倒转原则

员工是具体类,员工的岗位职责是抽象类。一个员工需要与另外一个员工进行协作时,认定的当然是这个岗位,而不是具体某个人。比如:运营中心的销售员需要向研发中心的程序员反馈客户的需求,他只要找到研发中心任何一个具有程序员岗位职责的人都可以,而不是非要找到研发中心的张三,这就是依赖抽象(岗位职责),不依赖具体(张三)。

里氏代换原则

实施部在客户仓库实施项目,实施员甲生病了,要请假回家休息,这时,公司的实施员乙马上奔赴现场,接替实施员甲的工作,保证项目按计划进度完成,项目质量未受到任何影响。
以上场景可以看出,实施员甲和乙两人都具有相同的岗位职责,因此,凡是实施员(基类)可以出现的地方,任何具体的实施员(具体类或者叫子类)都可以出现。

接口隔离原则

为什么一个管理良好的公司要分销售部、研发部、财务部?这就是接口隔离原则,分工合作,正所谓因为专注,所以专业。当一个类什么事情都要负责,那这个类会很健壮吗?

迪米特法则

销售部问研发部,XX软件在XX日期能否研发完?研发部说,我要先花XX天做什么什么工作,再花XX天做什么什么工作……销售部烦了,我没问你那么多,你只管说能还是不能就行了。
可以看出,上述对话中,研发部过多的暴露了内部的细节,不满足迪米特法则。因此,系统与系统通信、模块与模块通信、类与类通信之间的接口数量以及暴露的信息,在满足功能需要的前提下,越少越好。

说了这么多废话,相信大家都有自己的认识。其实完全可以将生活中的各种经验用在软件开发中,软件的灵感来自于生活,因为软件的目的是为了生活更美好!