大话重构.pdf

大话重构.pdf
 

书籍描述

内容简介
本书运用大量源于实践的示例,从编码、设计、组织、架构、测试、评估、应对需求变更等方面,深入而多角度地讲述了我们应该如何重构,建设性地提出了高效可行的重构七步。
读完本书,实践重构不再卡壳,需求变更不再纠结。全面领悟重构之美,遗留系统不再是梦魇,自动化测试原来可以这样做。
本书帮助程序员告别劣质代码步入精妙设计,让遗留系统的维护者逐步改善原有设计,指导重构实践者走出困惑步步坚定。同时,也为管理者加强软件质量的管理与监督,提供了好的方法与思路。

编辑推荐
本书的最大价值在于两点:
一,让读者明白真正的专业级软件开发是如何进行的;
二,让读者明白真正的重构具体是一步步怎么做的。
作者将繁复冗长模糊不清的软件重构过程划分成明确而清晰的七个步骤。使初学者在面对实际中的软件重构时,不会卡壳。
本书所讲解的重构远远超越了代码级,充分渗透到软件系统与设计的各个层面,涵盖从代码、函数、类与对象,直至设计模式、分层架构、领域模型、软件测试的整个过程。
你听过或没听过的那些术语和概念,多少明白或完全不明白的技术和方法,知道却没用过或完全不知道的工具和软件,这些之前各玩各的的独立散碎,在这本书中被榫卯成一个强韧的整体。你会明了它们中每一个的作用,应被安插到的位置,并见识它们各就各位时所发挥出的能量。头脑从未有过的清醒,你理解了以前所不理解的。

作者简介
范钢
1999年毕业于重庆大学,后攻读哈尔滨工业大学软件工程硕士。参与过国内数十个大型软件研发项目,现任航天信息股份有限公司系统架构师,先后担任过软件工程师、需求分析员、主管设计师、项目经理、系统架构师等各项职务。长期关注软件设计与质量的基础理论研究。
2007年开始写作,先后发表了《一个优秀软件开发人员的必修课》、《谈谈软件开发那些事儿》、《一堂如何提高代码质量的培训课》、《一次迭代式开发的研究》等系列文章。
《大话重构》是我的第一部著作。
博客:fangang.iteye.com
邮箱:fangang2004@126.com

目录
目  录

第一部分 基础篇
第1章 重构:改变既有代码的一剂良药  2
1.1  什么是系统重构  2
1.2  在保险索上走钢丝  3
1.3  大布局与小步快跑  5
1.4  软件修改的四种动机  6
1.5  一个真实的谎言  9
第2章 重构方法工具箱  10
2.1  重构是一系列的等量变换——第一次HelloWorld重构  10
2.2  盘点我们的重构工具箱——对HelloWorld抽取类和接口  13
第3章 小步快跑的开发模式  19
3.1  大布局你伤不起  19
3.2  小设计而不是大布局  20
3.3  小步快跑是这样玩的——HelloWorld重构完成  22
第4章 保险索下的系统重构  30
4.1  你不能没有保险索  30
4.2  自动化测试——想说爱你不容易  31
4.3  我们是这样自动化测试的——JUnit下的HelloWorldTest  33
4.4  采用Mock技术完成测试  37
第二部分 实践篇
第5章 第一步:从分解大函数开始  44
5.1  超级大函数——软件退化的重灾区  44
5.2  抽取方法的实践  51
5.3  最常见的问题  54
第6章 第二步:拆分大对象  57
6.1  大对象的演化过程  57
6.2  大对象的拆分过程——抽取类与职责驱动设计  60
6.3  单一职责原则(SRP)与对象拆分  61
6.4  合久必分,分久必合——类的归并  63
第7章 第三步:提高代码复用率  66
7.1  顺序编程的烦恼  66
7.2  代码重复与DRY原则  67
7.3  提高代码复用的方法  69
7.3.1  当重复代码存在于同一对象中时——抽取方法  69
7.3.2  当重复代码存在于不同对象中时——抽取类  71
7.3.3  不同对象中复用代码的另一种方法——封装成实体类  72
7.3.4  当代码所在类具有某种并列关系时——抽取父类  75
7.3.5  当出现继承泛滥时——将继承转换为组合  76
7.3.6  当重复代码被割裂成碎片时——继承结合模板模式  78
7.4  代码重复的检查工具  79
第8章 第四步:发现程序可扩展点  80
8.1  开放?封闭原则与可扩展点设计  81
8.2  过程的扩展与放置钩子——运用模板模式增加可扩展点  85
8.3  面向切面的可扩展设计  89
8.4  其他可扩展设计  93
第9章 第五步:降低程序依赖度  98
9.1  接口、实现与工厂模式  98
9.1.1  彻底理解工厂模式和依赖反转原则  98
9.1.2  工厂模式在重构中的实际运用  102
9.2  外部接口与适配器模式——与外部系统解耦  106
9.3  继承的泛滥与桥接模式  109
9.4  方法的解耦与策略模式  112
9.5  过程的解耦与命令模式  116
9.6  透明的功能扩展与设计——组合模式与装饰者模式  119
第10章 第六步:我们开始分层了  128
10.1  什么才是我们需要的分层  128
10.2  怎样才能拥抱需求的变化  131
10.3  贫血模型与充血模型  136
10.4  我们怎样面对技术的变革  139
第11章 一次完整的重构过程  143
11.1  第一步:分解大函数  143
11.2  第二步:拆分大对象  145
11.3  第三步:提高复用率  147
11.4  第四步:发现扩展点  148
11.5  第五步:降低依赖度  151
11.6  第六步:分层  151
11.7  第七步:领域驱动设计  153
第三部分 进阶篇
第12章 什么时候重构  156
12.1  重构是一种习惯  156
12.2  重构让程序可读  158
12.3  重构,才好复用  159
12.4  先重构,再扩展  161
12.5  变更任务紧急时,又该如何重构  163
第13章 测试驱动开发  166
13.1  测试驱动开发(TDD)vs.后测试开发(TAD)  167
13.2  测试驱动开发与重构  170
13.3  遗留系统怎样开展TDD  178
第14章 全面的升级任务  182
14.1  计划式设计vs.演进式设计  182
14.2  风险驱动设计  184
14.3  制定系统重构计划  188
第15章 我们怎样拥抱变化  190
15.1  领域才是软件系统的“心”——工资软件的三次设计演变  190
15.2  领域模型分析方法  197
15.3  原文分析法  199
15.4  领域驱动设计——使用领域模型与客户一起设计  203
15.5  在遗留系统中的应用  209
第16章 测试的困境  213
16.1  重构初期的困局  213
16.2  解耦与自动化测试  215
16.3  开发人员,还是测试人员  219
16.4  建立自动化测试体系  223
第17章 系统重构的评价  225
17.1  评价软件质量的指标  225
17.2  怎样评价软件质量呢  228
结束语:重构改变了世界  233
附录  235

序言
【前言】
我常常感到幸运,我们现在所处的是一个令人振奋的时代,我们进入了软件工业时代。在这个时代里,我们进行软件开发已经不再是一个一个的小作坊,我们在进行着集团化的大规模开发。我们开发的软件不再是为某个车间、某个工序设计的辅助工具,它从某个单位走向整个集团,走向整个行业,甚至整个社会,发挥着越来越重要的作用。一套软件所起到的作用与影响有多大,已经远远超越了所有人的想象,成为一个地区、一个社会,乃至整个国家不可或缺的组成部分。慢慢地,人们已经难以想象没有某某软件或系统的生活和工作会是怎样的。这就是软件工业时代的重要特征。
然而,在这个令人振奋的软件工业时代,处于时代中心的各大软件企业却令人沮丧。在软件规模越来越庞大,软件结构越来越复杂的同时,却是软件质量越来越低下,软件维护变得越来越困难,以至于每个小小的变更都变得需要伤筋动骨。研发人员为此手足无措,测试人员成为唯一的救星,每个小小的变更都需要付出巨大代价进行测试。软件企业在这样一种恶性循环中苦苦支撑。毫无疑问,这也成为这个令人振奋的时代的另一个特征。
是的,面对软件工业时代我们并没有做好准备。过去,一套软件的生命周期不过2~3年时间,随着软件需求的变化,我们总是选择将软件推倒了重新开发,但是现在这样的情况在发生着改变。随着软件规模的扩大,软件数据的积累,软件影响力的提升,我们,以及我们的客户,都真切地感受到,要推倒一套软件重新开发,将变得越来越困难且不切实际。这样的结果就是,我们的软件将不停地修改、维护、再修改、再维护……直到永远。这是一件多么痛苦的事情!
一套软件,当它第一次被开发出来的时候,一切都十分清晰:清晰的业务需求、清晰的设计思路、清晰的程序代码。但经历了几次需求变更与维护以后,一切就变得不那么清晰了。业务需求文档变得模糊不清,设计思路已经跟不上变更的脚步,程序代码则随着业务逻辑的复杂而臃肿不堪。程序员开始读不懂代码,软件开发工作变得不再是一种乐趣。
随着时间的推移,软件经过数年、数十次的变更与维护,情况变得越来越糟。最初的程序员已经不愿再看到自己的代码而选择离去。他的继任者们变得更加无所适从,由于看不懂程序,代码的每一次修改如同在走钢丝。测试人员变成了唯一的希望,开发人员的每一次修改都意味着测试人员需要把所有程序测试一遍。继任者们开始质问最初的设计者们,程序是怎么设计的。如果此时恰巧又有什么新技术出现,就会更显得原有系统的破旧与不堪。
相信这就是软件工业时代的所有企业都不得不面对的尴尬境地。难道真的是我们最初的设计错了吗?是的,我们都这样质问过我们自己,因此我们开始尝试在软件设计之初投入更多的精力。我们开始投入更多的时间作需求调研,考虑更多可能的需求变化,做更多的接口,实现更加灵活但复杂的设计。然后呢,解决了我们的问题了吗?显然是没有。需求并没有像我们想象的那样发生变更:我们之前认为可能发生的变更并没有发生,使我们为之做出的设计变成了摆设;我们之前没有考虑到的变更却发生了,让我们猝不及防,软件质量开始下降,我们被打回了原形。难道真的是无药可解了吗?在我看来,如果我们没有看明白软件开发的规律与特点,那么我们永远找不到那味向往已久的解药。现在,让我们真正静下心来分析分析软件开发的规律与特点。
软件,特别是管理软件,其实质是对真实世界的模拟。我们通过对真实世界的模拟,实现计算机的信息化管理,来提高我们的生产效率。然而,真实的世界复杂而多变的,我们认识世界却是一个由简单到复杂循序渐进的过程,这是一个我们无法改变的客观规律。因此,毫无疑问,遵循着这样一个客观规律,我们的软件开发过程必然也是一个由简单到复杂循序渐进的过程。
最初,我们开发的是一个对真实世界最简单、最主要、最核心部分的模拟。因为简单,我们的思路变得清晰而明了。但是,我们的软件不能永远只是模拟那些最简单、最主要、最核心的部分。我们的客户在使用软件的过程中,如果遇到那些不那么简单、不那么主要、不那么核心的情况时,我们的软件就无法处理了,这是客户所不能接受的。因此,当软件的第一个版本交付客户以后,客户的需求就开始变更。
客户的需求永远不会脱离真实世界,也就是说,真实世界不存在的事物、现象、关系永远都不可能出现在软件需求中。但是,真实世界的事物、规则与联系并不是那么地简单与清晰的。随着我们的软件对它模拟得越来越细致,程序的业务逻辑开始变得不再清晰而易于理解,这就是软件质量下降最关键的内因。
任何一个软件的设计,总是与软件的复杂度有密切的关系。举例来说吧,客户资料是许多系统都必须要记录的重要信息。起初,我们程序简单,客户资料只记录了一些简单的信息,如客户名称、地址、电话等等,但随着程序复杂度的增加,客户资料开始变得复杂。比如,起初“地址”字段就仅仅需要一个字符串就可以了,但随着需求的变更,它开始有了省份、城市、地区、街道等信息。随后还会有邮政编码、所属社区、派出所等信息。起初增加一个两个字段时我们还可以在“客户信息表”里凑合一下,但后来我们必须要及时调整我们的设计,将地址提取出来单独形成一个“地址信息表”。如果不及时予以调整,“客户信息表”将越来越臃肿,由10来个字段,变成50个、80个、上100个……
信息表尚且如此,业务操作更是如此。起初的业务操作是如此地简单而明了,以至于我们不需要花费太多的类就可以将它们描述清楚。比如开票操作,最初的需求就是将已开具的票据信息读取出来,保存,并统计出本月开票量及金额。这样一个简单操作,设计成一个简单的“开票业务类”合情合理。但随后的业务逻辑变得越来越复杂,我们要检查客户是否存在、开票人是否有权限、票据是否还有库存,等等。起初的开票方式只有一种,但随着非正常开票的加入,开票方式不再单一,而统计方式也随之变化……随着业务的不断增加,软件代码的规模也在发生着质的变化。如果这时我们不及时调整我们的设计,而是将所有的程序都硬塞进“开票业务类”,那么程序质量必然会退化。“开票业务类”由原有的数十行,激增到数百行,甚至上千行。这时的代码将难于阅读,维护它将变成一种痛苦,毫无乐趣可言。
面对这样的状况,我们应当怎样走出困境呢?毫无疑问,就是重构。开票前的校验真的属于“开票业务类”吗?它们是否应当被提取出来,解耦成一个一个的校验类。正常开票与非正常开票真的应该写在一起吗?是否我们应当把“开票业务类”抽象成接口,以及正常开票与非正常开票的实现类。这就是我给大家的良方:当软件因为需求变更而开始渐渐退化时,运用软件重构改善我们的结构,使之重新适应软件需求的变化。


范钢
2014年元旦

文摘
前言

购买书籍

当当网购书 京东购书 卓越购书

PDF电子书下载地址

相关书籍

搜索更多