《代码大全》读书笔记-第5章 软件构建的设计

有人会说,设计不是真正的构建活动。但在小项目中,包括设计在内的许多活动都被认为是构建。有些设计更关注系统级问题,许多设计工作留给构建。有些大型项目设计非常详细,导致编码成为一项机械性劳动。小型项目的设计更多的是程序员坐在电脑前完成的,不管是小项目还是大项目都会在精心的设计中获益的。

1.设计的挑战

设计是一个棘手问题,定义为只有通过解决它或解决它的一部分才能明确定义的问题。这个悖论意味着,必须“解决”一次问题才能清晰地定义它,然后再解决一次才能创建有效的解决方案。塔科马海峡吊桥问题就是典型的棘手问题,这艘桥在设计时主要考虑的是有足够的强度来支持设计的负载,在建成使用时,因为大风产生的侧向谐波导致的大桥梁坍塌。
在这里插入图片描述
设计没有章法,设计之所以没有章法,是因为你会采取很多不恰当的步骤,走入死胡同,会犯很多错,越早意识到错误并且修正错误是很重要的;另外就是很难知道自己的设计是不是“足够好”,由于设计永无止境,最常见的衡量办法就是“当你时间不够的时候”。
设计关乎取舍,设计工作的关键是权衡相互竞争的设计特性,并从中取得平衡。什么样的目标决定什么样的设计。
设计是不确定的和启发式的,不同的人设计相同的程序,方案都是不同的。由于设计师不确定的,所以设计技术都是启发式的,需要用到“经验法则”或者“试行”的策略。
设计是水到渠成的,设计是一个自然浮现,需要通过设计评审、讨论、写代码和修改代码的过程中逐渐完善和改进的。

2.关键设计概念

2.1 管理复杂性

软件项目常见的失败原因是需求不到位、计划不周或管理不善。软件如此复杂,以至于没人知道它在做什么。一旦没人完全理解一个区域的代码变化对其它区域的影响,项目就无法进一步发展了。软件开发人员应该用一种安全的、一次只专注于其中一部分的方法来组织程序,目标是尽量减少需要考虑程序的数量。在架构方面,通过划分为子系统来降低复杂度,子系统越独立,就能使其安全地专注于解决一个复杂的点。

2.2 理想的设计特征:

  • 最小化复杂性 要做简单的、易于理解的设计,不要做“聪明的”、难以理解的设计
  • 易于维护 程序是写给人看的,而不是机器。写代码时不断想象别人使用软件时会提出什么样的问题,把系统设计得不言而喻。
  • 松散耦合 松散耦合是指在设计师,将不同程序的关联控制在最小范围内。通过遵循良好的接口规则、信息分装来设计相互关联尽可能少的类。
  • 可拓展性 在不破化底层的前提下对系统进行增强。进程间调用、rpc、消息队列等技术都很值得借鉴。
  • 精简性 精简性意味着没有多余的设计,在软件中,只要写入了代码,就要花时间区阅读、理解、审查、编译、测试这些代码。这些都会对项目的质量造成影响,借助git等版本管理工具,可以安心地删除多于代码。
  • 层次性 尽量保持分层地层次,一般在控制软件中,将软件分为通讯层、设备层、指令层,上层调用下层,可以使程序更容易理解。
  • 标准技术 多借助标准技术,因为大家都很熟悉。

3.设计构建基块:启发式方法

由于设计是不确定地,所以熟练运用一套有效地启发式方法便成了优秀软件设计地核心活动

3.1 映射现实中的对象

最流行的设计方案就是“按部就班”的面向对象的方法,它侧重于现实世界对象的映射,设计步骤如下:

  • 确定对象及其属性
  • 确定公共方法
  • 确定私有方法
  • 提炼接口、抽象公共部分

3.2 形成一致的抽象

抽象是指在使用一个概念时,安全忽略其部分细节的能力,也就是在不同层次处理不同细节的能力。基类和接口是一种抽象,允许在处理它们时忽略具体的细节,降低复杂度。好的程序员会在路由接口层、类接口层和包接口层创建抽象,以更快和更安全的方式进行编程。
封装实现细节、继承、信息隐藏等都是解耦的好途径。

4.隐藏信息

4.1 障碍

  • 信息过度分散 硬编码字面量、大量的cv、重复的逻辑,在你修改一个需求时需要动到多出代码时,就要警惕信息过度分散了
  • 循环依赖
  • 类数据误作全局数据
  • 显著的新能损失,人们经常担心间接访问数据项会因为额外的对象实例化、子程序调用等造成运行时的性能损失。这种担心为时尚早,只要代码足够整洁,新能瓶颈很容易找到并且优化

5.识别容易变动的区域

预测变化是优秀设计师的共性,如何识别软件中的变与不变,隔离不稳定区,这样变化就会限制在一个子程序、类或包中。这种的设计步骤是

  • 确定可能会有变动的地方
  • 分离可能发生变化的项
  • 隔离可能发生变化的项
    业务规则、硬件依赖性、输入和输出、非标准语言特性、困难的设计和构建区域、状态变量都是可能发生变化的区域。

6.寻找常用的设计模式

设计模式精炼了众多现成的解决方案,由于解决软件许多常见的问题。大部分具有共性的问题,都可以用“模式来解决”。与完全定制的设计相比,设计模式具有以下好处:

  • 提供既有抽象来降低复杂性
  • 通过将常见解决方案的细化制度来减少错误
  • 为启发式设计提供思路
  • 通过将设计对话转移到一个更高的层次来简化沟通
    使用模式一般都要经过三个阶段,强行套用模式、觉得模式用处不大、随着代码的演变自然地使用模式

7.其他启发式方法

  • 力求强内聚性
  • 建立层次结构
  • 建立类的契约
  • 分配职责
  • 为测试而设计
  • 避免失败,在设计时仔细考虑可能失败地方式,而不是照搬前人成功地经验,像塔科马海峡大桥这样地失败是可以避免的
  • 建立中心控制点,任何可能的维护更改都只在一个正确的地方进行,控制可以集中在类、子程序、预处理类、#include文件中。
  • 考虑使用蛮力,很多情况下,顺序搜索就够了,不必再去使用二分查找。
  • 画图
  • 保持设计的模块化

8.启发式方法的原则

不要拘泥于单一的方法,UML、自然语言、蛮力、铅笔画图等都是设计的好方法,如果所有方法都失败了,就放下问题,清空大脑,抛开一段时间。要知道很多设计都是在积累了充分的信息后才能找到更好的解决方案,在没有充分的信息之前,本来就不适合强行解决那些问题。

9.设计实践

  • 迭代
  • 分而治之
  • 自上而下和自下而上
  • 实验性的原型设计
  • 协作式设计
  • 记录设计工作

本章小结

这一章内容很多,足足有50页。主要讲了设计的一些基本方法,可以和着面向对象的继承、封装、多态很好地结合在一起。告诉我们软件设计的主要工作就是找到变于不变,每一次设计的迭代都能加深对变化的理解,随着每一次深入的思考,逐渐得到一个好用的设计方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值