敏捷开发笔记
敏捷是因为需求的多变
通过随时防止“臭味”,来保持整洁的架构
通过一些原则来帮我们判断是否有臭味和如何修改
这些原则都是为了更好(更适合你需求)的抽象服务的
SRP
一个类多职责会让这些职责的代码耦合在一起,导致脆弱性
比如矩形类又要计算面积,又要展示UI
耦合导致改动会互相影响
通过拆分成两个接口解耦
职责的定义是变化的原因,
个人理解这其实是很主观的判断,
比如UI和计算可能显然是两个职责
比如计算如果很复杂,
有加减乘除,还有向量运算,还有微积分等
那光计算本身又是多个职责。
其实类的每个可以独立使用public方法
或者一组方法
都是一个职责
那么什么时候要用SRP拆分?
这个度这么掌握呢?
比如计算什么时候是一个职责呢?
我开始觉得是有两个不同的地方只用到它的
不重合的一部分方法的时候
比如前面矩形类单独被一个模块用来计算
被另一个模块用来显示
作者给了一个方法是:
当它们总是同时发生变化的时候,
就没必要去分离,分离会造成不必要的复杂性。
我们来试着总结一下SRP的运用方法:
当你刚开始做设计时,
你尽量把会一起变化的职责(也即一个或一组可以独立用的方法)
放在一个类里
在做修改的时候,如果发现一个类只有一个职责发生了变化
那么可能就需要分离它的其他职责,以免受到影响
OCP
通过抽象和多态可以获得OC
如画应用:
在开始设计的时候对很可能扩展的地方做抽象,
在改动的时候,对没有抽象而产生扩展的地方做抽象(只被愚弄一次)
为了让变化尽早到来检验我们的抽象,应该这样来刺激变化:
通过编写测试来检验
短迭代周期
在加入基础结构前就开发特性,并经常展示给使用者
首先开发最重要的特性
尽早,尽可能频繁的发布
效果:
带来灵活性,重用性,可维护性
OCP是OOD的核心
LSP
子类可以替换基类
golang通过实现interface而不是继承基类的方式复用
这个语言特性来避免了违法这个原则。
不过当你还没抽象,只有struct的时候,复用代码是直接内嵌,还是抽象
也要考虑这个
在做初始设计和改动的时候,如果一组类都有一个公共的职责,
提取它作为一个公共的抽象
LSP帮助达到OCP,因为基类的功能才通过增加实现子类而扩展
IS A的子类确定方式,不如“可以替换”的确定方式
DIP
高层模块不依赖低层,他们都依赖抽象
抽象不依赖细节,而是反过来
抽象接口属于用户侧
启发式规则:只依赖抽象
任何变量都不持有具体类
任何类都不从具体类派生
任何方法都不覆盖基类已实现的方法
tradeoff
有些用于程序初始化的代码不用这样
有些具体但却稳定的类,是可以依赖的(比如java的String)
不过大多数类都是不稳定的,如果只是单纯从类抽象接口
,则类变了,接口很可能也变。
但如果客户保有它们需要的接口,可以保证接口的稳定,
只有用户需求变了,接口才变
模版可以解决一些多态能解决的问题(静态多态),但不是全部,性能会好
但是不能运行时换新类型,扩展类型会导致重新部署
在设计时构建富有弹性的代码