切开代码,就切开了依赖吗?
从一条要发邮件的规则开始。先把判断和执行分开,再检查分层、对象和抽象:改动一条业务规则时,哪些地方还是必须一起改?
本文的问题 · 17
把可以独立的职责真正拆开
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.同一滴锡上的三次照射,能交换次序吗?
这台极紫外光源先改变锡滴的形状,再将整形后的靶转为等离子体。把每次脉冲都记成一个功率数字,会丢掉前一步为后一步准备了什么。画出每一步前后的锡滴形状,再问「把两步换序,下一束光遇到的还是同一个靶吗?」
原文与时间戳 · 2
It hits one tiny tin droplet three times in a rowwhere you evaporate the pancake and turn it into a plasma.删掉一枚硬币,需要修改每张价格标签吗?
Grey 讨论的关键决定在结算时。先把购物篮内按分计价的商品相加,再对现金总额舍入,与先把每件商品舍入再相加会给出不同数值。用三件各自有尾数的商品算两遍,就能检验一条政策说明是否把舍入放在了正确步骤。
原文与时间戳 · 2
round to the nearest 5 cents for cash transactionsautomatically rounding to the nearest five cents.一套规则可以稳定产生什么结果?
Grey 用陪审团的例子区分程序规定的职责,以及不同规则一起运作后哪些结果可能在实践中维持。先把每条规定写成“谁能在何时改变谁的决定”,再沿无罪与有罪两条路径各走一次。这是对影片所述制度的分析;用来理解某地真实案件时,还需核对适用的具体程序。
原文与时间戳 · 2
juries can't be punished for a wrong decisiontheir not-guilty decision can't be changed.隔离规则之后,哪些决定可以晚一点做?
Rich Hickey 把复杂性与原本可以独立的事物之间的纠缠联系起来。Robert C. Martin 回忆 FitNesse 团队曾用内存和文件保存数据,让应用行为可以先开发,等出现实际需求再选数据库。Rafal Dittwald 的纸牌例子把计算下一回合和打印战报分开,使计算结果可以脱离输出步骤检查。
把同一条规则放进两个问题里检查。换一种存储时,规则能否照常执行?改变要输出的内容时,规则与执行输出的代码各要改哪里?第一个问题检查实现选择能否推迟,第二个问题检查副作用是否仍然与规则绑在一起。
原文与时间戳 · 3
interconnections between things that could be independenta good architecture allows major decisions to be deferredminimizing concentrating and deferring拆出的对象和文件,分别替谁承担变化?
Pete Hunt 用表格隔行着色说明,模板和控制器分处两地,改一种显示方式仍可能要修改它们共同约定的字段。Jack Diederich 从另一头检查边界。他举的问候对象只保存一个参数、调用一次方法,函数就能表达它要做的事;如果一组操作确实共同维护一份可变数据,他认为类就有作用。
选一项将要发生的修改,列出必须随它改变的数据和规则。这比数文件或类更容易看出,拆分之后哪些改动仍会一起发生。
原文与时间戳 · 3
templates separate technologies and not concerns.you should have just written a functiona bundle of mutable data and a bunch of related functions入口统一以后,谁少维护一项,谁多一项协调?
Rails World 2024 上,Hansson 介绍用同一种数据库系统支持后台任务、缓存和 WebSocket 通信。他的目标是减少应用团队在上线时要学习和运维的组件。Muratori 的提议落在另一层。他想为整套片上系统规定可直接编程的稳定接口,并在问答里指出,厂商就共同接口达成一致要花时间。两段论证各自点出一个承担方。评估统一方案时,可以同时问,使用者可以少维护哪些东西,以及以后要修改这个约定时,哪些提供者需要一起行动?
原文与时间戳 · 2
one thing to learn one thing to operatepeople have to agree and agreeing on things takes time读完再想一步
画出一次规则变更会波及的地方,再看文件边界是否与它重合。