第一章 注重实效的哲学

1. 我的源码让猫给吃了

  • 在所有的弱点中,最大的弱点就是害怕暴露弱点
  • 提供各种选择,不要找蹩脚的借口。
  • 如存在供应商不能按时供货的风险,应该预先制定一份应急计划;如果磁盘垮了,带走了源码,而你没有做备份,那是你的错。
  • 注重实效的程序员应该提供解决方案,而非寻找借口。

2. 软件的熵

  • 物理学中,熵指的是某个系统中无序的总量。热力学定律保证了宇宙中的熵倾向于最大化。
  • 当软件中的无序增长时,程序员们称之为软件腐烂。
  • 破窗理论:不要容忍破窗户(低劣的设计、错误决策、或是糟糕的代码),发现一个就修一个,如果没有足够的时间进行适当的修理,就用木板把它钉起来。或许你可以把出问题的代码放入注释,或是显示“未实现”消息,或是用虚设的数据加以替代。总之,采取某种行动防止进一步的损坏,并说明情势处在你的控制之下。

3. 石头汤与煮青蛙

  • 做变化的催化剂。参与正在发生的成功要更容易,让他们瞥见未来,你就能让他们聚集在你周围。
  • 记住大图景,要持续不断地观察周围发生的事情,而不只是你自己在做的事情。

4. 足够好的软件

  • 使质量称为需求问题。你所制作的系统的范围和质量应该作为系统需求的一部分规定下来。
  • 不要因为过度修饰和过于求精二毁损完好的程序。继续前进,让你的代码凭着自己的质量站立一会儿。它也许不完美,但不用担心:它不可能完美。

5. 你的知识资产

  • 把程序员所知道的关于计算技术和他们所工作的应用领域的全部事实、以及他们的所有经验视为他们的知识资产。
  • 经营你的资产,定期为你的知识资产投资:
    • 定期投资:定期为你的知识资产投资
    • 多元化:你掌握的技术越多,你就越能更好地进行调整,赶上计算技术的变化。
    • 管理风险:不要把你所有的技术鸡蛋都放在一个篮子里。
    • 低买高卖:在新兴的技术流行之前学习它可能就和找到被低估的股票一样困难,但所得到的就和那样的股票带来的收益一样。
    • 重新评估和平衡技术
  • 建议:
    • 每年至少学习一种新语言
    • 每季度阅读一本技术书籍
    • 也要阅读非技术书籍
    • 上课
    • 参加本地用户组织
    • 试验不同的环境
    • 跟上潮流:订阅商务杂志和其他期刊
    • 上网查看技术信息
    • 持续投入,学习的过程将扩展思维,使你想着新的可能性和新的做事方式拓展。
    • 设法把你学到的东西应用在你当前的项目中,即使你的项目没有使用该技术,但你或许也能借鉴一些想法,如面向对象。
  • 批判地分析你读到的和听到的,web搜索引擎把某个页面列在最前面,并不意味着那就是最佳选择。

6. 交流

  • 知道你想要说什么:规划你想要说的东西,写出大纲,然后问你自己:“这是否讲清了我要说的所有内容?”提炼它,直到确实如此为止。
  • 了解你的听众:需要了解你的听众的需要、兴趣、能力。
  • 选择时机:弄清楚听众的轻重缓急是什么,要让你所说的适得其时,在内容上切实相关,有时候,只要简单地问一句“现在我们可以谈谈……吗?”就可以了。
  • 选择交流风格,让其适应你的听众:正式的事实简报、书面文档、电子邮件等
  • 让文档美观:让内容以美观的方式传递给你的听众
  • 让听众参与:让你的读者参与文档的早期草稿的制作,获取他们的反馈,并汲取他们的智慧,你讲建立良好的工作关系,并很可能在此过程中制作出更好的文档。
  • 做倾听者:你想要大家听你讲话,你也要听他们说话。
  • 回复他人:及时回复消息,即使内容只是“我稍后回复你”
    • 你说什么和你怎么说同样重要

第二章 注重实效的途径

7. 重复的危害

  • DRY原则:Don’t Repeat Yourself,系统的每一项知识都必须具有单一、无歧义、权威的表示
    • 如果有多处重复,当改变其中一处时,必须改变其他各处,不便于维护
  • 强加的重复
    • 信息的多种表示:编写简单的过滤器或代码生成器,根据公共的元数据表示构建多种语言下的结构。可以根据在线数据库schema、或是最初用于构建schema的元数据,自动生成类定义。
    • 代码中的文档:糟糕的代码才需要许多注释。把低级的知识放在代码中,把注释保留给其他的高级说明,否则就是在重复知识,而每一次改变都意味着既要改变代码也要改变注释,注释将不可避免地变得过时,而不可信任的注释比完全没有注释更糟。
    • 文档和代码:文档和代码都含有同一知识的表示,当ddl逼近时,我们往往会推迟文档的更新。尝试根据文档自动生成测试套件?
    • 语言问题:应该用头文件记在接口问题,用实现文件记载代码的使用者无须了解的实际细节。
  • 无意的重复
    • 线段类有start、end和length属性,但是length重复了,因为长度是由起点和终点决定的,最好让长度成为计算字段,将length属性改变为方法length(),返回start和end点之间的距离。
    • 可以因为性能原因而选择违反DRY原则,如当你需要缓存数据以避免重复昂贵的操作时,其诀窍是使影响局部化。对DRY原则的违反没有暴露给外界。
    • 在可能的情况下,应该总是用访问器(getter、setter)函数来读写对象的属性。
  • 无耐性的重复
    • copy原来的代码?想一想古老的格言:欲速则不达
  • 开发者之间的重复
    • 鼓励开发者相互进行交流,设置论坛,用于讨论常见问题。让某个团队成员担任项目资料管理员以促进知识的交流。在源码树中指定一个中央区域,用于存放实用例程和脚本。
    • 让复用变得容易

8. 正交性

  • 在几何学中,如果两条直线相交成直角,它们就是正交的。用向量术语说,这两条直线互补依赖,沿着某一条直线移动,你投影到另一条直线上的位置不变。
  • 在计算技术中,正交用于表示某种不相依赖性或是解耦性,如果两个或更多事物中的一个发生变化,不会影响其他事物,这些事物就是正交的。
    • 如数据库代码应该与用户界面正交
    • 当任何系统的各组件互相高度依赖时,就不再有局部修正这样的事情。
  • 消除无关事物之间的影响
  • 想要设计自足的组件:独立,具有单一、良好定义的目的(内聚)。
  • 正交的系统的两个主要好处:提高生产率,降低风险
  • 团队也应注重正交性,划分为责任得到良好定义的小组,并使得重叠降至最低。
  • 设计正交组件:问问自己:如果显著地改变某个特定功能背后的需求,有多少模块会受影响?在正交系统中答案应该是一个。
    • 不要依赖你无法控制的事物属性
  • 在引入第三方工具箱和库时,要注意保持系统的正交性。
  • 编码时,应用若干技术用于维持正交性:
    • 让你的代码保持解耦,不要没有必要地向其他模块暴露任何事情,也不依赖其他模块的实现
    • 避免使用全局数据:如果把你所需的任何语境(context上下文)显式地传入模块,你的代码就会更易于理解和维护。
    • 避免编写相似的函数:可以使用策略模式
  • 正交的系统也更易于测试,修正bug也是评估整个系统正交性的好时候
  • 正交性也适用于文档,其坐标轴是内容和表现形式。

9. 可撤销性

  • 不存在最终决策
  • 灵活的架构:定义良好的抽象接口、引入元数据,并且使用某种自动机制(如Aspect)——把必需的语句插入代码自身。

10. 曳光弹

  • 用曳光弹找到目标
  • 做大型项目时,先出一个简陋可运行可展示的版本。不要在黑夜中盲狙,先完成一部分可用功能再集成其他功能
  • 曳光代码 vs 原型制作:原型制作生成用过就扔的代码,而曳光代码虽然简约,却是完整的,并且构成了最终系统的骨架的一部分。可以把原型制作视为在第一发曳光弹发射之前进行的侦查和情报搜集工作。

11. 原型与便笺