分层架构设计原则

分层架构设计原则

原则一:先画依赖方向图,再定目录结构

在写任何目录之前,先明确一条单向依赖链,例如:

api → application → domain(workflows/models) → infra(外部服务客户端)

规则:

  • 箭头只能从左指向右,右边的模块永远不知道左边模块的存在。
  • domain 层(纯业务逻辑,如 LangGraph 的 state/graph/node)不应该
    import 任何具体技术实现(Redis、数据库驱动、HTTP 框架)。
  • infra 层(数据库、消息队列、外部 API 客户端)不应该反过来
    import api 层的数据结构或 application 层的编排逻辑。

设计时问自己:如果把某一层整个删掉重写,其他层要不要跟着改?如果答案是"要改",说明依赖方向画错了。

原则二:先列出所有"调用入口",再决定模块归属

在分包之前,先列清楚这个系统有几个独立的入口/进程,例如:

  • Web API 进程
  • 后台 worker 进程
  • 命令行脚本/定时任务
  • 未来可能的第二个消费方(如另一个服务复用同一套业务逻辑)

规则:

  • 一个模块如果会被 两个以上独立入口 直接调用,
    它就该被放在这些入口都够得到的公共层级,
    不能被塞进只服务于其中一个入口的目录里。
  • 只被单一入口用到的东西,才适合放在贴近该入口的位置。

这一步应该在写代码前就做,而不是等到发现"worker.py 要伸手进application 内部"才回头调整。

原则三:每一层只对外暴露一个"接口文件",不暴露内部路径

规则:

  • 每一层(尤其是 domain/infra)应该有一个类似
    __init__.pybootstrap.py 的统一入口,
    外部调用方只 import 这个文件,不直接深入到内部的实现文件。
  • 内部再怎么拆分子模块、重命名文件,只要对外接口不变,
    调用方完全不受影响。

判断标准:如果调用方的 import 路径深度超过 2~3 层
(如 application.workflows.adaptive_rag.graph.create_xxx),
基本可以判断这一层没有做好封装。

原则四:成对出现的模式,设计时就该规划对称的位置

常见的成对模式:

  • CQRS(读/写分离)
  • Command/Query
  • Producer/Consumer
  • Request/Response DTO

规则:

  • 设计阶段就应该决定:这一对逻辑放在同一层的同一个文件/模块里,
    还是分别放在不同层但对称的位置(比如都在 pipeline 层,
    一个叫 xxx_write.py,一个叫 xxx_read.py)。
  • 不要让"哪个先写就放哪"决定最终位置——这样容易出现
    一半在 router、一半在 pipeline 的不对称结构。

原则五:共享的基础设施,一开始就应该是独立层,而不是某层的子目录

对于会被多个 domain/workflow 共用的东西
(数据库连接池、缓存客户端、模型工厂、日志配置等):

  • 设计时就单独开一个 core/infra/ 包,与 domain、application 平级。
  • 不要因为"现在只有一个 workflow 在用"就先放进这个 workflow 目录里,
    等第二个 workflow 出现时再重构——这是可以预见的扩展点,
    应该在设计阶段直接留好位置。

原则六:跨层的数据结构,归属于"共享契约层",不归属于任何一侧

如果一个数据结构(DTO/Schema)会被多层引用(比如 api 和 infra 都要用),
它不应该定义在其中任何一层内部,而应该单独放在一个
双方都能依赖、但不依赖任何一方的位置(如 core/schema.py)。

设计前自查清单

在写第一行代码之前,建议对着这几条过一遍:

  1. 画出模块间的依赖箭头,确认全部单向。
  2. 列出所有独立入口,确认每个共享模块的位置能被所有入口够到。
  3. 每一层是否都有清晰、单一的对外接口,而不是暴露内部路径。
  4. 成对出现的模式(读/写、生产/消费)是否规划在对称位置。
  5. 跨 workflow/domain 共用的基础设施是否单独成层。
  6. 跨层数据结构是否放在独立的共享契约层。

最终我的代理流架构

app/
  api/            # 只 import application
  application/    # 编排:调 domain、infra、core;暴露 pipelines 给 api
  domain/          # 纯业务逻辑(原来的 workflows),不 import 任何人
  infra/           # 外部服务客户端(chroma/paddle/sam3/redis 连接)
  core/            # 共享层:settings、schema、model_factory、graph_bootstrap
  main.py
  worker.py
posted @ 2026-07-14 18:04  asphyxiasea  阅读(4)  评论(0)    收藏  举报