🐎 第9章 集腋成裘:Plugins 生态
📄 一句话概括

四条原则:单一职责、渐进式迭代、最小权限、文档是必需品。四条都不新鲜,但在这个场景下格外要紧。 实测四个包:只有一个全过,一个四条全踩。 而四条全踩的那个,往往是一开始只是「顺手多干一点」。

📝 本章和前面几章的关系

上一节讲怎么发,这一节讲发出去的东西该长什么样。 这一节有真跑:四个包按四条原则逐条查,看谁过谁不过。

一、四条原则各管什么

单一职责:一个包只解决一类问题。混装之后,别人没法只装他要的那部分。 渐进式迭代:从小处开始,用得多了再加。一次写完的包,第一次用就没人敢改。 最小权限:能只读就别给写。包会被装到别人的机器上,权限是你替他要的。

文档是必需品:怎么装、怎么用、边界在哪。没文档的包等于没发布。 四条里前两条管「包的形状」,后两条管「包的边界」。

二、真跑:四个包逐个查

演示里四个包:sec-scan、do-everything、deploy-kit、tmp-helper。 结果只有一个全过;do-everything 四条全踩,另外两个各缺一两条。 do-everything 是最容易被写出来的那种包:六件事都做、一次写完、全权限、没文档。

而它一开始往往只是「顺手多干一点」,攒着攒着就成了一个谁也说不清边界的包。

三、单一职责为什么排第一

因为另外三条都建立在它上面:职责混了,权限就没法收窄,迭代也没法小步走。 实操判据:这个包能不能用一句话说清「它解决什么问题」?说不清就该拆。 拆开之后还有个好处:别人能只装他要的那部分,常驻预算也省(6.7 节那一笔)。

所以「拆」不只是代码整洁的问题,它直接关系到别人的窗口够不够用。

四、最小权限在这个场景更硬

自己机器上的配置,权限给宽了只影响自己。包会被装到别人机器上,权限是你替他要的。 所以包里凡是能只读的,就只读;凡是能限定目录的,就限定。 这一条和 8.8 节那四道防线是一条线:防线是使用者设的,权限是作者该收的。

两边都做,才叫「纵深」;只有一边,另一边就是缺口。

五、文档写什么

三件事:怎么装、怎么用(一条最典型的命令)、边界在哪(它不做什么)。 第三条最常被漏,也最有用:写清「它不做什么」,能挡掉一半「为什么它不帮我……」的问题。 写文档还有一个副作用:你会发现有些组件说不清楚为什么要存在。

而那些说不清的组件,通常就是该删的。

六、动手 Demo:四个包按四条原则打分,只有两个及格

Plugin 的设计原则不多,四条:单一职责、渐进式迭代、最小权限、文档是必需品。 这里拿四个包逐条查一遍,看哪条最容易踩。

rules = [
    (u"单一职责", lambda f: u"只" in f[0]),
    (u"最小权限", lambda f: u"只读" in f[2]),
    (u"文档", lambda f: u"README" in f[3]),
]

实跑输出:

--------------------------------------------------------------------
四个包按四条原则打分,只有两个及格
--------------------------------------------------------------------

  Plugin 的设计原则不多,四条:单一职责、渐进式迭代、最小权限、文档是必需品。
  四条都不新鲜,但它们在「打包分发」这个场景下格外要紧——因为包会被别人装走。

  ① 四条原则各管什么
  --------------------------------------------------------------------
| 原则 | 要求 | 不遵守会怎样 |
|---|---|---|
| 单一职责 | 一个包只解决一类问题 | 混装之后,别人没法只装他要的那部分 |
| 渐进式迭代 | 从小处开始,用得多了再加 | 一次写完的包,第一次用就没人敢改 |
| 最小权限 | 能只读就别给写 | 包会被装到别人的机器上,权限是你替他要的 |
| 文档是必需品 | 怎么装、怎么用、边界在哪 | 没文档的包等于没发布 |


  ② 真跑:四个包逐个查
  --------------------------------------------------------------------
| 包 | 单一职责 | 迭代 | 最小权限 | 文档 | 合计 |
|---|:---:|:---:|:---:|:---:|:---:|
| sec-scan | 过 | 过 | 过 | 过 | 4/4 |
| do-everything | 没过 | 没过 | 没过 | 没过 | 0/4 |
| deploy-kit | 过 | 过 | 没过 | 过 | 3/4 |
| tmp-helper | 过 | 没过 | 过 | 没过 | 2/4 |

  四个包里只有一个全过;do-everything 四条全踩,deploy-kit 和 tmp-helper 各缺一两条。
  do-everything 是最容易被写出来的那种包:六件事都做、一次写完、全权限、没文档。
  而它一开始往往只是「顺手多干一点」,攒着攒着就成了一个谁也说不清边界的包。

  ③ 单一职责为什么排第一
  --------------------------------------------------------------------
  因为另外三条都建立在它上面:职责混了,权限就没法收窄,迭代也没法小步走。
  实操判据:这个包能不能用一句话说清「它解决什么问题」?说不清就该拆。
  拆开之后还有个好处:别人能只装他要的那部分,常驻预算也省(6.7 节那一笔)。

  ④ 最小权限在这个场景更硬
  --------------------------------------------------------------------
  自己机器上的配置,权限给宽了只影响自己。包会被装到别人机器上,权限是你替他要的。
  所以包里凡是能只读的,就只读;凡是能限定目录的,就限定。
  这一条和 8.8 节那四道防线是一条线:防线是使用者设的,权限是作者该收的。

  ⑤ 文档写什么
  --------------------------------------------------------------------
  三件事:怎么装、怎么用(一条最典型的命令)、边界在哪(它不做什么)。
  第三条最常被漏,也最有用:写清「它不做什么」,能挡掉一半「为什么它不帮我……」的问题。
  ! 这四条是教材归纳的设计原则,打分是示意,用来对照自己的包,不做评级。

①四条:单一职责(只解决一类问题)、渐进式迭代(从小处长起来)、最小权限(能只读就别给写)、 文档是必需品(怎么装、怎么用、边界在哪)。 ②四个包里只有一个全过。do-everything 四条全踩——六件事都做、一次写完、全权限、没文档。 而它一开始往往只是「顺手多干一点」,攒着攒着就成了谁也说不清边界的包。 ③单一职责排第一,因为另外三条都建立在它上面:职责混了,权限没法收窄,迭代也没法小步走。 ④最小权限在这个场景更硬:自己机器上给宽了只影响自己,包会被装到别人机器上,权限是你替他要的。

30 秒实验

  1. 把 do-everything 拆成两个包,重跑一遍。四项检查里哪几项会同时变好? 这说明「拆」的收益是单点的还是连锁的?
  2. 给 deploy-kit 的权限从读写改成只读,重跑一遍。它的功能会缺什么?这个缺口该怎么补?
  3. 给 tmp-helper 补一份 README,重跑一遍。它现在过几条?还差的那条为什么不写文档就发现不了?

常见误区

  1. 一个包装下六件事。别人没法只装他要的部分,权限也没法收窄。
  2. 一次写完再发布。第一次用就没人敢改,因为不知道改了会牵连什么。
  3. 给包全部工具权限。「能用得上」不是给权限的理由,包会被装到别人机器上。
  4. 不写「它不做什么」。会有一半的问题在问「为什么它不帮我……」。
  5. 以为设计原则是软的。在这个场景里,每一条都对应一个具体后果。
自测三问(点开对答案) 1. 四条设计原则是什么? —— 单一职责、渐进式迭代、最小权限、文档是必需品。 2. 为什么单一职责排第一? —— 因为另外三条都建立在它上面:职责混了,权限没法收窄,迭代也没法小步走。 3. 文档该写哪三件事? —— 怎么装、怎么用、边界在哪(它不做什么)。第三条最常被漏,也最有用。

原则有了,但打包本身有成本。下一节回答:什么时候不值得打包。

相关笔记