ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

46万行AI代码后,我重新理解了做产品的核心

46万行AI代码后,我重新理解了做产品的核心

1. 46万行代码背后的真实体感:从兴奋到冷静

第一次看到代码仓库里那个数字跳到46万行的时候,说实话,我心里是有点飘的。那是一个我主导的跨平台工具类产品,从零起步,前后迭代了大概十一个月。如果按传统手写代码的方式,这个体量至少需要一个五到八人的团队干上大半年。而我这边,核心开发长期只有两个人,外加一位兼职做UI的伙伴。AI编程助手在其中扮演的角色,不是“帮忙补全几行”,而是实打实地承担了六成以上的代码产出。

但数字带来的兴奋感消退得很快。大概在第三十万行左右的时候,我开始频繁遇到一种很别扭的情况:功能明明都实现了,测试也过了,可我就是说不清楚这个产品到底“长什么样”。不是UI层面的长相,而是它的架构、它的边界、它的演进方向,在我脑子里变得模糊了。以前手写代码,每一行都是自己敲的,哪个模块耦合重、哪个地方是临时方案,心里门儿清。现在呢?AI生成的代码质量其实不差,甚至有些地方比我写得还规范,但那种“亲手搭建”的掌控感被稀释了。

这让我不得不停下来重新思考一件事:当代码的生产成本急剧下降,做产品这件事的核心矛盾到底转移到了哪里?这篇文章不打算给你灌鸡汤,也不打算鼓吹什么“AI取代程序员”。我想做的,是把这46万行代码踩过的坑、验证过的方法、以及那些让我半夜睡不着觉的反思,原原本本地摊开来讲。如果你也在用AI辅助做产品,或者正准备这么做,这些经验应该能帮你少走一些弯路。

先交代一下背景,方便你判断这些经验的适用性。产品是一个面向中小团队的协作工具,包含任务管理、文档协同、轻量级数据看板三个核心模块。技术栈是前端React加TypeScript,后端Node.js加PostgreSQL,部署在容器化环境里。AI助手主要用于代码生成、重构建议、单元测试编写和部分架构设计讨论。整个过程中,我既是产品负责人,也是主力开发者之一,所以视角会兼顾“做产品”和“写代码”两条线。

2. 代码量暴涨之后,最先崩掉的不是服务器而是认知

2.1 46万行里有多少是“有效代码”

先泼一盆冷水。46万行这个数字,如果直接拿去跟手写代码对比,是有很大水分的。我后来做了一次粗略的代码审计,把整个仓库的代码按来源和性质分了类,结果如下:

代码类别大致行数占比说明
核心业务逻辑约9万行19.6%真正决定产品行为的代码
自动生成的类型定义约7万行15.2%由接口 schema 自动生成
单元测试与集成测试约12万行26.1%大部分由AI辅助生成
样式与UI组件约6万行13.0%含大量重复的样式变体
配置文件与脚本约3万行6.5%构建、部署、CI 相关
废弃与注释代码约5万行10.9%迭代过程中未清理的部分
第三方库封装约4万行8.7%对依赖的二次包装

真正属于“核心业务逻辑”的,不到十万行。这个比例其实挺健康的,但问题在于,AI生成代码的速度太快,导致废弃代码和重复代码的清理速度完全跟不上。你让AI写一个功能,它可能给你生成三百行,其中两百行是各种边界处理和类型守卫。这些代码不是没用,但它们的存在感太强了,强到会干扰你对产品核心的判断。

我踩过的一个典型坑是:有一次需要修改任务状态的流转逻辑,我让AI助手帮我定位相关代码。它给我列出了十七个文件,涉及四十多个函数。我花了整整一个下午才理清楚哪些是真正在用的,哪些是历史遗留。如果这些代码是我自己一行行写的,我大概十分钟就能定位到目标。这就是代码量暴涨带来的第一个认知负担:你知道东西都在仓库里,但你不知道它们之间的真实关系。

2.2 为什么“能跑就行”在AI辅助下变得危险

手写代码的时候,“能跑就行”是一种务实的妥协。你知道哪里是临时方案,哪里欠了技术债,心里有本账。但在AI辅助的场景下,“能跑就行”会变成一种系统性风险。因为AI生成的代码,往往在局部是自洽的,甚至看起来很优雅,但它不一定符合你产品的整体架构意图。

举个例子。我们的文档协同模块需要实现一个实时的光标位置同步。我让AI助手基于WebSocket写一个方案,它很快给了一套完整的实现,包括心跳检测、断线重连、消息队列。代码跑起来没问题,测试也过了。但后来我发现,这套实现里隐含了一个假设:每个文档的协同会话是独立的。而我们的产品设计里,文档是可以跨项目引用的,一个文档可能同时属于多个协作空间。这个架构层面的约束,我在给AI的提示里没有说清楚,它也不会主动问。

结果就是,当用户把一个文档同时放进两个项目时,光标同步会出现混乱。修复这个问题的成本,远高于当初手写一个符合架构约束的简单版本。这件事让我意识到,AI擅长在给定约束下求解,但不擅长发现约束本身。而做产品,恰恰是一个不断发现和调整约束的过程。

2.3 代码审查从“看逻辑”变成了“看意图”

以前做代码审查,重点是看逻辑对不对、边界处理全不全、有没有性能问题。现在做审查,第一件事变成了问:这段代码是谁让AI写的?当时给的提示是什么?它解决了哪个具体问题?

听起来有点荒谬,但这是真实的工作流变化。因为AI生成的代码,往往缺少“意图注释”。它不会告诉你“这里之所以用轮询而不是长连接,是因为部署环境不支持”。它只会给你一段能跑的代码。所以我现在要求团队里每个人,在让AI生成代码之前,先写一段简短的意图说明,包括:要解决什么问题、有哪些已知约束、期望的输入输出是什么。这段说明会作为注释保留在代码里,成为后续审查和维护的关键线索。

这个习惯看起来增加了工作量,但实际上节省了大量时间。最直接的好处是,当三个月后你回头看这段代码时,你能快速回忆起当时的决策背景,而不是对着一堆“完美但陌生”的代码发呆。

3. 产品决策的权重转移:从“能不能做”到“该不该做”

3.1 实现成本塌陷后,什么变成了稀缺资源

在传统开发模式下,产品决策很大程度上受制于实现成本。一个功能如果开发周期要两周,产品经理就会反复权衡值不值得做。但现在,AI辅助下,很多功能的实现周期被压缩到了几小时甚至几十分钟。这就带来一个很有意思的转变:实现成本不再是主要瓶颈,决策成本和维护成本变成了新的稀缺资源。

我举个具体的例子。我们的数据看板模块,用户反馈希望支持自定义图表配色。以前这种需求,评估下来大概需要三天:设计配色方案、实现颜色选择器、处理持久化、适配不同图表类型。现在呢?我让AI助手基于现有的图表库写一个配色方案扩展,大概四十分钟就出了第一版。功能上线后,用户确实用了,但随之而来的是大量关于“配色方案不协调”“导出后颜色失真”“深色模式适配有问题”的反馈。后续修修补补花的时间,远超最初那四十分钟。

这件事的教训不是“不要快速实现功能”,而是:当实现变得容易,你更需要克制。因为每一个新增的功能,都会带来新的维护面、新的测试用例、新的用户预期。代码行数增加了,产品的复杂度也增加了,而复杂度最终会以某种形式反噬你。

3.2 一个功能从想法到上线,我现在的判断流程

经过多次踩坑,我慢慢形成了一套自己的功能决策流程。不敢说多科学,但至少帮我避免了很多冲动型开发。流程大致是这样的:

  1. 先问“不做会怎样”:如果这个功能不做,用户会不会流失?现有方案能不能凑合?很多时候,答案是“其实也能用”,那就先不做。
  2. 再问“做了之后谁来维护”:AI可以帮你写第一版,但后续的bug修复、兼容性适配、用户支持,都需要人来处理。如果找不到明确的维护责任人,这个功能就不该上。
  3. 最后问“它会让产品更简单还是更复杂”:好的功能应该让产品用起来更简单,而不是增加用户的认知负担。如果一个功能需要用户学习新的概念或操作方式,就要格外谨慎。

这套流程听起来很朴素,但在AI辅助开发的环境下,它的价值被放大了。因为以前你还有“开发成本太高”这个天然的刹车片,现在这个刹车片没了,你就得自己装一个。

3.3 被AI“惯坏”之后,我重新捡起了原型工具

说出来有点丢人。在用AI辅助开发大概半年后,我发现自己越来越懒得画原型了。反正想到什么,直接让AI生成一版代码,跑起来看看效果再说。这种“代码即原型”的方式,在早期确实很快,但很快就暴露了问题:代码原型会绑架你的设计判断。

因为代码一旦跑起来,你就会不自觉地被它带着走。你会想“既然都写到这里了,不如再加个功能”,而不是“用户真正需要的是什么”。而且,代码原型的修改成本虽然比手写低,但依然远高于在原型工具里拖拽几个方块。

后来我强迫自己恢复了一个习惯:任何新功能,先用低保真原型工具画三到五个方案,跟团队讨论清楚之后再动手写代码。这个习惯让我们的返工率下降了很多。AI可以帮你快速实现,但它不能帮你做选择。选择这件事,还是得靠人,靠讨论,靠对用户的理解。

4. 架构演进中的AI盲区:那些它不会主动告诉你的风险

4.1 依赖膨胀:AI倾向于“用库解决问题”

AI助手有一个很明显的倾向:遇到问题,优先建议引入一个库或框架。这本身不是坏事,但累积起来会导致依赖膨胀。我们的项目在十一个月里,直接依赖从最初的二十三个增加到了六十七个。其中很多是AI建议引入的,用来解决一些其实可以用几十行代码搞定的小问题。

依赖膨胀的代价是多方面的。首先是构建时间变长,其次是安全漏洞的暴露面变大,最后是升级维护的负担加重。有一次,一个底层依赖的次要版本更新引入了一个破坏性变更,导致我们的构建流水线挂了整整一天。排查到最后,发现这个依赖是当初AI为了处理一个日期格式化问题而引入的,而那个问题其实用原生API就能解决。

我现在对AI的依赖建议会多问一句:这个库解决的核心问题是什么?有没有更轻量的替代方案?如果答案是“可以用标准库实现”,那就坚决不引入新依赖。

4.2 错误处理的“表面完整”与“实际脆弱”

AI生成的代码,在错误处理方面往往看起来很完整:try-catch包裹、错误日志记录、用户友好的提示信息,一应俱全。但深入看,很多错误处理是“表面完整”的。它捕获了异常,但没有真正处理异常;它记录了日志,但日志里没有足够的上下文来定位问题。

我遇到过最典型的一个案例:一个文件上传功能,AI生成的代码里对上传失败做了重试机制,看起来考虑得很周到。但实际运行时发现,当网络中断时,重试会无限循环,因为代码里没有区分“可重试错误”和“不可重试错误”。这个bug在测试环境很难复现,因为测试环境的网络太稳定了。

修复方案其实不复杂,加一个错误类型判断和重试次数上限就行。但发现这个问题的过程很痛苦,因为AI生成的代码“看起来”已经处理了错误,你不会本能地去质疑它。这让我养成了一个习惯:对AI生成的错误处理代码,必须逐行审查,重点看它是否区分了错误类型、是否有终止条件、日志是否包含足够的诊断信息。

4.3 性能盲区:AI不会主动帮你考虑规模

在小规模数据下,AI生成的代码性能通常没问题。但当数据量增长到一定程度,一些隐藏的性能问题就会暴露出来。比如,AI很喜欢用数组的filter和map链式调用,代码读起来很清晰,但在处理上万条数据时,多次遍历的性能损耗就很明显了。

我们有一个数据看板的聚合查询,在测试环境(几百条数据)下响应时间不到50毫秒。上线后,当某个用户的数据量达到五万条时,响应时间飙升到了三秒以上。排查后发现,AI生成的代码里对同一组数据做了四次独立的遍历。改成一次遍历完成所有聚合后,响应时间降到了200毫秒以内。

这件事的启示是:AI生成的代码,默认是按“正确性优先”来写的,性能优化需要你主动提出。在让AI生成涉及数据处理的代码时,我现在会明确加上一句提示:“请考虑数据量可能达到十万级别,避免多次遍历,尽量在一次遍历中完成计算。”

5. 团队协作的新摩擦:当每个人都有自己的AI助手

5.1 代码风格的分裂与统一

我们团队不大,但每个人用AI助手的习惯不一样。有人喜欢让AI生成完整的文件,有人喜欢让AI补全片段,有人喜欢用AI做重构。结果就是,代码库里的风格开始分裂。同样是处理一个HTTP请求,有的地方用async/await,有的地方用Promise链,有的地方用回调。功能上都没问题,但读起来很累。

统一风格这件事,以前靠代码规范和Code Review就能解决。现在不行了,因为AI生成的代码往往“看起来”符合规范,但细节上各有各的习惯。我们最后的解决方案是:在项目根目录放一个详细的代码风格指南,并且在让AI生成代码时,把这份指南作为提示的一部分传进去。同时,在CI流程里加了更严格的lint规则,不满足风格要求的代码直接拒绝合并。

这个做法有效,但增加了每次生成代码时的提示长度。不过相比后期统一风格的成本,这点投入是值得的。

5.2 知识断层:没人说得清某个模块为什么这样写

这是我觉得AI辅助开发带来的最隐蔽也最危险的问题。当代码主要由AI生成时,团队成员对代码的“所有权感”会下降。大家更倾向于认为“这是AI写的”,而不是“这是我写的”。这种心态会导致一个后果:当某个模块出问题时,没有人愿意主动去深挖原因。

我们有一个权限校验模块,在某个版本后突然出现了偶发的鉴权失败。排查过程很曲折,因为最初负责这个模块的同事已经离职了,而接手的人对代码不熟悉,只知道“这是AI生成的”。最后花了三天时间,才定位到是一个边界条件处理不当。如果这段代码是手写的,接手的人至少能从代码结构里看出一些设计意图,排查会快很多。

为了应对这个问题,我们现在强制要求:每个核心模块必须有一个明确的“负责人”,即使代码是AI生成的,负责人也要对模块的行为负责。负责人需要定期review模块代码,确保自己理解每一行逻辑。这个要求听起来有点重,但它是防止知识断层的唯一有效手段。

5.3 评审会从“讲方案”变成了“讲提示词”

以前的技术评审会,大家讨论的是架构方案、数据结构、接口设计。现在评审会上,越来越多的时间花在了讨论“你当时给AI的提示词是什么”“为什么这么给提示”。这本身不是坏事,说明大家开始重视提示工程。但问题在于,提示词的质量很难标准化,也很难评审。

我的做法是,把提示词也纳入版本管理。每个功能分支里,除了代码变更,还要包含一个prompts.md文件,记录这个功能开发过程中用到的关键提示词和AI的响应摘要。这样在评审时,大家可以快速了解代码的生成背景。这个做法增加了文档工作量,但显著提高了评审效率,也方便后续追溯。

6. 重新理解“做产品”:AI是放大器,不是替代品

6.1 产品品味的价值反而更高了

用了这么久AI辅助开发,我最大的体会是:AI可以帮你更快地到达某个地方,但它不能帮你决定去哪里。当实现成本不再是瓶颈,产品品味——也就是对“什么值得做”“什么应该做成什么样”的判断力——反而成了最稀缺的能力。

以前你可以说“这个功能开发成本太高,先不做”,现在这个借口没了。你必须直面一个问题:这个功能到底该不该做?它符合产品的整体方向吗?它会让用户更满意还是更困惑?这些问题,AI给不了答案,只能靠你对用户的理解、对市场的判断、对产品哲学的坚持。

我现在的做法是,每周留出固定的时间,不写代码,不看AI生成的任何东西,就是纯粹地思考产品。看用户反馈、看竞品、看行业动态,然后问自己:如果只能做三件事,是哪三件?这个习惯帮我避免了很多“因为能做所以做”的陷阱。

6.2 从“代码工人”到“产品导演”的角色转变

这46万行代码的经历,让我对自己的角色有了新的认识。以前我把自己定位成一个“写代码的人”,现在更像是一个“产品导演”。我不需要亲自演每一场戏,但我需要知道整个故事要怎么讲、每个角色要怎么配合、最终要呈现什么样的效果。

具体来说,我的工作重心从“实现功能”转移到了“定义问题”和“验证方案”。定义问题包括:用户到底遇到了什么困难?这个困难的本质是什么?验证方案包括:AI生成的实现是否真的解决了问题?有没有更好的方式?这些工作,比写代码更累,但也更有价值。

6.3 给同样在用AI做产品的你几条实在建议

最后,分享几条我踩坑之后总结出来的实在建议,不保证对所有人都适用,但至少是我自己验证过的:

  • 控制代码增长速度:每周做一次代码清理,删掉废弃代码和重复代码。不要让仓库无限膨胀,否则你会失去对产品的掌控感。
  • 给AI明确的约束:在提示词里写清楚架构约束、性能要求、错误处理规范。AI不会主动问,但你可以主动说。
  • 保留手写代码的习惯:核心模块、关键算法、架构决策相关的代码,尽量自己写。手写的过程也是思考的过程,这个价值AI替代不了。
  • 定期做“无AI日”:每隔一段时间,关掉AI助手,纯手写一天代码。这会帮你重新建立对代码的直觉。
  • 把提示词当资产:好的提示词是团队的知识资产,要像管理代码一样管理它们。

这46万行代码教会我的,不是“AI有多强”,而是“做产品这件事,哪些部分AI帮不了你”。想清楚这个问题,比多写十万行代码重要得多。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进