文章 · 2025-07-27

当AI辅助开发失败时:一份技术事后分析

我要求AI一次性构建完整的系统:一个健壮的asyncio调度器、动态参数调整的任务执行、自我改进任务生成,以及失败任务的人工工单系统。AI快速交付了可工作的代码。问题只在我尝试集成时才出现。

系统崩溃了。不是因为新颖的缺陷,而是经典的软件工程问题被无约束的开发过程放大:范围膨胀、集成未审查、紧密耦合、技术债务嵌入基础。

为何无约束的AI开发会失败

缺乏架构审查的范围膨胀

AI没有业务背景或架构直觉来说"不"。它是一个强大的实现引擎,优化用来执行请求。通过一次性要求一切而不定义集成点或架构约束,我无意中引导它解决一个尚不存在的未来问题,放弃了对稳定调度器的直接需求。

"智能"功能被强行附加到从未经受压力测试的核心上。我在把AI当作自主开发者,期望从功能清单中获得一致性。同事如果收到同样的需求,会提出异议、提议分阶段方法,并对复杂性表示担忧。AI直接执行了。

事件循环冲突

当我尝试运行集成系统时,它崩溃了。根本原因具有范例性:不同模块在隔离开发中试图管理同一个asyncio事件循环。

核心调度器使用一种模式初始化。然后工单系统,在独立开发中,用asyncio.run()处理失败任务:

问题代码片段1:冲突的事件循环

# 在scheduler_core.py中,由一个提示生成
import asyncio
from apscheduler.schedulers.asyncio import AsyncIOScheduler

class MainScheduler:
    def __init__(self):
        self.scheduler = AsyncIOScheduler()

    def run(self):
        self.scheduler.start()
        # 这个调用会永远阻塞,运行循环
        asyncio.get_event_loop().run_forever() 

# 在ticketing_system.py中,由另一个提示生成
import asyncio

class TicketingSystem:
    async def process_ticket(self, ticket_data):
        # ... 逻辑 ...
        print("处理工单")

    def handle_failed_task(self, task_info):
        # 这是反模式!它试图运行一个新循环
        asyncio.run(self.process_ticket(task_info))

当调度器在执行中调用handle_failed_task时,代码崩溃并报RuntimeError: This event loop is already running。工单系统的开发者(AI)看到一个本地问题——"我需要运行异步函数"——应用了标准解决方案,却没有理解全局背景:它是一个已在运行的事件循环的一部分。

第二个架构不匹配涉及apschedulerCronTrigger。它的阻塞实现和独立线程模型与我设想的异步设计冲突。结果:难以隔离的时序错误和竞态条件。

紧密耦合与级联失败

系统变成了一个单体,模块对彼此的内部有深层依赖。自我改进任务模块直接依赖工单系统的数据结构。主调度器知道任务执行逻辑的内部细节。

概念问题:紧密耦合

# 之前:依赖关系的混乱
class MainScheduler:
    def __init__(self):
        # 调度器直接实例化其"智能"组件
        self.improver = AutoTaskImprover()
        self.ticketer = TicketingSystem()

    def _execute_task(self, task):
        result = task.run()
        if not result.success:
            # 直接调用另一个模块的实现
            new_script = self.improver.analyze_and_suggest_fix(task.script, result.error)
            if new_script:
                task.update_script(new_script)
            else:
                # 另一个直接的深度调用
                self.ticketer.handle_failed_task(task.info) 

一个组件的失败会在整个系统中级联。调试变成不可能,因为错误不在其表现的地方发生。系统不是合作模块的集合;它是一台脆弱的机器。

放弃架构责任

我放弃了架构师的角色。我指定构建什么但没有指定如何构建或如何集成。没有每一步的手动代码审查和集成测试,我对不断积累的架构腐败是盲目的。

恢复和重新定位人机关系

从这次失败中重建揭示了一个清晰的有效人机协作框架。

从稳定核心开始

修复不是改进现有系统,而是放弃它,重新开始,目标单一明确:一个坚如磐石的、简单的异步调度器。没有智能功能。没有自我改进。只是稳定的、经过压力测试的基础。

只有在这个核心被构建、测试并验证可靠后,我才一次添加一个功能。每个新功能成为一个独立的、可选的模块,而非核心组件。

修复:模块化、可插拔架构

# 之后:使用依赖注入的清洁、解耦设计

# --- 核心调度器(对"智能"功能一无所知)---
class MainScheduler:
    def __init__(self, plugins=None):
        self.plugins = plugins or []

    def _execute_task(self, task):
        result = task.run()
        if not result.success:
            # 核心只发布事件,它不知道消费者
            self.publish_event('task_failed', task=task, result=result)

    def publish_event(self, event_type, **kwargs):
        for plugin in self.plugins:
            if hasattr(plugin, f"on_{event_type}"):
                getattr(plugin, f"on_{event_type}")(**kwargs)

# --- 可选插件 ---
class AutoImprovementPlugin:
    def on_task_failed(self, task, result):
        # 改进任务的逻辑现在被隔离在这里
        print(f"插件:分析任务失败 {task.id}")
        # ...

# --- 主应用程序连接 ---
core_scheduler = MainScheduler(plugins=[AutoImprovementPlugin()])
# 现在智能功能是可选插件,而不是核心依赖

这保持核心清洁,允许功能被交换、升级或禁用而不影响系统其余部分。

人类必须架构和审查

我把角色从"项目经理"改为"首席架构师和高级开发者"。新工作流:

  1. 定义一个小的、隔离的任务(如"创建一个插件记录任务失败到JSON文件")
  2. AI生成代码
  3. 我审查每一行。我检查反模式、架构不匹配和隐含假设。
  4. 我自己重构和集成。我将其连接到主应用,确保遵循既定架构。
  5. 我编写集成测试并提交

这个以人为中心的审查循环是必需的。它让人类控制架构决策和质量标准。

执行架构约束

asyncio问题通过执行一条规则解决:只有一个事件循环,由应用入口点管理。模块和插件绝不能调用asyncio.run()loop.run_forever()。它们暴露主循环可以等待的async函数。

修复:单一、统一的事件循环

# 在插件文件中(例如,ticketing_plugin.py)
class TicketingPlugin:
    async def on_task_failed(self, task, result):
        # 这个函数现在是异步的,期望被await
        await self.create_ticket(task.info)

    async def create_ticket(self, info):
        print(f"为 {info} 创建工单")
        # ... await 异步I/O操作 ...
        await asyncio.sleep(0.1) 

# 在主应用程序入口点
async def main():
    # 插件现在设计为被await
    ticketing_plugin = TicketingPlugin()
    scheduler = MainScheduler(plugins=[ticketing_plugin])
    
    # 调度器的`publish_event`需要是异步的
    # 并await插件调用
    
    # ... 启动逻辑 ...
    await scheduler.run() # 主run函数现在是可等待的

if __name__ == "__main__":
    # 运行事件循环的唯一地方
    asyncio.run(main())

这个原则——全局执行简单性——必须来自人类。为本地目标优化的AI可能不会选择全局最简方案。

经验教训:人类作为机长

AI开发工具是强大的副驾驶,不是自主机长。它们能以超人速度执行复杂指令,处理大量技术细节。但人类开发者必须保持指挥:负责架构、代码审查、集成和最终方向。

AI的承诺是真实的。它需要新的纪律:抵抗让它无监督运行的诱惑。相反,严格指导它、质疑假设,将其输出与仅有人类架构师才能提供的前瞻性相融合。

通过将战略性人类监督与AI的战术能力配对,你避免飞入积累复杂性的风暴,反而构建既非凡又可维护的软件。

真正有效的做法

© 2026 Yuxu Ge ·