1.行为准则
2.需求的不确定性2.1.不断变化的客户需求2.2.软件项目无法避免的挑战2.3.产品需求和环境会随着时间的推移而改变,你的应用程序也必须随之改变2.4.不断变化的需求会导致不稳定性,使开发工作偏离轨道2.5.通过构建可演进的架构来适应不断变化的需求2.5.1.可演进的架构可避免复杂性,复杂性是演进性的敌人2.5.2.矛盾的是,在软件中实现简洁性会很困难3.复杂性3.1.复杂系统的特点3.1.1.高依赖性3.1.1.1.致软件依赖于其他的API或代码行为3.1.1.2.依赖性显然不可避免,甚至是可取的,但必须取得平衡3.1.1.3.高依赖性的系统很难修改3.1.1.3.1.它们有紧密的耦合性和高度的变更放大效应3.1.1.3.2.紧密的耦合性是指那些严重依赖彼此的模块,它们导致了更高的变更放大的倍率,即某项单一的变更也需要修改依赖关系3.1.1.4.深思熟虑的API设计和有节制地使用抽象模型将最大限度地降低紧耦合性和变更放大效应3.1.2.高隐蔽性3.1.2.1.使得程序员很难预测某项变更的副作用、代码的行为方式,以及需要修改的地方3.1.2.2.晦涩的代码需要更长的时间来学习,开发人员更有可能在无意中破坏某些东西3.1.2.3.症状3.1.2.3.1.“知道”太多的对象3.1.2.3.2.鼓励副作用的全局状态3.1.2.3.3.掩盖代码的过度间接寻址3.1.2.3.4.影响程序远程行为的远距离操作3.1.2.4.采用具有明确的约定和标准模式的API可以减少隐蔽性3.1.3.高惯性3.1.3.1.指软件保持之前的使用习惯3.1.3.2.用于快速实验且很容易被丢弃的代码具有低惯性3.1.3.3.一项为十几个关键业务应用提供驱动力的服务具有高惯性3.1.3.4.复杂性的成本随着时间的推移而增加,所以高惯性、高变化的系统应该被简化,而低惯性或低变化的系统可以保持复杂(只要你抛弃它们或继续让它们保持不变)3.2.复杂性不总能被消除,但你可以选择把它放在哪里3.2.1.向后兼容的变更可能使代码使用起来更简单,实现起来却更复杂3.2.2.用于解耦子系统的间接层可降低依赖性,却会提高隐蔽性4.可演进的设计4.1.面对未来未知的需求策略4.1.1.试图预判未来的需求4.1.2.建立抽象模型作为逃生舱门,使后续的代码修改更容易4.1.3.都会导致复杂性提高4.2.KISS的原则4.2.1.要保持事情简单一些4.2.2.使用KISS记忆法,记住要以简单性为核心原则构建系统4.2.3.简单的代码可以让你在未来增加系统的复杂性4.3.保持代码简单的最简单的方法之一是避免什么代码都要写出来4.3.1.告诉你自己,你不是真的需要(You ain’t gonna need it,YAGNI)4.3.2.要使用最小惊讶原则和封装原则4.4.不要构建你不需要的东西4.4.1.靠猜测而编写出来的代码会继续使事情陷入困境,它需要被维护,开发人员需要理解它,它必须被构建和测试4.4.2.避免过早优化,避免不必要的灵活抽象模型,以及避免最小可行产品(minimum viable product,MVP)所不需要的产品特性4.4.3.过早优化是指开发人员在证明需要优化之前就对代码进行性能优化4.4.4.灵活的抽象模型——插件式架构、封装接口和通用数据结构(如键值对)是另一种诱惑4.4.4.1.抽象自有代价:它把实现的代码框在僵硬的边界里,而开发者最终会与之抗争4.4.4.2.灵活性也使代码更难以阅读和理解4.4.4.2.1.保持代码灵活性的最佳方法之一是减少代码的总量4.4.4.2.2.蒙茨法(muntzing),将使你的软件保持“苗条”和适应性4.4.5.MVP允许你先测试一个想法,而不必押宝在某项成熟的实施上4.4.5.1.在你怀疑可以插入优化的地方放置接口填充程序,但不要真正实现它们4.5.最小惊讶原则4.5.1.不要让用户感到惊讶,构建特性表现得要像用户最初期望的那样,具有上扬的学习曲线或奇怪表现的特性会使用户感到沮丧4.5.2.不要让开发者感到惊讶,令人惊讶的代码通常晦涩难懂,这会导致复杂性4.5.3.通过保持代码的针对性、避免隐性知识,以及使用标准类库和模式来消除惊讶4.5.4.凡是开发者在调用API时需要知道的但又不属于API本身的不明显的知识,都被视为隐性知识4.5.5.排序需求决定了某些动作必须按照某种特定的顺序进行4.5.5.1.使用文档来说明某些排序需求是种好办法,但最好是一开始就没有这个排序需求4.5.6.当一个方法的签名暗示了比该方法实际可以接受的有效输入范围更广时,就会出现隐藏的参数需求4.5.7.切记让参数需求具体化和可视化4.5.7.1.使用可准确适配约束的特定类型,当使用灵活的类型如JSON时,考虑使用JSON schema来描述预期的对象4.5.8.使用标准类库和开发模式4.5.8.1.请使用惯用的代码风格和开发模式4.6.封装专业领域知识4.6.1.将软件组件映射到业务领域,将使代码的变化保持专注和干净4.6.1.1.会计、计费、运输等4.6.2.封装的领域自然会倾向于高内聚和低耦合4.6.2.1.理想的特征4.6.2.2.高内聚和低耦合的软件更容易演进,因为变更的“爆炸半径”往往更小4.6.2.3.解耦的代码是自成一体的,对其逻辑的改变不需要对其他软件组件也进行改变4.6.3.开发人员经常以“层”为单位来思考软件:前端、中间层和后端4.6.3.1.每一层都有独立的团队,会增加协调成本,因为每一项业务逻辑的变化都会影响到所有的软件分层4.6.4.识别领域边界和封装领域知识既是一门科学又是一门艺术4.6.4.1.领域驱动设计(domain-driven design,DDD),它定义了一套广泛的概念和实践,将商业概念映射到软件上4.6.4.2.只有在最复杂的情况下才需要全覆盖的DDD4.6.4.3.熟悉DDD将有助于你做出更好的设计决策