AI会让我们困在2020年的架构中吗?
AI编码助手擅长2020时代的模式(如Spring),这可能阻碍新架构的采用。作者将Spring PetClinic REST转换为使用OfficeFloor YAML的显式函数注入,发现AI需要多次迭代才能理解,但最终成功。
每次使用AI编码助手时,我都会注意到同样的事情:它非常擅长Spring。注解、配置文件、@Autowired,以及整个回调栈驱动的bean注入舞蹈。AI已经见识了二十年的这种模式。即使需要推断配置文件特定的bean如何在运行时被选择,它也能很好地预测。这是因为它见过成千上万个完全相同的模式实例。
这引发了一个令人不安的问题:如果AI如此精通2020时代的模式,我们整个行业是否会因为这些模式是模型所知的而被锁定?AI是否是一种保守力量,悄悄地将软件架构拉向其训练数据的重心,无论新想法有多好?
我想通过自己的项目来找出答案。
赌注:显式索引胜过隐式索引
OfficeFloor第4版添加了一个我认为在AI时代真正有趣的功能:REST端点现在可以在YAML文件中定义,与现有的Spring Boot代码并存,目录结构遵循URL结构。文件greeting.POST.yml定义POST /greeting。文件greeting/{name}.GET.yml定义GET /greeting/{name}。在该文件中,你可以组合处理请求的小函数:
每个函数仍然像往常一样通过Spring注入依赖项。OfficeFloor不会取代Spring的依赖注入、持久化、安全或执行器设置。变化的是流程。在典型的@RestController中,验证、业务逻辑和审计运行的顺序是隐式的:它存在于调用栈中(在if语句以及哪个方法调用哪个方法中)。要理解它,你需要阅读代码。要改变它,你需要阅读更多代码,因为连接没有作为数据写下来;它被编译成控制流。
在OfficeFloor YAML版本中,这个连接就是文件本身。条件分支、顺序、错误流:它们被声明,而不是隐藏。链中的任何函数都不知道其他函数。没有注解在类内部描述关系。YAML是一个完整的、可读的端点行为规范,就位于目录树中端点自己的URL路径旁边。
这本质上是函数注入,与依赖注入数十年前所做的动作相同,但提高了一个层次。依赖注入将“我依赖什么”从命令式构造函数代码中取出,使其成为显式的、配置化的、一流的关注点。函数注入将“接下来发生什么”从隐式调用栈中取出,也使其显式化和可配置化。这是我多年来一直在写的“控制耦合反转”思想的延续:依赖注入只解决了耦合问题的一个切片。控制流耦合始终存在,只是不可见。
对于阅读代码的人类来说,这可能感觉像是洗牌,甚至可能是倒退。这正是业界首先选择注解放在代码旁边的原因:开发者希望连接靠近实现,而不是在某个独立的描述文件中。这种偏好当人类是主要读者时是有意义的。
但AI助手不是从上到下阅读的人类。AI助手试图找到进行正确、精确更改所需的最小上下文,这是一个搜索和导航问题,而不是风格问题。一个YAML文件命名了端点执行路径中的每个函数,按顺序,带有显式条件分支,这就是一个搜索索引。AI无需阅读代码库的其他部分就能确信它找到了与该端点相关的所有内容。它打开一个小的文件,该URL的整个行为契约就在那里。
至少理论上是这样。我想知道它是否真的能在几乎完全以另一种方式训练出来的模型上奏效。
实验:转换Spring PetClinic REST
为了真实测试,我采用了Spring PetClinic REST(Spring社区多年来使用的PetClinic示例应用的长期参考REST实现),并与AI合作将其端点转换为OfficeFloor REST YAML方法。
第一次尝试没有成功。大约迭代了五次才得到干净的转换,瓶颈不是OfficeFloor的运行时,也不是AI的编码能力。而是文档。每次尝试都暴露出教程中的空白:一些我因为显而易见而隐式保留的假设,YAML模式可能性未详尽说明的地方,Spring @RestController风格行为应如何映射的边缘情况。我利用AI的混淆作为信号:它猜错或问错的地方,正是教程需要另一段、另一个例子、另一条显式规则的地方。经过五轮“AI卡住,教程修复,再试一次”,转换终于顺利通过。
我录制了最终的转换过程。你可以在这里观看: