《程序员修炼之道:从小工到专家》4~6章

04 注重实效的偏执

21 按合约设计(简称 DBC)

  1. 客与供应者必须就权利与责任达成共识。
    • 死程序不撒谎
    • 断言程序,沿途校验你的代码

没有什么比常识和坦率更让人感到惊讶。
——爱默生《散文集》

  1. 你以为与计算机打交道难,但是与人打交道更困难。
  2. 接受的东西要严格,允诺返回的东西要尽可能少。

注释与业务流程

实现 DBC

  1. 循环不变项(条件是什么?)
  2. 语义不变项
  3. 动态合约与代理
  4. DBC难用么?

22 死程序不说谎

  1. 尽早检测问题 (RuntimeException)

23 断言编程

在自责中有一种满足感。当完美责备自己时,会决定再也没有人有权责备我们。
-- 奥斯卡*王尔德

这绝对不会发生。。。

  1. 使用代码检查。
  2. 让断言开着。(避免bug产生)
  3. 断言与副作用(影响业务)

24 何时使用异常

  1. 知道何时使用它们。
  2. 取决于实际。(什么异常)
  3. 错误处理器(怎么处理)

25 怎么配平资源

“我把你带进这个世界,”我的父亲会说:
“我也可以把你赶出去。那没有我影响。我要再造另外一个你。”

管理什么?

内存、事务、线程、定时器。

无论是谁分配的资源,它都应该负责接触该资源的分配

  1. 构造器,给予你特定的对象。
  2. 析构器,移除资源

问题

  1. 异常与解除资源的难点。
  2. java语言多了finally。
  3. 当你无法配平衡的时候。(明确选择)
  4. 检查配平

提示

  • 30 你不可写出完美的软
  • 31 通过合约进行设计
  • 32 早崩溃
  • 33 完美不要这样自我欺骗,特别是在编码时。
  • 34 将异常用于异常的问题。
  • 35 要有始有终

05 弯曲,或折断

26 解偶与得墨忒尔法则

好篱笆促成好邻居。

  1. 把你的代码组织成最小的单元模块,并限制它们之间的交互。
  2. 使耦合尽量地减少。
  3. 函数的墨忒尔法则

问题

  • 对某个模块的“简单”改动会传遍系统的一些无关模块。
  • 开发者害怕改动代码,因为它们不清楚哪些代码可能会受影响。

缩小响应集的规模,错误传播少。

27 元程序设计

再多的天才也无法胜过对细节的专注。

  1. 如何适应变化?
  2. 细节为什么会弄乱完美的整洁的代码?

动态配置

什么是元数据?

描述数据的数据。
schema 含有名称、存储长度,属性,字段。

元数据驱动的应用

好处

  • 解除你设计的耦合,从而带更灵活、可适应性更好的程序。
  • 推迟细节处理,创建更健壮、更抽象的设计——完全推迟程序之外。
  • 无需重新编译应用,你就可以对其进行定制。
  • 与通用的编程语言相比,可以通过一种大为接近问题的领域方式表示元数据。
  • 你甚至可以泳道相同的应用引起,但是不同的元数据,不同的目的。「能做得这样就不错了」

商业逻辑

  • 以一种非常灵活的格式维护它们是很有意义的。
  • 规则系统,专家系统。(纯文本的力量?)

例子:EJB

配置元数据,降低代码耦合度。
跨越事务+线程。

不要编写渡渡鸟代码

没有适应性和灵活性,就会死亡。

28 时间耦合

吸引我们的时间知识进度表上的时间,我们现在要谈论的是——
并发和次序。
思考:总是先做A再做B,这样思考带来时间耦合。
==>工作流,架构,设计,部署

工作流

  • 画出UML活动图。(某一时刻会发生什么,以及必须以严格的次序发生。)

架构

组件化。

数据库,例子嘘iaji(生产者与消费者)

  • 数据库操作需要长时间
  • 每个事务,在数据库事务处理的通过同时,我们不能阻塞阻碍通许点
  • 多个事务在每条数据显示能够并发又

为并发进行设计

面对多线程化如此有益。
被调用时,对象必须总是处于有效的状态中,而且它们可能会在最尴尬的时候被调用。

更简洁的接口

StringTokenizer 简洁可维护。

29 它知识视图

那人依然只听到,
他想要听到的东西,
而不顾其他,
啦-啦-啦。

分而治之

  • 划分模块,单一,责任明确。
  • 怎么互相交谈,怎么管理依赖?怎么状态同步?
  • ==>事件(event)

发布/订阅

推送哪些事件呢?需要密切关注么?耦合高?

方法

  • 发布/订阅
  • 总线

超越GUI

mvc 表面,实质可以协调机制。

设计方式——查看器网络,灵活性。

可能还有耦合

30 黑板

字迹在墙上...

特性

  • 看了黑板可以获取新的信息,并且加上他们的发现。
  • 经验不同,负责的内容也不同。
  • 多人协助,时空可以不同
  • 可以放各种信息。

实现

前期,语音识别,基于知识的推理。

如何组织你的黑板?(接口)

  • 有点类似mq(异步,时序)
  • 封装一些规则
  • 独立与隔离

提示

  • 36 使模块之间耦合减至最少
  • 37 要配置不要集成
  • 38 将抽象放进代码,细节放进元数据
  • 39 分析工作流,以改善并发性。
  • 40 用服务进行设计
  • 41 总是为并发进行设计
  • 42 使视图与模型分离
  • 43 用黑被协调工作流

第六章 当你编码时

不要机械地转换设计为可执行语句。
丑陋,抵消,糟糕,不可维护和完全错误。
==> 批判,思考(高效的程序员)

31 靠巧合编程

士兵探测地雷,侥幸就会炸死。
开发者不能靠运气和偶然的成功——而要深思熟虑。

考虑

  • 它也许不是真的能工作
  • 你依靠的边界条件也许只是一个偶然。
  • 没有计入文档的行为,可能会随着库的下一次发布而变化。
  • 多余的和不必要的调用会使你的代码编码。
  • 多余的调用还会增加引入它们自己的新bug

巧合

  1. 实现的偶然
  2. 语境的偶然
  3. 隐含的假定

怎么深思熟虑地编程?

  1. 总是意识到你在做什么?
  2. 不要盲目地编程。
  3. 按照计划行事。
  4. 依靠可靠的事物。
  5. 为你的假定建立文档。
  6. 不要只是测试你的代码,还要测试你的假定。
  7. 为你的工作划分优先等级。
  8. 不要做历史的奴隶,不要让已有的代码支配将来的代码。

32 算法速率

你知道1000条记录运行多久,但如果增加到100000条记录呢?
哪里需要优化?

O()表示法

近似计算,是线性相关还是。。。?
表示使用多少资源。

常识估算

  1. 简单循环
  2. 嵌套循环
  3. 二分法
  4. 分而治之
  5. 组合

最好的并非总是最好的

33 重构

周遭所见,皆是易与衰退。

你应该何时进行重构

  • 遇到绊脚石
  • 遇到合并或“错误”的东西。

Martin Fowler 建议

  1. 不要视图在重构的同时增加功能。
  2. 在开始重构之前,确保你拥有良好的测试。尽可能经常运行这些测试。
  3. 采取短小、深思熟虑的步骤。

软件的熵(破窗原理)

要管理痛苦:如果它现在有损害,但以后的损害会更大,你也许最好一劳永逸地去修正。

34 易于测试的代码

软件组件应该就像集成电路芯片一样进行组合,也要保证组件的可靠性。

单元测试(已知情况,人工环境)

在隔离状态下对每个模块进行测试,目的是检验其行为。

  1. 例子,可以说明你模块的所有功能。
  2. 用以构建回归测试、以验证未来对代码的任何改动是否正确的一种手段。

针对合约进行测试

确保:一、代码是否符合合约。
二、合约的含义是否与我所认为的一样。

流程

先检验子模,再测试模块自身。
仔细思考边界条件。
避免“下游的灾难”

使用测试装备

功能

  • 用以指定设置和清理的标准途径。
  • 用以选择个别或所有可用测试的方法。
  • 分析输出是否预期(或意外)结果的手段
  • 标准化的故障报告形式。

使用JUnit

测试文化(测试是技术,但更是文化)

都要进行测试,无论是团队还是最终用户。

35 邪恶的向导

现代软件越来越难维护了。
使用“向导”自动为你生成骨架代码。(需要理解和学习)

有人认为这是极端的,向导代码逐渐变成了程序员的代码。

提示

  • 44 不要靠巧合编程
  • 45 估算你的算法的阶
  • 46 测试你的估算
  • 47 早重构,常重构。
  • 48 为测试而设计
  • 49 测试你的软件,否则你的用户就得测试
posted on 2017-12-24 10:32  魔术师Carvendy  阅读(167)  评论(0编辑  收藏  举报