《程序员修炼之道》 —— 从小工到专家
《程序员修炼之道》这个书名实际上不如原版《The Pragmatic Programmer: From Journeyman to Master》来得更清晰明了。此书第一版写于1999年,我看的是11年的版本,但还是透流露着不少世纪初的观念和视野。除开一部分观点认识的过时,书中绝大多数观点都四溢着国外互联网行业的工作风格和流程,和国内凶猛生长、一把梭就是干的风格各有不同,甚至我感觉国内IT,尤其是互联网企业里的工作流更加讲求实效。尽管和读之前的预期不大一样,里面许多经验还是很有借鉴意义,比如正交性、不要依赖巧合等等。
书中内容在项目管理、编程哲学、以及编程过程的各个方面都有涉及,在这些方面上更加深入的探讨,书的最后也推荐了继续阅读的材料。下面就各章节的关键观点加以整理。
序
关于本书的读法:
- 能不能让正确原则指导正确的行动本身,其实就是区分是否是高手的一个显著标志
- 要能内化书中提到的各个小提示,不实践的话,是不会有太大收获的
- 思考,你的工作,多思考
实效哲学
- 对你的源码负责
- 不要容忍破窗,它们会增大你软件的熵(这个也是要结合实际情况看的)
- 记住大图景,注意方向是否有误,不要光低头做事
- 知道在何时打住,你不可能做到完美
- 定期为你的知识资产投资,就像经济投资一样
- 定期投资
- 多元化
- 管理风险,不要把所有技术放在一个篮子里
- 低买高卖,能看清形势
- 为此,你需要
- 每年至少学习一种新语言
- 每季度阅读一本技术书籍
- 也要阅读非技术书籍
- 批判地思考你读到和听到的
- 如何表达自己很重要,这会增加你的影响力
- 你想让谁知道
- 你想让他们知道什么
- 他们是否感兴趣
- 他们需要知道细节么
- 如何促使他们与你交流
实效途径
- DRY,不要重复自己
- 强加的重复 => 使用自动生成,减少是信息冗知识
- 无意的重复 => 优良的设计
- 无耐心的重复 => 考虑长远
- 开发者间的重复 => 加强组内交流,制定代码规范,制造更容易复用的环境
- 减少无关事物的影响,非正交 => 次级效应 => 补偿行为 => 经验依赖
- 好处:提高生产率(促进复用)、降低风险(风险隔离,易测试)
- 分层设计、抽象和接口约定
- 避免使用全局变量
- 考虑使用库的代码侵入性
- 文档和认同正交性
- 不存在最终决策,当需求变动频繁的时候,不仅要思考程序架构如何适应这种变动,也要反思是否是设计者没想清楚到底要做什么
- 使用曳光弹找到目标,即MVP + 快速迭代 + 即时的反馈
- 逐步逼近,摸着石头过河
- 曳光弹模式永远包含着一个可用的软件版本
- 原型和便笺,使用原型去表达和快速验证项目的可行性
- 靠近问题领域编程
- 使用DSL(Domain Specified Language)
- 估算,以避免意外,主要用来估计工期、分析风险
- 适当地降低估算速度,慎重思考隐藏的风险
基本工具
工具成为双手和大脑的延伸,优秀的工具可以放大你的才干。
- 纯文本以其自解释能力几乎可以永久保存,XML、JSON就是利用此成为通用的数据表现形式
- 利用shell的力量,它是自动化任务避不开的工具
- 要能烂熟地使用你的编辑器、要使用高级的编辑器,由于你的所有开发工作都建立在它上面,做好这两点可以节省你大量时间
- 反思一下,在用你的编辑器时,你有遇到过到比较繁琐的操作吗?
- 是因为你不会高级使用方式,还是编辑器本身不支持?
- 总是使用源码控制(这一点早已成为共识)
- 调试,debug
- 通常认为匪夷所思的bug,都来自健忘、自大和愚蠢
- QA角色的重要性之一:帮助复现、找到规律性
- 橡皮鸭调试法
- 二分查找法
- 如果bug来自某人的错误假设,那么需要清除团队其他人的相同误解
- 学习一种文本操纵语言或工具,例如awk,sed,处理数据和结果时一定能用上
- 编写代码生成器
- 开发者手动触发,如模板代码
- 程序自动出发,如scheme to idl,idl to code
偏执编程
- 通过合约设计,约定好接口,合作方基于接口开发
- 强类型语言更容易实现这一点
- 早崩溃,这在需要编译的软件开发上比较科学,对于web应用来说却不是这样
- 使用断言确保某事不会发生,减少预设条件代理的隐藏bug
- 不要滥用断言
- 只在异常处用异常
- 一定记住释放请求的资源,如内存、句柄等,可以通过封装统一的资源类实现自动的资源释放
时间的魔力
- 德墨忒尔法则,使模块间的依赖减少到最小
- 物理解耦
- 要配置不要hardcode,使用元数据动态描述你的程序
- 抽象放进代码,细节放进元数据
- 时间耦合:考虑并发和事件的发生顺序
- 在异步代码中,总考虑并发
- 一些GUI的设计模式
- 发布订阅
- MVC
- 基于规则/规则集的黑板系统
- 黑板给出统一接口
- 耦合方通过调用黑板接口避免耦合
- 黑板通过规则给出输出
编码时
- 不要靠巧合编程
- 改动要有文档沉淀
- 只依靠文档中记录的行为
- 把你的假设记入文档
- 在大数据量时,考虑算法数量级
- 兼顾效率和可读性
- 早重构,常重构,代码是业务设计的近似同构体,常重构才能保证代码完美贴合需求设计
- 重构和功能开发分开进行
- 重构一定要有测试
- 优秀的代码不是看新增了多少行,而是看删除了多少行
- 编写易于测试的代码
- 测试你的软件,否则你的用户会代你做测试
项目开始前
完美,不是在没有什么需要增加,而是在没有什么需要去掉的时候达到的。
- 去挖掘需求,思考用户做特定事情的原因,和如何去做的方式,让需求成为一种一般性的陈述
- 制作需求文档时的一大危险是太过具体,好的需求文档会保持抽象
- 经常性复盘
- 鼓励文档分享和交流
- 巧妙解决看似不能解决的难题,关键要找到真正的约束,去思考
- 有更容易的方法么
- 你是在解决真正的问题,还是被外围的技术问题转移了注意力
- 这件事为什么是一个问题
- 是什么让它难以解决
- 它必须这么做么
- 它必须完成么
- 准备好再开始,但不要让它成为你懈怠的借口
- 不要成为方法学的奴隶
实效项目
- 团队建设
- 不留破窗户(考验leader的管理能力)
- 经常性的复盘和例会
- 减少团队成员分工的冗余
- 自动化项目流程 => 效率工程团队开发内部工具
- 制造context,给成员足够空间
- 不要使用手动流程,它不可控且难以复制
- shell、crontab
- CI和自动化持续集成
- 代码生成
- 自动化测试
- 代码review和源码版本控制流程
- 常测试,早测试,自动化测试
- 单元测试/集成测试/压力测试/回归测试
- 测试状态覆盖,而不是代码覆盖,代码覆盖率提供的意义有限
- 关于如何生产文本
- 所有文档都是代码的反映
- 源码注释应该去把项目里那些难以描述、容易忘记、不能记录在其他地方的东西记载下来
- 比无意义的名称更糟糕的是有误导性的名称
- 除非有程序或人工维护,否则任何形式的文档都只是快照
- 温和地超出用户期望,如
- 友好的新手指引
- 快捷键
- 自动化安装
- 自豪地为你的作品签名
更多资源
- 《人月神话》
- 《Unix编程艺术》
- 《Effective C++》
- 《集市与大教堂》
–END–