1.我的源码让猫给吃了

  • 注重实效的程序员的特征是什么?

    我们觉得是他们处理问题、寻求解决方案时的态度、风格、哲学。
    他们能够越过直接的问题去思考,总是设法把问题放在更大的语境中,总是设法注意更大的图景。
    毕竟,没有这样的更大的语境,你又怎能注重实效?你又怎能做出明智的妥协和有见识的决策?
    他们成功的另一关键是他们对他们所做的每件事情负责。
  • 在所有的弱点中,最大的弱点就是害怕暴露弱点

  • 责任是你主动负担的东西

  • Provide Options, Don’t Make Lame Excuses. 提供各种选择,不要找蹩脚的借口

2.软件的墒

  • Don’t Live with Broken Windows. 不要容忍破窗户
  • Bea Catalyst for Change. 做变化的催化剂
  • Remember the Big Picture. 记住大图景

4.足够好的软件

  • 欲求更好,常把好事变糟。
  • 让你的用户参与权衡。
  • Make Quality a Requirements Issue. 使质量成为需求问题

5.你的知识资产

  • 知识上的投资总能得到最好的回报

    严肃的投资者定期投资 - 作为习惯
    多元化是长期成功的关键
    聪明的投资者在保守的投资和高风险、高回报的投资之间平衡他们的资产
    投资者设法低买高卖,以获取最大回报
    应该周期性地重新评估和平衡资产
  • Invest Regularly in Your Knowledge Portfolio. 定期为你的知识资产投资

    每年至少学习一种新语言
    每季度阅读一本技术书籍
    同时阅读非技术书籍
    上课
    参与本地用户组织
    实验不同的系统环境
    订阅商务杂志和其他期刊
    上网了解新语言或其他技术
  • 持续投入

  • 学习的机会

  • Critically Analyze What You Read and Hear. 批判的思考

6.交流

  • 我相信,被打量比被忽略要好。

  • 知道你想要说什么

  • 了解你的听众

    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? 你如何促使他们听你说话?
  • 选择时机

  • 选择风格

  • 让文档美观

  • 让听众参与

  • 做倾听者

  • 回复他人

  • It’s Both What You Say and the Way You Say It. 你说什么和你怎么说同样重要

  • 电子邮件交流

7.重复的危害

  • DRY - Don’t Repeat Yourself. 不要重复你自己

    要把低级的知识放在代码中,它属于那里;把注释保留给其他的高级说明
    鼓励开发者相互进行主动的交流
  • Make It Easy to Reuse. 让复用变得容易

    如果不容易,大家就不会去复用;而如果不进行复用,他们就会有重复知识的风险

8.正交性

该术语用于表示某种不相依赖性或解耦性。
如果两个或更多事务中的一个发生变化不会影响其他事物,这些事务就是正交的。

  • 当任何系统的各组件互相高度依赖时,就不再有局部修正(local fix)这样的可能

  • Eliminate Effects Between Unrelated Things. 消除无关事物之间的影响

    设计自足的组件:独立、具有单一、良好定义的目的(内聚, cohesion)。
    如果组件是相互隔离的,你就知道你能改变其中之一,而不用担心其余组件。
    只要你不改变组件的外部接口,你就可以放心:你不会造成波及整个系统的问题。
  • 编写正交的系统可以得到两个主要好处:

    • 提高生产率

      改动得以局部化,所以开发时间和测试时间得以降低
      正交的途径还能促进复用
      对正交的组件进行组合,成产率会有相当微妙的提高
    • 降低风险

      有问题的代码区域被隔离开来
      所得系统更健壮
      正交系统很可能得到更好的测试,因为涉及测试和运行测试更容易
      你不会与特定的供应商、产品、或是平台紧绑在一起,因为外部接口被隔离在独立的模块中
  • 应用正交原则的几种方式

    • 项目团队

      如果团队的组织有许多重叠,各个成员就会对责任感到困惑。每一次改动都需要整个团队开一次会,
      因为他们中的任何一个人都可能受到影响。
    • 设计

      系统应该由一组相互协作的模块组成,每个模块都实现不依赖于其他模块的功能。
      有时这些组件被组织为多个层次,每层提供一级抽象。
      这种分层的途径是涉及正交系统的强大方式。因为每层都只使用其下面的层次提供的抽象。
      如果我显著的改变某个特定功能背后的需求,会有多少模块受影响?在正交系统中,答案应该是一个。
      要问问自己,你的设计在多大程度上解除了与现实世界中的变化的耦合?不要依赖你无法控制的事物属性。
    • 工具箱与库

      在引入工具箱或库时,他是否会迫使你对代码进行不必要的改动?
      如果对象持久模型(object persistence scheme)是透明的,那么它就是正交的。
      正交性的一个有趣的变体是面向切片编程(Aspect-Oriented Programming, AOP)。使用AOP的Java版本,你可以通过编写aspect、在进入类的任何方法时写日志消息。
    • 编码

      每次你编写代码,都有降低应用正交性的风险。
      让你的代码保持解耦、高内聚、只暴露必要的接口。
      避免使用全局数据。一般而言,如果你把所需的任何语境(context)显式的传入模块,你的代码就会更易于理解和维护。
      避免编写相似的函数。可以借鉴策略模式。
      养成不断地批判对待自己的代码的习惯。寻找任何重新进行组织、以改善其结构和正交性的机会,这个过程叫做重构(refactoring)。
    • 测试

      正交地设计和实现的系统也更易于测试,因为系统的割组件间的交互是形式化的和有限的。
      我们建议让每个模块都拥有自己的、内建在代码中的单元测试,并让这些测试作为常规构建过程的一部分自动运行。(`cargo test in Rust`)
    • 认同正交性

      正交性和DRY原则紧密相关,DRY原则寻求使系统中的重复将至最小,正交性原则可降低系统的各组件的相互依赖。

9.可撤销性

  • 如果某个想法是你唯一的想法,再没有什么比这更危险的事情了。

  • There Are No Final Decisions. 不存在最终决策

  • 灵活的架构

    有许多人会设法保持代码的灵活性,而你还需要考虑维持架构、部署及供应商集成等领域的灵活性。

10.曳光弹

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

    用户能够及早看到能工作的东西。
    开发者构建了一个他们能在其中工作的结构。
    你拥有了一个集成平台。
    你有了可用于演示的东西。
    你将更能够感觉到工作进展。
  • 曳光弹并非总能击中目标

11.原型与便笺

  • Prototype to Learn. 为了学习而制作原型

    主要组件的责任是否得到了良好定义?是否适当?
    主要组件间的协作是否得到了良好定义?
    耦合是否得以最小化?
    你能否确定重复的潜在来源?
    接口定义和各项约束是否可接受?
    每个模块在执行过程中是否能访问到其所需的数据?是否能在需要时进行访问?

12.领域语言

  • 语言的界限就是一个人的世界的界限
  • 计算机语言会影响你思考问题的方式,以及你看待交流的方式,语言的特性都在提示或遮蔽特定的解决方案
  • Program Close to the Problem domain. 靠近问题领域编程
  • 易于开发还是易于维护

13.估算

  • Estimate to Avoid Surprises. 估算,以避免发生意外。

  • 多准确才足够准确

    你解答问题的语境是什么?
    他们是需要高度的准确性还是模糊的准确性?
    你使用的单位粒度会对结果的解读造成影响,要选择能反映你想要传达的精确度的单位。
  • 估算来自哪里

    所有的估算都以问题的模型为基础
    借鉴已做过的人的经验
  • 理解提问内容

    把握问题域的范围
  • 建立系统的模型

    对于一个项目,模型可以是你的组织在开发过程中所用的步骤、以及系统的实现方式的非常粗略的图景
    建模既可以是创造性的,又可以是长期有用的
    建模把不精确性引入了估算过程中
  • 把模型分解为组件

    一旦拥有了模型,你就可以把它分解为组件。
    你必须要找出描述这些组件怎样交互的数学规则。
    在典型情况下,每个组件都有一些参数,组件对模型造成的影响取决于它的参数。
  • 给每个参数指定值

    给参数赋值可能会引入一些错误,关键在于找出哪些参数对结果的影响最大。
    让线路速度加倍可以让1小时内接收的数据量加倍,而增加5毫秒的传输延迟不会有显著的效果。
    你应该采用一种合理的方式计算这些关键参数。
  • 计算答案

  • 追踪你的估算能力

    根据实际情况改进估算结果,使下一次估算更好。
  • 估算项目进度

    增量开发,改进上一个迭代的经验
    - 检查需求
    - 分析风险
    - 设计、实现、集成
    - 向用户确认
  • Iterate the Schedule with the Code. 通过代码对进度进行迭代

    使进度可视化,给予管理部门最精确的进度估算

14.纯文本的威力

  • 工具放大你的才干

  • 让需要驱动你的采购

  • 纯文本的威力

    作为注重实效的程序员,我们的基本材料不是木头不是铁,而是知识。
    我们搜集知识,将其变为知识,随后又在我们的设计、实现、测试、以及文档中表达这些知识。
    纯文本并非意味着文本是无结构的。
  • Keep Knowledge in Plain Text. 用纯文本保存知识

    人能够阅读的数据形式,以及自描述的数据,将比所有其他的数据形式和创建它们的应用都获得更久。
  • Unix哲学

    提供“锋利”的小工具、其中每一样都意在把一件事情做好

15.shell游戏

  • GUI的好处是 what you see is what you get, 缺点是 what you see is all you get.
  • Use the Power of Command Shells. 利用命令shell的力量。

16.强力编辑

  • Use a Single Editor Well. 用好一种编辑器

17.源码控制

  • 进步远非由变化组成,而是取决于好记性。不能记住过去的人,被判重复过去。
  • Always Use Souce Code Control. 总是使用源码控制。
  • 源码控制与构建
  • 源码控制产品

18.调试

这是痛苦的事:
看着你自己的烦忧,并且知道
不是别人、而是你自己一人所致

  • 没有人能写出完美的软件,所以调试肯定要占用你大量时间。
  • 调试就是解决问题,要据此发起进攻。
  • Fix the Problem, Not the Blame. 要修正问题,而不是发出指责。
  • 最容易欺骗的一个人是自己。
  • 调试的第一准则:Don’t Panic 不要恐慌。
  • “Select” Isn’t Broken. “Select”没有问题。
  • Don’t Assume it - Prove It. 不要假定,要证明。

19.文本操纵

  • Learn a Text Manipulation Language. 学习一种文本操纵语言。

  • 应用示例

    数据库schema维护
    测试数据生成
    自动生成书籍中的代码测试
    生成Web文档

20.代码生成器

Write Code That Writes Code. 编写能编写代码的代码。

  • 被动代码生成器:只运行一次来生成结果
  • 主动代码生成器:在每次需要其结果时被使用,比如schema表和对应访问它的数据结构

21.按合约设计

You Can’t Write Perfect Software. 你不可能写出完美的软件
当每个人都确实要对你不利时,偏执就是一个好主意。

  • 按合约设计

    没有什么比常识和坦率更让人感到惊讶
  • Design with Contracts. 通过合约进行设计

    对在开始之前接受的东西要严格,而允诺返回的东西要尽可能少
    继承和多态是面向对象语言的基石,是合约可以真正闪耀的领域

使用DBC的最大好处也许是它迫使需求与保证的问题走到前台来。
在设计时简单地列举输入域的范围是什么、边界条件是什么、例程允诺交付什么——是向着更好的软件的一次飞跃。
不对这些事项作出陈述,你就回到了靠巧合编程,那是许多项目开始、结束、失败的地方。
如果语言不在代码中支持DBC,你也可以把合约作为注释放到代码中,至少在遇到麻烦时,用注释表示的合约给了你一个着手的地方。

22.死程序不说谎

我们很容易掉进”它不可能发生“这样一种心理状态,但如果有一个错误,就说明非常糟糕的事情已经发生了。

  • Crash Early. 早奔溃
  • 要奔溃,不要破坏
  • 死程序带来的危害通常比有疾患的程序要小得多

23.断言式编程

在自责中有一种满足感。当我们责备自己时,会觉得再没有人有权责备我们。
人最容易欺骗的人是自己。

  • If It Can’t Happen, Use Assertions to Ensure That It Won’t.

如果它不可能发生,用断言确保它不会发生。

  • 让断言开着

即使你确实有性能问题,也只关闭哪些真的有很大影响的断言。

  • 断言与副作用

”海森堡虫子“——调试不应改变被调试系统的行为

24.何时使用异常

Use Exceptions for Exceptional Problems. 将异常用于异常的问题。
异常表示即时的、非局部的控制转移

  • 错误处理器是另一种选择

错误处理器是检测到错误时调用的例程。你可以登记一个例程处理特定范畴的错误。
处理器会在其中一种错误发生时被调用。

25.怎样配平资源

”我把你带进这个世界,“我的父亲会说:”我也可以把你赶出去。那没有我影响。我要再造一个你“
只要在编程,我们都要管理资源:内存、事务、线程、文件、定时器——所有数量有限的事物。
大多数时候,资源使用遵循一种可预测的模式:你分配资源、使用它,然后解除其分配。

  • Finish What You Start. 要有始有终。

    分配资源的例程也应该释放它(类的构造器与析构器)。
    以与资源分配的次序相反的次序解除资源的分配。这样如果一个自由含有对另一个资源的引用,你就不会造成资源被遗弃。
    在代码的不同地方分配同一组资源时,总是以相同的次序分配他们。这将降低发生死锁的可能性。
  • 检查配平

    注重实效的程序员谁也不信任,包括我们自己,所以我们觉得,构建代码、对资源确实得到了适当释放进行实际检查,这总是一个好主意。
    对于大多数应用,这通常意味着为每种资源类型编写包装,并使用这些包装追踪所有的分配和解除分配。