第2章 模块边界划分方法:业务域聚合、功能内聚、变化隔离、复用粒度

2.1 边界划分的四维决策模型

Agent系统的模块解耦首先回答“在哪切一刀”。实践中,单一维度(如仅按功能)常导致后续耦合扩散。本章提出四维模型,每一维度对应一种边界判据:

维度 核心判据 典型场景 反例警示
业务域聚合 同一业务上下文内的强相关职责归为一组 客服Agent:用户管理、工单、知识库 将“日志记录”分散到各域
功能内聚 单一功能的完整生命周期封闭在一个模块内 大语言模型调用(预处理→请求→后处理) 将token切分和API重试分属不同模块
变化隔离 将可能独立变化的因素封装起来 多模型提供商支持(OpenAI / Anthropic / 自研) 把prompt模板和模型参数混在同一次调用中
复用粒度 以团队或产品可独立交付的最小单元为界 记忆模块、工具注册中心、权限校验 将“工具执行器”与“工具定义”拆成两个模块
评审关键点:四维并非互斥;实际划分时,通常先按“业务域”切割大粒度,再按“功能内聚”细化,最后用“变化隔离”和“复用粒度”调整边界。

2.2 每种方法的组件职责与交互

以下从边界、分层、组件职责、数据流/控制流/信任链路层面分别展开。

2.2.1 业务域聚合 —— 以“用户上下文域”为例

  • 边界:该域包含用户画像、会话历史、偏好设置,不关心llm调用或工具执行。
  • 分层:接口层(REST/gRPC)→ 域服务层 → 持久化层。
  • 组件职责:
    • UserContextService:提供get/set会话变量。
    • SessionRepository:存储最新K条对话。
  • 数据流:编排器通过ContextPort请求上下文,域返回域内数据结构;信任链路:域内数据视为可信,外部输入需校验时间戳和类型。

2.2.2 功能内聚 —— 以“LLM调用模块”为例

  • 边界:只暴露一个GenerateResponse(prompt, options) → Response接口。
  • 组件职责:
    • TokenProcessor:切分、拼合。
    • RequestBuilder:组装请求体。
    • RetryHandler:指数退避。
    • ResponseParser:提取文本/工具调用。
  • 控制流:同步调用,内部使用CompletableFuture异步重试;信任链路:调用者只需传递可信参数,模块内部负责幂等和限流。

2.2.3 变化隔离 —— 以“模型提供商适配器”为例

  • 边界:每个适配器独立部署/版本,对上层暴露统一ModelAdapter接口。
  • 风险点:适配器若共享配置格式,当新增provider时易破坏现有解析逻辑。
  • 落地步骤:1.定义接口契约→2.实现第一个适配器→3.提取通用配置Schema→4.并行开发其他适配器。

2.2.4 复用粒度 —— 以“工具注册中心”为例

  • 边界:工具注册中心应独立于任何Agent,可被多个Agent实例复用。
  • 验收标准:引入新Agent时,只需注册新工具,无需修改注册中心代码。
  • 选型权衡:将工具元数据存数据库vs.内存;数据库增加分布式成本但支持动态热更新。

四维边界划分决策流程图(SVG)

模块边界四维划分决策流程 原始需求 / 功能列表 Step1: 按业务域聚合(域上下文) 内聚不够 Step2: 功能内聚检查 Step3: 变化隔离分析 Step4: 复用粒度评估与调整 最终模块划分方案 每步需输出边界定义 及依赖方向约束

2.3 选型权衡与风险点

  • 业务域 vs. 复用粒度冲突:按域划分的业务模块可能无法独立发布(需域内其他模块配合),此时应优先保障“独立可交付”的复用粒度。
  • 变化隔离过度:为每个潜在变化点创建接口导致接口爆炸;建议只在确定会变化(如模型提供商、存储后端)的维度使用适配器模式。
  • 功能内聚的陷阱:将跨多个层的逻辑硬塞进一个模块(例如把网络调用、缓存、序列化全放在一个类里),反而增加测试难度。

评审常见反例:某项目按“界面模块”“逻辑模块”“数据模块”分层,结果每个模块都耦合了业务细节,重构时所有变更都会波及三个模块。

2.4 落地步骤

  1. 梳理所有功能点列表,标注所属业务域。
  2. 对每个域做功能内聚审计:同一功能的所有步骤是否在域内完成?若否,则调整或新增模块。
  3. 识别变化因素:列出预期变化点(第三方依赖、配置源、输出格式),每个变化点至少预留一个适配器层。
  4. 评估复用粒度:以团队研发效率为目标,审视模块是否可以被打包成独立artifact(jar/dll/npm包)。
  5. 编写边界契约文档:明确每个模块的公开接口、依赖方向、数据所有权。

2.5 验收标准

  • 每个模块的职责用一句话能说清(例如“管理用户会话状态”)。
  • 新增一个功能时,最多修改2个模块。
  • 替换某个Provider(如从OpenAI切换到Anthropic)只修改1个适配器文件。
  • 单元测试中模块间依赖可100%用mock替换;集成测试仅验证跨模块交互结果。
  • 模块jar包/包的大小不超过特定阈值(如5MB),避免职责宽泛导致体积膨胀。

关键结论:模块边界划分是一个逐步逼近过程,四维模型提供检查清单而非机械规则。评审时应逐个维度检视,确保每个决策都有明确的权衡记录。