用 AI 编码智能体摸清遗留系统:改进软件架构的五种实战方法

2026-09-28 35 预计阅读时间: 1 分钟
来源: infoq.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:10 分钟

现代系统很少从零开始。一个看似清晰的服务架构,往往仍依赖十年前的接口、无人维护的批处理任务,或者只有少数工程师知道如何调用的内部服务。真正危险的不是“旧”,而是团队不知道它的输入、输出、副作用和故障边界。

AI 编码智能体适合处理这类知识缺口:它可以跨文件检索调用点、归纳接口行为、生成测试草案,并把零散发现整理成架构文档。但它不能替代运行时证据和工程师判断。更稳妥的定位,是把智能体当作一名速度很快、但所有结论都需要复核的架构调查助手。

1. 从调用点反推遗留服务的真实边界

文档描述的是“设计时的系统”,代码和配置暴露的则是“正在运行的系统”。可以让智能体扫描以下信息:

  • HTTP、RPC、消息队列和数据库调用点;
  • 环境变量、服务地址、超时和重试配置;
  • 请求参数、响应字段及错误处理分支;
  • 定时任务、补偿逻辑和人工操作脚本;
  • 哪些业务模块直接依赖遗留服务。

不要只问“这个服务做什么”。更有效的任务应要求智能体给出证据位置:

请调查仓库中对 legacy-billing 服务的全部依赖。

输出:
1. 调用文件和行号;
2. 使用的协议、路径与配置项;
3. 请求和响应字段;
4. 超时、重试、降级及异常处理;
5. 无法由代码确认的假设,单独列为“待验证”;
6. 不要修改代码。

这种输出可以形成依赖清单,但不能证明某个调用仍会在生产环境触发。还需要结合访问日志、链路追踪和配置中心进行验证。

2. 把代码考古结果变成可维护的接口契约

找到调用点后,下一步不是立即重构,而是把隐含契约显式化。智能体可以根据客户端模型、序列化逻辑和样例响应,起草 OpenAPI、JSON Schema 或消息格式说明。

建议为每个字段标注证据等级:

  • 已验证:来自生产流量、服务实现或集成测试;
  • 代码推断:从调用方代码推导,但尚未通过运行验证;
  • 未知:错误码、空值规则或边界行为仍不清楚。

下面是一份可以改造的契约草案。它是假设性示例,不代表任何特定遗留服务的真实 API:

openapi: 3.0.3
info:
  title: Legacy Billing Adapter
  version: 0.1.0-draft
paths:
  /v1/accounts/{accountId}/balance:
    get:
      parameters:
        - name: accountId
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Balance returned
          content:
            application/json:
              schema:
                type: object
                required: [accountId, amount, currency]
                properties:
                  accountId:
                    type: string
                  amount:
                    type: string
                    description: Decimal value; representation must be verified
                  currency:
                    type: string
                    minLength: 3
                    maxLength: 3
        '404':
          description: Account not found; error body remains to be verified

草案应进入版本控制,并由服务维护者和真实调用方共同审查。智能体可以提高整理速度,但不能凭几个客户端模型就确定服务端的全部行为。

3. 先生成特征测试,再考虑替换实现

遗留系统经常没有完整规格。此时最有价值的测试不是证明其行为“正确”,而是记录它“现在如何工作”。这类特征测试可以覆盖:

  • 常见输入与典型响应;
  • 空值、重复请求和超大数据;
  • 超时、限流及部分失败;
  • 字段顺序、日期格式和金额精度;
  • 调用是否产生写库、发消息等副作用。

可以让智能体从调用方夹具、日志样本和现有测试中生成测试草案,再由工程师删除敏感数据、补充断言并在隔离环境运行。不要让智能体直接拿生产凭据探测旧服务。

如果必须记录真实响应,应先脱敏,并区分稳定契约与偶然数据。例如,订单状态可能属于契约,而请求时间戳通常不应被写死在快照里。

4. 让智能体比较架构选项,而不是直接决定架构

当依赖和行为逐渐清楚后,智能体可以协助比较多个改造方案:

  • 保持现状,只补文档与监控;
  • 增加适配器或反腐层,隔离遗留数据模型;
  • 使用绞杀者模式逐步替换能力;
  • 将共享数据库访问收敛为明确的服务接口;
  • 暂缓迁移,先降低单点故障和运维风险。

让智能体生成架构决策记录(ADR)时,输入中必须包含约束,例如迁移窗口、合规要求、调用量、延迟预算、团队能力和回滚条件。否则,它很容易提出技术上优雅、组织上无法落地的方案。

一个有效的 ADR 至少应回答:为什么现在要改、有哪些备选方案、选择依据是什么、会引入哪些新风险,以及出现什么信号时需要撤销决定。

5. 用智能体持续检查架构漂移

一次性文档很快会过期。更有价值的做法,是把调查规则放进 CI:新增遗留依赖、绕过适配层、使用已废弃端点时自动生成报告或阻止合并。

下面的 Python 脚本只使用标准库,可以扫描仓库中常见的遗留服务标记。运行前请按项目修改 needles 和 allowed_suffixes:

#!/usr/bin/env python3
import json
import sys
from pathlib import Path

SKIP_DIRS = {'.git', '.idea', '.venv', 'node_modules', 'dist', 'build'}


def main() -> None:
    root = Path(sys.argv[1] if len(sys.argv) > 1 else '.').resolve()
    needles = ['LEGACY_BASE_URL', 'legacy.internal', '/v1/legacy/']
    allowed_suffixes = {'.py', '.js', '.ts', '.java', '.go', '.yaml', '.yml', '.json', '.env'}
    findings = []

    for path in root.rglob('*'):
        if not path.is_file() or path.suffix not in allowed_suffixes:
            continue
        if any(part in SKIP_DIRS for part in path.parts):
            continue

        try:
            lines = path.read_text(encoding='utf-8').splitlines()
        except (UnicodeDecodeError, OSError):
            continue

        for line_number, line in enumerate(lines, start=1):
            matches = [item for item in needles if item.lower() in line.lower()]
            if matches:
                findings.append({
                    'file': str(path.relative_to(root)),
                    'line': line_number,
                    'matches': matches,
                    'text': line.strip()[:240],
                })

    print(json.dumps({'root': str(root), 'findings': findings}, indent=2, ensure_ascii=False))


if __name__ == '__main__':
    main()

保存为 tools/legacy_inventory.py 后运行:

python tools/legacy_inventory.py . > legacy-usage.json

随后可以把 legacy-usage.json 交给编码智能体分类,但应避免上传令牌、连接串或客户数据。实际 CI 中还可以保存一份基线,只在新增依赖时失败,避免历史问题一次性阻塞所有交付。

落地时守住三条边界

引入 AI 编码智能体时,可以从一个风险可控的遗留服务开始,并遵循三条原则:

  1. 证据优先:每项结论都要能指向代码、配置、测试、日志或负责人确认;
  2. 只读起步:先允许搜索和生成报告,再逐步开放修改代码、执行测试等权限;
  3. 小步闭环:依赖清单、契约草案、特征测试、ADR 和 CI 规则应形成连续链路。

衡量成效时,不要只看智能体生成了多少文档。更值得关注的是:未知依赖是否减少、故障定位是否更快、迁移是否可以回滚,以及架构决策是否拥有可验证的依据。AI 能加快理解遗留系统的过程,但架构责任仍然属于团队。


相关推荐