🧩 第十章 面向对象设计:拟人化和职责分配
📄 一句话概括

职责分好之后,没有一个类需要懂业务全貌——实测上帝类要知道 8 件事,拆分后最多的一个类只要 3 件,但合起来什么都能干。

📝 本节和前面几节的关系

10.7 讲了分工的手感,这一节讲分工之后得到什么。

一、上帝类的问题

一个类知道 8 件事(额度、在不在架、借出日、应还日、罚款标准、逾期天数、是否已缴、通知谁)。 它能干所有事,但没有一件是它的专长。 最要命的是不能单独测:测罚款得先造出读者、书、借阅记录。

二、实测:8 件降到 3 件

拆成 5 个类:Reader(额度)、Book(在架)、Loan(三天日期)、Fine(标准与是否已缴)、Notifier(通知谁)。 上帝类要知道 8 件,拆分后没有一个类超过 3 件。 加一个通知渠道:上帝类要改那个唯一的类(等于改全部),拆分后只改 Notifier。

三、【奇妙】在哪

没有一个类懂业务全貌,但合起来什么都能干——这就是分工的奇妙。 每个人只管自己那一小块,接口对上就行,像一家公司而不是一个人。 所以 7.6 说业务本身就是一堆对象在分工——这句话在代码里应验了。

四、代价也要认

看一个功能要跳好几个类,读起来累。 所以要靠时序图和文档补回来(第八章那两张图正是干这个的)。 还有一个隐形成本:类多了,找东西变难——包和命名要跟上。

五、动手 Demo:进行了职责分配的软件创建的奇妙世界

对比上帝类与拆分后:类个数、单个类要知道的件数、加需求改哪里、能不能单测。 看【单个类要知道的事】降了多少。

god = ["读者额度", "书在不在架", "借出日", "应还日", "罚款标准",
       "逾期天数", "是否已缴", "通知谁"]
split = {"Reader": ["额度"], "Book": ["在不在架"],
         "Loan": ["借出日", "应还日", "逾期天数"],
         "Fine": ["罚款标准", "是否已缴"], "Notifier": ["通知谁"]}

print(len(god), max(len(v) for v in split.values()))   # 8 3

实跑输出:

--------------------------------------------------------------------
进行了职责分配的软件创建的奇妙世界
--------------------------------------------------------------------

  职责分好之后,**每个类需要知道的【全局信息】变少了。**实测对比:

  对比项                 上帝类                      职责分配后
  ---------------------------------------------------------------
  类个数                 1                           5
  单个类要知道的事       8                           最多 3 件
  加一个通知渠道改哪     改 1 个类(但它是全部)     改 Notifier
  能单独测吗             不能                        能

      上帝类要知道的事            8 件
      拆分后最多                  3 件
      【奇妙】在哪                8 件 → 3 件

  **同一个功能,上帝类要知道 8 件事,拆分后没有一个类超过 3 件。**
  **这就是【奇妙世界】的含义**:**没有一个类需要懂业务全貌**,但合起来什么都能干。
  **代价是**:看一个功能要跳好几个类,**所以得靠时序图和文档补回来。**

实测:上帝类要知道 8 件事,拆分后最多的类只要 3 件。 加一个通知渠道:上帝类改那唯一的类(等于全改),拆分后只改 Notifier。 代价是看一个功能要跳好几个类,得靠时序图和文档补。

30 秒实验

  1. 找出你项目里的一个上帝类,数它要知道几件事。
  2. 按职责把它拆一次,看看加一个新需求能只改一个类吗。

常见误区

  1. 以为一个类干所有事最省心。它不能单测、不能复用、不敢改。
  2. 以为拆分没有代价。看一个功能要跳好几个类,得靠图和文档补。
自测三问(点开对答案) 1. 上帝类最大的问题是什么? —— 知道 8 件事、能干所有事但没有专长,且不能单独测试。 2. 实测降了多少? —— 上帝类 8 件,拆分后最多的类 3 件;加通知渠道只改 Notifier。 3. 【奇妙】在哪、代价是什么? —— 没有一个类懂全貌但合起来什么都能干;代价是读一个功能要跳好几个类。

相关笔记