能描述一下RAIDS的数据组织措施有哪些方式和重构过程是如何实现的

一、简答题范围(25分左右)
1.简述軟件的定义及特征(第1章)
(1)指令的集合执行这些指令提供期望特性、功能、性能;
(2)数据结构,使程序合理地操纵信息;
(3)文档描述程序嘚操作和使用。
2.简述软件工程的定义(IEEE)及软件过程的5种框架活动(第2章)
软件工程是:(1)将系统化的、规范的、可量化的方法应用于軟件的开发、运行和维护即将工程化方法应用于软件。(2)在(1)中所述方法的研究
-需要规范,也需要可适应性和灵活性(有些方法对于┅个团队符合(1)但对于另一个团队可能是负担)
沟通(与客户沟通与协调,以理解项目目标)
策划(工作、技术任务、风险、资源、产品进度计划)
建模(用模型来理解软件需求,完成设计)
部署(软件交付用户用户测评并反馈)

3.画图说明软件过程流的各种类型(第3嶂)

4.画图说明软件过程的增量模型及适用情形和特点(第4章)

2.初始的软件需求明确,但是整个开发过程却不宜单纯运用线性模型同时,鈳能迫切需要为用户迅速提供一套功能有限的软件产品然后在后续版本中再进行细化和扩展功能。
例如第一个增量往往是核心产品附加功能进入下个增量计划。
3.综合了线性过程流和并行过程流的特征
每个增量都提交一个可以运行的产品。
例如:文字处理软件第一个增量是基本的文件管理、编辑和文档生成(核心功能);第二个增量是复杂的编辑和文档生成;第三个增量是拼写检查和语法检查功能;苐四个增量是高级页面排版功能;第2至4个增量是附加功能。
5.画图说明软件过程的原型模型及适用情形和特点(第4章)

客户提出了一些基本功能但没有详细定义功能和特性需求
开发人员可能对算法的效率、操作系统的兼容性和人机交互的形式等情况并不确定
很少是好用的,鈳能太慢太大难以使用。
一般作为被丢弃的系统

6.画图说明统一过程的各个阶段(第4章)

7.简述敏捷原则(第5章)

  1. 我们最优先要做的是通過尽早、持续地交付有价值的软件来使客户满意。
  2. 即使在开发的后期也欢迎需求的变更。敏捷过程利用变更为客户创造竞争优势
  3. 经常茭付可运行软件,交付的间隔可以从几个星期到几个月交付的时间间隔越短越好。
  4. 在整个项目开发期间业务人员和开发人员必须天天嘟在一起工作。
  5. 围绕有积极性的个人构建项目给他们提供所需的环境和支持,并且信任他们能够完成工作
  6. 在开发团队内部,最富有效果和效率的信息传递方法是面对面交谈
  7. 可运行软件是进度的首要衡量标准。
  8. 敏捷过程提倡可持续的开发责任人、开发者和用户应该能夠长期保持稳定的开发速度
  9. 不断地关注优秀的技能和好的设计会增强敏捷能力。
  10. 简单——使不必做的工作最大化的艺术——是必要的
  11. 最恏的架构、需求和设计出自于自组织措施有哪些团队。
  12. 每隔一定时间团队会反省如何才能更有效地工作,并相应调整自己的行为

8.简述需求建模的模型(第8章)
从用户角度来看的系统。
表示数据在系统内是如何转换的
定义对象、属性和关系。
表示数据在系统内是如何转換的
表示事件对系统状态的影响
9.简述CRC模型的评审步骤(第9章)
所有参加(CRC模型)评审的人员拿到一部分CRC模型索引卡。
拆分协作卡片(也僦是说每个评审员不得有两张存在协作关系的卡片)
分类管理所有的用例场景(以及相关的用例图)。
评审组长细致地阅读用例
当评審组长看到一个已命名的对象时,给拥有相应类索引卡的人员一个令牌
当令牌传递时,索引卡的拥有者需要描述卡上记录的职责
评审組确定(一个或多个)职责是否满足用例需求。
如果记录在索引卡上的职责和协作不能满足用例就需要修改卡片。
修改可能包括定义新類(和相关的CRC索引卡)或者在已有的卡上说明新的或修改的职责、协作。

10.简述行为建模的步骤(第10章)
列出不同的系统状态(系统如何表现)
表明系统如何从一个状态转变为另一个状态(系统怎样改变状态?)

11.画图说明从需求模型到设计模型的转换(第11章)

12.简述模块的功能独立及评估标准(第11章)
通过开发具有“专一”功能和“避免”与其他模块过多的交互的模块可以实现功能独立。
独立性有两条定性标准进行评估:
内聚性显示了某个模块相关功能的强度
一个内聚的模块执行一个独立的任务,与程序的其他部分构件只需要很少的交互简单地说,一个内聚的模块应该(理想情况下)只完成一件事情
耦合性显示了模块间的相互依赖性。
耦合性依赖于模块之间的接口複杂性、引用或进入模块所
13.简述重构的定义及重构时的检查要点(第11章)
“重构是使用这样一种方式改变软件系统的过程:不改变代码[设計]的外部行为而是改进其内部结构”
当重构软件时,检查现有设计:
拙劣的或不恰当的数据结构
其他设计不足修改这些不足以获取更恏的设计。
14.简述体系结构风格描述的4个要素及其分类(第12章)
每种风格描述一种系统类别包括:(1)完成系统所需要的某种功能的一组構件(例如数据库、计算模块);(2)能使构件间实现“通信、协调和合作”的一组连接件;(3)定义构件如何集成为系统的约束;(4)語义模型,能使设计者通过分析系统组成成分的已知属性来理解系统的整体性质
以数据为中心的体系结构

15.简述构件级设计的7个基本原则(第13章)
开闭原则(OCP)。“模块[构件]应该对外延具有开放性对修改具有封闭性”。
Liskov 替换原则(LSP)“子类可以替换它们的基类”。
依赖倒置原则(DIP)“依赖于抽象,而非具体实现”
接口分离原则(ISP)。“多个客户专用接口比一个通用接口要好”
发布复用等价性原则(REP)。“复用的粒度就昰发布的粒度”
共同封装原则(CCP)。“一同变更的类应该合在一起”
共同复用原则(CRP).。“不能一起复用的类不能被分到一组”
16.简述黄金规則中把控制权交给用户的规则(第14章)
以不强迫用户进入不必要的或不希望的动作的方式来定义交互模式。
允许用户交互被中断和撤销
當技能水平高时可以使交互流线化并允许定制交互。
使用户与内部技术细节隔离开来
设计应允许用户与出现在屏幕上的对象直接交互。

17.簡述黄金规则中减轻用户记忆负担的原则(第14章)
减少对短期记忆的要求
建立有意义的默认设置。
界面的视觉布局应该基于真实世界的潒征
以一种渐进的方式揭示信息。

18.简述黄金规则中保持界面一致的原则(第14章)
允许用户将当前任务放入有意义的环境中
在完整的产品线内保持一致性。
如果过去的交互模型已经建立起了用户期望除非有不得已的理由,否则不要改变它

19.简述OO测试中集成测试的3种策略(第17章)
集成测试应用三种不同的策略
基于线程的测试——对响应系统的一个输入或事件所需的一组类进行集成
基于使用的测试——对响應系统的一个用例所需的一组类进行集成
簇测试——对演示一个协作所需的一组类进行集成

20.简述压力测试并举例说明(第17章)
以非正常的數量、频率或容量的方式执行系统。测试是想要破坏程序
— 如果正常的中断频率为每秒5次,强度测试设计为每秒50次中断
— 把输入数据嘚量提高一个数量级来测试输入功能会如何响应。
— 若某系统正常运行可支持200个终端并行工作强度测试则检验1000个终端并行工作的情况。

21.簡述单元测试中桩模块和驱动模块的作用(第17章)

22.简述测试中症状与原因之间的关系(第17章)

23.简述软件基线及SCI和项目数据库并画图说明(第21章)
已经通过正式评审和批准的规格说明或产品,它可以作为进一步开发的基础并且只有通过正式的变更控制规程才能修改它。
基線是软件开发中的里程碑其标志是正式技术评审中已经获得批准的一个或多个软件配置项的交付。

24.简述选择软件团队结构时应考虑的7个洇素(第22章)
开发程序的规模 以代码行或者功能点来度量
团队成员需要共同工作的时间 (团队生存期)
能够对问题做模块化划分的程度
待开發系统的质量要求和可靠性要求
项目所需要的友好交流的程度
25.简述软件团队的组织措施有哪些范型(第22章)
封闭式范型 ——按照传统的权利层次来组织措施有哪些团队
1个高级工程师(主程序员),2-5个技术人员1个后备工程师
随机式范型 ——松散地组织措施有哪些团队,团队笁作依赖于团队成员个人的主动性
开放式范型 ——试图以一种既具有封闭式范型的控制性又包含随机式范型的创新性的方式来组织措施囿哪些团队
同步式范型——依赖于问题的自然划分,组织措施有哪些团队成员各自解决问题的一部分他们之间没有什么主动的交流
26.简述洳何避免“团队毒性”(第22章)
使团队成员浪费精力,同时也使他们在工作中表现出毫无目的性
引起团队成员间产生摩擦的重大挫折
由個人、商业和技术因素引起的重大挫折导致团队成员间产生摩擦。
“碎片式的或协调很差”的软件过程
缺乏定义的或选择不合适的过程模型都会成为成功路上的路障
在软件团队中没有清晰的角色定义
不清晰的角色定义导致缺乏责任,并相互指责
“接连不断地重蹈覆辙”
使团队成员失去信心并降低斗志。
二、综合题题型(25分左右)
1.用例图、类图、状态图、活动图(泳道图)
2.白盒测试(计算环复杂度、列出具体的独立路径可从代码或流程图画出流图、也可从流图画出流程图)
3.黑盒测试(用表列出有效等价类和无效等价类,设计测试用例和預期结果)一般与边界法相结合
4.过程度量与项目度量、软件项目估算(代码行功能点等)。见23章、24章
5.综合题亦可改变为简答题
三、填空、选择、判断(50分左右)(填空来自第8版PPT)
填空10分选择30分,判断10分

}

  课程代码:00051

  一、单项选擇题(本大题共40小题每小题1分,共40分)在每小题列出的四个选项中只有一个选项是符合题目要求的,请将正确选项前的字母填在题后嘚括号内

  1.关于企业中物流和信息的关系,正确的描述是()

  A.物流是单向的不可逆的;而信息流是双向的,即有信息反馈

  B.粅流是双向的可逆的;信息流也是双向的,即有信息反馈

  C.物流是单向的不可逆的;信息流也是单向不可逆的

  D.信息流是企业生產经营活动的主体流动

  2.有关管理信息的特点中,不正确的描述是()

  A.原始数据来源的分散性B.信息处理方式方法的单一性

  C.信息資源的非消耗性D.信息量大且具复杂性

  3.决策支持系统的特征是()

  A.主要处理结构化问题B.代替决策者进行决策

  C.通过人机对话提供決策信息D.与社会因素没有关系

  4.工业企业中固定信息之一是()

  A.工资信息B.财务信息

  C.定额信息D.市场信息

  5.数据库系统具有很高嘚数据独立性用户在编写应用程序时不必考虑数据的描述和存取问题,这是因为数据模型具有()

  A.数据映象功能B.完善的数据内部和外部结构

  C.多用户共享功能D.可控数据冗余度

  6.构成一个关系数据库是由()

  A.一个关系实现B.一张二维表实现

  C.若干不同关系实现D.┅个关系和一张二维表实现

  7.能够以实体间的层次关系描述数据以路径来描述数据间联系的数据模型是()

  A.网状模型和关系模型B.網状模型和层次模型

  C.层次模型和关系模型D.格式化模型和关系模型

  8.在修改数据库文件结构时,应使用命令()

  9.打开一个数据库攵件时最多可以同时打开其索引文件的数目为()

  10.在FoxBASE中可以建立9种类型的文件,其中备注文件和标签文件的扩展名分别为()

  11.FoxBASE索引查询命令的格式是FIND<常量>其中常量的数据类型是()

  B.字符型、数字型

  C.字符型、数字型、日期型

  D.字符型、数字型、日期型、逻辑型

  12.如果有二维数组MK(2,3)用自然数1~6依次向6个下标变量赋值后,执行命令MK(4)MK(2,1)结果显示为()

  13.设数据库文件有100條记录当执行GOTOP命令后,函数BOF()的值是()

  14.已经把字符串“天安门”赋予变量X若要从X中取出“安”字,应使用函数()

  15.打开┅个数据库文件执行命令APPENDBLANK后()

  A.在首记录前增加一个空记录B.在当前记录前增加一个空记录

  C.在当前记录后增加一个空记录D.在末记錄后增加一个空记录

  16.FoxBASE中使用PROMPT命令进行光带控制设计时,必须与之配合的命令是()

  17.数据校验方法包括重复校验、静态校验、界限校验和()

  A.动态校验、平衡校验B.动态校验、逻辑校验

  C.逻辑校验、平衡校验D.逻辑校验、物理校验

  18.由本企业开发信息系统的优点昰()

  A.本企业开发人员熟悉业务领导可以少参与

  B.开发周期短,易于开发一个高水平的信息系统

  C.可以锻炼本企业计算机开发應用队伍

  D.容易改变本企业习惯的管理方式

  19.计算机在企业中应用发展到管理信息系统阶段时能达到()

  A.根据人工过程编出相應的程序,并提高效率

  B.将企业看作一个整体实现信息的共享

  C.将各单项应用程序相加起来,形成整个企业的信息系统

  D.利用模型库技术全面辅助企业的决策

  20.生命周期法的主要优点是()

  A.经详细调查,能正确定义用户需求

  B.与用户直接见面开发周期短

  C.可以借助开发工具,实现开发自动化

  D.开发步骤清晰便于项目控制和管理

  21.总体方案的基本内容应包括下述四个方面:系统運行环境描述;计算机系统选型要求;系统开发计划以及()

  A.系统功能描述B.系统数据流程

  C.系统目标与范围的描述D.系统资源需求

  22.调查系统业务流程时,调查的范围应该是系统中()

  A.关键的管理业务流程B.所有环节的管理业务流程

  C.与系统外部有联系的业务流程D.有数据存贮的业务流程

  23.数据流程图中的数据存贮是指被存贮的()

  A.文件B.数据库

  C.逻辑数据D.台帐

  24.用分层次的数据流程图来描述系统的逻辑模型除了符合自顶向下的原则外,最主要的优点是()

  A.系统结构简明、清楚B.系统描述具体、详细

  C.便于管理人员叻解系统D.便于与各层次管理人员交流

  25.数据字典是用于定义和说明数据流程图上的每个()

  C.数据项D.数据结构

  26.应用程序设计的要求是源程序的语法正确并且()

  A.执行结果正确B.逻辑结构正确

  C.满足系统设计的功能要求D.运行无错误

  27.在对模块结构化设计时,模块凝聚程度最高的是()

  A.逻辑凝聚B.时间凝聚

  C.功能凝聚D.数据凝聚

  28.在下列网络拓扑结构中可靠性和灵活性都比较好的结构是()

  C.树型D.总线型

  29.在模块控制结构图中,→表示的是()

  A.模块间调用关系B.模块间控制信息的传递

  C.模块间数据的传递D.循环調用下层模块

  30.选择网络产品的原则是标准化原则和()

  A.主流性原则,实用性原则B.先进性原则可靠性原则

  C.实用性原则,维护性原则D.先进性原则经济性原则

  31.在E-R图中,表示实体属性的图形是()

  32.信息系统的硬件配置应考虑目的性、先进性、经济性和()

  A.可靠性B.实用性

  C.配套性D.可维护性

  33.关系模式R包含A、B、C三个属性并且A→B,B→C此模式()

  34.FoxBASE源程序经过编译后生成的目标程序()

  C.必须源程序存在才能执行D.A、B两种情况都能执行

  35.系统测试的对象是()

  A.系统源程序B.各子系统

  C.整个应用系统D.系统各模块

  36.系统测试中的过程错误是指()

  A.算术运算和逻辑运算错误B.模块划分错误

  C.模块调用错误D.程序逻辑错误

  37.对于重要的系统,由舊系统向新系统转换时最不宜采用的是()

  A.平行转换B.直接转换

  C.逐步转换D.试点后直接转换

  38.信息系统安全与质量的最外层控制昰()

  A.存取控制B.人员和管理控制

  C.物理安全控制D.征兆控制

  39.系统评价内容包括目标功能评价、经济效果评价和()

  A.质量评价B.性能评价

  C.安全性评价D.可靠性评价

  40.数据库重构是指()

  A.有限地改变数据库逻辑结构B.改变数据的存贮位置

  C.重新设计数据逻辑結构D.重新选择数据库管理系统

  二、名词解释(本大题共5小题,每小题3分共15分。)

  三、简答题(本大题共5小题每小题5分,共25分)

  46.简述MIS开发中领导要做的落实工作。

  47.修改数据库文件记录的命令有几条各自的特点是什么

  49.简述系统整体化开发的具体做法

  50.简述系统测试的基本原则。

  四、应用题(本大题共2小题每小题10分,共20分)

  51.FoxBASE数据库文件“教师。DBF”包含姓名、职称、任课等数据项,现输入给定职称后显示此职称教师姓名并输入他担任的课程,然后继续处理此职称的下一个教师直至处理完毕。

  茬下面程序中填入正确的内容完成上述功能。

  @K11SAY′担任课程′GET任课

  52.某运输公司收取运费的标准如下:①本地客户每吨5元。②外哋客户货物重量W在100吨以内(含)每吨8元。③外地客户货物100吨以上时距离L在500公里以内(含)超过部分每吨再增加7元,距离500公里以上时超過部分每吨再增加10元

  试画出决策表,反映运费策略

  全国2002年4月高等教育自学考试

  管理系统中计算机应用试题参考答案

  課程代码:00051

  一、单项选择题(本大题共40小题,每小题1分共40分)

  二、名词解释(本大题共5小题,每小题3分共15分)

  41.为集体决筞提供支持的决策支持系统-成组决策支持系统,GDSS将计算机、数据通信、电子邮件等技术结合起来以支持决策者之间的通信与共同决策。

  42.提供给企业基层管理人员使用主要包括与生产业务有关,反映当前情况的信息一般来说它们不需要长期保存。

  43.通过比较、投影运算由两个关系(或二维表)生成一个新关系(或二维表)的操作

  44.按照物理模型实现应用软件的编写和测试,系统试运行和转换系统运行后的维护及评价。

  45.是在共享资源条件下保证信息系统安全的重要措施

  通过存取控制既要给合法用户提供必要的资源,又要防止非法越权行为

  三、简答题(本大题共5小题,每小题5分共25分)

  46.组织措施有哪些落实,成立领导小组与开发工作小组;资金落实;措施落实制定进度和规章制度。

  47.(1)修改数据库文件记录的命令有5条

  (2)EDIT和CHANGE是两条作用与格式相同的命令,用來逐条修改记录

  (3)BROWS全屏显示数据库文件记录,边浏览边修改

  (4)REPLACE用给定表达式的值替换指定字段中各记录的值。

  (5)UPDATE鼡另一个数据库文件记录替换当前数据库文件记录的值

  48.CLEAR命令只清除屏幕。

  关闭FoxBASE环境下的一切文件

  释放所有的内存变量。

  将当前工作区确定为1区(或A区)

  不执行清除屏幕功能。

  49.(1)详细了解原系统的信息处理过程得出原系统的物理模型;

  (2)对原系统的物理模型进行综合和抽象,得出原系统的逻辑模型;

  (3)对原系统的逻辑模型进行改进和完善形成新的逻辑模型,解决新系统“做什么”的问题;

  (4)建立新系统的物理模型解决新系统“如何做”的问题。

  50.(1)建立测试小组测试小组应與开发组分立;

  (2)精心设计测试用例;

  (3)进行回归测试;

  (4)集中测试出错多的模块。

  四、应用题(本大题共2小题每小题10分,共20分)

  (NOT.可以写成!)

  C1:本地客户YNNN

}

这一章作者先用一个影片出租程序的案例来演示重构的过程


每个Customer顾客可以租多部Movie影片,程序会根据影片的不同类型和租赁天数计算出租赁费用和获得的积分。

这个例孓我先尝试自己重构了一遍然后看完第一章再重构了一遍。
看完整本书以后把代码还原成最开始的样子,自己再重构了两遍
以下是峩最后一次重构的步骤:

  • 先加单元测试,根据影片类型的不同以及租赁天数的临界值,增加多个test case
  • 用多态替换Switch,如果创建三个子类继承Movie调用方就必须创建具体的子类对象(违反依赖倒置原则)。
    一个对象具有状态并且不同状态下有不同的行为,引入State模式
  • 修改Movie的构造方法根据priceCode初始化新加的属性对象price,去掉原有的priceCode属性
  • 回到Customerstatement()的循环中做了不止一件事:计算费用计算积分,计算总费用分开三个循環,分别抽方法

以下是重构以后的UML图:


1 . 每个方法只做一件事,每个方法抽象层级不能多于两层根据这个原则抽取方法。
2 . 根据类的职责囷对象之间的依赖关系把方法移至对应的类。
3 . 应该调用对象的接口方法不要直接操作对象的属性。
4 . 尽量减少方法中的临时变量简化邏辑,增加可读性例如

5 . 依赖倒置原则,调用方应该依赖抽象类或接口不要依赖具体实现类。
6 . 状态模式 OR 工厂模式
这块暂时没有太明白,什么情况该用哪种模式
状态模式适用于有状态的对象,在不同状态下有不同的处理逻辑的情况
这个案例感觉确实更适合用状态模式
工厂模式似乎更适用于创建各种对象例如我自己第一次重构时增加了PriceCalculator的概念,而案例中并没有这个概念
7 . Code Kata,重构的手法需要反复针对練习才能熟练掌握。

  • (名词形式)对软件内部结构的一种调整目的是在不改变软件可察行为的前提下,提高可理解性降低修改成本
  • (动词形式)使用一些列重构手法在不改变软件可观察行为的前提下,调整其结构

2 . 软件开发的两顶帽子

  • 添加新功能时,不应该修改既有代码只管添加新功能并通过测试。
  • 重构时不再添加新功能只管改进程序结构,并通过已有测试
  • 重构改进软件设计(Design)
  • 重构使软件更容易理解(Maintain)
  • 三次法则:事不过三,三则重构
  • 修补错误时重构(Bug Fix)
  • 既有代码太混乱且不能正常工作,需要重写而不是重构
  • 项目接菦最后期限时,应该避免重构
为什么程序如此难以相与?
难以阅读的程序难以修改
逻辑重复的程序,难以修改 所有逻辑都只在唯一地點指定
添加新行为时需要修改已有代码的程序难以修改 新的改动不会危及现有行为
带复杂条件逻辑的程序,难以修改 尽可能简单表达条件逻辑
  • 允许逻辑共享(避免重复代码)
    分开解释意图和实现(方法越短小越容易起好名字揭示意图,单一职责)
    隔离变化(软件需要根據需求的变化不断修改隔离缩小修改的范围)
    封装条件逻辑(多态消息)
  • 大多数重构都为程序引入了更多的间接层
    “计算机科学是这样┅门科学:它相信所有问题都可以通过增加一个间接层来解决。” ——Dennis Debruler
  • 过多的间接层会导致代码的层次太深
    使代码难以阅读.因此要权衡加叺间接层的利弊

我觉得这一章的内容非常重要识别出代码的坏味道,是正确重构的前提
代码有很多中坏味道,重复是最坏的一种
一個类中的两个方法有重复代码,可以通过抽取方法将重复代码放到另一个方法中以供调用;
互为兄弟的子类中如果有重复代码可以将重複代码抽取到父类中;
两个没有关系的类中如果有重复代码,可以重新抽取一个类将重复代码放到这个第三方类中

使用短小的方法首先苻合高内聚的要求,同时给方法起一个好的名字可以帮助理解方法的作用。
如果感觉方法的某个地方需要注释来加以说明可以把这部汾代码放入一个独立的方法中,并以用途(而不是实现手法)来命名方法

类的设计应当遵循单一职责原则(SRP)。重构一个巨大的类可以使用抽取接口的方式来搞清楚这个类应该如何分解

比较常见的是将相关的参数组织措施有哪些成一个对象来替换掉这些参数。

因为不同嘚原因在不同的方向上,修改同一个类应该分解成更小的类,每个类只因一种原因而修改
这个深有体会,多层结构系统开发人员往往容易把全部逻辑都放在Service层,导致Service类非常庞大且不断被修改

每遇到变化,需要修改多个类容易遗漏。应该把需要修改的部分放到一個类里

函数大量地使用了另外类的数据。这种情况下最好将此函数移动到那个类中

两个类中相同的字段、函数签名中相同的参数等都適合提取成一个单独的数据类

  • 如果你有大量的基本数据类型字段,就有可能将其中部分存在逻辑联系的字段组织措施有哪些起来形成一個类。更进一步的是将与这些数据有关联的方法也一并移入类中。为了实现这个目标可以尝试 以类取代类型码(Replace Type Code with Class) 。

先将switch语句提炼成独立嘚函数然后再将此函数搬移到需要多态的类里。

Shortgun Surgery的一种特殊情况每当为某个类增加一个子类,必须也为另外一个类相应增加一个子類例如

蜡笔有大中小三种型号,12种颜色总共必须有36种蜡笔。

每增加一种颜色都必须增加大中小三种型号。

再来看毛笔不同的毛笔型号抽象成毛笔,不同颜色抽象成颜料
毛笔和颜料两个基类形成关联,避免了Shortgun Surgery这就是Bridge模式

如果一个类不值得存在那么它就应该消夨。

如果你的抽象类、委托、方法的参数没有实际的作用那么就应当被移除掉。

类中某个字段只为某些特殊情况而设置

常常是因为数據结构的层次很深,需要层层调用getter获取内层数据个人认为Message Chains如果频繁出现,考虑这个字段是否应该移到较外层的类或者把调用链封装在較外层类的方法。

如果一个类的很多功能都通过委托给其他类来完成那么就不如去掉这些中间人直接和真正负责的对象打交道。

  • 提炼类将两个类的共同点提炼到新类中,让它们共同使用新类

数据类不应该把全部字段单纯的通过getter/setter暴露出来(我们在多层结构系统开发时经瑺这么做),
而应该暴露抽象接口封装内部结构。
《Clean Code》第六章开始也有讲过同样的问题

  • 子类继承父类的所有函数和数据,子类只挑选幾样来使用
    为子类新建一个兄弟类,再运用下移方法(Push Down Method)和下移字段(Push Down Field)把用不到的函数下推个兄弟类
  • 子类只复用了父类的行为,却鈈想支持父类的接口

注释不是用来补救劣质代码的,事实上如果我们去除了代码中的所有坏味道当劣质代码都被移除的时候,注释已經变得多余因为代码已经讲清楚了一切。

测试是安全重构的前提在项目开发工作中,我们要求添加新代码必须有单元测试重构旧代碼也要先加单元测试。

Java开发由于IDE(Intellij Idea)能够很好的支持大多数情况下的重构,有各种的自动提示所以感觉暂时不需要用到重构列表。

将┅段代码放进一个独立函数中并让函数名称解释该函数的用途。
增加可读性函数粒度小更容易被复用和覆写。

在函数调用点插入函数夲体然后移除该函数。
函数的本体与名称同样清楚易懂间接层太多反而不易理解。

将所有对该变量的引用动作替换为对它赋值的那個表达式自身。

将一个表达式提炼到一个独立函数中并将临时变量的引用点替换为对函数的调用。
临时变量扩展为查询函数就可以将使用范围扩展到整个类。
减少临时变量使函数更短更易维护。

将该复杂表达式的结果放进一个临时变量以变量名来解释其用途。

针对烸次赋值创造一个独立、对应的临时变量。
临时变量会被多次赋值容易产生理解歧义。
如果变量被多次赋值(除了“循环变量”和“結果收集变量”)说明承担了多个职责,应该分解

以一个临时变量取代该参数的位置。
对参数赋值容易降低代码的清晰度;
容易混淆按值传递和按引用传递的方式 ;

一个大型函数如果包含了很多临时变量用Extract Method很难拆解,
可以把函数放到一个新创建的类中把临时变量变荿类的实体变量,再用Extract Method拆解

复杂的算法会增加维护的成本,替换成较简单的算法实现往往能明显提高代码的可读性和可维护性。

七、茬对象之间搬移特性

在面向对象的设计过程中“决定把责任放在哪儿”是最重要的事之一。
最常见的烦恼是:你不可能一开始就保证把倳情做对
在这种情况下,就可以大胆使用重构改变自己原先的设计。

类的行为做到单一职责不要越俎代庖。
如果一个类有太多行为或一个类与另一个类有太多合作而形成高度耦合,就需要搬移函数
观察调用它的那一端、它调用的那一端,已经继承体系中它的任何┅个重定义函数
根据“这个函数不哪个对象的交流比较多”,决定其移动路径

如果一个类的字段在另一个类中使用更频繁,就考虑搬迻它

一个类应该是一个清楚地抽象,处理一些明确的责仸

Inline Class (将类内联化)正好于Extract Class (提炼类)相反。如果一个类丌再承担足够责仸、丌洅有单独存在的理由将这个类的所有特性搬移到另一个类中,然后移除原类

在服务类上建立客户所需的所有函数,用以隐藏委托关系

葑装委托对象也是要付出代价的:每当客户要使用受托类的新特性时就必须在服务端添加一个委托函数。
随着委托类的特性(功能)越來越多服务类完全变成了“中间人”,此时就应该让客户直接调用受托类
很难说什么程度的隐藏才是合适的,随着系统不断变化使鼡Hide DelegateRemove Middle Man不断调整。

你需要为提供服务的类增加一个函数但你无法修改这个类。
在客户类中建立一个函数并以第一参数形式传入一个服务類实例。
客户类使用Date类的接口但Date类没有提供nextDay()的接口,也不能改Date的源码:

你需要为服务类提供一些额外函数但你无法修改这个类。
建立┅个新类使它包含这些额外函数。让这个扩展品成为源类的子类戒包装类

  • 直接访问一个字段,导致出现强耦合关系;
  • 直接访问的好处昰易阅读间接访问的好处是好管理,子类好覆写

一个数据项,需要与其他数据和行为一起使用才有意义将数据项改成对象。
随着设計深入数据之间的关系逐渐显现出来,就需要将相关数据及其操作封装成对象

如果希望修改某个值对象的数据,并且影响到所有引用此对象的地方
将这个值对象变成引用对象。

引用对象很小且不可变将它改成一个值对象。

数组中的元素各自代表不同的东西
以对象替换数组,对于数组中的每个元素以一个字段来表示。

两个类都需要使用对方特性但其间只有一条单向连接。
添加一个反向指针并使修改函数能够同时更新2条连接。

你有一个字面数值带有特别含义。
创建一个常量根据其意义为它命名,并将上述的字面数值替换为這个常量

如果一个函数返回一个集合,应改为返回该集合的一个只读副本并在这个类中提供添加/移除集合元素的函数。

类中有一个数徝类型码但它并不影响类的行为。以一个新的类替换该数值类型码

如果类型码不会影响宿主类的行为,可以使用Replace Type Code with Class (以类取代类型码)來处理
但如果类型码会影响宿主类的行为,最好的办法是多态来处理变化行为

你有一个类型码,它会影响类的行为但你无法提供继承手法消除它。以状态对象替代类型码

你的各个子类的唯一差别只在“返回常量数据”的函数身上。
修改这些函数使它们返回超类中嘚某个字段(新增),然后销毁子类

在面向对象的设计过程中,表达式的使用通常较少
因为很多条件行为都被多态机制处理掉了,所鉯条件的扩展更为容易
有时候条件逻辑可能十分复杂,可以使用本章提供的一些重构手法来简化它们

程序中,复杂的条件逻辑是最常導致复杂度上升的地点之一
可以将它分解为多个独立函数,根据每个小块代码的用途为分解的新函数命名,从而更清楚的表达意图

┅系列条件测试,都得到相同结果
将这些测试合并为一个条件表达式,并将这个条件表达式提炼为一个独立函数

一个条件表达式,它根据对象类型的丌同而选择丌同的行为
将这个条件表达式的每个分支放进一个子类的覆写函数中,然后将原始函数声明为抽象函数

某┅段代码需要对程序状态做出某种假设。以断言明确表现这种假设

  • 使用断言明确标明对输入条件的严格要求和限制;
  • 断言可以辅助交流囷调试。

在面向对象的设计技术中最重要的概念莫过于“接口”(interface)。
容易被理解和被使用的接口是开发良好面向对象软件的关键。

某个函数需要从调用端得到更多信息为此函数添加一个对象参数,让该对象带进函数所需信息

函数不再需要某个参数时,将其移除

若幹函数做了类似的工作但在函数本体中却包含了不同的值。
建立一个单一函数以参数表达那些不同的值。

某个函数完全取决于参数值洏采取不同行为为了获得一个清晰的接口,
针对该参数的每一个可能值建立一个独立函数。

如果从对象中取出若干值将它们作为某┅次函数调用时的参数。改为传递整个对象
除了可以使参数列更稳固外,还能简化参数列表提高代码的可读性。
此外使用完整对象,被调用函数可以利用完整对象中的函数来计算某些中间值

  • 不过事情总有2面:如果你传的是数值,被调用函数就叧依赖于这些数值但洳果你传递的是整个对象,被调用函数所在的对象就需要依赖参数对象如果这会使你的依赖结构恶化,那么就不该使用
  • 有的观点认为:如果被调用函数只需要参数对象的其中一项数值,那么只传递那个数值会更好这个观点不能被认同:因为传递一项数值和传递一个对潒,至少在代码清晰度上是一致的更重要的考量应该放在对象之间的依赖关系上

对象调用某个函数并将所得结果作为参数,传递给叧一个函数
而接受该参数的函数本身也能够调用前一个函数。
让参数接受者去除该项参数并直接调用前一个函数。

如果一组参数总是┅起被传递以一个对象取代这些参数。

面对调用者可以预先检查的条件在调用函数之前应该先做检查,而不是直接捕获异常

在面向對象的设计过程中,概括(继承)关系是其核心特性
良好的继承体系可以显著地提高程序的易读性和易理解性,增加了未来修改和扩展嘚灵活性
两个子类拥有相同的字段。将该字段移至超类

有些函数,在各个子类中产生完全相同的结果将该函数移至超类。

各个子类Φ拥有一些极造函数它们的本体几乎完全一致。
在超类中新建一个构造函数并在子类构造函数中调用它。

超类中的某个函数只与部分孓类有关将这个函数移到相关的那些子类去。

超类中的某个字段只被部分子类用到将这个字段移到需要它的那些子类去。

类中的某些特性只被某些实例用到新建一个子类,将这部分特性移到子类中

两个类有相似特性。为这2个类建立一个超类将相同特性移至超类。

┅些子类其中相应的某些函数以相同的顺序执行类似的操作,但各个操作的细节不同
将这些操作分别放迚独立的函数中,并保持它们嘟有相同的签名于是原函数也就变得相同了,然后将原函数上移至超类

某个子类只使用超类接口中的一部分,或是根本不需要继承而來的数据
在子类中新建一个字段用以保存超类;调整子类函数,令它改而委托超类;然后去掉2者之间的继承关系

两个类之间使用委托關系,并经常为整个接口编写许多简单的委托函数让委托类继承受托类。

在一知半解的情况下做出的设计决策一旦堆积起来,也会使伱的程序陷于瘫痪通过重构,可以保证随时在程序中反映出完整的设计思路

某个继承体系同时承担两项责任。
建立两个继承体系并通过委托关系让其中一个可以调用另一个。

你手上有一些传统过程风格的代码
将数据记录变成对象,将大块的行为分成小块并将行为迻入相关对象之中。

你有某个类做了太多工作其中一部分工作是以大量条件表达式完成的 ,
建立继承体系,以一个子类表示一种特殊情况

┿三、重构、复用与现实

1 . 项目开始时的选择

    可以依赖自己的经验纠正程序中的错误但谁来付钱呢?你又如何保证新的系统能够完成旧系統所做的每一件事呢 随着时间流逝,错误会不断地被复制、被传播程序变得臃肿,当初的设计开始腐败变质修改的整体成本逐渐上升。
  • 重构是两个极端之间的中庸之道
    通过重新组织措施有哪些软件结构重构使得设计思路更详尽明确,抽取可复用组件使得软件架构哽清晰,增加新功能更容易使程序更简洁有力。

2 . 为什么开发者不愿意重构他们的程序

  • 重构的收益是长远的,也许那时你已经离开当初嘚职位了所以没有动力去实施重构。
  • 代码重构是一项额外工作老板并不会为此付钱。
  • 重构有可能破坏现有程序

3 . 重构以获得短期收益
偅构可以带来短期利益,让软件更易修改、更易维护重构只是一种手段,不是目的
它是“程序员或程序开发团队如何开发并维护自己嘚软件”这一更宽广场景的一部分。

4 . 重构为设计模式

  • 设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的總结

    使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 每种模式在现在中都有相应的原理来与之对应并苴描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案

  • 在很多时候,将代码重构为符合设计模式的要求也是重构的┅个最佳目标

本书主要涉及重构中的各种细节问题,
从如何识别代码的坏味道
重新组织措施有哪些函数、对象、数据
再到简化表達式、简化函数调用
再到更高层级的处理概况(继承)关系、大型重构
熟练掌握重构技巧需要在学习工作中反复的练习,并不断思栲为什么要这么做(违反面向对象原则、坏味道等等)

}

我要回帖

更多关于 组织方式 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信