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

第一章 注重实效的哲学

注重实效的程序员的特点:

  • 处理问题,寻求解决方案时的态度,风格,哲学.
  • 越出直接的问题去思考,设法把问题放在更大的语境中.
  • 对所做的事情负责
  • 接受变化,注重交流
我的源码让猫吃了

对所做的事情负责,如果项目未能按时交付或者出现严重bug,要提供各种选择,不要找蹩脚的借口(比如说我的源码被猫吃了…).

软件的熵

是一个物理概率,指的是一个系统中无序的总量,在软件中,称为软件腐烂

破窗户是导致软件腐烂的原因之一,破窗户指的是那些低劣设计,错误决策或是糟糕的代码.

破窗户应该发现一个修一个,如果没有足够的时间进行适当的修复,就用木板把它钉起来(注释,#warning,或者假数据替换)

破窗户会间接影响其他开发人员的代码质量,导致整体的项目质量下降…

石头汤和煮青蛙

做变化的催化剂,写出高质量的代码,提供好的idea,侧面影响其他人…

大多数软件灾难都是从微不足道的小事情开始的,大多数项目的拖延都是一天一天发生的,系统一个特性一个特性的偏离起规范,一个又一个补丁被打到某段代码上,知道最初的代码一点没有留下.这就像温水煮青蛙.程序员不应该做一只温水里的青蛙.

你的知识产权

知识产权:程序员所知道的关于计算技术和他们所工作的应用领域的全部事实,以及他们的所有经验.

管理知识产权:

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

具体目标:

  • 每年至少学习一种新语言
  • 每季度阅读一本技术书籍
  • 也要阅读非技术
  • 上课
  • 参加线下活动
  • 试验不同的环境
  • 跟上潮流
  • 上网

学会抓住学习的机会

批判的思考:批判的分析你读到的听到的,要有自己的理解,不要人云亦云.

交流

知道你想要说什么,提前理好提纲或者打腹稿

了解你的听众,要知道对方期待听到什么内容

选择时机

选择风格(有点难,一般人都只有一种风格)

让文档美观(ppt大神)

让听众参与

学会做倾听者(但不要做垃圾桶)

回复他人

除非你生活在真空中,你才不需要能交流.交流越有效,你就越有影响力

第二章 注重实效的途径

有些提示和诀窍可应用于软件开发的所有层面,有些想法几乎是公理,有些过程实际上普遍适用.但是,人们几乎没有为这些途径建立这样的文档,你可能会发现,它们作为零散的段落写在关于设计,项目管理或编码的讨论中…

重复的危害

DRY:系统中的每一项知识都必须具有单一,无歧义,权威的表示.

重复是怎样产生的:

  • 强加的重复,开发着觉得无可选择,环境要求.
  • 无意的重复,开发者没有意识到他们在重复.
  • 无耐性的重复,开发者偷懒,copy比较容易.
  • 开发者之间的重复,几个人重复了同样的信息.
正交性

正交性是从几何学中借来的术语,如果两条直线相交成直角,它们就是正交的.沿着某一条直线移动,你投影到另一条直线上的位置不变.

正交性的好处:消除无关事物之间的影响(解耦不必要的依赖)

分层设计是正交系统的强大方式..因为每层都只适用在其下面的层次提供的抽象,在改动底层实现,而又不影响其他代码方面,你拥有极大的灵活性.分层也降低了模块间依赖关系失控的风险.

正交性的简单测试方法:如果我显著的改变某个特定功能背后的需求,有多少模块会受影响?在正交系统中,答案是一个

正交性在编码中的应用:

  • 让你的代码保持解耦
  • 避免使用全局数据
  • 避免编写相似的函数
  • 养成不断批判对待自己代码的习惯.寻找任何重新进行组织,以改善其结构和正交性的机会,这个过程叫做重构,它非常重要.
曳光弹

顾名思义,再开始一个项目之前,眼前是一片黑暗的,看不到未来的样子,这时我们可以发射一枚曳光弹,用在软件开发上就是先写一个大概的demo,有一个前行的方向…

曳光代码的好处:

  • 用户能够及早看到能工作的东西
  • 开发者构建了一个他们能在其中工作的结构
  • 你有了一个集成平台
  • 你有了可用于演示的东西
  • 你将更能够感受到工作进展

第三章 基本工具

纯文本的威力

xml,html,sgml…

用纯文本保存知识的好处:

  • 保证不过时
  • 杠杆作用
  • 更易于测试
shell游戏
文本编辑器

vim,Emacs…

源码控制

svn,git…

调试

调试的心理学:

  • 调试是解决问题,要据此发起进攻
  • 要修正问题,而不是发出指责(bug是你的还是别人的,这不是真的很有关系.)
  • 不要恐慌,如果你看到bug报告的第一反应是那不可能,你就完全错了.一个脑细胞都不要浪费在以“但那时不可能”起头的思路上,因为很明显,那不仅可能,而且已经发生.
  • 小心近视,要抵制只修正你看到的症状的急迫愿望,更有可能的情况是,实际的故障离你正在观察的地方可能还有几步远,并且可能涉及许多其他的相关事物.

调试策略:

  • 你需要与qa面谈,搜集比最初给你的数据更多的数据.
  • qa不可能全覆盖所有的case,你需要系统的进行这样的测试,比如分支语句,你可能需要自己造数据去覆盖所有的分支.
  • 复现bug
  • 是数据可视化(log)
  • 堆栈和断点
  • 橡皮鸭,把你的逻辑对着桌上的橡皮鸭描述一遍,看看有没有漏洞.
  • 消除过程,二分调试
  • 遇到自认为不可能的bug时,不要假定,要证明.
代码生成器

脚手架,代码块,模版工具…

第四章 注重实效的偏执

你不可能写出完美的软件

按合约设计

DBC:通过合约进行设计

死程序不说谎

尽早崩溃…

断言式编程

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

何时使用异常

将异常用于异常的问题…

怎样配平资源

只要在编程,我们都要管理资源:内存,事务,线程,文件,定时器所有数量有限的事物.大多数时候,资源使用遵循一种可预测的模式,你分配资源,使用它,然后释放它.

要有始有终

第五章 弯曲或折断

模块和组件的解耦方案

解耦与得墨忒耳法则

多模块耦合的危害

  • 调用链冗长
  • 对一个模块的简单改动会传遍系统中的一些无关模块
  • 开发者害怕改动代码,因为他们不清楚哪些代码可能受影响

函数的得墨忒耳法则规定,某个对象的任何方法都应该只调用以下情形的方法:

  • 它自身的方法
  • 传入该方法的任何对象的方法
  • 它创建的任何对象的方法
  • 任何直接持有的组件的对象的方法(比如全局对象)
元程序设计

细节会弄乱我们整洁的代码,特别是如果它经常变化.所以我们必须把细节赶出去,让我们的代码容易适应变化.

动态配置:要配置,不要集成.要用元数据描述应用的配置选项:调谐参数,用户偏好,安装目录等…

元数据就是数据的数据.

时间解耦

模块间的时间依赖…我们需要容许并发,并考虑解除任何时间或者次序上的依赖,这样我们才可以获取灵活性,并减少许多开发领域中的任何基于时间的依赖:工作流分析,架构,设计,还有部署.

工作流的改善:使用UML流程图优化工作流.

编写多线程代码,为并发设计.

黑板

将模块细节画到黑板上,用黑板协调工作流.

第六章 当你编码时

编码不是机械地把设计转换为可执行语句,这种态度是许多程序丑恶,低效,结构糟糕,不可维护和完全错误的最大一个原因.

靠巧合编程

深思熟虑的编程,而不是靠运气和偶然的成功.

怎样深思熟虑的编程:

  • 总是意识到你在做什么
  • 不要盲目的编程
  • 按照计划行事
  • 依靠可靠的事物,不要依靠巧合或假定
  • 为你的假定建立文档
  • 不要只是测试你的代码,还要测试你的假定
  • 为你的工作划分优先级
  • 不要做历史的奴隶,不要让已有的代码支配将来的代码,如果不再适用,所有的代码都可以被替换.
算法速率

大O表示法

常识估算:

  • 简单循环 O(n)
  • 嵌套循环 O(nn || nm)
  • 二分法 O(log(n))
  • 分而治之 O(nlog(n))
  • 组合 O(n!)

最快的并非是最好的…

重构

何时重构:

  • 重复,你发现了对DRY原则的违反
  • 非正交的设计
  • 过时的知识
  • 性能问题

早重构,常重构

如何重构:

  • 不要试图在重构的同时增加功能
  • 在开始重构之前,确保你拥有良好的测试.
  • 采取短小,深思熟虑的步骤.
易于测试的代码

针对合约进行测试

编写单元测试

使用测试设备

第七章 在项目开始之前

需求之坑

完美,不是再没有什么需要增加,而是在没有什么需要去掉时到达.

与用户一同工作,以像用户一样思考.

抽象比细节活得更长久

解开不可能解开的谜题

不要在盒子外面思考,要找到盒子.

不能可解决的问题:

  • 有更容易的方法吗
  • 你是在设法解决真正的问题,还是被外围的技术问题转移了注意力
  • 这件事情为什么是一个问题
  • 是什么使它如此难以解决
  • 它必须以这种方式完成吗
  • 它真的必须完成吗
规范陷阱

编写规范是一项重要职责,但每一个细节都被写在规范里的想法是错误的:

  • 规范将捕捉系统或其需求的每一处细节和细微差别这一想法是幼稚的
  • 语言自身的表达能力存在问题
  • 对有些事情,做胜于描述

第八章 注重实效的项目

注重实效的团队
  • 不要留破窗户
  • 不要做温水里的青蛙
  • 交流的重要性
  • DRY
  • 正交性
无处不在的自动化
  • 项目编译
  • 生成代码
  • 回归测试
  • 构建自动化
无情的测试

早测试,常测试,自动测试

要到通过全部测试,编码才算完成

测试什么:

  • 单元测试

    模块测试

  • 集成测试

    子系统能很好的系统工作

  • 验证和校验

    用户回归

  • 资源耗尽,错误及恢复

    1.内存空间
    2.磁盘空间
    3.cpu带宽
    4.挂钟时间
    5.磁盘带宽
    6.网络带宽
    7.调色板
    8.视频分辨率
    9.fps

  • 性能测试

    预期的用户数,连接数或每秒事务数

  • 可用性测试

    qa,灰度…

全都是写

把英语当作又一种编程语言

把文档建在里面,不要栓在外面

傲慢与偏见

在你的作品上签名,你的签名应该被视为质量的保证.