🧩 第六章 重用:OOP带来的软件重用和思想重用
📄 一句话概括

组件和类库差在独立程度:实测 textwrap 只依赖 1 条、csv 依赖 5 条——依赖越少越换得掉。

📝 本节和前面几节的关系

6.7 说会挑比会用值钱,这一节说挑的标准是什么。

一、组件是什么

能单独换掉、不牵连别人的构件。 它和类库不是两类东西,是同一件东西的两种评价:能换掉的是组件,换不掉的是负担。 所以【组件化】不是把代码拆碎,是【把依赖变少】。

二、实测依赖数

实测几个标准库模块的 import 行数:textwrap 1 条、json 3 条、base64 3 条、csv 5 条。 依赖越少,独立性越高——换掉它要动的地方就越少。 实测一个反面:依赖 20 条的模块,换它等于重写一片。

三、依赖为什么会传染

A 依赖 B,B 依赖 C——你想换 B,就得先看 C 会不会跟着动。 所以 10.6 要讲【避免依赖循环】:一旦成环,谁都换不掉。 判断办法:把某个模块拿掉,看要改几处;改得少,它就是组件。

四、怎么把东西做成组件

对外只留窄接口:入口少,别人才不需要知道里面。 不向外暴露内部类型:返回自己的类型,别把底层库的对象直接传出去。 依赖注入代替直接 new:让调用方把依赖递进来,换实现时外面改一行。

五、动手 Demo:独立性较高的构件——组件

数几个标准库模块的 import 行数,作为依赖数。 依赖少的独立性高,那是能单独换掉的构件。

import inspect, sys
for name in ("json", "csv", "base64", "textwrap"):
    src = inspect.getsource(__import__(name))
    deps = [l for l in src.split("\n")
            if l.startswith("import ") or l.startswith("from ")]
    print(name, len(deps), len(src.split("\n")))

实跑输出:

--------------------------------------------------------------------
独立性较高的构件——组件
--------------------------------------------------------------------

  【组件】和【类库】差在**独立程度**上:**能单独换掉,不牵连别人。**
  独立性的第一指标是依赖数。实测几个标准库模块的依赖:

  模块         依赖几条     源码多少行     独立性
  ------------------------------------------------
  json         3            366            中
  csv          5            514            中
  base64       3            629            中
  textwrap     1            498            高

  实测一个反面例子——**你自己写的模块依赖越多,越换不掉:**

      依赖 1 条                     换它要改 1 处
      依赖 6 条                     换它要改 6 处(还要改那 6 个的调用方)
      依赖 20 条                    换它等于重写一片

  **所以【组件化】不是把代码拆碎,是【把依赖变少】。**
  **10.4 讲的设计目标之一【提高构件独立性】,说的就是这一列的数。**

实测:textwrap 1 条依赖、json 与 base64 各 3 条、csv 5 条——依赖越少独立性越高。 依赖 20 条的模块换它等于重写一片——所以组件化不是拆碎代码,是把依赖变少。

30 秒实验

  1. 数一数你项目里最核心那个模块的 import 行数。
  2. 把它依赖最深的那个库换成别的,看要改几处。

常见误区

  1. 以为拆得越碎越组件化。依赖不减少,拆了也换不掉。
  2. 以为依赖多只是不好看。它决定你能不能用别的东西替换。
自测三问(点开对答案) 1. 组件和类库差在哪? —— 独立程度:组件能单独换掉不牵连别人;类库换不掉就成了负担。不是两类东西,是两种评价。 2. 实测几个模块的依赖数是多少? —— textwrap 1 条、json 3 条、base64 3 条、csv 5 条——依赖越少独立性越高。 3. 怎么把东西做成组件? —— 对外只留窄接口、不暴露内部类型、用依赖注入代替直接 new,让对方能换实现。

相关笔记