《程序员修炼之道–从小工到专家》读书笔记

第一章 注重实效的哲学

1 我的源码让猫给吃了

  • 在所有的弱点中,最大的弱点就是害怕暴露弱点;
  • 同意为某个结果负责,就应切实负起责任;
  • 不要抱怨,总是把问题归咎于别人;
  • 辩解听起来很愚蠢,说话之前先将借口清除,谈话之前自己先预演一遍;
  • 提供选择,而不是找借口,不要说做不到,而是能够做什么挽回局面;

2 软件的熵

  • 破窗口理论;
  • 不要容忍任何一个破窗户(设计、决策、代码);
  • 不要成为第一个弄脏东西的人(灭火故事);

3 石头汤与煮青蛙

  • 做变化的催化剂,遇到冷漠和漠然,先做出样例,设计出合理的东西,参与正在发生的成功更容易;
  • 破窗户(容忍,因为觉察没人在意)/ 煮青蛙(没有注意到变化);
  • 留心大图景,也要持续观察周围发生的事情;

4 足够好的软件

  • 做足够好的软件;
  • 让质量也成为需求,持续集成,及早让客户反馈;
  • 不要过度修饰和过于求精而毁损完好的程序;

5 你的知识资产

  • 知识和经验是有时效的资产;
  • 经营你的资产:
    • 定期投资;
    • 多元化;
    • 管理风险; 高风险高回报,低风险,低回报;
    • 低买高卖;
    • 重新评估和平衡;
  • 目标:
    • 每年至少一门新语言;
    • 没季度至少一本技术书;
    • 也要阅读非技术书籍;
    • 上课;
    • 参加本地用户组织;
    • 试验不同的环境;
    • 上网;
    • 持续投入;
  • 批判的分析你看到的和读到的;
  • 和别人请教的礼仪:
    • 明确具体的问题;
    • 组织问题的语言;
    • 自己找找答案;
    • 公开和私下询问;
    • 耐心等候;

6 交流

  • 规划你想要说的东西,写出大纲;
  • 了解你的听众的需要、兴趣、能力;对不同的人适当的修改让他们感兴趣;
  • 选择合适的时机;“现在我们可以谈谈吗?“
  • 调整你的交流风格;
  • 让文档更加美观,不要只关心内容;
  • 让听众参与进来,获取反馈;
  • 停他们说话,做一个聆听者;
  • 第一时间回复:”我稍后回复“;

第二章 注重实效的途径

7 重复的危害

  • 系统中的每一项知识都必须是单一、无歧义、权威的表示;
  • DRY- Dont repeat yourself 不要重复你自己;
  • 重复如何发生
    • 强加的重复
      • 信息的多种表示
      • 代码中的文档; 把注释保留给其他的高级说明
      • 文档与代码
      • 语言问题;
    • 无意的重复
      • 设计问题; 使影响局部化;
    • 无耐性的重复
      • 走捷径;欲速则不达
    • 开发者之间的重复
      • 交流,促进知识的沟通;

8 正交性

  • 正交性:表示某种不相依赖性或是解耦性;
  • 消除无关事物之间的影响,让组件独立、具有单一、良好定义的目的称为内聚;

正交的好处

  • 提高生产率
    • 改动能局部化;
    • 促进复用;
    • 重叠减少,生产率提高
  • 降低风险
    • 降低开发中的固有风险
    • 问题代码被隔离
    • 系统更健壮;
    • 更好的测试;
  • 项目团队
    • 团队的组织有许多重叠,各个成员对责任感到困惑,效率差;
  • 设计
    • 系统多个模块,分层架构
  • 工具箱与库
    • 引入第三方要注意保持系统正交性明智选择技术
    • 面向切面编程 AOP
  • 编码
    • 每次编码都有降低系统正交性的危险;
    • 让你的代码保持解耦
    • 避免使用全局数据
    • 避免写相似的函数
    • 养成不断批判对待自己代码的习惯;
  • 测试
    • 正交的设计和实现,易于测试;
  • 文档
    • 正交性利于文档的编写

9 可撤销性

  • 不必作出许多关键的、不可逆转的决策;
  • 不存在最终决策;
  • 保持架构的灵活性,预先考虑问题,抽象服务等,只需要改配置文件;
  • 薛定谔的猫
    • 猫,粒子50%机会分裂猫会死,猫是死是活?
    • 答案都是; 每当有两种可能结果的亚核反应发生时,宇宙就会克隆,一个发生一个不发生,只有你打开盒子才知道,你在哪一个宇宙中;
    • 每一项代码决策都导致不同版本的未来;

10 曳光弹

  • 黑暗中机枪射击?1 找出目标确切的位置 2 曳光弹与常规弹交接射击,不断获得反馈;
  • 在黑暗中发光的代码;总有改动需要完成,总有功能需要增加,渐进的过程;
  • 优点
    • 用户能及早看到能工作的东西
    • 开发者构建了一个他们能在其中工作的结构;
    • 有了一个集成平台;
    • 有了可演示的东西
    • 能感觉到工作的进展;
  • 原型制作:探究系统的某项具体的方面,对概念实验后,东西扔掉,根据学到的经验教训重新编码;
    • 你设计一个用户界面,用户满意后,把它扔掉,重新用目标语言编码;
  • 原型制作生成用过就扔的东西,曳光代码虽然简约,却是完整的,并且构成了最终系统骨架的一部分。

11 原型与便笺

  • 为了学习而制作原型
  • 怎样使用原型
    • 正确性:适当使用虚假数据
    • 完整性:出错入参
    • 健壮性:可能不完整
    • 风格:
  • 制作架构原型
    • 主要组件的责任是否得到良好的定义
    • 主要组件的协作是否定义
    • 耦合是否最小化
    • 能否确定重复的潜在来源
    • 接口定义和各项约束是否可接受
  • 怎样不适用原型
    • 确定是用过就扔,不会不熟的,不完整;
    • 坚持部署原型,适用曳光弹;

12 领域语言

  • 靠近问题领域编程
    • 实现小型语言
    • 数据语言与命令语言
    • 独立语言
    • 易于开发还是易于维护?可扩展性与维护权衡

13 估算

  • 估算,以避免意外发生;
  • 多准确才足够准确; 某种程度上,所有的解答都是估算,只不过有一些更准确;
  • 使用估算的单位不同会对结果的解读产生影响;
    • 130个工作日,相当接近的时间完成
    • 6个月,5-7个月完成;
    • 130更高的精确程度;
  • 估算来自哪里;以问题的模型为基础;
    • 理解提问的内容
    • 建立系统的模型;建立粗略、就绪的思维模型
    • 把模型分解为组件;每个组件都有一些参数
    • 给每个参数指定值
    • 计算答案
    • 追踪你的估算能力
  • 估算项目的进度
    • 检查需求
    • 分析风险
    • 设计、实现、集成
    • 向用户确认
  • 在被要求估算时说什么
    • 我等会儿回答你,今天晚上给你答复;

第三章 基本工具

工具能放大你的才干,称为你手的延伸;

14 纯文本的威力

  • 持久存储知识的最佳格式是纯文本;
  • 用纯文本保存知识;
  • 缺点:存储空间多,计算代价高;
  • 优点:
    • 保证不过时;活的久,可阅读;
    • 杠杆作用:各种格式都可纯文本保存;
    • 易于测试;

15 shell游戏

  • 工作台就是命令shell; iterm2
  • GUI好处所见即所得,所见即全部所得;
  • 学习shell,利用命令shell的理论;

16 强力编辑

  • 学习一种编辑器,将用于所有编辑任务:代码,文档,备忘录,系统管理等;
  • 优点:可配置;可扩展;可编程; 语法突显;自动完成;自动缩进;类IDE特性等;
  • 选一个强大的编辑器,sublime,好好学习,设法扩展,提高生产率;

17 源码控制

  • 源码控制系统追踪你在源码和文档中做出的每一项改动;
  • gitlab,github等;

18 调试

  • 调试就是解决问题,要修正问题,不要发出任何指责;
  • 不要恐慌;
  • 要设法找出问题的根源,不要只是问题的特定表现;
  • 从何处开始:搜集比最初给你的数据更多,要强硬测试边界条件;
  • 让数据可视化,看看操作的数据;
  • 橡皮鸭:找出问题有用的方式,向别人解释它,解释时明确陈述你在检查代码的事情,可能突然获得对问题的新洞见;
  • 消除过程:无论bug处于什么阶段,归于谁,都要先消除你的代码中的bug;
  • 当你抱怨时,不如沉下心仔细阅读技术文档,或者从它的周围找找线索;
  • 变更永远是触发问题的导火索,无论直接还是间接;
  • 你感到吃惊的程度与你正在运行的代码中的信任和信心成正比,充分测试就不会慌;
  • 不要假定,要证明;

19 文本操纵

  • 文本操纵工具,脚本语言,perl;

20 代码生成器

  • 编写能编写的代码,主动、被动代码生成器只运行一次生成结果、每次需要结果时被使用;

第四章 注重实效的偏执

  • 你不可能写出完美的软件;
  • 防卫性编程,对自己错误也进行防御式编程;
  • 断言式编程,主动检验自己的假定代码;

21 按合约设计

  • 合约规定你的权利与责任,也规定对方的权利与责任;
  • DBC: 文档记载生命,并进行校验,是按合约设计(DBC)核心所在;
  • 前条件:调用例程前,必须为真的条件;
  • 后条件:例程保证会做的事情,例程完成时世界的状态;
  • 类不变项:类确保从调用者的视角,该条件总为真;
  • 允诺返回东西要尽可能少;
  • DBC最大好处迫使需求与保证的问题走到前台,列举输入域的范围是什么,边界条件是什么,允诺交付什么;
  • 能够用断言做DBC的一切:断言不能沿着继承层向下遗传;代码增加;库不支持,不会被检查;
  • 预处理器:会把这些注释展开成检验断言的代码;
  • DBC与早崩溃:谁负责检查前条件,调用者;通过早崩溃,在问题现场找到和诊断问题要容易的多;
  • 不变项的用法
    • 循环不变项:循环的最终目标陈述;
    • 语义不变项:表达不可违反的需求;出错时要偏向消费者;

22 死程序不说谎

  • 它不可能发生,是一种心理状态;
  • 要崩溃,不要破坏:异常机制,确保对异常做出处理;

23 断言式编程

  • 在自责中有一种满足感,当我们责备自己时,会觉得再没人有权责备我们;
  • 这绝不会发生,如果它不可能发生,用断言确保它不会发生;
  • 无论何时,你觉得那当然不可能发生,增加代码检查它,最容易的办法是用断言;
  • 不要用断言代替真正的错误处理,断言检查是绝不应该发生的事;
  • 让断言打开:断言增加开销,因为检查是不应该发生的事;
    • 假定测试能找到所有的bug,防线检查任何可能的错误;
    • 程序运行在危险的世界中,防线使用断言设法检测你疏漏的错误;
  • 断言与副作用:不要因为增加断言,制造了新的错误;

24 何时使用异常

  • 异常应该保留给意外事件;
  • 将异常用于异常的问题,异常表示的即时的,非局部的控制转移;
  • 错误处理器:exceptionHandler;

25 怎样配平资源

  • 要有始有终,资源分配和解除分配的处理;
  • 嵌套的分配:以资源分配的相反次序解除资源分配;代码不同地方分配同一资源,相同的次序分配它们,降低死锁发生的概率;
  • 对象与异常:异常的地方解除资源棘手;构造器与析构器,finanlly;
  • 当你无法配平资源时:为内存设一语义不变项,垃圾回收,引用计数;
  • 检查配平;

第五章 弯曲,或折断

26 解耦与德墨忒尔法则

  • 前文正交性和合约设计的羞怯工作方式,不向别人暴露你自己,不与太多人打交道;
  • 德墨忒尔法则,最小知识原则,把代码组织成最小单位/模块,并限制他们之间的交互;
  • 使耦合程度最少;对象间的直接关系导致依赖关系的组合爆炸,修改影响很多模块,害怕修改;
  • 德墨忒尔试图使程序中的模块耦合程度减至最低,设法阻止你为了获得第三个对象的方法访问而进入某个对象;

27 元程序设计

  • 细节会弄乱我们整洁的代码,把细节赶出代码;
  • 动态配置:让系统高度可配置,不要集成,用元数据描述应用的配置选项:参数,偏好,安装目录等;
  • 元数据,是关于数据的数据;
  • 将抽象放进代码,将细节放进元数据
    • 迫使你解除你的设计的耦合;
    • 迫使你通过推迟细节处理,创建更健壮、抽象的设计
    • 无需重新编译应用,可以对齐进行定制;
    • 与通用编程语言比,可以用更接近问题领域的方式表式元数据;
  • 不要变写渡渡鸟代码:
    • 没有元数据,代码及不能有它的适应性与灵活性;

28 时间耦合

  • 时间是软件架构设计经常忽略的因素:并发和次序;
  • 日常编写程序,经常事情是线性的;
  • 通过容许并发,解除任何时间或次序上的依赖;
  • 分析工作流、活动图、UML图,改善并发性;
  • 用服务进行设计,降低组件的耦合;
  • 用并发进行设计:必须对全局或静态变量加以保护,免于并发访问;不管次序如何,确保给出的是一致的状态信息;引导设计更整洁的接口;

29 它只是视图

  • 事件使得系统耦合减至最少;
  • 发布/订阅;推模式/拉模式;
  • 视图与模型分离:
    • 模型:表示目标对象的抽象数据模型;
    • 视图:解释模型的方式;
    • 控制器:控制视图,并向模型提供新数据的途径;

30 黑板

  • 黑板方法:没有侦探需要知道其他任何侦探的存储;侦探可能受过不同训练,具有不同程度的背景;
  • 很多项目设计工作流或分布式数据采集过程;
  • 黑板系统让我们完全解除我们的对象之间的耦合,提供一个”论坛“,知识消费者和生成者可以在哪里匿名,异步交换数据;
  • 一种键值对模型为基础实现;
  • 与黑板有单一、一致的接口;消除了太多接口的需要,带来更优雅、一致的方案;
  • 例子:黑板,结合封装法律需求的规则引擎;

第六章 当你编码时

31 靠巧合编程

  • 避免靠巧合编程-依靠运气和偶然的成功-要深思熟虑的编程;
  • 如何靠巧合-一开始就不知道它为什么能工作;
  • 实现的偶然-现在的代码编码方式导致,要开没有计入文档的错误或者边界条件;良好的模块化及把实现隐藏在撰写了良好文档的小接口之后;
    • 不是真的能工作;
    • 边界条件;
    • 未记入文档;
    • 多余调用,慢,引发bug;
  • 语境的偶然
  • 如何深思熟虑的编程?
    • 总是意识到你在做什么;
    • 不要盲目编程,构建不完全理解的应用或不熟悉的技术;
    • 按照计划行事;
    • 依靠可靠的事物,不要依靠巧合或假定;
    • 为你的假定建立文档;
    • 不要只是测试你的代码,还要测试你的假定;
    • 为你的工作划分优先级,时间花在重要的的方面;
    • 不要做历史的奴隶,实在不行就重构;

32 算法速率

  • 估算算法使用的资源-时间、处理器、内存等;
  • O()表示法
  • O(1)常量型,O(lgn)对数,O(n)线性,O(nlgn)比线性差,O(n2)平方,O(Cn)指数;
  • 100条1秒,1000条?O(1) 1秒, O(lgn)3秒,O(n) 10秒 O(nlgn) 33秒,O(n^2 100秒, O(2n)10263年
  • 简单循环 n,嵌套循环 m*n,二分法 lgn,分而治之nlgn,组合
  • 估算你算法的阶;
  • 最好并非是总是最好的,合适的,注重实效;

33 重构

  • 周遭所见皆是变易与衰败
  • 重写、重做、重新架构合起来为重构;
  • 何时重构? 代码不合适,重复、非正交的设计、过时的知识、性能;
  • 现实世界的复杂情况: 时间压力的借口,肿瘤,早重构,常重构;
  • 重构就是重新设计:
  • 不要试图在重构的时候增加功能;
  • 在开始重构之前,确保有良好的测试;
  • 采取短小、深思熟虑的步骤,小布重构;

34 易于测试的代码

  • 单元测试,对模块进行演练的代码;
  • 针对合约进行测试;
  • 为测试而设计
  • 单元测试:说明你的模块的所有功能,文档; 构建回归测试,验证未来对代码的改动是否正确;
  • 使用测试装备:Junit
  • 构建测试窗口
  • 测试文化: 大大降低维护费用,减少客户服务电话;
  • 测试你的软件,否则你的用户就得测试;

35 邪恶的向导

  • 不要使用你不理解的向导代码;
  • 开发者每天都依赖他们完全不理解的事物? 如果开发知识依赖的库调用或标准的操作系统服务,但是向导代码编程了应用的完整组成部分;

第七章 在项目开始之前

36 需求之坑

  • 完美,不是在没有什么需要增加,而是在没有什么需要去掉时达到的;
  • 不要搜集需求,挖掘他们;
  • 挖掘需求:需求是对需要完成的某家事情的陈述;
  • 只有指定人员才能查看员工档案;-> 只有员工的上级和人事可以查看员工的档案;政策和需求分开;
  • 这样搜集需求让你去开发为支持元数据而进行了良好分解的系统;
  • 找出用户为何要做特定事情的原因,而不只是他们目前做这件事情的方式;
  • 与用户一同工作,以像用户一样的思考;
  • 建立需求文档:用例图,简图
  • 规定过度: 制作需求文档不能太过具体,好的需求文档保持抽象,需求不是架构不是设计,需求是需要; 抽象比细节获得更久;
  • 特性膨胀:只增加一个特性,实际增加若干;
  • 维护项目的词汇表;
  • 需求分析,把话说出来,制作成超文本文档;

37 解开不可能解开的谜题

  • 问题真的有这么难吗?解开的秘诀是确定真正的约束,在其中找出解决办法,有些约束是绝对的,有些则是先入之见;
  • 自由度:确定加给你的各种约束,确定你确实拥有的自由度;
  • 四个点,怎么三条直线连,并返回起点?(外面套个三角形)
  • 不要在盒子外面思考-要找到盒子
  • 有更容易的方法吗?
  • 真正设法解决问题,还是被外围的技术转移了注意力?
  • 这件事情为什么是一个问题?
  • 是什么让它难以解决?
  • 它必须以这种方法解决?
  • 它真的必须完成?
  • 难以解开的结-一刀砍断;

38 等你准备好

  • 倾听反复出现的疑虑 - 等你准备好再开始
  • 是良好的判读,还是拖延

39 规范陷阱

  • 1 规范将捕捉系统或需求的每一处细节结细微差别,幼稚,变更需求淹没;
  • 2 语言自身的表达能力存在这问题;对有些事情做胜于描述
  • 3 紧身衣效应:没有给编码留下任何解释余地的设计剥夺了他们发挥技巧和艺术才能的权利;
  • 注重实效的程序员,倾向于把需求搜集、设计、实现视为一个过程-交付高质量的系统的不同方面;
  • 不是返回生成规范,而是随着规范越来越详细,得到回报越来越低,甚至是负回报;

40 圆圈与箭头

  • 不要做形式方法的奴隶;
  • 缺点:
    • 大多数形式方法结合图和某项文字说明捕捉需求,对最终用户无意义;
    • 形式方法鼓励专门化,树模型,架构,需求搜集人员,设计和编码之间产生隔阂;
    • 动态性,形式方法建立静态关系,实际对象本来动态编织在一起;
  • 形式方法带来好处,不要低估新方法和新工具的好处和代价;
  • 批判看待方法学,并从各种方法学中提取精华,融合成每个月都在变得更好的工作习惯;
  • 昂贵的工具不一定能制作更好的设计;

第八章 注重实效的项目

41 注重实效的团队

  • 不要留破窗户:质量官员-团队保证产品质量的责任委派给个人,荒谬的,质量只可能源于全体团队成员作出自己的贡献;
  • 煮青蛙:确保每个人都主动监视环境的变化;
  • 交流:创立团队的品牌,身份标识,给人难忘与工作相联;
  • 不要重复你自己;团队重复工作的危害;
  • 正交性:围绕功能、而不是工作职务进行组织;
  • 项目:技术主管:设计开发哲学和风格,团队指派责任,关注大图;行政主管:调度团队所需的各种资源,监视并报告进展情况;
  • 自动化:
  • 知道何时停止绘画:给团队成员足够的空间并支持,确保项目的交付符合需求,抵抗不断画下去的风险;

42 无处不在的自动化

  • 一切都要自动化,不要使用手工流程;
  • 项目编译
  • 生成代码
  • 回归测试
  • 构建自动化,自动化管理
  • 文档,网站生成
  • 自动化管理

43 无情的测试

  • 早测试,常测试,自动测试;
  • 编一点,测一点;
  • 好的项目拥有的测试代码比产品代码还要多;
  • 要用过全部测试,编码才算完成;
  • 测试什么?
    • 单元:针对模块演练
    • 集成:子系统工作;
    • 验证和校验:功能性测试,满足需求
    • 资源耗尽、错误及恢复:系统失败时;
    • 性能测试:性能、压力、负载测试;
    • 可用性测试:真正的用户
  • 怎样测试
    • 回归测试:当前测试的输出与先前的对比
    • 测试数据:现实的,构造的,大量的,边界的
    • 演练GUI系统:
    • 对测试而测试:通过盱眙破话测试你的代码;测试要先红再绿;
    • 彻底测试:测试状态覆盖,不是代码覆盖;100%行覆盖
  • 何时测试
    • 大多数测试自动完成;
    • 频繁的测试;
  • 把网收紧:bug过了测试网,增加新的测试,一个bug只抓一次;

44 全都是写

  • 好记性不如烂笔头
  • 把英语当做又一种编程语言;
  • 把代码和文档紧密的结合在一起;
  • 代码中的注释
    • 应该有,太多和太少一样糟糕
    • 注释,为何做某事,它的目的和目标
    • 变量名应该精心挑选,并且有意义
    • 比无意义的更糟的时误导人的,get,里面有写入;
  • 可执行文档
  • 技术文档撰写者,程序员
  • 打印或编排在web上
  • 标记语言:docBook

45 极大的期望

  • 项目的成功是多大程度的满足对用户的期望;
  • 温和的超出用户的期望;
  • 整个开发过程进行这样的交流,管理期望;
  • 额外的一英里:和用户紧密协作,分享他们的期望,和他们交流我们正在做的事情,项目交付不会有太多吃惊的事情;
  • 给他们的的东西比他们期望的多一点;

46 傲慢与偏见

  • 乐于接受挑战,在你的作品上签名;
  • 黄金法则,你要别人怎么对你,你就是怎么样的人;
  • 代码必须所有人,不一定个人,或团队,你的签名是质量的保证;

附录

  1. 关心你的技艺 Care About Your Craft
    如果你不在乎能否漂亮的开发出软件,你又为何要耗费生命去开发软件呢?

  2. 思考!你的工作 Think! About Your Work
    关掉自动驾驶仪,接管操作。不断地批评和评估你的工作。

  3. 提供各种选择,不要找蹩脚的借口 Provide Options, Don’t Make Lame Excuses
    要提供各种选择,而不是找借口。不要说事情做不到;说明能够做什么。

  4. 不要容忍破窗户 Don’t Live with Broken Windows
    当你看到糟糕的设计、错误的决策和糟糕的代码时,修正它们。

  5. 做变化的催化剂 Be a Catalyst for Change
    你不能强迫人们改变。相反,要向他们展示未来可能会怎样,并帮助他们参与对未来的创造。

  6. 记住大图景 Remember the Big Picture
    不要太过专注于细节,以至忘了查看你周围正在发生什么。

  7. 使质量成为需求问题 Make Quality a Requirements lssue
    让你的用户参与确定项目真正的质量需求。

  8. 定期为你的知识资产投资 Invest Regularly in Your Knowledge Portfolio
    让学习成为习惯。

  9. 批判地分析你读到的和听到的 Critically Analyze What You Read and Hear
    不要被供应商、媒体炒作、或教条左右。要依照你自己的看法和你的项目的情况去对信息进行分析。

  10. 你说什么和你怎么说同样重要 It’s both What You Say and the Way You Say it
    如果你不能有效地向他人传达你的了不起的想法,这些想法就毫无用处。

  11. 不要重复你自己 DRY - Don’t Repeat Yourself
    系统中的每一项知识都必须具有单一、无歧义、权威的表示。

  12. 让复用变得容易 Make It Easy to Reuse
    如果复用很容易,人们就会去复用。创造一个支持复用的环境。

  13. 消除无关事物之间的影响 Eliminate Effects Between Unrelated Things
    设计自足、独立、并具有单一、良好定义的目的的组件。

  14. 不存在最终决策 There Are No Final Decisions
    没有决策是浇铸在石头上的。相反,要把每项决策都视为是写在沙滩上的,并为变化做好计划。

  15. 用曳光弹找到目标 Use Tracer Bullets to Find the Target

曳光弹能通过试验各种事物并检查它们离目标有多远来让你追踪目标。

  1. 为了学习而制作原型 Prototype to Learn
    原型制作是一种学习经验。其价值并不在于所产生的代码,而在于所学到的经验教训。

  2. 靠近问题领域编程 Program Close to the Problem domain
    用你的用户的语言进行设计和编码。

  3. 估算,以避免发生意外 Estimate to Avoid Surprises
    在着手之前先进行估算。你将提前发现潜在的问题。

  4. 通过代码对进度表进行迭代 Iterate the Schedule with the Code
    用你在进行实现时获得的经验提炼项目的时间标度。

  5. 用纯文本保存知识 Keep Knowledge in Plain Text
    纯文本不会过时。它能够帮助你有效利用你的工作。并简化掉时和测试。

  6. 利用命令shell的力量 Use the Power of Command Shells
    当图形用户界面无能为力时使用shell。

  7. 用好一种编辑器 Use a Single Editor Well
    编辑器应该是你的手的延伸;确保你的编辑器是可配置、科扩展和可编程的。

  8. 总是使用源码控制 Always Use Source Code Control
    源码控制是你的工作的时间机器–你能够回到过去。

  9. 要修正问题,而不是发出指责 Fix the Problem, Not the Blame
    bug是你的过错还是别人的过错,并不是真的很有关系–它仍然是你的问题,它仍然需要修正。

  10. 调试时不要恐慌 Don’t Panic When Debuging
    做一次深呼吸,思考什么可能是bug的原因。

  11. “Select”没有问题 “Select” Isn’t Broken
    在OS或编译器、甚或是第三方产品或库中很少发现bug。bug很可能在应用中。

  12. 不要假定,要证明 Don’t Assume It - Prove It
    在实际环境中–使用真正的数据和辩解条件–证明你的假定。

  13. 学习一种文本操纵语言 Learn a Text Manipulation Language
    你用每天的很大一部分时间处理文本,为什么不让计算机替你完成部分工作呢?

  14. 编写能编写代码的代码 Write Code That Writes Code
    代码生成器能提高你的生产率,并有助于避免重复。

  15. 你不可能写出完美的软件 You Can’t Write Perfect Software
    软件不可能完美。保护你的代码和用户,使它(他)们免于能够预见的错误。

  16. 通过合约进行设计 Design with Contracts
    使用合约建立文档,并检验代码所做的事情正好是它声明要做的。

  17. 早崩溃 Crash Early
    死程序造成的危害通常比有问题的程序要小得多。

  18. 用断言避免不可能发生的事情 Use Assertions to Prevent the Impossible
    断言验证你的各种假定。在一个不确定的世界里,用断言保护你的代码。

  19. 将异常用于异常的问题 Use Exceptinos for Exceptional Problems
    异常可能会遭受经典的意大利面条式代码的所有可读性和可维护性问题的折磨。将异常保留给异常的事物。

  20. 要有始有终 Finish What You Start
    只要可能,分配某资源的例程或对象也应该负责解除其分配。

  21. 使模块之间的耦合减至最少 Minimize Coupling Between Modules
    通过编写“羞怯的”代码并应用得墨忒耳法则来避免耦合。

  22. 要配置,不要集成 Configure, Don’t Integrate
    要将应用的各种技术选择实现为配置选项,而不是通过集成或工程方法实现。

  23. 将抽象放进代码,细节放进元数据 Put Abstractions in Code, Details in Metadata
    为一般情况编程,将细节放在被编译的代码库之外。

  24. 分析工作流,以改善并发性 Analyze Workflow to Imporve Concurrency
    利用你的用户的工作流中的并发性。

  25. 用服务进行设计 Design Using Services
    根据服务–独立的、在良好定义、一致的接口之后的兵法对象–进行设计。

  26. 总是为并发进行设计 Always Design for Concurrency

容许并发,你将会设计出更整洁、具有更少假定的接口。

  1. 使视图与模型分离 Separate Views from Models

要根据模型和视图设计你的应用,从而以低廉的代码获取灵活性。

  1. 用黑板协调工作流 Use Blackboards to Coordinate Workflow

用黑板协调完全不同的事实和因素,同时又使各参与方保持独立和隔离。

  1. 不要靠巧合编程 Don’t Program by Coincidence

只依靠可靠的事物。注意偶发的复杂性,不要把幸运的巧合与有目的的计划混为一谈。

  1. 估算你的算法的阶 Estimate the Order of Your Algorithms

在你编写代码之前,先大致估算事情需要多长时间。

  1. 测试你的估算 Test Your Estimates

对算法的数学分析并不会告诉你每一件事情。在你的代码的目标环境中测定它的速度。

  1. 早重构,常重构 Refactor Early, Refactor Often

就和你会在华园里除草、并重新布置一样,在需要时对代码进行重写、重做和重新架构。要铲除问题的根源。

  1. 为测试而设计 Design to Test

在你还没有编写代码时就开始思考测试问题。

  1. 测试你的软件,否则你的用户就得测试 Test Your Software, or Your Users Will

无情地测试。不要让你的用户为你查找bug。

  1. 不要使用你不理解的向导代码 Don’t Use Wizard Code You Don’t Understand

想到可以生成大量代码。在你把它们合并进你的项目之前,确保你理解全部这些代码。

  1. 不要搜集需求–挖掘它们 Don’t Gather Requirements - Dig for Them

需求很少存在于表面上。它们深深地埋藏在层层假定、误解和政治手段的下面。

  1. 与用户一同工作,以像用户一样思考 Work with a User to Think Like a User

要了解系统实际上将如何被使用,这是最好的方法。

  1. 抽象比细节活得更长久 Abstractions Live Longer than Details

“投资”于抽象,而不是实现。

  1. 使用项目词汇表 Use a Project Glossary

创建并维护项目中使用的专用术语和词汇的单一信息源。

  1. 不要在盒子外面思考–要找到盒子 Don’t Think Outside the Box - Find the Box

在遇到不可能解决的问题时,要确定真正的约束。问问你自己:“它必须以这种方式完成吗? 它真的必须完成吗?”

  1. 等你准备好再开始 Start When You’re Ready

你的一生都在积累经验。不要忽视反复出现的疑惑。

  1. 对有些事情“做”胜于“描述” Some Things Are Better Done than Described

不要掉进规范的螺旋

  1. 不要做形式方法的奴隶 Don’t Be a Slave to Formal Methods

如果你没有把某项技术放进你的开发时间和能力的语境中,不要盲目地采用它。

  1. 昂贵的工具不一定能制作出更好的设计 Costly Tools Don’t Produce Better Disigns

小心供应商的炒作,行业教条,以及价格标签的诱惑。要根据工具的价值判断它们。

  1. 围绕功能组织团队 Organize Teams Around Fucntionality

不要把设计师与编码员分开,也不要把测试员与数据建模员分开。按照你构建代码的方式构建团队。

  1. 不要使用手工流程 Don’t Use Manual Procedures

shell脚本或批文件会一次次地以同一顺序执行同样的指令。

  1. 早测试,常测试,自动测试。 Test Early. Test Often. Test Automatically

与呆在书架上的测试计划相比,每次构建试运行的测试要有效得多。

  1. 要到通过全部测试,编码才算完成。 Coding Ain’t Done ‘Til All the Tests Run

就是这样。

  1. 通过“蓄意破坏”测试你的测试。 Use Saboteurs to Test Your Testing

在单独的软件副本上故意引入bug,以检验测试能够抓住它们。

  1. 测试状态覆盖,而不是代码覆盖 Test State Coverage, Not Code Coverage

确定并测试重要的程序状态。只是测试代码行是不够的。

  1. 一个bug只抓一次 Find Bugs Once
    一旦测试员找到一个bug,这应该是测试员最后一次找到它。此后自动测试应该对其进行检查。

  2. 英语就是一种编程语言 English is Just a Programming Language
    像你编写代码一样编写文档:遵守DRY原则、使用元数据、MVC、自动生成、等等。

  3. 把文档建在里面,不要栓在外面 Build Documentation In, Don’t Bolt It On
    与代码分离的文档不太可能被修正和更新。

  4. 温和地超出用户的期望 Gently Exceed Your Users’ Expectations
    要理解你的用户的期望,然后给他们的东西要多那么一点。

  5. 在你的作品上签名 Sign Your Work
    过去时代的手艺人为能在他们作品上签名而自豪。你也应该如此。

检查清单

  1. 要学习的语言
    厌倦了C、C++和JAVA?试试CLOS、Dylan、Eiffel、Objectve C、Prolog、Smailltalk或TOM。它们每一种都有不同的能力和不同的“风味”。用其中的一种或多种语言在家里开发一个小项目。

  2. WISDOM离合诗
    What do you want them to learn? 你想让他们学到什么?
    What is their interest in what you’ve got to say? 他们对你讲的什么感兴趣?
    How sophisticated are they? 他们有多富有经验?
    How much detail do they want? 他们想要多少细节?
    Whom do you want to own the information? 你想要让谁拥有这些信息?
    How can you motivate them to listen to you? 你如何促使他们听你说话?

  3. 怎样维持正交性
    设计独立、良好定义的组件。
    使你的代码保持解耦。
    避免使用全局数据。
    重构相似的函数。

  4. 应制作原型的事物
    架构
    已有系统中的新功能
    外部数据的结构或内容
    第三方工具或组件
    性能问题
    用户界面设计

  5. 架构问题
    责任是否得到了良好定义?
    写作是否得到了良好定义?
    耦合是否得以最小化?
    你能否确定潜在的重复?
    接口定义和各项约束是否可接受?
    模块能否在需要时访问所需数据?

  6. 调试检查清单
    正在报告的问题是底层bug的直接结果,还是只是症状?
    bug真的在编译器里?在OS里?或者是在你的代码里?
    如果你向同事详细解释这个问题,你会说什么?
    如果可疑代码通过了单元测试,测试是否足够完整?如果你用该数据运行单元测试,会发生什么?

  • *·造成这个bug的条件是否存在于系统中的其它任何地方?
  1. 函数的得墨忒耳法则
    某个对象的方法应该只调用属于以下情况的方法:
    它自身
    传入的任何参数
    它创建的对象
    组件对象

  2. 怎样深思熟虑地编程
    总是意识到你在做什么。
    不要盲目地编程。
    按照计划行事。
    依靠可靠的事物。
    为你的假定建立文档。
    不要只是测试你的代码,还要测试你的假定。
    维护的工作划分优先级。
    不要做历史的奴隶。

  3. 何时进行重构
    你发现了对DRY原则的违反。
    你发现事物可以更为正交。
    你的知识扩展了。
    需求演变了。
    你需要改善性能。

  4. 劈开戈尔迪斯结
    在解决不可能解决的问题时,问问你自己:
    有更容易的方法吗?
    我是在解决正确的问题吗?
    这件事情为什么是一个问题?
    是什么使它如此难以解决?
    它必须以这种方式完成吗?
    它真的必须完成吗?

  5. 测试的各个方面
    单元测试
    集成测试
    炎症和校验
    资源耗尽、错误及恢复
    性能测试
    可用性测试
    对测试自身进行测试

你可能感兴趣的:(个人总结区[--新--])