← 全部笔记

架构拓扑与选型

用于技术栈、模块边界或部署方式尚不清楚的任务。已有结构能满足需求时沿用,不为采用模式而重构。

从约束选技术

先沿本次任务从触发、执行走到完成或退出,找出必须兑现的行为和运行约束,再判断现有能力缺在哪里。组件能完成某一步,不代表整条任务成立;不要从熟悉的技术组件反推产品方案。确有缺口再决定新增、替换还是沿用。

默认沿用。 惯性是给问题配新工具;先查项目里已有的能力,能复用就不引入。新增要能指出它解决的需求或遇到过的障碍,说不出就先不加。

有缺口才选型,只比少量候选,先用硬约束排除不可行的选项:运行环境、权限、数据能否离开本机、性能与合规。工具必须离线、文件不能上传,本地方案优先;多人跨设备协作,则要核对共享状态、身份与同步。

缺口先问先例。 要补的机制,先看手头栈的配置面,再看生态里有真实用户的成熟实现,按“直接采用、移植其逻辑与测试、循其约定换机制、自研”定位,前三种不引入运行时依赖。选自研时,对照成熟实现写明差异与代价。

在剩余候选里比代价:成本、接入步骤和维护负担容易被低估,要算进去;性能与成本的判断不靠感觉,用代表性数据核实。要求、偏好和假设分开,影响选择的未知先做最小验证,例如在目标设备上测一次导入耗时。

常见场景有默认倾向:

  • 数据:关系约束和事务是重点就用关系型数据库,“数据是文档形态”不是换库的充分理由。
  • 性能:先定位慢查询或重复计算,再谈索引和缓存;引入缓存要一并考虑失效、容量与不可用时的行为,不默认加 Redis。
  • 结构:单体优先,独立扩容、隔离的收益足以抵消部署和一致性成本时才拆服务。
  • 依赖:小工具函数自写通常优于引依赖;机制逻辑的成熟实现优先于自研。新增依赖看版本兼容、维护状态、许可和供应链风险。

决定和依据写入已有任务记录;改变对用户的既有承诺前,先取得确认。

划分可理解的边界

沿入口、业务规则、数据与外部副作用追踪一条真实调用链,明确谁判定操作有效、谁执行、谁确认结果,失败后谁继续负责恢复。跨边界交接要说明接收方接管什么、何时原责任才结束。边界可以是函数、模块或服务,不要求固定目录层数。

业务政策由掌握其含义的模块决定,协议转换、存储访问等模块提供执行能力,避免同一规则散落在多个入口。例如缓存什么、允许数据陈旧多久由业务语义决定,缓存读写由具体组件实现;这种职责分离不要求新增层级或转发类。

依赖方向上让容易变化的部分依赖稳定的部分:业务规则通常比框架、存储等技术选型稳定,协议转换与存储实现围绕业务规则适配,而不是相反。

复杂规则需要独立测试时,可分离规则计算和数据库、网络操作。领域驱动设计(DDD)适合领域规则与语言足够复杂的情况;三层架构适合项目已有约定。简单脚本或增删改查不必增加转发类。

共同记录只说明本次必要边界和理由;代码路径足以表达结构时不画结构图,跨模块职责难懂时才补局部图。

隔离第三方依赖的变化

第三方库的 API、模块结构或实现发生变化,不应迫使业务代码跟着大范围重构。对影响面广、替换风险高或承载业务语义的外部能力,优先通过项目自有的稳定契约访问,将第三方导入、类型、调用方式和错误转换集中在适配模块中。

契约围绕业务需要设计,不照搬库的完整 API,也不向调用方泄露第三方专有对象。边界可以只是一个函数或模块,不必引入类、依赖注入框架或为每个库建立包装层;局部使用的简单工具,直接调用通常更清楚。

例如业务需要的是验证密码,而不是调用某个 bcrypt 包:

interface PasswordService {
  verify(plainText: string, storedHash: string): Promise<boolean>
}

业务代码只依赖 PasswordService,具体包由密码服务的实现模块导入并适配。更换 bcrypt 实现库时,目标是将改动收敛在该模块,保持调用方契约不变。

替换验证不能只看编译通过或修改文件数量:应覆盖正确与错误密码、历史哈希兼容性、异常行为和安全参数。更换实现库与更换密码算法是不同的变化;算法改变仍可能需要兼容旧哈希并逐步迁移,接口隔离不能消除这些真实成本。

增量修改的影响面

查找调用者、导出接口、定时任务和共享状态,区分新增、替换、保留部分。性能修改保留基线,用同一负载对照。避免将局部优化扩展成未授权的整体重写。

仓库内搜不到调用者不等于没有兼容义务。公共接口、导出格式和可被解析的输出,还应按影响范围查发布说明、接口文档、历史样例、存量数据、实际使用记录及已知外部消费者;行为看似有误,也可能已被用户脚本依赖。

缺少文档或测试时,用代表性输入保存现有行为,再向受影响使用者或维护者核实其依赖。旧输出只证明现状,不自动成为正确规范;无法确认外部依赖时说明未知及改变的代价,不宣称“无人使用”。涉及破坏既有承诺时先确认替换或迁移办法,再变更;验证既覆盖新行为,也覆盖需要保留的消费者路径。

Arkk

专题 · 关于