切开代码,就切开了依赖吗?
从一条要发邮件的规则开始。先把判断和执行分开,再检查分层、对象和抽象:改动一条业务规则时,哪些地方还是必须一起改?
本文的问题 · 11
把可以独立的职责真正拆开
Simple Made Easy 建议辨认原本可独立却被纠缠的部分;Boundaries 将计算核心与命令式外壳分开,是可以用来检验这一原则的具体架构例子。
对照原文与时间戳 · 2
start seeing interconnections between things that could be independentan imperative shell that surrounds the functional core.这是跨资源分析,不是讲者宣称的继承关系;拆层的价值取决于真实依赖,而不是增加模块数量。
把副作用集中起来,让其余行为更容易推理
Overwatch 的 ECS 讲解指出主要行为副作用集中在一个调用侧;Bernhardt 则把决策留给函数式核心,并由命令式外壳处理数据库和邮件。合读可看到两种架构都通过明确副作用边界,降低理解和测试时需要追踪的交互范围。
对照原文与时间戳 · 2
all major behavioral side effects are localized to that call sidean imperative shell that surrounds the functional core.ECS 的系统调用组织与函数式核心/命令式外壳不是同一种模式;不能据此认为所有副作用都应放进单一函数或单一文件。
不必更换语言,也能隔离副作用
函数式是否主流的演讲把语言流行与无突变风格区分开;Boundaries 在 Ruby 中用值驱动的核心处理决策、命令外壳承接 I/O,提供无需先改语言的具体做法。
对照原文与时间戳 · 2
no language features are required to program this stylethe expired users class makes all the decisions and the sweeper class has all the dependencies.Ruby 不会自动禁止突变;该设计靠边界纪律,且外壳仍保留必要副作用。
值的语义,如何落实为模块边界?
Hickey 强调不可变和语义透明;Bernhardt 展示以值作为交互边界,减少同步方法调用及测试替身的耦合。前者解释值的性质,后者给出组织代码的具体策略。
对照原文与时间戳 · 2
values are immutable right and values are semantically transparentwe now have values as boundaries.值并不自动保证整个系统纯函数化;I/O 仍留在外壳。两位讲者没有在这些片段中直接互相回应。
形式分层不足以消除语义纠缠
Simple Made Easy警告分开类与层次并不自动带来简单;Maybe Not用schema示例指出把数据形状和调用场景的可选性绑定会造成复用困难,修正需要分离这两个语义维度。
对照原文与时间戳 · 2
it's a mistake to put optionality in aggregate definitionsdon't associate simplicity with partitioning and stratification, right?不主张任何模块拆分都无效;Maybe Not讨论特定信息约束建模。
小组件与值边界都在减少彼此耦合
Metz 建议把代码拆成更小的东西;Bernhardt 说明以值作为对象边界,可以替代组件之间的同步方法调用。合读可把“缩小组件规模”和“选择低耦合交互方式”看作两个不同但互补的边界设计手段。
对照原文与时间戳 · 2
make smaller thingswe now have values as boundaries.小类或小方法不自动形成良好边界;值边界的好处取决于交互是否适合通过数据传递表达。
提防错误抽象,也要让必要抽象足够深
Metz 提醒保留重复有时比维护错误抽象便宜;Ousterhout 则强调深模块以简单接口隐藏大量能力。把两者并读可帮助判断抽象质量:抽象不应只是消除重复,而应真正提供稳定、足够有价值的能力边界。
对照原文与时间戳 · 2
It is far cheaper to keep duplication than it is to have to mess with the wrong abstraction.very simple interface with a very large amount of functionality underneath it两位讲者没有互相回应。Metz 反对的是错误抽象,并未主张避免一切抽象;Ousterhout 也没有说每段重复代码都应被抽成模块。
都在写类,却对面向对象给出不同建议
Metz 建议把类、方法和相互依赖变小;另一位讲者主张转向过程式风格,却明确说问题并不在类本身。两个片段帮助区分语言构造与组织代码的方式。
对照原文与时间戳 · 2
make smaller thingsthe problem is really not classes per se不能从标题推断两人对每种类设计都直接对立;这些片段不构成相互回应。
从识别结构纠缠,退回到审视构思
Simple Made Easy 让我们检查概念之间不必要的关联;Hammock 则提醒许多严重问题源于错误构思。两者把关注点从更快地写出代码移向先理解问题与结构。
对照原文与时间戳 · 2
start seeing interconnections between things that could be independentmost of the big problems we have with software are problems of misconception两段分别谈系统结构与问题求解,不可把所有构思错误归因为耦合,也不是效率提升的实证证明。
拆成两个类以后,怎样判断真的拆开了?
先用设计讲座里的做法写下障碍:每次换邮件服务都得改到期计算。熟悉的新库也许很好用,但《Simplicity Matters》提醒我们,熟悉程度不说明两个职责是否还纠缠。Sierra 把依赖显式交给系统装配,Hickey 的 transducer 则把逐项处理从承载它的集合或通道抽出。可用两次替换来检验:替换服务而不改判断,再把同一判断放在另一条输入流上;哪一次还得重写规则?
原文与时间戳 · 4
describing, diagnosing, delimiting the problem, choosing a direction at a high levelIt is really about the interleaving, not the cardinality.I'm going to do is declare my dependencies and they'll get filled in laterthe exact same process bags I defined here, this concrete thing being reused in a completely different context谁选择给人看的候选项?
Urmson 的车遇到可能迈步的行人,可以先放慢速度再观察。这里动作的作用之一是给下一次判断买时间。Suarez 谈到另一种决策边界:如果传感器产生的数据多到人看不完,机器必须先选择给人看什么,人保留最后批准权也只能批准已进入队列的对象。读这两段时,可以把「收集新证据」「选择候选」「批准行动」画成三步,然后逐步检查是谁能改变下一步看到的东西。
原文与时间戳 · 2
Whereas a self-driving system can look at that pedestrian and say, I don't know what they're about to do, slow down, take a better look, and then react appropriately after that.drones will tell humans what to look at, not the other way around.读完再想一步
画出一次规则变更会波及的地方,再看文件边界是否与它重合。