AI 写的代码越来越难改,怎样保持简单?
围绕真实变化整理职责,避免一边修耦合、一边制造过度设计。
本页目录
直接回答
先分清难改是职责纠缠、资料不足,还是需求尚未定清。模块化应使一次业务变化集中在可理解的范围,同时保护其他行为。高内聚、低耦合和单一职责可以帮助判断,也要遵守 YAGNI、KISS 并及时暴露错误。行数和函数长度只是检查信号,不能机械决定是否重构。
实践建议:说不出新接口服务于哪个当前调用方时,先不加入。记录现有方案的限制与升级触发条件,等真实需要出现再扩展。
适用场景
- 改一处总牵动多个无关页面。
- 项目里开始出现重复逻辑、巨型函数或很多“以后用得上”的封装。
一步一步做
沿用户动作找出真实调用链
从页面或接口入口往下看数据怎么流动、哪些模块处理什么。先搜索所有调用方,不要只看到大文件就拆。记录当前正确行为和必须保持的约束。
把职责混杂的问题具体化
例如支付模块内部税额函数被购物车直接使用,导致修改支付破坏购物车;问题是依赖了内部细节。应定义稳定职责或移到真正共享的位置,不是简单改文件名。
采用最小充分修改
已有实现能解决就复用,标准平台功能足够就不用新依赖。只为当前需求增加接口,不先造通用插件架构、抽象工厂或微服务。必要拆分保持错误处理与验证完整。
让命名表达业务含义
名称说明值的单位、状态和用途,例如剩余额度与已用额度不能都叫 count。函数名称承诺的结果应与实际一致;不能把失败兜底写成成功对象返回。
针对变化验证并留下边界
检查主要调用方与失败分支。已知限制写清何时需要升级;先确认用户问题被解决,再考虑进一步整理。不要为追求整洁扩大修改面。
把五种代码气味变成一张变更影响表
针对杂物职责、长函数、散弹式修改、长参数列表和循环依赖,各找一个实际变更,列出修改位置、变化理由、消费者和重复故障。不要只因超过某个行数或命中几种气味就重构。一条业务规则散落多个模块时先收拢该规则;只是排版长但职责一致的实现可保留。循环依赖说明边界可能难理解,不自动等于运行时死锁。选出一个真正值得修的痛点。
先画边界,再用行为不变约束重构
画出“入口→业务决策→数据/外部服务”,列明公开接口输入、返回、错误与副作用。购物车需要税额时调用明确的公共计算接口,不依赖支付内部方法。注册可以由调度函数组织校验、落库与发信,但每步须有准确的失败语义:创建用户成功而邮件失败时,不应谎称全部失败并重建用户,应标记通知待重试或准确的部分完成状态。拆文件并不自动解决事务与补偿。
把异常分成可拒绝、可恢复和结果未知
无效输入在信任边界明确拒绝;临时上游失败按策略有限重试,并给可恢复状态。支付超时而结果未知时,先查询同一交易或使用幂等键,不能再创建一笔扣款。不可恢复的内部错误交给统一处理,保留脱敏诊断,不伪造空结果或成功。用户提示应给下一步,日志只留定位信息,不回显密钥与完整个人资料。catch 的价值在于明确恢复、转译或记录后传播。
检查“更短”是否偷偷改变类型、边界或副作用
教学简写不等于生产契约。Python 的 and 会返回操作数,紧凑的会员判断可能返回 None;包含 @ 也不证明邮箱有效或归属已验证。名为 get 的函数可以合理抛错或记日志,但不应隐藏重要业务写入。缩短代码前列出输入类型、空值、单位、返回类型和副作用,用调用方及相称的检查确认行为不变。可以删除未用抽象,不能因流量小而省掉已知鉴权、限流或金额精度要求。
案例拆解
假设示例:购物车依赖支付内部函数
购物车直接调用支付内部的 calculateTax,支付调整后购物车也失败。这暴露的是职责和接口边界。修复应先核对税额计算到底归谁负责,保留业务测试,再调整依赖;拆成更多文件本身不会消除这个问题。
行动检查
可复制模板
最小改动审查模板
本次用户问题:
需要保持的不变量:
入口与全部调用方:
现有实现为什么不足:
最小可行改动:
被删除/替代的重复逻辑:
错误处理与边界校验是否保留:
相关验证与未验证项:
请指出不必要的抽象,但不要为减少行数损害可读性或正确性。
气味到最小重构单
真实变更/故障:
气味:杂物职责/长函数/散弹修改/长参数/循环依赖
证据:变更过哪些文件、哪些调用方受影响:
各职责会因什么原因变化:
最小边界调整:
公开入口:输入、返回、错误、单位、权限:
调用方与迁移顺序:
必须保持的业务结果和副作用顺序:
不做的抽象/暂缓的优化:
证明行为不变的检查:
何时需要再次升级:
错误处理决策表
操作 | 错误类别 | 用户可见状态 | 是否可重试 | 幂等/查状态办法 | 内部诊断
输入错误:拒绝并指出可修正字段。
依赖暂时不可用:限定重试/超时,保留用户输入。
有副作用且结果未知:先查同一请求状态,不重复创建交易。
部分成功:说明已完成哪一步、待补哪一步。
内部缺陷:不返回假成功,保留脱敏关联ID。
需要验证的边界:空值/重复/中断/超时/异常金额或单位。
易错点
- 短代码不等于易读,难懂的一行可能比清晰的几行更难维护。
- 不能为减少校验删除信任边界检查。
- 固定行数和风险档位只能作为启发式提醒,不能充当通用质量评分。
- 为让函数更短改变返回类型,或用极简教学片段替代生产验证。
- 拆了注册/支付函数就认为事务、幂等和失败恢复自动正确。
- 把循环依赖一律解释为死锁,或把命名习惯当绝对禁令。