| name | software-design-philosophy |
| description | 评估、诊断和改进软件架构、模块边界与接口设计。当用户要求审计当前架构并报告问题、风险和建议,区分架构问题与实现细节,分析系统为何难以理解或修改,裁决模块如何划分、接口如何覆盖真实需求与扩展,以及在性能、兼容性、部署等约束下进行结构设计或规划遗留系统演化时使用。不用于纯语法或库用法查询、仍在扩大的生产事故止血、设计已经确定的机械实现,以及没有行为收益的风格清理。 |
软件设计哲学
把软件设计问题转化为可观察的复杂性证据,再联合所需方法与结构候选。不要把本技能当作原则或 pattern 清单:广义架构审计要完整加载发现判据,其他任务按需加载;加载不等于机械执行全部流程或采用流行组件。
主书 John Ousterhout 的《软件设计的哲学(第二版)》决定评价尺度和方法边界;Robert C. Martin 的《架构整洁之道》补充案例、依赖判据和实现细则;《架构设计的本质》补充从性质、受众、利益、目标和建模到架构、建设与验证的纵向设计链,以及实体、功能、关系、边界和外部环境的横向系统分析;System Design 101 补充具体结构 pattern、失效场景和演化案例。来源发生张力时,遵循本文件的裁决、来源裁决和 System Design 101 来源边界,主书优先;pattern 只是受真实压力准入的候选。
核心定义
- 架构设计:承接系统的风险、主体、价值、目标和需求模型,对系统中的实体、责任及其关系进行抽象,决定如何按知识与变化划分单元、谁拥有关键决策与不变量、单元如何协作,以及运行、部署和生命周期责任如何安排。它规定系统的构造规则,并约束一族后续实现。
- 系统实体:本次范围内参与系统行为的稳定对象,可以是参与者、模块、进程、数据、设备或外部系统;不是看到领域 Entity、代码类或数据库表就直接映射成架构元素。
- 实现细节:在既定边界、责任和契约内,某个单元如何完成工作。只要替换它不要求调用者或其他单元改变契约、知识、依赖方向、生命周期责任或部署协作,它就是相对于该边界的实现细节。
- 明确边界:先固定正在评价的系统范围。决定若改变该范围内的实体/责任划分、稳定关系、外部边界、跨边界契约或关键质量约束的分配,就是架构决定;若能在其中一个既定单元内独立替换而不改变这些事项,就是实现细节。无法证明任一侧时列为候选,不靠代码位置或职位名称猜测。
- 二者不是“高层/低层”或“大改/小改”的绝对分界,而是连续体中的操作性分类。底层的所有权、持久化保证、内存布局或协议选择一旦成为跨边界契约,也可能是架构决定;严重的局部漏洞仍可能只是实现问题。
- 架构问题不是任何架构相关代码中的缺陷,而是已有证据表明某个结构决定通过边界、依赖、知识归属、接口或生命周期责任,系统性增加真实任务的变更、理解、运行或协调成本。完整准入见 软件架构审计。
执行流程
1. 固定用户目标,不让上下文扩张任务
先用用户自己的表述写清这次要达到的结果、交付物、范围和授权动作,不替用户归纳成预设任务类型。再把其余输入区分为:
- 背景与倾向:例如 performance-first、兼容优先、公开插件生态、当前保持单体;
- 硬约束:必须满足的正确性、延迟、资源、安全、平台或发布条件;
- 证据:代码、真实任务、变更历史、benchmark、profile、事故和调用方行为。
背景、倾向、约束和证据会修正判断、否决方案或触发方法联合,但不会自行改变用户目标或新增交付。只有用户明确改变或扩展目标时,才随之调整任务范围。
- 生产事故仍在扩大时,先止血、隔离和恢复;稳定后再讨论长期结构。
- 纯语法、框架参数、单次机械修改或无行为收益的风格偏好,直接完成任务,不展开本技能。
- 只有“感觉系统很乱”而没有明确根因时,先从真实任务采样,不凭代码行数、层数或类数量下结论。
- 用户已经给出明确设计问题时,直接进入对应方法,不强制先做全系统诊断。
- 用户要求“评估/审计当前仓库或子系统架构并报告问题、风险、建议”时,先完整读取 软件架构审计,再按其中加载合同逐一读完全部 11 个方法、系统设计模式选择器及四个 pattern 家族。它们共同参与候选发现,但只对证据命中的方法执行深入产物、只对条件成立的 pattern 形成候选;必须先判类别,再评严重度。
2. 从真实任务、约束和压力建立评价基线
优先检查真实代码、接口、变更记录、调用方胶水、错误路径、运行测量或用户给出的实际用例。把事实、假设和待验证项分开。先有评价基线,再使用方法;不要仅凭抽象原则要求重写。
至少明确:
- 当前任务与期望结果;
- 真实使用者及其完整工作流;
- 已发生或有明确外部证据的约束、压力与失败后果;
- 哪些任务高频,哪些后果高影响,当前成本落在谁身上;
- 哪些决定已确定,哪些仍待选择;
- 改动范围以及必须保留的行为。
架构审计先建立下表;范围很窄的明确设计问题可以只保留相关行:
| 输入 | 性质:背景/约束/证据 | 来源 | 受影响的使用者/任务 | 频率与失败后果 | 对本次交付的作用 |
|---|
每个被选方法必须回答一个处于用户目标范围内的问题;每项范围内的高权重压力必须得到处理,或明确列为证据缺口。不要把同一封装模板套给所有仓库:真实任务和压力不同,合理的知识边界、接口与逃逸也会不同。
3. 按证据选择方法集合与结构候选
11 个方法 references 回答怎样发现、裁决和验证设计;pattern references 提供可复用的结构动作。二者都可联合,不是互斥流程标签。普通设计任务按用户目标、真实压力和证据读取所需内容;广义架构审计按完整加载合同读取全部方法和四个 pattern 家族,避免“没读判据所以看不见问题”。不设置主/辅或数量上限。读取只提供判断上下文,不代表执行全部步骤、采用 pattern 或输出整套手册。
| 问题或证据信号 | 可用 reference | 第一动作 |
|---|
| 评估/审计仓库架构,输出当前问题、风险和改进建议 | 软件架构审计 | 固定范围,完整加载 11 个方法与四个 pattern 家族,完成细则覆盖,再执行问题准入和风险分栏 |
| 需要从微服务、Gateway、消息、缓存、分片、复制、韧性或发布等结构中选择,但不接受组件清单式设计 | 系统设计模式选择器 | 先写完整工作流、压力与契约,再路由到相关 pattern 家族并比较更简单候选 |
| 局部修改牵动多处、背景知识过多、经常遗漏隐蔽依赖,但根因尚不清楚 | 复杂性加权诊断 | 重放近期真实任务,区分变更放大、认知负荷与未知依赖 |
| 给现有系统加功能或修缺陷,需要在期限内改善结构而不是留下永久补丁 | 战略式演化设计 | 写出目标抽象、最小结构切口和分期退出条件 |
| 要用少量接口覆盖多数真实需求,调用方胶水或配置膨胀,并要治理长尾能力 | 深模块设计闭环 | 建立加权用例、知识、覆盖和逃逸表 |
| 同一格式、规则、状态机或内部表示在多个模块重复解释 | 信息泄露审计 | 以设计知识为单位画出依赖图并指定唯一权威 |
| 纠结两个类、函数、服务或组件该合并还是拆分 | 组合或拆分 | 比较共享知识、变化轴、共同使用和边界成本 |
| API 异常过多,各层反复捕获、转换、重试或包装 | 缩减异常处理面 | 依次判断能否定义消除、就地恢复、边界聚合或明确失败 |
| 第一个重要方案看似可行,却缺少真正不同的候选和统一比较 | 设计两次 | 画出至少两个结构不同的候选并用同一组真实用例评分 |
| 新接口难以说清行为、约束、副作用、不变量或失败语义 | 注释优先的抽象设计 | 在实现前写面向调用者的简短完整契约 |
| 核心概念和契约已经选定,但读者仍猜错名称、控制流或代码入口 | 读者易理解性闭环 | 记录首次阅读的误解路径,再减少必须知道的信息 |
| 有明确延迟、吞吐、CPU、内存或 I/O 目标及运行证据,准备引入缓存、并行或快速路径 |
四个具体候选家族为:结构与边界、通信与工作流、数据与一致性、韧性/伸缩/交付。普通任务由选择器按压力读取;广义架构审计全部读取。
术语含义不清或多个方法使用同一概念时,按需读取 共享术语词典;模式、组件、架构发现和实现细节混淆时读取 系统设计模式选择器。
4. 处理容易混淆的进入条件
按以下优先级裁决,不要因为关键词相同就同时展开多个方法:
- 尚不知道哪里复杂:先做复杂性诊断;已定位为某项共享知识散落时,直接做信息泄露审计。
- 不知道什么最重要:先围绕重要性设计;核心概念已经确定、只是不易被读者看见时,做读者易理解性闭环。
- 边界在哪里尚未确定:先裁决组合或拆分;边界已确定、需要设计有限接口及长尾出口时,做深模块设计。
- 接口整体尚未形成:做深模块设计;接口总体稳定、只剩错误和恢复责任时,做异常处理面设计。
- 重要候选需要纸面比较:做设计两次;性能候选的去留依赖实际收益时,必须转入关键路径测量。
- 实现前无法表达契约:做注释优先设计;契约已清楚但实现仍让读者误解时,做易理解性闭环。
- 已有明确变更且受交付约束:使用战略式演化组织交付台阶,同时按根因联合专门方法,不要把诊断报告当交付物。
- 以性能为由要求穿透底层,但没有目标、基线或剖析:先用围绕重要性设计反查通用接口是否失当。只有确认接口没有遗漏核心原语,并取得真实热点证据后,才转入关键路径测量或设计受控逃逸。
- 背景不是新任务:性能、安全、兼容性或部署倾向可以改变架构判断和验证条件,但不能把架构审计扩张成性能、安全或运维专项手册;用户明确要求组合任务时再完整展开。
5. 让方法围绕同一真实任务协作
下面是常见的协作关系,不是固定流程,也不要求从左到右全部执行。方法的进入与先后由知识依赖和真实证据决定:
- 新模块经常同时需要重要性、候选比较、深模块和契约设计。
- 遗留系统变更经常把复杂性诊断、根因专门方法和战略式演化结合起来。
- API 重构可同时使用深模块与异常处理;契约难以表达时加入注释优先。
- 边界重组可联合信息泄露与组合/拆分;新边界确定后再检查接口深度。
- 性能改造以测量为准入;若热点涉及公共边界,同时使用重要性和深模块处理性能逃逸。
- 架构审计让全部 11 个方法参与设计细则覆盖;再由真实压力决定哪些方法深入展开。覆盖义务不是固定执行顺序,也不要求每种细则都产生问题。
- 广义架构审计还让结构与边界、通信与工作流、数据与一致性、韧性/伸缩/交付四个 pattern 家族参与候选发现;缺少某个 pattern 不是问题,已有 pattern 也不是健康证据。
- 性能取向的架构审计仍以架构问题为交付;性能方法用于保护已证实的关键路径、判断逃逸是否合理并约束候选。用户要求性能优化或架构性能调优时,再完整执行测量、热点和 A/B 流程。
当多个方法给出不同方向时,回到同一真实任务,比较它们对整体理解、修改、运行和失败成本的净影响;不要靠“哪个是主方法”裁决。
全局裁决
这些规则覆盖各 reference 中可能产生歧义的辅助观点:
- 以真实任务造成的整体理解和修改成本评价设计,不把行数、层数、类数、组件指标或“策略/细节”标签当自动结论。
- Pattern 不是方法、需求或结论。任何 pattern 推荐都必须给出真实压力、关键契约、知识所有者、结构动作、新增成本/失效方式、更简单候选、验证和退出;技术品牌不能代替其中任一项。
- 不从“读多、数据大、要高可用、服务多、云原生”等标签直接推出缓存、分片、双活、Gateway、消息队列或微服务。组件缺失不构成架构问题,组件存在也不证明结构合理。
- “严重”与“属于架构”是两个不同判断。局部安全、配置、测试或实现问题可以具有最高全局严重度,但只有证据落到边界、依赖方向、知识归属、接口或生命周期责任,并产生系统性理解/修改成本时,才进入架构问题主表。
- 循环构造、跨层引用、基础设施类型穿透、进程数量和目录形状都只是调查线索;必须说明它们通过什么结构机制影响真实任务,不能看见关键词就定罪。
- 封装服务于仓库的核心任务,不是越多越好。若调用者必须控制所有权、生命周期、数据布局、批量边界或硬件能力才能满足已证实的性能契约,这些信息应通过窄而类型化的高级入口显式表达;不能以“隐藏细节”为由强迫复制或阻断关键路径。
- 用户目标决定交付边界;上下文只能修正判断,不能自行扩题。发现范围外高风险事项时简短分栏升级,不顺势完成另一份专项审计。
- 性能取向不自动产生性能问题。它意味着架构发现和建议必须尊重已有性能证据:不能把必要的
view/span、批量接口、编译期结构或多表示直接定罪,也不能提出未经验证的复制、动态分派或跨边界方案。
- 当前实现优先简洁、低代码量和低复杂度。只为已有证据且未来难以逆转的变化保留窄接缝或受控逃逸,不预建全部未来选项。
- 用例和参与者是发现知识与变化轴的证据,不自动等于模块、端口、服务或部署边界。
- 出现底层依赖时,先反查核心接口是否遗漏重要原语;只有调用者确实承担该决策且模块无法推断时,才显式暴露。
- 首版先保证主流程正确。性能穿透、缓存、并行和快速路径只在测量证明热点,或确有数量级收益且顺序不可反转时进入设计。
- 测试是按风险配置的行为安全网,不是架构生成器。先写目标抽象和行为契约,再决定测试预算;不要用私有分支全覆盖替代设计。
- 拒绝通过多个含状态基类或模板方法实现插件扩展;优先组合、接口、trait 或 C++ concept,并保持状态和调用顺序的唯一所有者。
- 设计深模块时,必须主动询问设计者是否需要独立测试/Agent 调试面。未获明确要求不得创建;获准后才设计与生产严格隔离、具有 schema、幂等、限权、审计和自动回收的 CLI/API。
需要追溯来源分歧、用户原始裁决或 Linux 文件系统补充模型时,完整读取 来源裁决;需要追溯新增 pattern 与案例的材料路径、限制或未吸收主张时,读取 System Design 101 来源边界。
输出约定
除非用户指定其他格式,交付应包含:
- 问题与证据:真实任务、观察事实、约束和仍待验证的假设;
- 方法集合:每个方法在本次目标中负责发现、设计、约束或验证什么,以及为何没有扩张到相邻任务;
- 分析产物:使用所选 reference 要求的表、图、契约、矩阵或实验;
- 设计决定:具体边界、接口、责任、演化步骤或保留/撤销结论;
- 边界与逃逸:不能覆盖的情况、责任归属、风险和重新收编条件;
- 结构候选:若使用 pattern,写清准入压力、契约、代价、失效、与更简单候选的比较;
- 验证方式:调用方演练、变更演练、读者测试、基准或其他可复现证据。
给出可执行决定,不要只复述书中原则。若证据不足以裁决,明确缺口和最小验证动作,不用权威口吻补齐未知事实。
架构审计的完整方法加载、设计细则覆盖、类别与双轨优先级以 软件架构审计 为准,不得把安全、配置、测试或局部实现问题混入架构问题主表来抬高结论。
完成检查
- 是否从真实任务或测量出发,而不是从流行原则出发?
- 是否把用户目标与背景/倾向/约束/证据分开,并避免由上下文擅自扩张交付?
- 每个被选方法是否回答范围内问题,每项范围内的高权重压力是否都得到处理或明确列为证据缺口?
- 若为广义架构审计,是否确实读完全部 11 个方法、模式选择器和四个 pattern 家族,分别给出覆盖结论,并对命中项使用完整判据?每项主表问题是否通过架构准入,相邻 P0 是否单列?
- 若采用或否决某个 pattern,是否以真实压力和契约裁决,并说明新增故障、验证与退出,而不是从标签或公司案例直接映射?
- 是否先按仓库使命和产品约束选择判据,而不是套用固定分层/封装模板?
- 若性能是背景约束,是否用它修正架构判断而未自动输出性能手册;若用户要求性能设计,是否取得相应测量?
- 是否把事实、假设和偏好分开?
- 是否同时考虑调用者成本、实现成本和长期修改成本?
- 是否说明不能覆盖的情况及其受控处理方式?
- 是否尊重当前简单性、显式高风险决策和用户已裁决的边界?
- 若涉及深模块,是否主动询问调试面需求且未擅自创建?
- 是否提供了能够推翻或验证当前决定的证据?