最近一直在抱怨说:外包的程序很滥,一点儿也不易维护,扩展性也不好。但是到底什么是程序的“易维护性”和“可扩展性”?还没有做过比较深入的思考,通过这篇文章对自己的认识做个总结。提供给大家做个讨论的引子。
易维护性,可扩展性是很模糊的概念我们经常挂在嘴边但是又很难一下子给出个明确的定义,我主要根据自己撰写和维护程序的经验从下面四个问题展开讨论。
1. 维护中遇到的不易维护不易扩展的程序有什么特点?是怎样制造出来的?
2. 易维护和易扩展的程序应该具有什么样的特点?
3. 怎样在实践中撰写出易维护和易扩展的程序?
4. 在易维护和易扩展的基础上怎样保证程序的质量?
打开一个程序浏览一下代码,如果发现变量和函数的命名很乱,排版很乱,一个按钮事情翻了三个屏幕还没结束,我就很头痛很反感阅读这样的代码更别说要快乐的
去修改他了,如果天天面对这样的工作我这样的人会崩溃的。这样的代码对我来说就很难维护更别说要扩展他了。细数我所经历的难维护的不良代码主要表现在以下
方面:
- 变量和函数命名不符合大家的习惯(team的规范),命名随便没有意义。
- 乱用全局变量而且还在不同的单元中引用。
- 代码没有模块化处理一个程序的代码几乎都集中在几个按钮的事件中,导致事件代码过长,处理的逻辑复杂。
- SQL语句到处都是还动态生成嵌套了N层,不知道使用外连接,从来不用参数的方式。
- 代码很少处理错误和异常,一个不合法的输入就会崩溃。
浏览以前我写的代码,很惭愧的发现上面几条都很符合,原来我一直抱怨的东西,自己也一直在制造!有必要来反思我撰写程序的行为了,这样滥的代码到底是怎么制造出来的呢?如何去改进自己撰写方式?
我发现我大部分的程序是这样的写出的:简单的阅读UC,spec(自己写程序的时候spec可能还是写好程序后撰写的),设计好table(或者了解了已
经设计好的table结构),就迫不及待的在Delphi里拖控件画UI,在按钮里写事件,写着写着发现需要一个全局变量,就加一个,过一会发现又要加一
个,还要在其它的单元中引用,很快就写好了,能跑起来了。嘿,很高兴!功能都实现了。如果程序的功能很简单这样问题也不大,写好后修改的可能性都很小。如
果程序很复杂还需要经常修改。那就惨了!
仔细的分析我这种开发行为是很有问题的,首先过多的关注UI的操作方式或者说程序的思考点是从UI开始的而不是从实际的业务运作开始其次缺少全局的设计规
划,没有对程序做模块化处理,更不要说对模块之间耦合做处理了。要想改善这种撰写程序的方式就需要了解我们所撰写的程序的特点,以及易维护和可扩展的程序
特点。
我们在工厂做开发直接面对用户,有的时候用户需求变动很大时间又紧迫,这样对程序的易维护性和扩展性要求会很高。易维护和可扩展的代码往往表现在代码模块
化处理的比较好,模块与模块之间耦合度低(修一个模块对另一个模块影响程度低),模块内部内聚性强(一个模块或者一个函数功能集中单一这样修改起来比较简
单),模块的封装和复用比较好,模块与模块之间通过接口交互。这些都是书上的内容在实践中在变量和函数命名都符合大家的规范保证代码可读性基础上如何改善
代码的可维护性和扩展性呢。
参考面向对象的分析和设计方法我们首要要改变自己撰写程序的方式,即把思考点从UI的操作上转移到业务对象的设计和交互上,从全局出发设计各个模块。其次在实际撰写代码时再对模块的内聚性下功夫。
如何对程序模块化我们可以参考“表现,行为,数据”在逻辑上对程序划分为三个层次(如图一个程序例子)。
- 表现:主要是呈现给用户操作的UI,窗体所对于的pas文件中不要写任何业务处理的代码。
- 行为:业务对象的行为,集中所有的业务处理逻辑,同时提供接口来响应“表现”层发出的请求。
- 数据:DataModual层持有所有程序所使用的数据集,负责与数据库进行交互和事务的管理。我喜欢把所有的SQL语句都写在数据层里面,方便集中修改。
对程序进行这样的模块化处理难点是业务对象分析,因为目前Delphi的数据库程序开发是数据库驱动的不是对象驱动的。这样做会丧失一些Delphi快速开发的优势。但是对后续程序的维护和测试会很方便。
高质量的程序不是一下就写好的,需要后续维护中不停的重构和测试。这篇文章主要对开发方式的转变进行总结,新的方式的使用还在以后开发中做进一步的验证。