第五章 软件构建中的设计

设计中的挑战

软件设计意味着去构思、创造或发明一套方案,把一份计算机软件的规格说明书转变为可实际运行的软件。设计就是把需求分析和编码调试连在一起的活动。
设计是一个险恶的问题:只有通过解决或部分解决才能被明确的问题。
设计是个了无章法的过程(即使他能得出清爽的成果)。
设计就是确定取舍和调整顺序的过程。
设计受到诸多限制。
设计是不确定的。
实际是一个启发式过程。
设计是自然而然形成的。

关键的设计概念

好的设计源于对一小批关键设计概念的理解。

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

偶然的难题和本质的难题:偶然是碰巧的,大部分偶然性难题在很久之前已经得到了解决。在软件开发剩下的那些本质性困难上的进展相对缓慢,本质性困难来自很多方面:必须去面对复杂、无序的现实世界;精确而完整地识别出各种依赖关系与例外情况;设计出完全正确而不是大致正确的解决方案;诸如此类。
管理复杂度的重要性:
当项目由技术原因导致失败的时候,其原因通常就是失控的复杂度。有关软件变得极端复杂,让人无法知道他究竟是做什么的。
如何应对复杂度:
把任何人在同一时间需要处理的本质复杂度的2⃣️减到最少;
不要让偶然性的复杂度没有限制地快熟增长。

理想的设计特征

最小的复杂度、易于维护、松散耦合、可扩展性、可重用性、高扇入、低扇出、可移植性、精简行、层次性、标准技术

设计的层次

第1层:软件系统
第2层:分解为子系统和包
第3层:分解为包中的类
第4层:分解为类中的数据和子层序
第5层:子层序内部

设计构造块:启发式方法

由于软件是非确定性的,因此,灵活熟练地运用一组有效的启发式方法(试探法),便成了合理的软件设计核心工作。
找出现实世界中的对象
使用对象进行设计的步骤是:
* 辨识对象及其属性(方法和数据)。
* 确定可以对各个对象进行的操作。
* 确定各个对象能对其他对象进行的操作。
* 确定对象的哪些部分对其他对象可见——哪些部分是公用的,哪些部分是私有的。
* 定义每个对象的公开接口。
形成一致的抽象
抽象是一种能让你在关注某一概念的同时可以放心地忽略其中一些细节的能力——在不同的层次处理不同的细节。
封装实现细节
封装填补了抽象留下的空白。
当继承能简化设计时就继承
定义对象之间的相同点和不同点叫继承。继承的好处在于他能够很好地辅佐抽象的概念。继承能简化编程的工作。继承是面向对象编程中最强大的工具之一。
隐藏信息
信息隐藏是结构化程序设计与面向对象设计的基础之一,信息隐藏是减少重复工作的强大技术。
两种秘密:
* 隐藏复杂度:这样你就不用再去应付他,除非需要特别关注的时候。
* 隐藏变化源:这样当变化发生时,其影响就能被限制在局部范围内。
信息隐藏的障碍:信息过度分散、循环依赖、把类内数据误认为是全局数据、可以觉察的性能损耗。
信息隐藏的价值:修改容易、有启发力、有助于设计类的公开接口。
找出容易改变的区域
1. 找出看起来容易变化的项目。
2. 把容易变化的项目分离出来。
3. 把看起来容易变化的项目隔离开来。
一些容易变化的区域:业务规则、对硬件的依赖性、输入和输出、非标准语言特性、困难的设计区域和构建区域、状态变量。
保持松散耦合
偶和标准:规模、可见性、灵活性。
耦合种类:简单数据参数耦合、简单对象耦合、对象参数耦合、语义上的耦合。
查阅常见的设计模式
常见的设计模式包括适配器、桥接、装饰器、外观、工厂方法、观察者、单件、策略及模板方法。
使用设计模式的好处:
设计模式通过提供现成的抽象来减少复杂度;设计模式通过把常见解决方案的细节予以制度化来减少出错;设计模式通过提供多种设计方案而带来启发性的价值;设计模式通过把设计对话提升到一个更高的层次上来简化交流。
其他启发式方法
高内聚性、构造分层结构、严格描述类契约、分配职责、为测试而设计、避免失误、有意识地选择绑定时间、创建中央控制点、考虑使用蛮力突破、画一个图、保持设计的模块化
关于设计启发的总结
主要的启发式方法:
寻找现实世界中的对象
形成一致的抽象
封装实现细节
在可能的情况下继承
信息隐藏
找出容易改变的区域
保持松散的耦合
探寻通用的设计模式
下列启发式方法又是也很有用:
高内聚性
构造分层结构
严格描述类契约
分类职责
为测试而设计
有意识地选择绑定时间
创建中央控制点
考虑使用蛮力
画一个图
保持设计模块化

设计实践

迭代、分而治之、自上而下和自下而上的设计方法、建立试验性原型、合作设计、要做多少设计才够、记录你的设计成果

核对表:软件构造中的设计

设计实践
- [ ] 你已经做过多次迭代,并且从众多尝试结果中选择了最佳的一种,而不是简单选择第一次尝试的结果吗?
- [ ] 你尝试多种方案来分解系统,以确定最佳方案吗?
- [ ] 你同时用自下而上和自上而下的方法来解决软件设计问题吗?
- [ ] 为了解决某些特定的问题,你对系统中的风险部分或者不熟悉的部分创建过原型、写出数量最少的可抛弃式代码吗?
- [ ] 你的设计方案被别人检查了吗?
- [ ] 你一直在展开设计,直到实施细节跃然纸上了吗?
- [ ] 你用某种适当的技术——比如说wiki、电子邮件、挂图、数码照片、UML、CRC卡或者在代码写注释——来保留设计成果吗?
设计目标
- [ ] 你的设计是否充分地处理了由系统架构层定义出并且推迟确定的事项?
- [ ] 你的设计被划分为层次吗?
- [ ] 你对吧这一程序分解为子层序、包和类的方式感到满意吗?
- [ ] 你把对这个类分解成子层序的方法感到满意吗?
- [ ] 类与类之间的交互关系是否已设计为最小化了?
- [ ] 类和子程序是否被设计为能够在其他系统中重用?
- [ ] 程序是不是易于维护?
- [ ] 实际是否精简?设计出来的每一部分都绝对必要吗?
- [ ] 设计中是否采用了标准的技术?是否避免使用怪异且难以理解的元素?
- [ ] 整体而言,你的设计是否有助于最小化偶然性的和本质性的复杂度吗?

posted @ 2019-09-11 10:14  Liam-Ji  阅读(369)  评论(0编辑  收藏  举报