For AI agents: the complete documentation index is available at https://tingfeng347.github.io/windwiki/llms.txt, the full documentation bundle is available at https://tingfeng347.github.io/windwiki/llms-full.txt, and this page is available as Markdown at https://tingfeng347.github.io/windwiki/terminology/software-engineering.md.

软件工程与架构 · 面试清单

面试权重:★★★★★ 区分「会写代码」与「会做设计」的分水岭;问法多为「你项目里怎么做的」,光背定义会被追问穿。


一、复杂度与设计原则

术语一句话释义
本质复杂度问题本身固有的复杂度,无法消除,只能承认(Brooks, 1986)
偶然复杂度由工具、技术选型、架构不当引入的复杂度,是工程师真正该消除的部分
内聚 Cohesion模块内部元素的相关程度;功能内聚最高,逻辑/时间内聚最低——越高越好
耦合 Coupling模块之间的依赖强度;内容耦合最差,非直接/消息耦合最好——越低越好
高内聚低耦合一切设计原则的目标函数,其余原则都是实现它的手段
SRP 单一职责一个类只对一个变化原因负责,判据是「变化的原因」而不是「代码行数」
OCP 开闭原则对扩展开放、对修改关闭,靠抽象与多态实现
LSP 里氏替换子类必须能替换父类而不改变程序正确性;违反的典型是正方形继承长方形
ISP 接口隔离不强迫客户依赖用不到的方法,接口要小而专
DIP 依赖倒置高层与低层都依赖抽象,抽象不依赖细节;它是插件式架构的理论基础
DRY消除知识的重复而非代码字面重复,滥用 DRY 会造出高度耦合的抽象
KISS / YAGNI保持简单 / 不要实现当下用不到的功能,是控制偶然复杂度的第一手段
迪米特法则只与直接朋友说话,减少链式调用 a.getB().getC().do()
组合优于继承继承是强耦合的白箱复用,组合更灵活、更易测试
康威定律系统架构会复制组织的沟通结构——想改架构先改团队划分
逆康威定律反过来按目标架构调整团队,用组织设计反推系统演进(Team Topologies)
最少知识原则模块不应了解它不需要知道的东西,与迪米特法则同源

二、DDD 领域驱动设计

术语一句话释义
DDD 解决什么问题业务复杂度高、模型需要反复演化时,用统一语言与限界上下文把复杂业务切割清楚
通用语言 UL业务与研发共用的一套术语,代码里的类名必须与之对应,否则模型会漂移
限界上下文 Bounded Context一个术语有明确边界与统一语义的范围;同一个词在不同上下文含义可以不同
战略设计划定边界:子域划分 + 上下文映射 + 通用语言,决定「怎么拆」
战术设计在单个上下文内建模:实体、值对象、聚合、领域事件、仓储等,决定「怎么建」
核心子域 / 支撑子域 / 通用子域核心竞争力 / 必须做但不差异化 / 直接买或开源的,资源应按此分配
上下文映射上下文之间的集成关系,共 6 种:共享内核、客户-供应商、遵奉者、防腐层、开放主机服务、各行其道
防腐层 ACL在外来模型与本域模型之间加一层转换,避免外部概念污染本域
共享内核多个上下文共享一小块模型,耦合最强,必须严格控制规模
客户-供应商 / 遵奉者上游按下游需求排期 / 下游无条件接受上游模型
实体 Entity有唯一标识、生命周期内身份不变的领域对象(订单、用户)
值对象 VO不可变、无标识、由属性值定义相等的对象(金额、地址),优先使用它
聚合 Aggregate一致性边界:一组对象的整体,事务以它为最小单位
聚合根 Aggregate Root聚合的唯一入口,外部只能通过它引用内部;它负责维护内部不变式
聚合设计原则聚合要小、一次事务只改一个聚合、跨聚合用最终一致
领域事件 Domain Event领域内已发生的事实(OrderPlaced),用于解耦副作用与跨上下文集成
领域服务不属于任何实体的领域行为(如转账),无状态
应用服务编排用例:加载聚合、调用领域行为、保存、发事件;不含业务规则
仓储 Repository以「集合」的语义提供聚合的持久化入口,屏蔽数据库细节
工厂 Factory封装复杂对象的创建逻辑,保证创建即合法
贫血模型 vs 充血模型只有 getter/setter 的是贫血模型,业务逻辑散落在 Service;充血把行为放进对象,才是 DDD 的做法
DDD 常见误用用小规模 CRUD 项目硬套 DDD、把所有表都拆成聚合、限界上下文与微服务一对一绑定

三、架构描述与决策

术语一句话释义
质量属性性能、可用性、可修改性、安全性、可测试性、易用性等非功能需求,是架构的主要驱动力
质量属性场景六要素刺激源、刺激、环境、制品、响应、响应度量——把模糊的「要快」写成可验证的句子
架构战术实现质量属性的具体手段:性能用资源调度与并发引入,可用性用心跳与冗余,可修改性用封装与限制依赖
敏感点 vs 权衡点 vs 风险点显著影响某质量属性的决策 / 同时影响多个属性需取舍的决策 / 可能出问题的决策
4+1 视图逻辑、进程、开发、物理 + 场景视图,从不同关注点描述同一架构
C4 模型Context、Container、Component、Code 四层递进,一个图只能有一个抽象层级
ADR 架构决策记录一页纸记录一次决策的背景、选项、决策与后果,重点写清「被否掉的方案与原因」
架构评估方法SAAM、ATAM、CBAM、ALMA、FAAM;ATAM 最常用,核心产出是敏感点与权衡点
效用树 Utility TreeATAM 里把「场景 → 质量属性 → 优先级(重要性 × 难度)」结构化的工具
架构漂移 vs 架构侵蚀漂移是设计随需求演进而偏离,侵蚀是实现了违反既定约束的设计
架构决策的成本越早做的决策越难改,所以要用「可逆性」筛选决策——优先选可逆方案
Y-statementADR 的紧凑写法:面对什么上下文 → 我们决定 → 以达到 → 接受什么代价

四、架构风格与演进

术语一句话释义
单体 Monolith单部署单元,开发简单、事务天然一致,规模上来后协作与发布成为瓶颈
模块化单体单部署但内部强边界(按限界上下文分模块),是很多团队性价比最高的选择
分层架构表现层 / 应用层 / 领域层 / 基础设施层,依赖必须单向朝内
六边形架构(端口适配器)业务在中心,外部依赖通过端口与适配器接入,便于替换与测试
洋葱架构与六边形同源,强调依赖方向由外向内、领域模型在核心
微服务按业务能力拆分为独立部署的小服务,各自拥有数据;代价是分布式复杂度
服务拆分依据按限界上下文与业务能力拆,而不是按技术分层拆(那是分布式单体)
分布式单体服务拆开了但必须一起发布、共享数据库,是最差的一种形态
CQRS读写模型分离,写侧保证一致性、读侧可专门优化;不必然需要两个数据库
事件溯源 Event Sourcing用事件序列而非当前状态作为事实来源,可重放与审计,代价是查询与版本迁移复杂
事件驱动架构通过事件发布订阅解耦,天然最终一致;难点是幂等、顺序与重复消费
Saga长事务拆成多个本地事务 + 补偿操作,编排式或协同式
Outbox 模式业务数据与待发消息在同一事务写入本地表,再由中继投递,解决「写库成功但消息丢了」
BFF为每种前端(App/Web)各做一层后端聚合,避免通用网关适配所有人
API 网关统一入口,负责路由、鉴权、限流、协议转换;不要往里塞业务逻辑
服务网格 Service Mesh把流量治理(重试、熔断、mTLS、观测)下沉到 Sidecar,与业务代码解耦
无服务器 Serverless / FaaS按调用付费、免运维,代价是冷启动与运行时限制
单体 → 微服务的演进思路先模块化单体理顺边界,等真的遇到独立部署/扩容压力再拆,不要为了简历拆

五、设计模式

术语一句话释义
创建型:工厂方法 / 抽象工厂把对象创建延迟到子类 / 创建一族相关对象,隔离具体类型
创建型:单例全局唯一实例;在并发与测试上是反模式,优先用依赖注入
创建型:建造者分步构造复杂对象,替代超长参数列表
创建型:原型通过克隆创建对象,适合创建成本高的场景
结构型:适配器 / 桥接转换接口使其可用 / 把抽象与实现分离,两者各自独立变化
结构型:装饰器在不改原类的前提下动态叠加职责,Java IO 是典型
结构型:代理控制对对象的访问(远程、虚拟、保护、日志),与装饰器的差别是意图不同
结构型:外观 / 组合 / 享元简化子系统入口 / 树形结构统一处理整体与部分 / 共享细粒度对象省内存
行为型:策略把算法族封装为可互换的对象,消除大量 if-else
行为型:观察者一对多依赖通知,是事件驱动与响应式的基础
行为型:模板方法 / 责任链父类定骨架、子类填步骤 / 请求沿链传递直到被处理(过滤器、审批流)
行为型:状态 / 命令状态即对象,行为随状态改变 / 把请求封装为对象,支持撤销与排队
行为型:迭代器 / 中介者 / 备忘录 / 解释器 / 访问者遍历抽象 / 集中交互 / 保存恢复 / 语法解释 / 在不改元素类的前提下加操作
模式使用的正确姿势模式是结果不是目标;能说清「这里不加模式会怎样」才算真的会
反模式 Anti-pattern看似合理实则有害的常见做法:上帝类、意大利面条代码、面条式集成、复制粘贴编程、魔法数
依赖注入 DI / IoC由容器把依赖从外部注入,降低耦合、便于替换与测试

六、代码质量与重构

术语一句话释义
圈复杂度 McCabe独立路径数,约等于判定点 +1;工具默认阈值:ESLint 20、SonarQube 默认 15、Microsoft CA1502 为 25
认知复杂度SonarSource 提出,按嵌套层级递增惩罚,比圈复杂度更贴近「人读起来有多难」
可维护性指数 MI由圈复杂度、代码行数、Halstead 体积、注释比例算出的 0–100 综合分
Halstead 度量由操作符与操作数的数量推算程序体积与难度
代码坏味道长函数、大类、长参数列表、发散式变化、霰弹式修改、依恋情结、数据泥团、重复代码等 20 余种
重构手法提炼函数/变量、内联、搬移特性、重新组织数据、简化条件表达式、简化函数调用六大类
小步重构每一步都保持测试通过,绝不「重构顺便加功能」
重构 vs 重写有测试网兜住时优先重构;重写会丢掉积累的隐性知识,风险极高
技术债四象限按「鲁莽-谨慎」×「有意-无意」分类;有意且谨慎的债要登记并排期偿还
静态分析编译期发现问题:lint、类型检查、安全扫描(SAST)、依赖漏洞扫描
SonarQube 七轴可靠性、安全性、安全热点、可维护性、覆盖率、重复率、规模
代码评审 Code Review目标是共享知识与把关设计,不是挑错;PR 控制在 400 行以内效果最好
Google 代码评审标准只要改动让代码整体变好就该批准,不要求完美
度量反模式用代码行数 / 提交数考核工程师,会导致指标被游戏化(古德哈特定律)

七、测试体系

术语一句话释义
测试金字塔单元层最多、集成层居中、E2E 层最少——因为越往上越慢越脆越贵
测试奖杯模型现代前端/应用的折中版:静态检查最多,其次集成,单元与 E2E 各占一档
单元测试隔离测试单个函数/类,毫秒级、可重复,是重构的安全网
集成测试验证模块与真实依赖(数据库、中间件)协作,比单元慢但更有信心
组件测试把被测服务作为整体隔离测试,外部依赖用桩替代
契约测试消费方与提供方各自验证契约(Pact),避免改动导致跨服务破坏
E2E 测试从用户视角走完整链路,最接近真实但慢、脆、维护成本高
测试替身五种Dummy(占位)、Stub(返回预设值)、Spy(记录调用)、Mock(验证交互)、Fake(简化实现)
TDD 红绿重构先写失败的测试(红)→ 最少代码使其通过(绿)→ 重构,逼出可测试设计
BDD 与 Gherkin用 Given/When/Then 描述行为,让业务、开发、测试共用一份可执行文档
测试覆盖率类型行、语句、分支、条件、路径;分支覆盖率比行覆盖率更有意义
覆盖率的陷阱100% 覆盖不代表正确,只代表每行都执行过;不要把它当 KPI
Diff Coverage 门禁只要求本次改动的新增代码达标(如 80%),比全量门禁更可行
变异测试故意改坏代码看测试能否发现,用来评估测试有效性而非代码覆盖
测试数据管理工厂函数 + 事务回滚或独立 schema,避免测试间互相污染与顺序依赖
不稳定的测试 Flaky Test时快时慢、随机失败;必须优先修复或隔离,否则整个测试套件会被忽略

八、API 设计

术语一句话释义
REST 六约束客户端-服务端、无状态、可缓存、统一接口、分层系统、按需代码(可选)
资源与 URI名词复数表资源(/orders/{id}),动作用 HTTP 方法表达,URI 里不出现动词
HTTP 方法语义GET/HEAD 安全且幂等,PUT/DELETE 幂等,POST 非幂等,PATCH 局部更新
幂等 Idempotency同一请求执行多次与一次效果相同;支付、下单必须做幂等键
状态码要点201 创建成功、204 无内容、409 冲突、422 语义校验失败、429 限流
统一错误结构code + message + details + traceId,让客户端能稳定判断与排障
版本策略URI 版本(/v1)最直观、Header 版本更纯粹、媒体类型版本最规范;选一种并写进规范
废弃流程先标记 Deprecated、给 Sunset 头、双跑一段时间,再下线
分页offset 分页简单但深分页慢且会漏数据,大数据量用游标(cursor)分页
过滤 / 排序 / 字段裁剪统一 ?filter=&sort=&fields= 约定,避免为每种组合开新接口
乐观锁与 ETagIf-Match + 版本号防并发覆盖,冲突返回 412
限流响应头X-RateLimit-Limit/Remaining/Reset、Retry-After,让客户端可自适应退避
HATEOAS响应中给出后续可用链接;理论优雅,实践成本高,多数团队不用
REST vs gRPCREST 通用易调试,gRPC 用 HTTP/2 + Protobuf,强类型、高性能、适合内部服务
gRPC 四种流一元、服务端流、客户端流、双向流;还有 deadline、metadata、拦截器
GraphQL客户端按需取字段、单请求多资源;难点是 N+1(用 DataLoader 批处理)、复杂度限流与缓存
API 设计评审要点命名一致、错误可判、幂等明确、向后兼容、可观测(traceId)、有文档与示例

九、研发流程与协作

术语一句话释义
敏捷宣言个体与互动、可工作软件、客户合作、响应变化——右侧项也有价值,但左侧更被看重
Scrum 三五三3 角色(PO/SM/团队)、5 会议(计划/每日站会/评审/回顾/细化)、3 产物(待办、迭代待办、增量)
Sprint 与迭代固定时长的短周期,目标是可交付增量而非「完成百分比」
用户故事与 INVEST从用户价值出发的需求描述,要独立、可协商、有价值、可估算、小、可测试
故事点与速率用相对估算替代工时,速率用于预测而非考核
Kanban 与 WIP 限制可视化流动、限制在制品,先完成再开始
利特尔法则平均交付时间 = 在制品数 / 吞吐量,是限制 WIP 的数学依据
XP 五价值观简单、沟通、反馈、勇气、尊重;实践包括结对、TDD、持续集成、小版本
三框架分工Scrum 管优先级与节奏、Kanban 管流动与瓶颈、XP 管质量与工程实践,实际常混用
结对编程经验值大约是减少约 15% 缺陷、增加约 15% 时间,适合高风险或知识传递场景
持续集成 CI频繁合并到主干并自动构建测试,防止长时间分支带来的合并地狱
主干开发 Trunk-Based短生命周期分支或直接提交主干,靠特性开关(Feature Flag)控制发布
DORA 四指标部署频率、变更前置时间、变更失败率、恢复时长——团队交付能力的事实标准
特性开关 Feature Flag用开关控制代码可见性,把「部署」与「发布」解耦;要定期清理死开关
古德哈特定律指标一旦成为目标就不再是好指标,所以 DORA 四指标不能拿来排名
研发流程的反模式站会变汇报、回顾无行动项、估算被当承诺、度量被用来考核个人

十、最容易混的对比

对比一句话区分
架构 vs 设计架构关注系统级结构与质量属性,设计关注模块与类的职责划分
战略 DDD vs 战术 DDD前者划边界定语言,后者在边界内建模型
实体 vs 值对象有无唯一标识、是否可变、相等靠什么判断
聚合 vs 聚合根聚合是一致性边界整体,聚合根是唯一外部入口
领域服务 vs 应用服务前者是领域逻辑(无状态但属于领域),后者只做用例编排
CQRS vs 事件溯源CQRS 分读写模型,事件溯源用事件存状态,两者常一起用但互不依赖
Saga vs TCCSaga 是长流程加补偿,TCC 是显式三段式预留确认,TCC 更强一致也更重
适配器 vs 装饰器 vs 代理都是为了包装,区别在意图:转换接口 / 加职责 / 控访问
圈复杂度 vs 认知复杂度前者数路径,后者按嵌套加权,后者更贴近可读性
单元测试 vs 集成测试是否替换掉真实外部依赖
Mock vs StubStub 给返回值,Mock 还验证交互是否发生
重构 vs 重写保持外部行为不变地改进结构 vs 丢掉旧实现重新设计
微服务 vs 模块化单体是否独立部署与独立数据,后者性价比常更高
限流 vs 熔断 vs 降级主动限制流量 / 依赖故障时快速失败 / 返回兜底内容
技术债 vs 架构侵蚀债务是已知的权衡,侵蚀是违规实现导致的架构退化

参考资料

  • Robert C. Martin《Clean Architecture》《敏捷软件开发》
  • Eric Evans《领域驱动设计》、Vaughn Vernon《实现领域驱动设计》
  • Martin Fowler 的架构与重构系列:https://martinfowler.com/
  • 《架构师应该知道的 97 件事》、SEI ATAM 方法文档
  • Google Engineering Practices:https://google.github.io/eng-practices/