0%

软件小设计读书笔记

1. 设计原则

1.1. 通用原则

1.1.1. KISS原则(keep it sample and stupid)

  • 懒人原则
  • 注重简约的原则, 逻辑处理上应该用简单直接的设计.
  • 圈复杂度越小越好, if for case while的数量.

如非必要, 请远离各种设计模式

1.2. 核心原则

1.2.1. 单一职责原则(SRP)

做一个专一的人

不能存在多于一个导致类变更的原因, 一个类之负责一项职责.

迭代器的实现, 集合只负责存储数据, 迭代器完成遍历数据的功能

1.2.2. 开放封闭原则 (OCP)

改造世界的大部分不能破坏原来的秩序

软件实体应该是可扩展, 不可修改的. 对扩展开放, 对修改封闭
新的修改不要大幅度波及现有的对象

小技巧: 使用继承/组合封装变化点,
将变化点封装出一个抽象基类, 使用继承机制, 让子类演绎变化

1.2.3. 里氏替换原则 (LSP)

长大后, 我就成了你

任何积累可以出现的地方, 子类一定可以出现.

子类不破坏父类的接口成员
当基类出现了子类不想要的接口成员时, 继承关系欠缺考虑, 违反LSP原则

1.2.4. 接口分离原则 (ISP)

不要一口吃成胖子

不能强迫用户去依赖那些不使用的接口, 使用多个专门的接口比使用单一的总接口要好

1.2.5. 依赖倒置原则 (DIP)

抽象的艺术才有生命力

  • 高层模块不应依赖底层模块, 两者都应依赖于抽象
  • 抽象不应依赖细节
  • 细节(具体实现类)依赖抽象

1.2.6. 核心原则小结

类要单纯, 继承要纯粹, 变化要封装, 抽象类型要多用

1.3. 扩展规则

1.3.1. 狄米特法则

尽量不与无关的类发生关系

最少知识原则: 你调用的类的内部是如何实现的, 与我无关. 我只知道你提供的接口方法, 其他的一概不关心.

通俗点的说法:

  • 只与你的朋友说话
  • 不要与陌生人说话
  • 对象因该只与必须交互的对象通信

技术上的说法, 对象只与下类必须交互的各类对象进行通信:

  • 当前对象本身(this)
  • 以参数形式传入当前方法中的对象
  • 当前对象的成员对象 (this的成员变量)
  • 如果成员对象是一个集合, 集合中的元素也是可以交互的
  • 当前对象创建的对象

1.3.2. 好莱坞法则

不要调用我, 让我调用你

多使用回调的方式.

1.3.3. 优先使用组合

多使用组合, 少使用继承.

继承使用的场景:

满足严格的IS-A关系, 即子类可以完全复用基类的所有信息时, 继承是必须的

要么有冗余关系, 要么复用程度不够时, 不推荐完全使用继承关系.

1.4. 应对变化

1.4.1. 增量修改原则

开闭原则, 尽量不修改原有的类和方法, 通过新增类和方法实现.

1.4.2. 整体策略原则

设计整体上考虑变化,而不仅仅考虑变化点周围的小区域

1.4.3. 应对变化的设计思路

  • 预先设计
    程序设计时就把可能存在的变化考虑到, 在程序上预留一定的扩展性
    采用抽象类型来描述稳定的接口, 使用子类和多态机制来描述变化.

  • 简单设计+封装变化
    很多时候, 变化总是不期而至,无法做到预先设计,当变化来的时候, 通过封装变化点来重构程序

1.5. 设计的四个阶段

1.5.1. 设计不足

  • 没有系统的观念, 代码写到哪想到哪,想到哪写到哪.
  • 代码随意堆彻, 各种编程元素随意使用, 元素可见性\生命周期使用混乱
  • 元素随意命名, 数字随意使用
  • 代码随意复制和粘贴, 功能相似的函数不考虑复用
  • 代码无法应对需求变化, 维护成本很高

1.5.2. 模仿设计

  • 开始考虑程序对系统其他方面的影响, 开始考虑设计
  • 开始应用简单的模式
  • 开始学习一些好的写法, 并学会整理自己的代码

1.5.3. 过度设计

  • 见到全局的概念就使用单例模式
  • 需要通知就使用观察者模式
  • 见到稍微复杂一点的对象创建就使用抽象工厂模式
  • 见到算法变化了一点就使用策略模式
  • 见到软件就分三层
  • 见到变化就抽象
  • 见到依赖就注入
  • 任何行为都想抽象接口
  • 任何设计都考虑是否具有通用扩展性

过度设计是在软件设计过程中实施了不必要的通用的扩展性设计, 增加了不必要的面向未来的设计, 进行了不必要的抽象封装.

适度设计

合时宜, 恰如其分,有时间制约, 合适的时间成本, 恰当的对接需求.