目录

前言

本章主题

5.1 设计中的挑战

5.1.1 设计在软件构建中所处的角色

5.1.2 设计是一个险恶的问题

5.2 关键的设计概念

5.2.1 软件的首要技术使命:管理复杂度

1. 管理复杂度的重要性

5.2.2 理想的设计特征

5.2.3 设计的层次

第1层:软件系统

第2层:分解为子系统或者包

第3层:分解为类

第4层:分解成子程序

第5层:子程序的内部设计

5.3 设计构造块:启发式方法

找出现实中的对象

形成一致的抽象

当继承能简化设计时就继承

关于设计启发的总结

5.4设计实践

5.5 对流行的设计方法的评论


《Code_Complete_2》持续更新中......_@来杯咖啡的博客-CSDN博客这本书有意设计成使你既可以从头到尾阅读,也可以按主题阅读。1. 如果你想从头到尾阅读,那么你可以直接从第2章“用隐喻来更充分地理解软件开发”开始钻研。2. 如果你想学习特定的编程技巧,那么你可以从第6章“可以工作的类”开始,然后根据交叉引用的提示去寻找你感兴趣的主题。3. 如果你不确定哪种阅读方式更适合你,那么你可以从第3章3.2节“辦明你所从事的软件的类型”开始。.....................https://blog.csdn.net/qq_43783527/article/details/126275083

前言

本章的所讲的设计,你可以理解是“构建活动”中的“详设(详细设计)”。

设计是个庞大的话题,而这一章只能涵盖其中的少数侧面。这里的“设计”可能就是指在编写具体代码之前先用伪代码写出一个类的接口,也可能就是在编码之前画出几个类之间的关系图,还可能就是询问另一位程序员用哪个设计模式会更好。

        一个好的类或子程序的设计在很大程度上是由系统的架构所决定的,因此,请确保第3.5 节中所论述过的架构先决条件已经满足。

更多的设计工作是在个别的类和子程序这个层次上完成的,第6章“可以工作的类”,以及第7章”高质量的子程序”中会分别予以介绍。

本章主题

5.1 设计中的挑战

本节主题:概述设计过程中需要面临哪些挑战。

5.1.1 设计在软件构建中所处的角色

“软件设计”一词意味着去构思、创造或发明一套方案,把一份计算机软件的规格说明书要求转变为可实际运行的软件。设计就是把需求分析和编码调试连在一起的活动。对于大、小项目都不可或缺。

5.1.2 设计是一个险恶的问题

1、设计是需要经过多次修订和修饰的

你在学校中所开发的程序和你在职业生涯中所开发的程序的主要差异就在于,学校里的程序所解决的设计问题很少(如果有的话)是险恶的。学校里给你的编程作业都是为了让你能从头到尾直线前进而设计的。如果有位老师给你一份编程作业,你刚完成设计时他就把作业的要求改了,然后就在你将要提交完整的程序时,他又对作业的要求再次改动,这时你肯定会十分生气。然而这一过程正是在专业编程中每日可见的真实情形

2、设计是一个了无章法的过程

另外,说设计了无章法,还因为你很难判断设计何时算是“足够好”了设计到什么细节才算够?有多少设计需要用形式化的设计符号完成,又有多少设计可以留到编码时再做?什么时候才算完成?因为设计永无止境,因此对上述问题最常见的回答是“到你没时间再做了为止〞

3、设计是一个启发的过程

正因为设计过程充满了不确定性,因此设计技术也就超于具有探索性—“经验法则”或者“试试没准能行的办法”——而不是保证能产生预期结果的可重复的过程。设计过程中总会有试验和犯错误。在一件工作或一件工作的某个方面十分奏效的设计工具或技术,不一定在下一个项目中适用没有任何工具是用之四海而皆灵的

5.2 关键的设计概念

5.2.1 软件的首要技术使命:管理复杂度

1. 管理复杂度的重要性

在对导致软件项目失败的原因进行调查时,人们很少把技术原因归为项目失败的首要因素。

1、项目的失败大多数都是由差强人意的需求、规划和管理所导致的。

        2、但是,当项目确由技术因素导致失败时,其原因通常就是失控的复杂度。有关的软件变得极端复杂,让人无法知道它究竟是做什么的。当没人知道对一处代码的改动会对其他代码带来什么影响时,项目也就快停止进展了。管理复杂度是软件开发中最为重要的技术话题。在我看来,软件的首要技术使命便是管理复杂度,它实在是太重要了。

Dijkstra 还指出,没有谁的大脑能容得下一个现代的计算机程序 (Dijkstra1972),也就是说,作为软件开发人员,我们不应该试着在同一时间把整个程序都塞进自己的大脑,而应该试着以某种方式去组织程序,以便能够在一个时刻可以专注于一个特定的部分这么做的目的是尽量减少在任一时间所要考虑的程序量。你可以把它想做是一种心理上的杂耍(边抛边接:通过轮流抛接使两个或两个以上物体同时保持于空中)——程序要求你在空中保持的(精神上的)球越多,你就越可能漏掉其中的某一个,从而导致设计或编码的错误。

在软件架构的层次上,可以通过把整个系统分解为多个子系统来降低问题的复杂度

保持子程序的短小精悍也能帮助你减少思考的负担从问题的领域着手,而不是从底层实现细节入手去编写程序,在最抽象的层次上工作,也能减少人的脑力负担

5.2.2 理想的设计特征

1、可扩展性(extensibility)。可扩展性是说你能增强系统的功能而无须破坏其底层结构。你可以改动系统的某-部分而不会影响到其他部分。越是可能发生的改动,越不会给系统造成什么破坏。

2、可重用性 (reusability)。可重用性意味着所设计的系统的组成部分能在其他系统中重复使用

3、高扇入(high fan-in) 。高扇入就是说让大量的类使用某个给定的类。这意味着设计出的系统很好地利用了在较低层次上的工具类 (utility classes)。

4、低扇出(low fan-out)。 低扇出就是说让一个类里少量或适中地使用其他的类。高扇出(超过约7个)说明一个类使用了大量其他的类,因此可能变得过于复杂。研究发现,无论考虑某个子程序调用其他子程序的量,还是考虑某个类使用其他类的量,低扇出的原则都是有益的(Card and Glass 1990; Basili, Briand, and Melo1996)。

5、 层次性(stratification)。层次性意味着尽量保持系统各个分解层的层次性,使你能在任意的层面上观察系统,并得到某种具有一致性的看法。设计出来的系统应该能在任意层次上观察而不需要进入其他层次。

  • 举例来说,假设你正在编写一个新系统,其中用到很多设计不佳的代码,这时你就应该为新系统编写一个负责同旧代码交互的层在设计这一层时,要让它能隐藏旧代码的低劣质量,同时为新的层次提供一组一致的服务。这样,你的系统的其他部分就只需与这一层进行交互,而无须直接同旧代码打交道了。在这个例了中,层次化设计的益处有:(1)它把低劣代码的烂泥潭禁闭起来;(2)如果你最终能抛弃或者重构旧代码,那时就不必修改除交互层之外的任何新代码。

交叉参考: 关于在旧有系统上进行工作的更多内容,请参见第24.5节“重构的策略”。

  6、标准技术(Standard techniques)。一个系统所依赖的外来的、古怪的东西越多,别人在第一次想要理解它的时候就越是头疼。要尽量用标准化的、常用的方法,让整个系统给人一种熟悉的感觉。

交叉参考:一种特别有价值的标准化就是使用设计模式,在第 5.3节“查阅常用的设计模式”中会有论述。

5.2.3 设计的层次

第1层:软件系统

第一个层次就是整个系统。有的程序员直接从系统层次就开始设计类,但是往往先从子系统或者包(package)这些类的更高组织层次来思考会更有益处

第2层:分解为子系统或者包

在这一层次上设计的主要成果是识别出所有的主要子系统。这些子系统可能会很大,比如说数据库、用户界面、业务规则、命令解释器、报表引擎等。这一层的主要设计活动就是确定如何把程序分为主要的子系统,并定义清楚充许各子系统如何使用其他子系统。对于任何至少需要几周时间才能完成的项目,在这一层次上进行划分通常都是必需的。在每个子系统的内部可能要用到不同的设计方法——请对系统中的每一部分选用最恰当的方法。在图 5-2 中,这一层次的设计是用②注明的。

     在这一层次中,有一点特别重要,即不同子系统之间相互通信的规则。如果所有的子系统都能同其他子系统通信,你就完全失去了把它们分开所带来的好处。应该通过限制子系统之间的通信来让每个子系统更有存在意义。

第3层:分解为类

文叉参考:关于高质量的类的具体特性,请见第6章“可以工作的类”

在这一层次上的设计包括识别出系统中所有的类。例如,数据库接口子系统可能会被进一步划分成数据访问类、持久化框架类以及数据库元数据。图 5-2中的第3层就展示了第2层中一个子系统是如何被分解为类的,当然这也暗示着第2层的其他三个子系统也被分解为类了。

类与对象的比较。 面向对象设计的一个核心概念就是对象 (objeet)与类(class)的区分对象是指运行期间在程序中实际存在的具体实体(enity),而类是指在程序源码中存在的静态事物

  • 对象是动态的,它拥有你在程序运行期间所能得到的具体的值和属性。例如,你可以定义一个名为 Person 的类,它具有姓名、年龄、性别等属性。在程序运行期间,你可以有 nancy、 hank、 diane、 tony 等对象—它们是类的具体实例。如果你熟悉数据库术语的话,类与对象的关系就如同“模式(schema)”与“实例(instance)”一样。你可以把类看做是蛋糕模具,而把对象看做是蛋糕。在本书中,对这两个术语的使用并非十分正规,一般情况也会或多或少互换地使用类和对象这两个术语。

第4层:分解成子程序

这一层的设计包括把每个类细分为子程序。在第3层中定义出的类接口已经定义了其中一些子程序,而第 4 层的设计将细化出类的私用(private)子程序。当你查看类里面子程序的细节时,就会发现很多子程序都很简单,但也有些子程序是由更多层次化组织的子程序所组成的,这就需要更多的设计工作了。

第5层:子程序的内部设计

交叉参考 :关于创建高质量的子程序的具体做法,请见第7章“高质量的子程序”和第8章“防御式编程”

在子程序层次上进行设计就是为每个子程序布置详细的功能。子程序内部的设计工作通常是由负责该子程序的开发人员来完成的。这里的设计工作包括编写伪代码、选择算法、组织子程序内部的代码块,以及用编程语言编写代码。这一层的设计工作总是需要做的,尽管有时做得很不在意或者很差劲,有时则是经过深思熟虑而出色完成的。在图 5-2 中的第5步就是这一层的设计工作。

5.3 设计构造块:启发式方法

由于软件设计是非确定性的,因此,灵活熟练地运用一组有效的启发式方法(试探法),便成了合理的软件设计的核心工作。下面将几小节将阐述一些启发式方法,也即一些思考问题的方法,它们有时能够产生优秀设计成果。你可以把启发式方法看做是指引试错(tail and error)法中“试验”部分的指导书,你也一定曾经用过其中一些方法。因此,以下部分会依据软件的首要技术使命—管理复杂度——的原则来讲解每一种启发式方法。

找出现实中的对象

在确定设计方案时,首选且最流行的一种做法便是“常规的”面向对象设计方法,此方法的要点是辦识现实世界中的对象(objeet,物体)以及人造的(synthetic)对象。使用对象进行设计的步骤是:

  • 辦识对象及其属性(方法(method)和数据 (data))。
  • 确定可以对各个对象进行的操作。
  • 确定各个对象能对其他对象进行的操作。
  • 确定对象的哪些部分对其他对象可见——哪些部分可以是公用(public)的,哪些部分应该是私用(private)的。
  • 定义每个对象的公开接口 (public interface)

形成一致的抽象

基类也是一种抽象,它使你能集中精力关注一组派生类所具有的共同特性,并在基类的层次上忽略各个具体派生类的细节。一个好的接口也是一种抽象,它能让你关注于接口本身而不是类的内部工作方式。一个设计良好的子程序接口也在较低的层次上提供了同样的好处,而设计良好的包(package)和子系统的接口则在更高的层次上提供了同样的好处。

封装实现细节

封装填补了抽象留下的空白。抽象是说:“可以让你从高层的细节来看待一个对象。”而封装则说:“除此之外,你不能看到对象的任何其他细节层次。”
        继续刚才关于房屋材质的比喻:封装是说,你可以从房屋的外面看,但不能靠得太近去把门的细节都看清楚。可以让你知道哪里有门,让你知道门是开着的还是关着的,但不能让你知道门是木质的、纤维玻璃的、钢质的还是其他什么材质的,当然就更不能让你看到每一根木纤维。
        如图 5-8 所示,封裝帮助你管理复杂度的方法是不让你看到那些复杂度。在第 6.2 节中的“良好的封装”中还会对进一步阐述这一话题,讨论如何把它应用于类的设计。

当继承能简化设计时就继承

在设计软件系统时,你经常会发现一些大同小异的对象。比如说,在一套账务系统中包含有全职员工和兼职员工,两者的大多数数据是相同的,只是某些数据不同。在面向对象编程时,你可以定义一个代表普通员工的通用(general)类型,然后把全职员工定义为普通员工——除了有一些不同之处;同样,把兼职员工也定义为普通员工——除了一些不同之处。当一项针对员工的操作与具体的员工类别无关时,这一操作就可以仅针对通用员工类型来进行。当该操作需要区别全职员工与兼职员工时,就需要按照不同的方法来处理了。

定义这种对象之间的相同点和不同点就叫“继承”,因为特殊的全职员工类型和特殊的兼职员工类型都从基本员工类型继承了某些特征。

继承的好处在于它能很好地辅佐抽象的概念。抽象是从不同的细节层次来看对象的。

关于设计启发的总结

下面是对主要的设计中的启发式方法的总结(以下方式详细的说明请看书):

  • 寻找现实世界的对象 (object,物体)
  • 形成一致的抽象
  • 封装实现细节
  • 在可能的情况下继承
  • 藏住秘密(信息隐藏)
  • 找出容易改变的区域
  • 保持松散耦合
  • 探寻通用的设计模式

下列的启发式方法有时也很有用:

  • 高内聚性
  • 构造分层结构
  • 严格描述类契约
  • 分配职责
  • 为测试而设计
  • 避免失误
  • 有意识地选择绑定时间
  • 创建中央控制点
  • 考虑使用蛮力
  • 画一个图
  • 保持设计模块化

5.4设计实践

5.5 对流行的设计方法的评论

《代码大全2》第5章 软件构建中的设计相关推荐

  1. 《代码大全》阅读笔记-5-软件构建中的设计

    无论是以何种方式来进行设计,小型项目也能和大型项目一样从精心的设计之中获益,而如果能认识到设计是一项明确的活动,你就更会获益匪浅. 设计过程充满了不确定性,因此设计技术也趋于探索性质. 软件的首要技术 ...

  2. 读书笔记:《代码大全第2版》 02.创建高质量的代码之软件构建中的设计

    文章目录 软件构建中的设计 1.软件设计的特征与挑战 2.管理复杂度 3.好的设计所具有的特征 4.软件设计的层次 5.软件设计方法 5.1 找出现实世界中的对象 5.2 形成一致的抽象 5.3 封装 ...

  3. 读书笔记_代码大全_第14章_组织直线型代码_第15章_使用条件语句

    组织直线型代码 + 使用条件语句 希望我的读书笔试能带你翻过18页的书 http://www.cnblogs.com/jerry19880126/ <代码大全>第14章和第15章的内容比较 ...

  4. 用计算机设计软件,平面设计中计算机设计软件的作用

    摘要:计算机平面设计在整个平面作品的设计中扮演着十分重要的角色,通过有效的计算机平面设计能够为人们提供更多的平面设计作品.为此,文章在阐述平面设计中计算机设计软件应用意义的基础上,为如何将计算机设计软 ...

  5. 【软件构造】第二章 软件构建的过程和工具(2)

    二.软件构造的编程.系统.工具 [广义软件构造的过程] 1. 编程 (1)开发语言:Java.C.C++.Python等 ·IDE:集成开发环境 - 方便编写代码和管理文件 - 能够编译.构建 - 结 ...

  6. 读书笔记:《代码大全第2版》软件工艺

    征服复杂度 软件开发的核心是降低复杂度 降低复杂度的方法 将系统拆分成多个子系统 设计抽象的接口,隐藏底层细节(抽象最能降低复杂度) 避免使用全局变量 避免深层次的继承 避免深度嵌套的循环或条件判断 ...

  7. 读书笔记:《代码大全第2版》软件行业应有的性格

    人的性格对其编程能力有直接影响. 好性格与培养正确的习惯关系甚大.要成为杰出的程序员,先要养成良好习惯,其他自然水到渠成. 聪明与谦虚 按照一定的原则,降低程序的复杂度,减少大脑的负荷,就能够在软件开 ...

  8. 读书笔记_代码大全2第七章_高质量的子程序

    创建子程序的正当理由 降低复杂度 把嵌套的部分提取出来形成一个独立的子程序,可以降低外围子程序的复杂度. 引入中间,易懂的抽象 避免代码重复 支持子类化 可覆盖的子程序保持简单,那在实现派生类时也会减 ...

  9. 读书笔记_代码大全2第十一章_选择好的变量名

    选择好的变量名的注意事项 名字要准确的描述出该变量所代表的事物(eg:好的变量名:currentDate,todayDate坏的变量名:cd,date) 以问题为导向 平均长度在10-16和8-20个 ...

最新文章

  1. cvc-complex-type.3.2.2: 元素 'constructor-arg' 中不允许出现属性 'name'
  2. svn服务器如何导入导出文件,如何导入svn dump备份文件或源代码文件?
  3. [vue] 你了解什么是高阶组件吗?可否举个例子说明下?
  4. 二、十六进制数互相转换
  5. Code First系列之视图,存储过程和异步API
  6. linux opendir php,php目录遍历函数opendir用法实例
  7. MYSQL 某个数据库下所有表的 批量删除表语句
  8. 玩转大数据系列之二:数据分析与处理
  9. LPDDR4X与LPDDR4 区别 <转>
  10. 技术博客对找工作有帮助吗?
  11. 系统没有安装任何软件如何查看电脑开机启动项
  12. 打击感在动作游戏中如何实现?【战斗篇】
  13. PLM -Aras Innovator 安装
  14. 深入学习区块链的隐私保护(四)秘密共享
  15. 一文理解二元logistic回归
  16. 应用软件安全编程概述
  17. P4417 [COCI2006-2007#2] STOL
  18. 有哪些 必装软件或者app
  19. A geometric interpretation of the covariance matrix(reproduced)
  20. Educational Codeforces Round 131 (Rated for Div. 2) A-D题解

热门文章

  1. PAT A1089 Insert or Merge ——秋水共长天一色
  2. 用 Git 向 Github 提交代码
  3. php点击弹遮罩层,小程序:防止点击遮罩层后遮罩层下面也反应的解决方法
  4. 转载雷霄骅点评过的鸡汤文世界上最伟大的推销员
  5. openssl-隐形战友
  6. Linux初入19 Apache服务
  7. 【uniapp】小程序中进行公众号授权
  8. 完全平方数(分解质因数)
  9. Chroma from Luma 预测方法总结
  10. (附源码)计算机毕业设计SSM基于web的家教管理系统