第2章:注重实效的途径
这一章讲的是:
通用于软件开发各个层面的道理,包括:
- 不要有重复的内容
- 让你的设计有正交性
- 让你的决定有可撤销性
- 开发一个新工程时先写好直达核心功能的部分,之后再往上面加内容
- 制作原型以实验不确定的内容
- 使用特定领域的专门语言更容易找到方案
- 练习估算能力使你能快速知道一个方案的可行性
7《重复的危害》
系统中的每一项知识都必须具有单一、无歧义、权威的表示
简称为DRY(Don’t Repeat Yourself)
否则,当一个知识需要变化时,就需要改动多处,假如没有改全则会造成矛盾。
这算是最重要的道理之一。
大多数重复都可归为如下范畴:
强加的重复
——开发者觉得他们别无选择,因为环境似乎要求重复。
例如:
- 代码中表示了一遍知识,随后文档又描述了一遍相同的内容。
- 多个平台需要各自的编程语言,开发环境。
- 编程语言自身要求某些重复信息的结构。
这种重复相对不容易解决,但是发挥聪明才智可以解决一部分。
一些方法例如:
- 抽象出重复的东西以公用。
- 代码生成器。
- 根据代码自动生成文档的生成器。
无意的重复
——开发者没有意识到他们在重复信息。
此种情况多缘于设计上的错误。
无耐性的重复
——开发者偷懒,他们重复是因为这样更容易。
这经常缘于项目的时间压力。
这种重复相对容易检测出来。
不过需要你愿意为避免以后的痛苦而现在花费一些时间。
开发者之间的重复
——同一团队(或不同团队)的几个人重复了同样的信息。
这个较难检测和处理。
在团队的高层,领导应通过清晰的设计和强有力的技术对则责任进行理解和划分。
但在更下层,问题被隐蔽,有时难以有明确的责任划分。
此时最佳方式就是鼓励多交流。
8《正交性》
“正交性”是几何学术语。如果两条直线相交成直角,他们就是正交的。
它的特点是:两条轴上的值他们之间不互相依赖:你改变X值的时候,Y值不受影响。
在软件中,该术语表示两个或多个事物之间不相依赖或者说解耦性。
例如:
- 数据库代码和用户界面是正交的:你可以改动界面逻辑而不影响数据库逻辑;也可以改动数据库逻辑而不影响界面。
换言之——
消除无关事物之间的影响
正交性与DRY紧密相关。拥有多种好处,例如:
- 提高生产率
- 降低风险
- 项目团队更好的职责划分
- 更有利于测试
编写代码时有若干技术维护正交性,例如:
- 设计独立、良好定义的组件
- 让你的代码保持解耦
- 避免使用全局数据
- 避免编写相似的函数
9《可撤销性》
出于多种原因,一个决定很可能会在未来被改变。
为了让此造成的损失最小,需要让自己的劳动具备“可撤销性”。
换言之,就是更具有灵活性
- 小到底层代码具有灵活性
- 大到整体架构具有灵活性
10《曳光弹》
在黑暗中用机枪射击时,怎样知道正确的射击角度?
有两种选择:
- 掌握所有的情况,例如:子弹射击速度,重力,气压,风向等等等,最终精确计算出正确的射击角度。
- 使用曳光弹!它具有和常规子弹相同的弹道,而且会发光。这样,你可以及时根据曳光弹的弹道来调整,最终得到正确的射击角度。
软件开发也是一样,当接触一个新项目时:
有两种选择:
- 你可以准确地划分模块,然后每个模块在真空中测试。等到所有模块都制作完毕,再将他们合并在一块看效果。
- 你也可以像“曳光弹”一样:先构建一个能直达核心功能的代码,明确轨迹。然后再一步步往上面添加需要的功能。
使用曳光弹有很多好处:
- 用户能够及早看到工作的东西
- 开发者构建了一个他们能在其中工作的结构
- 你有了一个集成的平台
- 你有了可用于演示的东西
- 你将更能感受到工作进展
不过,曳光弹并非总能击中目标。
如果失败了,你可以进行调整,而花费的代价会相对较少。
“曳光弹”与“原型制作”有区别:
- 原型用后即扔,但是曳光弹会成为骨架的一部分。
- 原型是在曳光弹之前的情报搜集工作。
11《原型与便笺》
许多不同的行业都使用原型实验来验证具体的想法,例如:
- 制作粘土模型用于风洞测试。
软件工程也是一样,使用原型是为了分析和揭示风险,降低修正的代价。
原型应该研究什么样的问题?
- 有风险的
- 没有试过的
- 关键性的
- 未被证明的
- 实验性的
- 有疑问的
具体来说:
- 架构
- 已有系统的新功能
- 外部数据的结构或内容
- 第三方工具或组件
- 性能问题
- 用户界面设计
构建原型时忽略哪些细节?
- 正确性
- 完整性
- 健壮性
- 风格
架构原型要考虑的问题:
- 责任是否得到了良好的定义
- 协作是否得到了良好的定义
- 耦合是否得以最小化
- 你能否确定潜在的重复
- 接口定义和各项约束是否可以接受
- 模块是否能在需要时访问到数据
如果发现自己处于不能放弃细节的环境中,就要问自己,是否真的在构建原型,是不是应该构建“曳光弹”?
12《领域语言》
虽然,计算机语言应该是抽象的。
但是,计算机语言会影响你思考具体问题的方式。
每种语言都有自己的特性,例如:静态或动态,单继承或多继承。
这样的特性将会为你提示或者隐藏特定的解决方案。
相反,领域专门的语言,将提示出方案。
实现这样的小语言的方式:
- 写解析器
- 扩展已有的语言,比如Python。
这样的语言有两种方式使用:
- 数据语言。(通常表示配置)
- 命令语言。(表示流程)
按照与主应用的关系,可以分为:
- 独立的
- 嵌入主应用的
另外,实现这样的小语言也是有成本的,你需要进行权衡:
- 容易开发的语言,可能不容易理解和使用。
- 难开发的语言,可能使用起来容易。
13《估算》
通过学习估算,你可以对事物的数量级有直觉,快速确定一个方案的可行性。
在某种程度上,所有的解答都是估算,因此关键是:解答的语境是什么?
另一件有趣的事情是,使用的单位会对结果的解读造成影响。
估算的流程:
- 理解提问内容
- 建立系统的模型
- 把模型分解为组件
- 给每个参数指定值
- 计算答案
最后,追踪自己的估算能力。