[合集]架构筑基:驾驭 AI 编程的底层方法论
AI 负责“手速”,人类负责“图纸”。 本专栏概述了常见的软件架构设计技巧,旨在教你如何通过“架构设计”与“规则约束(Prompt / Rules)”,驯服 AI 编写出工业级、高维护性的高质量代码,避免陷入“代码越写越多、系统崩溃越快”的泥潭。 ...
AI 负责“手速”,人类负责“图纸”。 本专栏概述了常见的软件架构设计技巧,旨在教你如何通过“架构设计”与“规则约束(Prompt / Rules)”,驯服 AI 编写出工业级、高维护性的高质量代码,避免陷入“代码越写越多、系统崩溃越快”的泥潭。 ...
AI 写代码很快,但也很容易出现一种典型问题: 每增加一个功能,就继续往核心代码里加 if/elif。 例如: if domain == "legal": ... elif domain == "finance": ... elif domain == "medical": ... 功能少时没有问题,但随着类型不断增加,核心模块会越来越臃肿,每次新增功能都可能影响已有逻辑。 更合理的做法是提前定义: Plugin:插件 Extension Point:扩展点 让 AI 遵循一个原则: 新增能力优先增加模块,而不是修改核心流程。 ...
这一系列文章,我们讨论了前后端分离、DDD(Domain-Driven Design,领域驱动设计)、分层架构、DI(Dependency Injection,依赖注入)、RESTful(Representational State Transfer,表现层状态转移)、异步并发、SSE(Server-Sent Events,服务器发送事件)、插件化以及 Project Rules(项目规则)等一系列工程方法。 看起来讲了很多技术,但它们最终都指向同一个问题: 当 AI 已经能够大量生成代码,程序员最重要的能力还是什么? 答案正在从: “如何把代码写出来” 转向: “如何设计一个让 AI 能够正确写代码的系统”。 ...
在 Web 系统里,有一类需求特别容易被 AI 写成“能跑,但很笨”的实现: 前端: 每 1 秒问一次服务器 “任务完成了吗?” 服务器: “没有。” 1 秒后再问: “完成了吗?” 这种方式叫: Polling:轮询 偶尔查询一次状态没有问题,但如果是 AI 流式回答、OCR 进度、文档解析、知识库构建、后台任务状态等实时场景,高频轮询会产生大量无效请求。 更合适的方案通常是: SSE(Server-Sent Events,服务器发送事件) 或者: WebSocket:Web 套接字,全双工长连接通信协议 核心思想只有一句: 不要让客户端不停问“有消息了吗”,而是让服务器有消息时主动推送。 ...
AI 写代码有一个很常见的问题: 代码能跑,但一到多人访问就变慢。 尤其在 Python Web 项目中,即使使用 FastAPI,函数也写成了 async def,数据库查询、HTTP 请求、大模型调用等操作仍然可能同步阻塞。 问题的关键在于: async def 只是异步函数的入口,并不会自动把里面的同步代码变成异步代码。 对于 Web 服务、知识库和智能体平台这类大量依赖外部 I/O 的系统,建立统一的异步与并发架构,是提升系统吞吐能力的重要基础。 ...
AI(Artificial Intelligence,人工智能)写代码有一个很常见的问题: 它特别喜欢“顺手写死”。 timeout = 30 max_retries = 3 model = "qwen3:14b" raise ValueError("用户不存在") 单独看,每一行都没什么大问题。 但当几十个模块都有自己的 30、3、模型名称和提示文案时,维护者就会开始头疼: 这些值是什么意思?在哪里修改?换环境怎么办?支持英文怎么办? 因此,AI 编程项目最好提前建立一条明确的架构规则: 具有业务含义、环境差异或用户可见含义的值,不允许散落在业务代码中。 解决这个问题,主要依靠两套机制: 中心化配置 + I18n 国际化。 ...
很多项目一开始只有一个数据库。于是 AI 很自然地写出: async def get_user(user_id: int): async with sqlite_session() as session: ... 或者更直接: conn = sqlite3.connect("app.db") 功能当然能跑,但问题会在以后出现。 今天是 SQLite ,明天可能要换成 PostgreSQL … 随着代码规模的增加,项目很快就会变成: 业务代码和具体存储技术绑死。 这正是 Multi-Data-Source Architecture(多数据源架构) 要解决的问题。 ...
AI 写业务代码时,有一种非常典型的倾向: async def get_user(user_id: int): return await user_db.get_by_id(user_id) 功能没错。但如果项目里所有读取都变成: 查用户 → 数据库 查权限 → 数据库 查模型 → 数据库 查 Agent → 数据库 查知识库 → 数据库 查配置 → 数据库 系统很快就会进入一种状态: 每个函数都很正确,整体架构却越来越低效。 问题不只是“有没有缓存”,而是: AI 没有先判断:我要复用的是一个“值”,还是一个“已经构建好的运行对象”? 这正是 miniagent 当前缓存架构最值得借鉴的地方。 它不是简单地做一套缓存,而是明确分成两类: Object Cache 对象缓存 Value Cache 值缓存 两者解决的根本不是同一个问题。 ...
在 AI 编程里,有一类代码特别容易“越写越多、越写越乱”: if user.role != "admin": raise HTTPException(status_code=403) 换一个接口,AI 又写: if "user:delete" not in user.permissions: raise ForbiddenError() 再换一个接口: if current_user.id != owner_id and not current_user.is_admin: raise HTTPException(status_code=403) 每一段单独看都说得过去。但当项目里出现几十种这样的 if,权限系统实际上已经失控了。 真正成熟的做法不是“让 AI 更认真地写 if”,而是建立一套统一的: 身份认证 + 权限模型 + 权限执行机制 其中最常见的一种权限模型,就是 RBAC(Role-Based Access Control,基于角色的访问控制)。 ...
在 AI 编程时代,有一种代码特别容易疯狂复制: logger.info("开始处理请求") if not token: raise UnauthorizedError() start = time.time() result = await service.do_something() logger.info(f"执行耗时: {time.time() - start}") return result 一开始只有一个接口,看起来没什么问题。 但当项目发展到几十个甚至几百个接口以后,情况很快变成: 用户接口 ├─ 鉴权 ├─ 日志 ├─ 参数检查 ├─ 业务逻辑 └─ 埋点 智能体接口 ├─ 鉴权 ├─ 日志 ├─ 参数检查 ├─ 业务逻辑 └─ 埋点 知识库接口 ├─ 鉴权 ├─ 日志 ├─ 参数检查 ├─ 业务逻辑 └─ 埋点 ... 真正不同的可能只有中间那几行业务代码,其余代码,AI 每写一个接口,就顺手再复制一遍。 这正是 AOP(Aspect-Oriented Programming,面向切面编程) 要解决的问题。 ...