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

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

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

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

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

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

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

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

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

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

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

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

图6.1 开票业务的演化过程

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

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

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

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

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

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

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

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

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

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

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

图6.2 开票业务的拆分

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

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

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

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

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

串行卧重建19:大对象的演变相关推荐

  1. php 串行化数据,php中对象的串行化

    我们大家有知道PHP串行化可以把变量包括对象,转化成连续bytes数据,你可以将串行化后的变量存在一个文件里或在网络上传输,然后再反串行化还原为原来的数据.文章这里就PHP串行化为大家详细的介绍.你在 ...

  2. 13000行代码、19大技术,这位16岁高中生用C++从头到尾构建了一个机器学习库!...

    作者 | 苏宓 出品 | CSDN(ID:CSDNnews) 你是从什么时候开始编程的? 据 CSDN 调研数万名开发者的数据显示,近六成的开发者表示自己写下第一行代码的年龄是在 16-20 岁间.其 ...

  3. php 串行化数据,PHP中的串行化变量和序列化对象

    串行化大概就是把一些变量转化成为字符串的字节流的形式,这样比较容易传输.存储.当然,关是传输存储没有什么,关键是变成串的形式以后还能够转化回来,而且能够保持原来数据的结构. 在PHP中有多串行化处理的 ...

  4. 利用XMLSerializer将对象串行化到XML

    微软已经意识到串行化数据的重要性,因此在.NET框架中包含了命名空间System.Runtime.Serialization和System.Xml.Serialization以提供串行化功能,为用户自 ...

  5. Java中对象的串行化(Serialization)和transient关键字

    Java中对象的串行化(Serialization)和transient关键字 前言: 该篇文章参考自网上资料,但是部分内容经过笔者更改,因此算作原创吧,原文地址: http://www.golden ...

  6. java input是关键字吗_Java中对象的串行化(Serialization)和transient关键字 - 金色阳光...

    Java中对象的串行化(Serialization)和transient关键字: 对象的串行化(Serialization) 一.串行化的概念和目的 1.什么是串行化 对象的寿命通常随着生成该对象的程 ...

  7. 并发计算中的串行思考

    软件系统性能的提升的重要方法之一是支持并发性编程,尤其是采用多核体系结构的时候.在全局数据库.云计算和区块链应用程序中,并发性对于实现容错和分布式服务也是至关重要的.然而,对并发性的掌握一直是令人畏惧 ...

  8. 锁与并发工具包与线程池与LockSupport与Fork/Join框架与并行流串行流与阻塞队列与JPS,jstack命令查看死锁查看线程状态与AQS个人笔记九

    朝闻道,夕死可矣 本文共计 86564字,估计阅读时长1小时 点击进入->Thread源码万字逐行解析 文章目录 本文共计 86564字,估计阅读时长1小时 一锁 二Java中13个原子操作类 ...

  9. 从串行线程封闭到对象池、线程池

    今天讲一个牛逼而实用的概念,串行线程封闭.对象池是串行线程封闭的典型应用场景:线程池糅合了对象池技术,但核心实现不依赖于对象池,很容易产生误会. 本文从串行线程封闭和对象池入手,最后通过源码分析线程池 ...

  10. 在asp.net2.0中使用串行化对象实现自定义配置

    在一次升级一个entlib1.0到entlib的高版本程序时,碰到entlib的一个通过XmlSerializer方式实现的自定义配置.而在entlib的高版本中这样的配置不再被支持.可是又不希望修改 ...

最新文章

  1. avue form提交变为不可编辑_教程42——富文本编辑器的原理(项目)
  2. java biginteger使用_java中的BigInteger的基本用法 | 学步园
  3. 在中国使用pip更新或安装库的配置
  4. LinCode落单的数
  5. asp.net 六大对象之Request、Response
  6. java 正则匹配引号_java 正则 贪婪匹配 匹配sql语句中的引号内容
  7. 修复版GEP宝塔内嵌版全解源码
  8. SpringBoot—数据库初始化脚本配置
  9. MySQL (一)(未完成)
  10. Pytest之fixture
  11. html弄多个按钮_html - 一个表单中的两个提交按钮
  12. VMS-B230/260如何登录存储控制器
  13. 聊聊前端工程师如果做职业规划
  14. sublime解决中文乱码问题
  15. lan pci 联想开机_联想bios设置硬盘启动
  16. errMsg: “getUserProfile:fail can only be invoked by user TAP gesture.(微信小程序报错)
  17. 大数据比较 同比与环比的区别
  18. Android的根证书颁发机构列表
  19. python用递归方式实现最大公约数_Python - 最大公约数算法
  20. 网络购书挑战书业传统营销模式

热门文章

  1. 2020 网易 面经
  2. 最新android APP框架介绍
  3. 【14年浙江省赛 ZOJ 3780】Paint the Grid Again【图转换】
  4. 【扩展KMP】【HDU 4333】Revolving Digits
  5. Raki的PRML阅读笔记 第1章:Introduction
  6. mysql数据库创建删除带横杠的数据库名
  7. ________________定时器
  8. django xadmin 安装和使用
  9. TCP/IP 原理 -- ICMP:因特网控制报文协议
  10. 实时分析你的Windows Phone 7使用状况