zl程序教程

您现在的位置是:首页 >  后端

当前栏目

串行卧重建19:大对象的演变

对象 19 重建 演变 串行
2023-09-14 09:08:04 时间

那很好。我们终于迈出了第一步重建,而在一个代码问题,我们的目标第一步的重灾区——超强功能。

超强功能的原因是最难通过的代码问题打,这是因为它们通常难以读、难以维持。面对我们已经采取了大量功能的方法是拆分,充当核心,以分割成一个单独的函数。拆分后的程序变为易于阅读,程序你不再须要读全然部代码。选择性的读取那些顶级函数。仅仅需了了数行代码,你就能够明确整个程序。

可是。当我们将数千行的大函数分解成数十个小函数时,还有一个问题出现了。

想象一下,数十个函数被杂乱无章地堆放在一个对象中,看看就让人头疼。

实际上。我们是不会这样做的。当我们開始了对大函数的分解时。随之而来的就是对大对象的分解。

大对象,就是指的那些包括数十个甚至上百个方法或者函数,功能无所不包的超级对象。

在非常多遗留系统中。总有那么几个超级对象。系统差点儿全部的功能都在它的里面有相应方法。这种对象。密密麻麻的方法让人困惑,更关键的是,各种各样的功能被耦合在一起,稍有改动就会影响到很多功能,甚至让那些毫不相干的功能产生BUG。因此,我们应当合理地拆分我们的大对象。

与大函数一样,非常多时候遗留系统中的大对象。也都是伴随系统业务复杂度的逐渐增长而出现的。我们来看看它的演进过程吧。我们说软件实际上是对现实世界的模拟。通过这样的模拟,实现信息化的管理,来提高我们的生产效率。可是,现实世界是复杂的。各种事物之间存在着各种各样纷繁复杂的联系。因此我们不可能全然模拟现实世界的全部,仅仅可能是现实世界的一部分,客户急须要模拟的那一部分。

人的大脑认识事物总是一个由简单到复杂的过程,这是我们的客观规律。因此,我们的软件模拟真实世界也是一个由简单到复杂的过程。最开初我们的想法总是很easy而单纯的。就是让软件做一件很easy而明白的事情。

因为这时候业务很easy,我们不须要太多的类和方法就能够实现业务操作。比方开票业务。就是将已开具的发票信息读取出来,保存。这样一个简单操作,设计成一个简单的开票业务类合情合理。

可是。随着软件模拟真实世界的不断发展。业务变得越来越复杂。

比方这个开票业务,我们随后的业务開始变更。要检查购方是否存在、开票人是否有权限、库存中是否还有发票,等等。起初仅仅有一种开票方式。但随着非正常开票业务的添加。很多相关的业务也随之变化……随着业务的不断添加,软件代码的规模也在发生着质的变化(如图6.1所看到的)。


图6.1 开票业务的演化过程

 

过去开票业务类仅仅有百来行代码,如今被膨胀到数千行代码。各种条件语句层层嵌套,各种暂时变量穿插跑位。程序变得难于理解。因为读不懂代码。修改代码的程序猿開始在走钢丝,一不小心修改了某个关键程序就可能引入重大BUG。为了避免重大BUG的出现。測试人员耗费巨大精力进行严格的測试。毫无疑问,软件開始进入一种恶性循环。软件退化開始一步步加深。

面对这样的软件规模增大而带来的恶性循环,我们必须做出改变。面对问题我们不能病急乱投医,而是应当对症下药。

这个正确的药方就是以职责驱动设计思想为核心。调整我们的程序结构,构建高内聚、低耦合的软件系统。职责驱动设计,就是要求我们设计的全部类和接口,都要有自己的职责定义。

而每一个类和接口内部的全部方法和属性都是环绕着该职责来进行的,它们都是高度相关的。每一个类和接口决不去做跟自己职责无关的事情,全部与自己职责无关的事情。都应当交给其他拥有该职责的类来完毕。而自己不过去调用。

这就是职责驱动设计的思想,而每一个类其内部包括的功能所达到的高度相关的程度。我们称之为“内聚”。

概念似乎有一些抽象,我们来举例说明吧。

对于开票业务。我们设计了开票业务类来处理它。因此开票业务类的职责就是完毕开票操作。这似乎毫无问题。可是,我们细致审视开票操作。就会发现它包括了好几个部分:首先。我们读取客户、开票人、发票库存等信息进行相关的校验,然后保存这些发票到数据库中。最后统计当月的票量及金额。通过这种分析,它们似乎不再那么功能相关了。读取和校验客户、开票人、发票库存等信息是客户、开票人、发票库存实体类的职责。读取和保存发票似乎是发票类的职责,而统计当月票量与金额似乎是財会统计类的职责。

分与不分,全然取决于软件代码的复杂程度。假设总共也就几十行代码,我们写成一个类中的几个方法就能够了;但随着功能复杂度的加深,那么我们必须得拆分。分配到不同的类中配合完毕我们的功能。

随着软件业务的不断变化,我们的软件在发生着质的变化。

发票保存前我们必需要进行一系列的校验工作:检查购方是否存在、开票人是否有权限、是否还有发票库存。等等。不同的校验。读取的是不同的数据,它们的顺序可能变化。校验的个数也可能在调整。随着需求的变化,一些校验被添加进来而还有一些则被剔除。

我们推断功能是否相关的一个很重要的原则,就是是否是软件变更的同一个原因。比方,“检查购方是否存在”与“开票人是否有权限”,不是软件变更的同一个原因:“检查购方是否存在”是与客户信息管理直接相关。而“开票人是否有权限”则是与用户权限定义密切相关。因此它们不能放在同一个类中。为什么呢?由于“检查购方是否存在”的业务逻辑变更时。不应当影响到“检查开票人是否有权限”的功能。最好的办法就是。将它们各自封装在各种相关的业务类中(如图6.2所看到的)。

图6.2 开票业务的拆分

 

经过以上分析我们发现。开票操作随着业务逻辑的不断发展,应当在原有的程序结构上。将开票业务类拆分成几个部分:各种校验类、发票业务类与財会统计类。这种拆分使得开票业务类终于由一个什么都干的多面手,变成了一个管理者。它不再參与那些详细的工作,而是将工作分配给不同的人。成为一个组织协调者。

经过这种调整,我们的程序将变得更加易于阅读、维护、变更。


大话重构连载首页:http://blog.csdn.net/mooodo/article/details/32083021

特别说明:希望网友们在转载本文时,应当注明作者或出处,以示对作者的关于。谢谢!



版权声明:本文博主原创文章,博客,未经同意不得转载。