AI 能写代码,但工程架构还是应该由人来定

0 阅读10分钟

AI 能写代码,但工程架构还是应该由人来定

d8d800b1-7402-4236-ad4b-66043eec266f.png

做 Android 车载开发这些年,我越来越觉得,有些问题并不是代码写出来就算解决了。

尤其是在维护项目里。

有时候只是改一个功能,顺着代码往下看,才发现它还牵涉到另外一个 Service,某个广播又会影响设备状态,状态变化之后还要通知其他模块。改到最后,原本想解决的问题还没处理完,反而发现了几个之前没注意到的隐患。

最近使用 AI 编程工具比较多,我也开始思考一个问题:

既然 AI 已经能够帮我们写代码、分析问题,甚至参与方案设计,那工程师应该把哪些工作交给 AI,哪些事情又应该自己把握?

我的想法是,具体工作可以让 AI 多参与,但工程架构、整体方向和关键决策,还是应该由人来确定。

01. 一个看起来很小的需求,背后可能牵涉好几个模块

普通 Android 开发中,很多需求相对独立。修改一个页面、增加一个按钮,或者调整某个业务逻辑,通常沿着当前模块就能找到入口。

车载项目有时候不太一样。

以设备管理为例,从蓝牙扫描、设备发现、配对,到后续连接和投屏,中间涉及多个状态和模块之间的配合。

一个设备被发现了,不代表它已经配对;配对成功了,也不代表连接已经建立。不同阶段的状态变化,还可能通过广播、回调或者服务接口通知其他模块。

如果只盯着某一个方法,很容易觉得问题已经解决了。

但实际运行时,可能还有另外一个模块没有收到预期的状态,或者某个异常分支没有被处理。

这类问题在维护项目中并不少见。

有些代码单独看没有问题,放到整个业务流程里,就不一定了。

所以我现在接到一个需求时,通常不会马上考虑怎么改代码,而是先弄清楚它涉及哪些模块,现有流程是怎么走的,修改之后会影响哪些地方。

这一步如果没有想清楚,后面写得再快,也可能是在错误的方向上做事情。

02. AI 确实提高了开发效率,但它需要工程上下文

这段时间使用 AI 编程工具,我最大的感受就是效率确实提高了。

以前遇到一个不熟悉的类,需要自己查调用关系、看接口、翻日志。现在可以让 AI 帮忙分析调用流程,解释异常,甚至给出修改建议。

一些重复性的代码,也不需要再完全从头写起。

但我发现一个问题:AI 给出的答案,往往取决于它拿到了多少有效的上下文。

比如一个 Service,单独拿出来看,AI 可以很快理解它的功能。但如果它还依赖另外两个服务,其中一个服务负责设备状态,另一个负责连接管理,那么只看当前类,就很难判断一次修改会不会影响其他模块。

更麻烦的是维护项目中的历史逻辑。

有些判断看起来多余,实际上是为了兼容某些设备;有些接口看起来可以合并,却可能已经被其他模块依赖。

如果这些背景没有交代清楚,AI 很可能会按照当前代码的表面逻辑给出修改建议。

所以我现在越来越重视给 AI 提供工程上下文。

让它先了解模块职责、接口关系、状态流转和现有约束,再去分析具体问题。

AI 可以帮助我们理解项目,但不能因为它给出了一个完整答案,就认为它已经考虑了整个项目的所有情况。

03. 真正麻烦的问题,往往不是代码本身

之前做过一次蓝牙扫描相关的长时间压测。

刚开始运行时一切正常,扫描回调也一直在正常返回。日志里不断打印设备名称、设备 ID 等信息,页面也会跟着刷新。

短时间运行似乎没有什么异常,但测试时间拉长之后,最终还是出现了 OOM。

后来排查发现,高频回调带来的日志输出和刷新操作,也是需要关注的地方。频繁打印日志、反复进行字符串拼接,以及不必要的刷新,都会增加额外开销。

最后通过减少高频日志、降低刷新频率,解决了这次问题。

这件事让我意识到,有些问题不能只从一个方法判断。

代码能不能运行,只是一个方面。长时间运行是否稳定、资源是否持续增长、异常情况下状态能不能恢复,这些同样需要考虑。

AI 可以帮忙检查代码、分析日志,也可以提供性能优化建议。

但如果没有真实的运行数据、压测结果和现场信息,很多判断都只能停留在推测阶段。

这也是为什么我认为,AI 应该参与工程分析,但不能替代工程师对最终结果的判断。

04. 方案可以让 AI 推演,但方向不能完全交给 AI

前段时间和同事一起讨论一个技术方案,遇到过一个比较纠结的问题。

按照其中一个方案处理,会引出另外一个问题;如果优先解决另一个问题,又可能破坏当前的处理逻辑。

当时也让 AI 推演了好几个方向。

它给出的方案并不是完全没有道理,单独看每一种处理方式,都能找到一定的依据。

但把它们放到一起,就发现有些地方根本衔接不上。甚至某些修改还可能让之前修复过的问题重新出现。

后来我逐渐意识到,我们当时缺少的可能不是更多方案,而是一个明确的整体设计。

例如:

  • 当前问题的边界到底在哪里?
  • 哪个模块负责处理设备状态?
  • 服务之间的调用关系应该怎么组织?
  • 异常发生之后,状态如何恢复?
  • 修改之后,之前的功能会不会受到影响?

这些问题没有弄清楚之前,让 AI 不断生成新方案,其实很难真正解决问题。

我的习惯是先把整体流程理清楚,确定模块职责和接口关系,再让 AI 参与具体实现。

AI 可以提供不同思路,也可以指出设计中的遗漏,但最终选择哪种方案,还是要结合项目现状来决定。

05. 工程架构应该由人来定,AI 负责把事情做得更快

我现在对 AI 编程的理解,越来越接近一种分工。

工程师负责确定方向,AI 负责辅助执行。

比如一个设备管理功能,在开始开发之前,应该先明确设备状态由谁维护,哪些服务负责处理连接,模块之间通过什么接口通信,状态变化如何通知其他模块。

这些属于工程设计,需要结合整个项目来考虑。

确定好之后,AI 就有很多事情可以做了。

它可以帮忙梳理现有代码,分析接口调用关系,补充具体实现,检查异常分支,编写测试代码,甚至从不同角度审查方案。

如果发现现有设计存在问题,也可以让它提供几种调整思路,帮助我们比较不同方案的影响。

但这里有一个前提:我们必须知道自己要解决什么问题。

否则 AI 给出的代码越多,可能只是让一个没有确定方向的方案变得越来越复杂。

我并不认为架构设计就完全不能交给 AI 参与。相反,AI 可以成为一个很好的方案讨论对象。

只是讨论归讨论,最终的架构决策和取舍,应该由了解项目的人来负责。

06. 维护项目尤其不能只看眼前的代码

新项目和维护项目,使用 AI 的方式应该有所区别。

新项目有一定的设计空间,架构、接口和模块职责都可以提前规划。

维护项目则有很多历史包袱。

现有代码可能已经运行了很长时间,有些实现虽然看起来不够漂亮,却承担着兼容和稳定运行的责任。

AI 可能会建议你把某段代码抽象出来,重新设计状态管理,甚至调整整个调用结构。

从代码质量的角度看,这些建议未必有问题。

但对于一个正在维护的项目来说,改动越大,影响范围也越难控制。

我更愿意先明确本次需求的边界,尽量控制修改范围。确实有必要调整架构的地方,再评估依赖关系、兼容性和回归场景。

AI 可以帮助我们完成修改,也可以提醒我们哪些地方值得关注。

但哪些地方可以改,哪些地方不能动,还是需要工程师结合项目实际情况来判断。

毕竟,维护项目最怕的不是代码写得不够漂亮,而是解决了一个问题,又带来了另一个问题。

07. AI 编程之后,工程师需要保留自己的判断能力

最近使用 AI 编程工具越来越多,我也有一个比较明显的感受。

有时候 AI 给出的代码很完整,解释也很清楚,甚至看起来比自己写的还规范。

但如果自己没有真正理解它的实现过程,后续出了问题,还是得重新回来梳理。

这让我觉得,使用 AI 的过程中,有一件事不能丢:自己分析和判断问题的能力。

Android 开发中的 Framework、Binder、Service、Handler、线程、生命周期等基础知识,仍然有必要掌握。

不一定每次开发都要从底层原理开始,但至少应该知道系统为什么这样运行,模块之间为什么这样设计。

特别是车载项目,很多问题并不是单纯修改几行代码就能解决的。

我们需要知道设备状态怎么变化,服务什么时候启动,异常发生之后如何恢复,以及一个模块的修改会不会影响其他模块。

这些能力决定了我们能不能看懂 AI 写出来的代码,也决定了我们能不能判断它给出的方案是否适合当前项目。

写在最后

我并不排斥 AI 编程。

相反,我觉得它确实改变了很多日常开发方式。一些重复性工作、代码实现和问题排查,现在都可以借助 AI 提高效率。

但我不希望自己逐渐变成一个只负责给 AI 提需求、复制代码、检查运行结果的人。

我更愿意把 AI 当成一个可以协作的工具。

具体实现可以交给它,代码分析可以让它参与,方案设计也可以一起讨论。

但项目要往哪个方向走,整体架构怎么组织,模块之间的边界怎么划分,以及最终方案是否符合项目实际情况,这些事情还是应该由工程师来决定。

架构由人定,细节让 AI 做,最终结果由人来把关。

至少在我看来,这才是 AI 编程更合理的使用方式。

66cd2c40-bb3b-4c6b-87b4-2603caa7f8a7.png