当前位置: 首页 > 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.jsqmd.com/news/1043577/

相关文章:

  • 2026苏州建筑渗漏修缮痛点如何破?苏州鸣川防水补漏公司专业服务商适配推荐 专业防水公司排名推荐(2026年6月防水补漏最新TOP权威排名) - 鼎壹万修缮说
  • 天津钻石回收专业甄选指南,资深商户实地走访,估价合理交易省心 - 名奢变现站
  • Flexport:AI 驱动全球贸易,多项物流服务赋能,诚邀加入共创未来!
  • 黄金钻石彩宝翡翠!添价收首饰回收样样在行 - 薛定谔的梨花猫
  • 抖音去水印免费工具推荐:免费软件小程序都能用 - 工具软件使用方法推荐
  • 2026 杭州黄金回收避雷攻略,本地人亲测 6 家靠谱机构 - 开心测评
  • 实地走访武汉6家黄金回收门店,从资质到结算,前列实至名归 - 名奢变现站
  • 深圳黄金回收本地领跑品牌,2026全方位实力测评解析 - 奢侈品回收测评
  • Anthropic 推出 Claude 认证架构师考试:不是考 Prompt,而是考你能不能造一个生产级 Agent
  • 02梦断代码阅读笔记之一
  • Pot-desktop:跨平台翻译与OCR识别的高效开源解决方案
  • 2026深圳黄金回收门店实力大排名,透明回收、报价公道商家一览 - 奢侈品回收测评
  • 2026杭州黄金回收行情解读 正规交易流程指南 - 开心测评
  • 上海大牌首饰回收避坑:卡地亚、梵克雅宝变现别信虚高报价 - 逸程
  • 个人寄快递省钱攻略2026:散户寄件全流程低价指南 - 快递物流资讯
  • 厦门黄金回收门店实测,选对正规门店,不怕被压价 - 奢品小当家
  • 2026佛山翡翠回收盘点:正规鉴定无套路,本地靠谱变现渠道全测评 - 薛定谔的梨花猫
  • MC68HC908GT Flash与ADC模块深度解析与实战编程指南
  • Hi3751 V352 Android9.0 eMMC分区扩容与自定义配置实战
  • AI率总超标?2026年AI写作辅助平台排行榜权威发布,快速成文不是梦!
  • 2026南京闲置包包回收横向实测|7家门店客观盘点+行业干货科普 - 薛定谔的梨花猫
  • 2026 宁波黄金回收领先行业测评|高价合规变现第三方中立指南 - 奢侈品回收测评
  • 2026成都金豆、小金珠零散黄金回收,小件不会额外收取手续费 - 逸程
  • 2026成都黄金回收用 “两、钱” 换算一定要警惕猫腻 - 逸程
  • 在浏览器里重建了一座能逛能聊能吟诗对弈的唐长安城
  • 今日大盘金价更新,昆明旧黄金出手窗口期别错过 - 奢侈品回收评测
  • Microchip无线模块固件升级与增益表更新实战指南
  • 深入解析S12P微控制器PWM模块:时钟配置、通道级联与实战调试
  • 2026年深圳与香港房子同步全屋定制可行吗?深港跨境真实避坑指南
  • 企业AI使用政策设计:从风险识别到落地执行的实操框架