第一章 务实的哲学
- 编程是一门技艺
- 是什么造就了务实的程序员
- 早期的采纳者/快速的适配者。对技术和技巧有一种直觉,喜欢尝试。
- 好奇。倾向于问问题
- 批判性的思考着:在没有得到证实前很少接受既定的现实
- 现实主义:理解面临的每个问题的本质。这种现实主义让你对事情有多困难、需要用多长时间有一个很好的感知。
- 多面手。熟悉各种技术和环境,并努力跟上新的进展。
- 关注你的技艺。如果你不关心怎么把软件开发好,那么软件开发领域就再也没有什么好谈的事情了。
- 思考!思考你的工作。为了成为一名务实的程序员,我们要求你在做事的时候,思考一下自己正在做什么。
- 我活着不是为了满足你的期望,正如你也不是因为我的期望而活着。——李小龙
- 人生是你自己的,是你在拥有、经营和创造。
- 你有权选择:你可以去改变组织,或是让自己换一个组织。
在你的职业发展、学习教育,以及你的项目、每天的工作等各方面对你自己负责,对你的行为负责,这是务实哲学的基石之一。一个务实的程序员能完全掌握自己的职业生涯,从不害怕承认无知和错误。
- 团队信任:你的团队需要能信赖和依赖你——你也应该同样地放心依赖他们每个人
- 承担责任:责任意味着你对某事积极认同。你保证事情能搞定,并为之做出承诺,但你不必直接掌控事情的每个方面,但是需要分析超出控制范围的风险。
- 提供选择,别找借口。不要说搞不定,而是需要去找怎么才能挽救这个局面。
- 破窗效应。不要打破窗户
- 心理学家研究表明,绝望是会传染的,就像狭窄空间中的流感病毒。无视一个明显损坏的东西,会强化这样一种观念:看来没有什么是能修好的,也没人在乎,一切都命中注定了。所有的负面情绪会在团队成员间蔓延,变成恶性循环。
- 做推动变革的催化剂。当遇到一个异常复杂糟糕的系统,可以先找出合理的请求,然后不断的完善,一旦有成果产出,展示给人们看,让他们大吃一惊。
人们觉得,加入一个推进中的成功项目更容易一些。因为只要一窥未来,大家就能团结在一起。
- 牢记全景:永远留意着大局,持续不断地审视你身边发生的事情,而不要只专注于你个人在做的事情。
- 够好的软件:所有系统必须达到用户的需求才算完成,需要达到基本的性能、隐私和安全标准。你做的东西,从用户需求角度来说是否足够好?最好还是留给用户一个机会,让他们能亲自参与评估。
- 将质量要求视为需求问题
- 不要过度的修饰和精炼侵蚀掉一个完好的程序。继续前行,让代码在它该有的位置驻留一段时间。它或许并不完美,不要紧的——它就算永不完美也没关系。
- 投资知识
- 批判性地分析你读到和听到的东西
- 交流
- 了解听众:为了把信息传达,你需要了解受众的需求,兴趣和能力
- 明白自己想说什么
- 选择时机
- 挑选风格:根据听众调整你的表达方式。
- 让它看起来不错。
- 让听众参与
- 做倾听者。如果你不听他们的,他们也不会听你的
- 回应别人。
- 文档交流。务实的程序员会把文档视为整个开发过程的一个组成部分。把代码和源码绑定在一起
第二章 务实的方法
- ETC(Easier To Change):优秀的设计比糟糕的设计更容易变更
- DRY:不要重复你自己。在一个系统中,每一处知识都必须单一、明确、权威地表达。
- 让复用更容易。你要努力的方向,应该是孕育出一个更容易找到和复用已有事物的环境,而不是自己重新编写。
如果复用不容易,人们就不会这么做。(创造复用条件)
如果你未能复用,就有重复知识的风险。 - 正交性:在计算机科学中,这个术语象征着独立性或解耦性。对于两个或多个事物,其中一个的改变不影响其他任何一个,则这些事物是正交的。
- 非正交系统天生就复杂,难以变更和控制。当系统的组件相互之间高度依赖时,就没有局部修理这回事。
- 消除不相关事物之间的影响:当组件批次隔离时,你知道可以变更其中一个组件,而不必担心影响到其他组件。
正交系统的两个主要收益:提高生产力及降低风险
。- 获得生产力
- 将变更限制在局部后,开发时间和测试时间都会减少。
- 正交的方法同时促进了重用。
- 组合正交组件能获得相当微妙的生产力提升。
- 减少风险
- 代码中病变的部分被隔离开
- 获得的系统不那么脆弱。任何问题都限制在局部
- 正交系统利于测试,因为为其组件设计和运行测试更加容易。
- 不会被特定的供应商、产品或平台紧紧束缚。
- 获得生产力
- 模块化、基于组件和分层
- 不要依赖那些你无法控制的东西。
- 编写正交性代码的几种方法:
- 保持代码解耦:模块不会向其他模块透露任何不必要的信息,也不依赖于其他模块的实现。
- 避免全局数据:只要代码引用全局数据,就会将自己绑定到共享该数据的其他组件上。
- 避免相似的函数:
- 不做最终决定:灵活的架构。
- 曳光代码:可运行的生产级别代码,可不断优化。原型代码:一次性代码,用完就丢。
- 估算:所有的估算都是基于对问题的建模。
- 建模会给估算过程引入不准确性,这不可避免,但也是有益的。你在用模型的简单性来换取精确性。
- 将模型分解成组件。一旦得到了模型,就可以将其分解成组件。每个组件都有相关的估算
- 估算项目进度:三个估算值,乐观的、一个最有可能的和一个悲观的估计。
- 估算时间根据项目进度不断迭代。
第三章 基础工具
- 将知识用纯文本保存。人类可读形式的数据与自描述数据,会比所有其他形式的数据,以及创建数据的应用程序,更有生命力。
- 发挥shell命令的威力
- 加强编辑能力
- 永远使用版本控制
- 调试
- 去解决问题,而不是责备。Bug是你的错还是别人的错并不重要。无论是谁的错,问题仍然要你来面对。
- 不要恐慌
- 修代码前先让代码在测试中失败。 对于前期复现步骤很长的bug,不要每次都重头开始去测试。有时,只要强制自己对暴露Bug的环境进行隔离,就能获得对如何修Bug的洞察力。
读一下那些该死的出错信息。
二分法找bug
第四章 务实的偏执
- 你无法写出完美的软件
- 契约规定了你的权利和责任,同时也规定了对方的权利和责任。
- 契约式设计:如果调用者满足了例程的所有前置条件,则例程应保证在完成时所有后置条件和不变式都为真。
- 前置条件:一个例程永远不应该在前置条件被违反的时候被调用
- 后置条件:例程保证要做的是什么?例程完成时世界的状态。例程有后置条件这个事实,意味着能得出这样的结论——不允许无限循环。
- 类的不变式:从调用者的角度来看,类会确保该条件始终为真。在例程的内部处理期间,可以不遵守不变式,但是当例程退出并将控制权返回给调用者时,不变式必须为真。
- 尽早崩溃
- 使用断言去预防不可能的事情。不要用断言来代替真正的错误处理。断言检查的是不可能发生的事情。
- 有始有终。理想情况下,分配资源的例程也应该负责释放它。
- 资源嵌套分配
- 释放资源的顺序和分配资源的顺序相反。
- 在代码的不同位置,如果都会分配同一组资源,就始终以相同的顺序分配它们。这将减少死锁的可能性。
- 小步前进——由始至终,总是采取经过深思熟虑的小步骤,同时检查反馈,并在推进前不断调整。把反馈的频率当做速度限制,永远不要进行“太大”的步骤或任务。
第五章 宁弯不折
- 解耦代码让改变更容易
- 只管命令不要询问。这个原则说的是,不应该根据对象的内部状态做出决策,然后更新该对象。这样做完全破坏了封装的优势,并且在这样做时,也会把实现相关的知识扩散到整个代码中。
- 不要链式调用方法。方法是可变的,对于不可变的,可采用。
- 继承增加了耦合
- 编程讲的是代码,而程序讲的是数据。
- 继承就是耦合。替代方案
- 接口和协议。尽量使用接口表达多态。
- 委托
- 使用外部配置参数化应用程序。如果代码依赖某些值,而这些值在应用程序发布后还有可能改变,那么就把这些值放在程序外部。
第六章 并发
- 通过分析工作流来提高并发性
- 随机故障通常是并发问题
- 用角色实现并发性时不必共享状态。采用消息传递取代共享状态
- 使用黑板协调工作流。
第七章 当你编码时
- 务实的程序员会对代码进行批判性思考,包括自己的代码。
- 编程应该深思熟虑,不要依靠巧合式编程。
- 时刻注意你在做什么。
- 能向初级程序员解释自己的代码。
- 不要在黑暗中编程。构件一个没有完全掌握的应用程序,或者使用一个并不理解的技术,就很可能会被巧合咬伤。
- 要按计划推进。
- 只依赖可靠的东西。不依赖假设。如果你不知道某件事是否可靠,就要做最坏的打算。
- 将假设文档化。
- 不要只测试代码,还要测试假设。写一个断言来测试假设
- 为你的精力投放排一个优先级
- 不要成为历史的奴隶。不要让现有的代码去支配未来的代码。如果不再合适,所有的代码都可以替换。即使一个程序正在进展中,也不要让已经做完的事情限制下一步要做的事情——准备好重构。
- 评估算法的级别。
- 对估算做测试。
- 尽早重构,经常重构
- 测试是代码的第一个用户。测试驱动编码
- 为测试做设计。
- 要对软件做测试,否则只能留给用户去做。
- 保持代码简洁,让攻击面最小
- 好好取名;需要时更名
第八章 项目启动之前
- 无人确切知道自己想要什么。需求一开始是不明确的。
- 程序员帮助人们理解他们想要什么。完善客户需求,告知用户细节。
- 需求是从反馈循环中学到的。帮助客户理解他们所陈述需求的后果。
- 和用户一起工作以便从用户角度思考。
- 创建详细文档的错误:
- 客户并不确切知道自己想要什么
- 客户从不阅读文档。
- 就需求而言,最简单最能准确反映业务需求的语句是最好的。需求不是架构:需求无关设计,也非用户界面;需求就是需要的东西。
- 不要跳出框框思考——找到框框。解决谜题的关键是,认识到你所受到的约束和你所拥有的的自由度,因为认识到这些就会找到答案。
- 跳出自身的局限。当遇到复杂问题,放松大脑。注意力分散的人容易解决复杂问题时比有意识的人做的更好。 放松时潜意识脑在思考。
- 康威定律:设计系统的架构受制于产生这些设计的组织的沟通结构。
- 合作性事务的小技巧:
- 打造代码,而非打造自我。这与谁最聪明无关;我们都有许多闪光的瞬间,也有糟糕的时刻。
- 从小规模做起,只需要4-5人的群体,或者开始时只组成几对,做一些短期活动。
- 批评要针对代码,而不针对人。“让我们看看这一块”听起来比“你搞错了”好得多。
- 倾听他人的观点并试着理解。观点不同不是错误。
- 频繁进行回顾,为下一次做好准备。
- 不要一个人埋头钻进代码中。交流。
- 敏捷不是一个名称;敏捷有关你如何做事。敏捷宣言:
- 个体和互动高于流程和工具
- 工作的软件高于详尽的文档
- 客户合作高于合同谈判
- 响应变化高于遵循计划
- 也就是说,尽管右项有其价值,我们更重视左项的价值。
第九章 务实的项目
- 维持小而稳定的团队。
- 对于需要做的事务排上日程。而不是“以后再说”
- 组织全功能的团队。
- 自动化是每个项目团队的基本组成部分。确保团队拥有构件工具的技能,以便可以构件和部署工具,用其来将项目开发和生产部署自动化。
- 务实的入门套件
- 版本控制
- 回归测试
- 完全自动化
- 使用版本控制来驱动构件、测试和发布。
- 尽早测试,经常测试,自动测试
- 直到所有的测试都已运行,编码才算完成。
- 使用破坏者检测你的测试
- 测试状态覆盖率,而非代码覆盖率
- 每个Bug只找一次。
- 取悦用户,而不要只是交付代码。代码最终是为了解决用户问题而开发的,
对社会和用户
先勿伤害。
保护用户不受伤害。不要助纣为虐。
不要创造危害社会的代码。你要为自己的人生做主,精心营造,与人分享,为之喝彩。好好享受吧!
你正在为自己和子孙后代建设未来——这是你的职责所在,去创造一个让所有人心向往之的宜居未来。