知识卡片
拆分不同行为者依赖的代码,及SRP在组件与架构层面的映射
内容
[[SRP的真正含义是只对一类行为者负责而非只做一件事]]的解法都指向同一个方向:把服务不同行为者的函数划分进不同的类。最直接的办法是把数据与函数彻底分离,设计一个不含任何函数的简单EmployeeData类,再让PayCalculator、HourReporter、EmployeeSaver三个类各自持有对它的引用、只实现与自己相关的函数,彼此互不可见——代价是程序员现在要在系统里协调管理三个类而非一个。另一种办法是引入Facade模式:EmployeeFacade类本身只保留很少的代码,仅负责初始化并调用三个具体实现类的函数,把”哪个功能归哪个类”这件事对外部调用者屏蔽起来。还有一种折中方案是把最重要的业务逻辑连同数据一起保留在Employee类里,让它去调用另外两个次要的类。三种方案表面上看每个类似乎”只有一个函数”,实际不然——计算工资、生成报表、保存数据本身都是复杂过程,每个类内部完全可以包含许多私有函数;关键是每个类只容纳服务于同一行为者的一组函数,作用域之外彼此的私有函数互不可见。SRP作为一个原则并不止步于函数与类的关系:在组件层面,它演化为共同闭包原则(因同一类原因需要变更的代码应该聚在一起);在架构层面,它则成为划定架构边界的”变更轴心”——同一个行为者引发的变更应该被限制在尽量少的模块内。
参考来源
- 位置:《架构整洁之道》第7章《SRP:单一职责原则》"解决方案""本章小结"(源文件:_epub-src/text/part0012_split_001.html)
- 结论依据:原文给出数据函数分离、Facade模式、保留核心逻辑三种拆分方案的具体做法,并说明SRP在组件层面对应共同闭包原则、在架构层面对应划定架构边界的变更轴心,直接支撑本卡片结论。
- 原始内容:最简单直接的办法是将数据与函数分离,设计三个类共同使用一个不包括函数的、十分简单的EmployeeData类……在组件层面,我们可以将其称为共同闭包原则……在软件架构层面,它则是用于奠定架构边界的变更轴心。