从坏味道到设计原则,构建灵活可维护的软件系统(《敏捷软件开发:原则、模式与实践》读书笔记)

1. 软件设计中的坏味道(对应原书第7章)

核心理解:

  • 抽象不足:业务代码中掺杂过多细节,导致代码僵化、脆弱、难以理解和维护。
  • 业务逻辑应调用功能,而非实现功能:业务逻辑应通过调用功能接口来完成,而不是直接实现功能细节。
  • 功能抽象为接口,业务逻辑组合接口:功能应抽象为接口,业务逻辑通过组合和调度这些接口来实现。
  • 接口可扩展但不可修改:接口应保持稳定,允许扩展但不允许修改。
  • 功能实现可变,接口不可变:功能的实现可以灵活变化,但接口应保持稳定。
  • 优先调用库而非原始实现:尽量使用通用库(如STL、Boost),避免重复造轮子。

坏味道分类:

  1. 僵化性 :设计难以修改,单一改动可能引发依赖模块的连锁反应。
    • 表现:实际工作量超出预期,未预料到的关联改动。
  2. 脆弱性:设计易于破坏,一个改动可能导致多个地方出现问题。
  3. 顽固性:设计难以重用,重用部分需要巨大努力和风险。
  4. 粘滞性 :难以做正确的事情,保持设计的方法比临时拼凑更难。
    • 表现:编译时间长、源代码控制系统效率低。
  5. 不必要的复杂性:过度设计,包含当前无用的组成部分。
  6. 不必要的重复:滥用复制粘贴,忽视抽象。
  7. 晦涩性:模块难以理解,表达混乱。

2. 软件设计中的原则(对应原书第8、9、10、11、12、28章)

2.1 设计原则概览
序号 原则名称 缩写 英文全称 核心描述 对应设计模式
1 单一职责原则 SRP The Single Responsibility Principle 一个类(或接口)应只有一个发生变化的原因。 适配器模式(Adapter Pattern)、代理模式(Proxy Pattern)
2 开放-封闭原则 OCP The Open-Close Principle 软件实体(类、模块、函数等)应可扩展但不可修改。 策略模式(Strategy Pattern)、装饰者模式(Decorator Pattern)、观察者模式(Observer Pattern)
3 Liskov替换原则 LSP The Liskov Substitution Principle 子类型必须能够替换其基类型。 工厂模式(Factory Pattern)、模板方法模式(Template Method Pattern)
4 依赖倒置原则 DIP The Dependency-Inversion Principle 高层模块不应依赖低层模块,二者都应依赖抽象。 依赖注入(Dependency Injection)、服务定位器模式(Service Locator Pattern)
5 接口隔离原则 ISP The Interface Segregation Principle 为用户提供专用接口,避免强迫其依赖不需要的方法。 适配器模式(Adapter Pattern)、代理模式(Proxy Pattern)、装饰者模式(Decorator Pattern)
2.2 设计原则的价值与代价
序号 原则 违反的坏处 遵循的好处 代价
1 单一职责原则 代码复杂性增加、难以复用、高耦合性、测试困难 提高可维护性、增强可复用性、降低耦合性、简化测试 增加类的数量、初始设计复杂性、管理和组织难度、潜在的性能开销
2 开放-封闭原则 高风险修改、难以维护、影响其他功能 提高稳定性、增强灵活性、提高可维护性 设计复杂性增加、初始开发成本增加、可能的性能开销
3 Liskov替换原则 程序不稳定、难以维护、降低复用性 提高代码的灵活性和复用性、增强系统的稳定性、简化代码维护 设计复杂性增加、可能需要更多的抽象、初始开发成本增加
4 依赖倒置原则 高耦合、难以测试、降低灵活性 降低耦合度、提高可测试性、增强可扩展性 设计复杂性增加、初始开发成本增加、可能的性能开销
5 接口隔离原则 臃肿的接口、难以维护、降低灵活性 提高灵活性、增强可维护性、提高代码的可理解性 增加设计复杂性、初始开发成本增加、可能的代码冗余

个人理解:

  • 抽象带来自由:通过抽象隐藏实现细节,编写者和调用者都能获得更大的灵活性。
  • 抽象不足的代价:抽象不足会导致编写者和调用者都失去自由,代码难以维护和扩展。
  • 隐藏实现细节:将实现隐藏在接口后,编写者可以自由修改实现,调用者无需引入不必要的细节。
2.3 包和组件的设计原则
序号 分离 概述 原则名称 缩写 英文全称 描述
1 内聚性原则 帮助开发者决定如何将类划分到组件 重用-发布等价原则 REP Reuse-Release Equivalence Principle 重用的粒度就是发布的粒度
2 共同重用原则 CRP Common-Reuse Principle 一个组件中的所有类应共同重用
3 共同封闭原则 CCP Common-Closure Principle 组件中的所有类应对同一种变化共同封闭
4 组件耦合性原则 处理组件之间的关系,平衡可开发性和逻辑设计 无环依赖原则 ADP Acyclic-Dependencies Principle 组件之间的依赖关系不应形成循环
5 稳定依赖原则 SIP Stable-Dependencies Principle 依赖应朝向稳定的方向
6 稳定抽象原则 SAP Stable-Abstractions Principle 组件的抽象程度应与其稳定程度一致

3. 开发中的经验与教训

  • 避免重复犯错:将正确的代码封装为通用函数,避免重复错误。
  • 优先使用通用库:尽量使用通用库(如STL、Boost),避免重复造轮子。如果通用库中没有所需功能,可以自行开发通用库。

4. 总结

  • 抽象与接口的重要性:通过抽象和接口设计,可以显著提高代码的灵活性、可维护性和可复用性。
  • 设计原则的权衡:虽然遵循设计原则会增加初始设计的复杂性,但长远来看,能够显著提升代码质量和开发效率。
  • 识别与避免坏味道:通过识别和避免软件设计中的坏味道,可以有效提升代码的可读性和可维护性,降低后期维护成本。
相关推荐
重生之绝世牛码1 个月前
Java设计模式 —— 【行为型模式】命令模式(Command Pattern) 详解
java·大数据·开发语言·设计模式·命令模式·设计原则
萤火虫Coding2 个月前
SOLID-开闭原则
java·设计模式·设计原则·开闭原则·solid·open-closed
重生之绝世牛码2 个月前
Java设计模式 —— 【行为型模式】模板方法模式(Template Method Pattern) 详解
java·大数据·开发语言·设计模式·设计原则·模板方法模式
重生之绝世牛码2 个月前
Java设计模式 —— 【结构型模式】享元模式(Flyweight Pattern) 详解
java·大数据·开发语言·设计模式·享元模式·设计原则
重生之绝世牛码2 个月前
Java设计模式 —— 【结构型模式】外观模式详解
java·大数据·开发语言·设计模式·设计原则·外观模式
重生之绝世牛码2 个月前
Java设计模式 —— 【结构型模式】桥接模式详解
java·大数据·开发语言·设计模式·桥接模式·设计原则
重生之绝世牛码2 个月前
Java设计模式 —— 【创建型模式】建造者模式详解
java·大数据·开发语言·设计模式·建造者模式·设计原则
Amd7942 个月前
数据库设计原则与方法
设计原则·数据建模·er模型·数据库设计·数据完整性·规范化·数据关系
重生之绝世牛码3 个月前
Java设计模式 —— 【创建型模式】工厂模式(简单工厂、工厂方法模式、抽象工厂)详解
java·大数据·开发语言·设计模式·工厂方法模式·设计原则·工厂模式