资讯动态

第4节:应用架构与代码组织

发布时间:2026/10/27 10:40:33 来源:尧图企业网站定制
AI编程企业级实战上一节第3节动第一行代码前你应该想清楚什么本节第4节应用架构与代码组织下一节待更新这一讲回答一个更具体的问题代码怎么组织、外部调用怎么处理很多工程师拿到需求直接开始写代码写到一半发现模块之间耦合得死死的、线程池被LLM调用占满了管理页面打不开、不同模块的代码风格完全不一样。这些问题不是写代码的问题是动手之前没想清楚应用架构。这一讲和下一讲合起来是 Hify 的完整架构设计。这一讲上篇聚焦代码层面——模块怎么分、Spring代码怎么组织、外部调用怎么处理。下一讲下篇聚焦系统层面——怎么部署、瓶颈在哪、未来怎么扩展、数据怎么存。应用架构模块化单体第一个问题一个Spring Boot应用内部怎么组织Hify是一个Spring Boot单体应用功能包括模型提供商管理、Agent配置、对话引擎、知识库RAG、简版工作流、MCP工具接入。一个人开发一期50人使用但后续可能要扩到几千人。代码内部怎么组织给我方案对比。Claude Code给了三个方案方案A按package分层。所有功能放在一个模块里按controller/service/mapper分package。最简单但所有功能混在一起后面代码量大了找文件费劲想拆分也拆不动。方案BMaven多模块按功能拆。一个Spring Boot应用内部按Maven多模块组织每个功能一个模块。模块之间通过接口调用代码层面严格隔离。后续想拆分成微服务只需要把接口调用改成远程调用模块内部不用动。方案C微服务。每个功能一个独立服务通过网关路由服务间Feign调用。它推荐了方案 C理由是方便独立扩展。我追问一个人维护六七个微服务每个要独立部署、独立配置、独立监控精力消耗会不会太大它承认了说一人开发建议方案B。我的判断选方案 B模块化单体。一个人维护一个应用比维护六七个微服务轻松太多。但代码上做好模块隔离后续需要拆分时成本可控。最终的模块划分hify/ ├── hify-app/ # 启动模块Spring Boot Application ├── hify-provider/ # 模型提供商管理 ├── hify-agent/ # Agent 管理与配置 ├── hify-chat/ # 对话引擎 ├── hify-mcp/ # MCP 工具管理与调用 ├── hify-workflow/ # 工作流编排与执行 ├── hify-knowledge/ # 知识库与 RAG ├── hify-common/ # 公共模块工具类、常量、异常、DTO ├── hify-web/ # Vue 前端 └── deploy/ # Docker Compose 配置模块之间的依赖关系需要想清楚。我让Claude Code分析基于 Hify 的功能帮我梳理这些模块之间的依赖关系。谁依赖谁有没有循环依赖的风险它给的分析hify-chat是依赖最多的模块——对话时要读Agent配置依赖hify-agent、调模型依赖hify-provider、可能走工作流依赖hify-workflow、可能做RAG检索依赖hify-knowledge、可能调工具依赖hify-mcp。hify-agent依赖hify-mcpAgent要绑工具和hify-knowledgeAgent要绑知识库。所有模块依赖hify-common。关键原则依赖是单向的不能循环。 hify-chat 可以依赖 hify-agent但 hify-agent 不能反过来依赖hify-chat。如果出现循环依赖说明模块边界划错了需要把共用的部分下沉到 hify-common。Spring 代码组织规范Controller、Service、Mapper三层架构谁不知道人写代码确实不需要讲。你凭经验和习惯自然知道业务逻辑放Service里、Controller只做参数校验。但AI不知道。你不告诉它规矩它可能把事务管理写在Controller里、把数据库查询写在DTO里、直接引用另一个模块的Mapper把两个模块焊死。这些规范不是写给人看的是写给Claude Code看的。后面每一行代码都是它生成的这些规矩定不好生成出来的代码越多越乱。我让Claude Code帮我梳理Hify是模块化单体用Spring Boot MyBatis-Plus。帮我定义代码组织规范覆盖每个模块内部的分层结构、每一层的职责边界、跨模块调用的规则。要求具体到AI能直接执行不要模糊的描述。每个业务模块内部统一结构src/main/java/com/hify/{module}/ ├── controller/ # REST 接口 ├── service/ # 业务逻辑接口 ├── service/impl/ # 业务逻辑实现 ├── mapper/ # MyBatis-Plus Mapper ├── entity/ # 数据库实体 ├── dto/ # 请求/响应对象 ├── config/ # 配置类 ├── exception/ # 模块级自定义异常 └── constant/ # 模块级常量每一层的职责边界Controller只做两件事参数校验和调用Service。不写业务逻辑、不做数据查询、不处理事务。为什么要这么严格因为Claude Code特别喜欢在Controller里“顺手”加逻辑它觉得方便但你后面测试、重构、拆分全部受影响。Service处理所有业务逻辑包括事务管理、数据校验、业务规则。Service之间可以互相调用但只能调接口interface不能直接new实现类。Mapper只做数据库操作。不要在Mapper的XML里写业务逻辑比如复杂的条件判断那是Service的事。Entity和数据库表一一对应。DTO是给接口用的请求/响应对象。Entity和DTO之间要做转换不要把Entity直接返回给前端——Entity里可能有敏感字段API KeyDTO可以控制暴露哪些字段。跨模块调用规则这条是模块化单体最关键的规范。模块之间只能通过Service接口调用不能直接引用另一个模块的Mapper、Entity或内部类。为什么因为我们选模块化单体的一个重要理由是“后续能拆分”。如果hify-chat直接引用了hify-agent的Mapper两个模块就焊死了——拆分时你要把所有这种引用找出来改成远程调用。但如果只通过Service接口调用拆分时只需要把本地调用改成HTTP/RPC调用接口签名都不用变。我追问Claude Code如果有一天要把hify-chat拆成独立服务按照这套规范改动量大概多大它分析了一下Service接口不变实现类里的本地调用改成Feign调用加上网络异常处理。每个跨模块调用点改两三行代码。改动量可控。这就验证了这套规范的合理性。这里我标注下能考虑到未来的拆分主要靠的是自己的项目经验我希望你可以记下这个就当积累一个经验。外部调用设计Hify最大的技术挑战不在CRUD在外部LLM调用。LLM API调用有三个特点慢一次对话3-30秒、不稳定随时可能超时、限流、报错、多供应商每家行为不一样。不提前设计好上线就炸。我让Claude Code系统性地分析Hify要调用多个外部LLM APIOpenAI、Claude、Gemini、Ollama这些调用慢且不稳定。从线程管理、容错、超时、重试四个维度给出完整的技术方案。它给的方案很全面我逐个判断线程池隔离——同意。LLM调用必须用独立线程池不能和Tomcat的业务线程池共用。第03讲分析过50个并发SSE连接每个持续10-30秒如果共用线程池管理页面的请求排在队列里等用户看到的就是页面一直转圈。独立线程池解决这个问题——对话请求用自己的池子管理请求用Tomcat默认的池子互不影响。熔断机制——同意。某个LLM提供商连续失败时快速熔断后续请求直接返回错误不浪费时间等超时。Claude Code建议Resilience4j每个提供商独立熔断器——OpenAI挂了不影响Claude。合理。超时控制——同意但我追问了细节。它建议对话接口60秒超时连通性测试10秒。我追问流式响应场景下一个SSE连接可能持续一两分钟60秒会不会把正常对话切断它调整了SSE连接超时设120秒普通同步调用60秒。合理。重试策略——同意细节有价值。不是所有失败都值得重试。网络抖动重试有意义认证失败重试没用重试一百次还是认证失败限流需要退避重试等一等再试。按异常类型区分重试策略这个细节Claude Code给得很好。我又追问了一个它没主动提到的问题流式响应用SSESpring MVC怎么处理需不需要引入WebFlux它建议WebFlux做异步非阻塞。我不同意——前面已经确定不引入额外技术栈。SSE场景用Spring MVC的SseEmitter就够配合独立线程池和120秒超时50人完全能扛。不为了“技术上更优雅”引入一套新的编程模型。写进CLAUDE.md这一讲的所有决策写进CLAUDE.md## 架构设计 ### 应用架构 模块化单体。一个 Spring Boot 应用Maven 多模块组织。 模块划分 - hify-provider模型提供商管理 - hify-agentAgent 管理与配置 - hify-chat对话引擎 - hify-mcpMCP 工具管理与调用 - hify-workflow工作流编排与执行 - hify-knowledge知识库与 RAG - hify-common公共模块 依赖原则单向依赖不循环。共用逻辑下沉 hify-common。 ### 代码组织 每个业务模块统一结构controller / service / mapper / entity / dto / config 分层规则 - Controller 只做参数校验和调用 Service不写业务逻辑 - Service 处理所有业务逻辑包括事务管理 - 跨模块调用走 Service 接口不直接引用其他模块的 Mapper 或 Entity - Entity 不直接返回给前端用 DTO 做转换 ### 外部调用处理 - LLM 调用使用独立线程池和业务请求隔离 - Resilience4j 熔断每个提供商独立熔断器 - 同步调用 60s 超时SSE 流式 120s 超时连通性测试 10s - 按异常类型区分重试网络抖动重试、认证失败不重试、限流退避重试 - 流式响应使用 SseEmitter 独立线程池不引入 WebFlux总结这一讲做了三件事确定了模块化单体的应用架构定义了Spring代码组织规范设计了外部调用处理方案。回顾整个过程最有价值的不是最终方案而是和Claude Code的追问环节。它推荐微服务被我用“一个人维护太重”否决了。它建议WebFlux被我用“不增加技术栈复杂度”否决了。它给的超时时间对SSE不够用被我追问后调整了。每一次追问的背后都是你在用项目的真实约束来修正AI的通用建议。AI给的是技术上最优的方案你要基于约束选对你最优的方案。这两者经常不一样。还有一点值得强调代码组织规范看起来是常识但对AI写代码来说是刚需。人凭习惯知道Controller不写业务逻辑AI不知道。你不告诉它它就按自己的理解来而且每次理解都不一样。这些规范现在花半小时定好后面几百次代码生成都受益。到这里你可能会说我没有架构知识不知道要问什么问题。那我想说你以前没有当看完这节课不就有了吗你或者可以把这节课当作一个实践的架构课。记下来我们怎么思考的以后就有经验了知道怎么问问题了。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑