独立性可以数:一个方法要接收多少个外部对象——实测强依赖版 6 个参数、打包成一组数据后 1 个;依赖从 6 降到 1,等于少知道 5 个类。
10.3 去掉重复,这一节处理另一个成本来源:耦合。改一个东西,会不会连带改一片。
一、独立性怎么量
看参数个数:一个方法要 6 个外部对象,说明它认识 6 个类。 看 import 个数:一个文件 import 了 15 个模块,它就跑不远。 看直接访问别人字段的次数:越多,越怕对方改。 这三个数都能数,所以独立性不是感觉。
二、实测:参数从 6 降到 1
强依赖版:make(self, reader, book, loan, fine, cashier, printer)——6 个参数。
弱依赖版:make(self, rows)——1 个参数,把要的数据打包成一组传进来。
依赖从 6 降到 1——调用方不用再知道那 5 个类的存在。
三、打包不是万能药
打包只是把依赖从【方法级】移到【调用方】:调用方还是要造那 6 个对象。
真正的好处是:Report 这个类以后谁都能用,不用带着 6 个类一起搬。
所以判断标准是:这个类将来要不要单独拿走?要,就该打包。
四、独立性的两个误区
以为参数少就一定好:把 6 个参数塞进 1 个没人看得懂的 dict,那叫藏依赖。 以为独立性越高越好:过度拆分会让调用方拼装成本上升,总成本反而变高。 所以目标是【刚好够独立】:这个类能单独测、能单独拿走,就够了。
五、动手 Demo:设计目标之二:提高构件的独立性
用 ast 读出两个版本的方法参数个数(参数就是依赖)。
对比强依赖版与打包版的差别。
import ast
A = """
class Report:
def make(self, reader, book, loan, fine, cashier, printer):
return 0
"""
B = """
class Report:
def make(self, rows):
return 0
"""
def params(code):
for n in ast.walk(ast.parse(code)):
if isinstance(n, ast.FunctionDef):
return [a.arg for a in n.args.args if a.arg != "self"]
print(len(params(A)), len(params(B))) # 6 1
实跑输出:
--------------------------------------------------------------------
设计目标之二:提高构件的独立性
--------------------------------------------------------------------
独立性可以量:**一个方法要接收多少个外部对象。**实测两个类:
类 参数(=依赖) 个数
-------------------------------------------------------------------------
Report(强依赖) reader/book/loan/fine/cashier/printer 6
Report(弱依赖) rows 1
强依赖版的依赖 6 个(reader/book/loan/fine/cashier/printer)
弱依赖版的依赖 1 个(rows)
依赖从 6 个降到 1 个
**参数个数就是依赖个数**——6 个参数意味着调用方必须知道 6 个类。
**把它们打包成一组数据传进来,依赖从 6 降到 1。**
**这就是【提高独立性】的具体动作**:不是少写代码,是少知道别人。
实测:强依赖版 6 个参数(reader/book/loan/fine/cashier/printer),弱依赖版 1 个。 参数个数就是依赖个数——依赖从 6 降到 1,等于少知道 5 个类。 但打包只是把依赖移到调用方,真正的好处是这个类能单独拿走。
30 秒实验
- 数一数你项目里参数最多的那个方法,它认识几个类。
- 找出一个文件 import 超过 10 个模块的地方,看能不能分层。
常见误区
- 以为参数少就一定独立。把 6 个塞进一个 dict 只是藏依赖。
- 以为越独立越好。过度拆分让调用方拼装成本上升。
自测三问(点开对答案)
1. 独立性可以用哪三个数来量? —— 方法参数个数、文件 import 个数、直接访问别人字段的次数。 2. 实测参数从几个降到几个? —— 从 6 个(6 个外部对象)降到 1 个(一组数据)。 3. 打包的局限是什么? —— 依赖只是移到调用方;真正的好处是这个类能单独拿起走。- ☐ 10.5 提高构件独立性的诀窍
相关笔记
- 设计目标之一:去除重复 — 上一个目标
- 提高构件独立性的诀窍 — 具体三个手法
- 类的功能之二:隐藏 — 隐藏与独立的同源
- 🧩 面向对象是怎样工作的 · 索引