当前位置: 首页 > news >正文

后端代码优化

一次关于拆分、解耦和异常治理的代码进化记录

一、单一职责落地

痛点回顾

ai_chat_service.py在一个文件里同时承担了:

  • LLM 流式调用编排
  • 会话记忆管理
  • 用户问题意图识别
  • SQL 安全校验

每次改动任何一个维度,都得在这700行里小心翻找,而且任何修改都有波及其他功能的风险。

重构方案

单一职责原则拆分为独立模块:

services/ai_chat/ ├── __init__.py # 统一导出,对外透明 ├── service.py # 主服务:stream_chat 入口 ├── memory.py # MemoryManager:记忆管理 ├── planner.py # LLMQuestionPlanner:意图识别 └── sql_safety.py # SQL 安全作用域

关键的细节在__init__.py

fromopenapi_server.services.ai_chat.serviceimportAIChatService,get_ai_chat_servicefromopenapi_server.services.ai_chat.memoryimportMemoryManager# ...__all__=["AIChatService","get_ai_chat_service","MemoryManager",...]

调用方只需要改 import 路径,符号名称完全不变:

# 优化前fromopenapi_server.services.ai_chat_serviceimportAIChatService# 优化后fromopenapi_server.services.ai_chatimportAIChatService

收益

维度优化前优化后
单文件行数700+各模块 < 150 行
职责耦合高度混编单一职责
改动风险改一处可能波及全局边界清晰
单元测试几乎不可能每个模块可独立测试

二、代码去重

痛点回顾

uploadWechatBillDatauploadAlipayBillData两个接口,除了解析 Excel/CSV 的细节不同,后续的 AI 分类、分批入库、SSE 进度推送完全一致,维护成本翻倍。

重构方案

提取公共方法_process_uploaded_bills()

asyncdef_process_uploaded_bills(parsed_data:list[Bill],user:UserDep,platform_name:str,batch_size:int=50,)->StreamingResponse:"""处理上传账单的公共逻辑:AI分类 + 分批入库 + SSE推送"""asyncdefevent_stream():foriinrange(0,len(parsed_data),batch_size):batch=parsed_data[i:i+batch_size]# AI 分类results=awaitclassify_bill_batch(batch)forj,rinenumerate(results):batch[j].transaction_type=r.transaction_type# 入库withSession(engine)asdb_session:db_session.add_all(batch)db_session.commit()yield_sse_event({"processed":processed,"total":total})yield_sse_event({"status":"completed"})returnStreamingResponse(event_stream(),media_type="text/event-stream")

两个上传接口瞬间精简:

@BillAPIRouter.post('/uploadWechatBillData')asyncdefupload_wechat_bill_data(excelData:UploadFile,user:UserDep):parsed_data=parse_wechat_bill(excelData)returnawait_process_uploaded_bills(parsed_data,user,"微信")@BillAPIRouter.post('/uploadAlipayBillData')asyncdefupload_alipay_bill_data(csvData:UploadFile,user:UserDep):parsed_data=parse_alipay_bill(csvData)returnawait_process_uploaded_bills(parsed_data,user,"支付宝")

启发

去重的关键不在于机械地提取函数,而在于识别业务流程的本质——两个接口的差异只在于第一步的解析,后续流程完全相同。这种“模板方法”模式在业务开发中非常实用。

三、模型文件拆分:从混乱到有序

30多个 Pydantic 模型堆在apis/models.py一个文件里,每次改一个接口的模型都要翻半天。按业务域拆分:

apis/models/ ├── auth.py # 登录/注册/刷新Token ├── bill.py # 账单CRUD ├── analysis.py # 月度报告/分类统计/趋势 ├── budget.py # 预算 └── ai_chat.py # AI聊天

__init__.py统一重导出,调用方无需任何修改

fromopenapi_server.apis.modelsimportBillItem# 完全没变

四、异常处理统一:告别散落的 HTTPException

重构前

每个路由都直接raise HTTPException(status_code=xxx, detail="...")

ifbillisNone:raiseHTTPException(status_code=404,detail="账单不存在")ifnotuser:raiseHTTPException(status_code=401,detail="用户不存在")

问题:

  • 错误消息硬编码,分散在各处
  • 同类错误的 HTTP 状态码在不同路由可能不一致
  • 无法统一做日志告警、重试等策略

重构后

定义异常层次结构:

classAppException(Exception):def__init__(self,message:str,status_code:int=500):self.message=message self.status_code=status_codeclassResourceNotFoundError(AppException):def__init__(self,resource_type:str,resource_id:int|str=None):message=f"{resource_type}不存在"+(f" (ID:{resource_id})"ifresource_idelse"")super().__init__(message,status_code=404)classBillNotFoundError(ResourceNotFoundError):def__init__(self,bill_id:int=None):super().__init__("账单",bill_id)classUnauthorizedError(AppException):def__init__(self,message:str="权限不足"):super().__init__(message,status_code=401)

配合中间件统一捕获处理:

classExceptionHandlerMiddleware(BaseHTTPMiddleware):asyncdefdispatch(self,request,call_next):try:returnawaitcall_next(request)exceptAppExceptionase:logger.warning("应用异常: %s, 路径: %s",e.message,request.url.path)returnJSONResponse(status_code=e.status_code,content={"detail":e.message})exceptSQLAlchemyErrorase:logger.error("数据库异常: %s",str(e))returnJSONResponse(status_code=500,content={"detail":"数据库操作失败"})exceptExceptionase:logger.exception("未处理异常: %s",type(e).__name__)returnJSONResponse(status_code=500,content={"detail":"服务器内部错误"})

路由层语义清晰:

# 重构前raiseHTTPException(status_code=404,detail="账单不存在")# 重构后raiseBillNotFoundError(bill_id)

替换统计

文件替换项数改进点
bill_api.py7 处404→BillNotFoundError,500→DatabaseError
user_api.py8 处401→UnauthorizedError
analysis_api.py6 处400→ValidationError
budget_api.py5 处404→BudgetNotFoundError

五、两个细节

5.1 语法错误修复

services/ai_chat/service.py隐藏的语法错误——Prompt 字符串里的 ASCII 双引号与 Python 字符串定界符冲突:

# 有问题的代码"禁止使用同比或环比,统一写"与指定对比"周期相比"。"# ↑ 这个双引号结束了字符串# 修复后——使用中文引号"禁止使用同比或环比,统一写“与指定对比”周期相比。"

这类语法错误在动态语言中很容易被忽视,直到特定路径被触发才暴露。

5.2 全局变量的隐患

重构前模块级全局变量在 import 时就创建实例:

_ai_chat_service=AIChatService()# 模块加载时立即创建defget_ai_chat_service():return_ai_chat_service

问题:

  • 不必要的初始化开销
  • 测试时必须用dependency_overridesmock,属于“后门”注入
  • 不利于延迟初始化和多实例管理

改为@lru_cache实现懒加载单例:

fromfunctoolsimportlru_cache@lru_cache(maxsize=1)defget_ai_chat_service():returnAIChatService()
维度优化前优化后
初始化时机import 时首次调用时
测试友好度仅能 dependency_overrides可用@patch直接 mock
代码行数4 行3 行

小结

这次重构的核心原则是:在保持对外接口完全不变的前提下,彻底重构内部架构。

改进项收益
单一职责拆分可维护性大幅提升
代码去重减少 200+ 行冗余代码
统一异常处理日志可观测性提升,错误语义化
懒加载单例可测试性提升
http://www.gsyq.cn/news/1555484.html

相关文章:

  • Flexport:AI 驱动全球贸易,多项物流服务赋能,诚邀加入共创未来!
  • 黄金钻石彩宝翡翠!添价收首饰回收样样在行 - 薛定谔的梨花猫
  • 2026苏州建筑渗漏修缮痛点如何破?苏州鸣川防水补漏公司专业服务商适配推荐 专业防水公司排名推荐(2026年6月防水补漏最新TOP权威排名) - 鼎壹万修缮说
  • 实地走访武汉6家黄金回收门店,从资质到结算,前列实至名归 - 名奢变现站
  • 深圳黄金回收本地领跑品牌,2026全方位实力测评解析 - 奢侈品回收测评
  • 上海大牌首饰回收避坑:卡地亚、梵克雅宝变现别信虚高报价 - 逸程
  • 在浏览器里重建了一座能逛能聊能吟诗对弈的唐长安城
  • 2026成都金豆、小金珠零散黄金回收,小件不会额外收取手续费 - 逸程
  • Microchip无线模块固件升级与增益表更新实战指南
  • 2026成都黄金回收用 “两、钱” 换算一定要警惕猫腻 - 逸程
  • 2026成都黄金回收常见8项隐形扣费,正规商家一项都不收 - 逸程
  • SAP WM模块中仓储单位SU的生命周期与业务闭环追踪
  • 2026 天津钻石回收|全国连锁 资质齐全,本地门店榜单出炉,专业鉴钻安心变现 - 名奢变现站
  • 技术指南:解决transformers库版本兼容性问题的5个实战技巧
  • 2026年6月武汉奢侈品回收性价比实测|七家机构横向对比,谁才是真正的收益最大化首选? - 薛定谔的梨花猫
  • 告别臃肿!这款轻量级工具让你的华硕笔记本重获新生
  • 机器学习模型上线后的系统级运维与可信决策实践
  • 2026苏州黄金回收TOP1龙头测评 领先高价变现全维度解析 - 奢侈品回收测评
  • vCenter证书过期登录失败:从SSL报错到服务重启的完整恢复指南
  • AI 全栈开发实战(12):性能优化与监控——从慢查询定位到 Prometheus 监控
  • 互联网行业计算机程序员IT软件开发个人求职面试简历模板 格式word简历模板可编辑
  • 终极指南:免费在Switch上使用虚拟Amiibo的完整教程
  • MC68020特权级、虚拟化与流水线架构深度解析
  • 2026常州回收普拉达包包优质门店排行, 资质合规变现首选禹竞名奢汇 - 名奢变现站
  • https://www.cnblogs.com/-1688/p/20655376 - 速递信息
  • OpenWebRL:40亿参数网页智能体实战指南
  • 构建之法5
  • 从报错到成功:手把手教你用BiocManager搞定clusterProfiler安装全流程
  • Windows微信防撤回实战:开源工具原理与安全配置指南
  • 6 家门店实地测评!2026 杭州黄金回收完整避坑教程,变现不踩雷 - 开心测评