AI Coding
又遇到了一个好的时机,时隔大半年再次尝试体验了下现在的 ‘vibe coding’. 在前后跨度近两周但累计也就十来个小时的开发后,烧掉了半个月的 premium requests 额度,做出来了一个桌游平台 C/S 架构的 demo,虽然功能还十分粗糙,有无数细节待打磨,但是怎么说也是把 《并购》 Acquire 这个游戏的流程走通了,项目开源并部署在了网站 上,欢迎体验。
cat **/*.{rs,dart} | wc -l
8979
目前项目的代码量大概是 9000。从结果来看,AI 提效显著;从质量上看,嗯大部分代码细节我没有看过所以无法给出评价;从效率上看,只投入了一些前期规划、大量的 Prompting 和数个小时的调试时间,期间因为等 AI 我甚至同时在开另一个项目的迭代工作流。
想着感慨一下总结一点经验作为分享,本来想命名为 Coding with AI, 但是这段经历里我作为主体,并没有做 Coding 这个动作,只做了 Prompting 和调试,以及非常粗略的 Review ,一行代码没“写”,感觉不太贴切,还是称之为 AI Coding 吧,尊重一下劳动者。
Write code that is easy to be deleted
一些过往的经验价值里,比如每行代码是很昂贵的,修改要最小化,能不动就不动;每个函数的长度要控制在 x 行,每个文件要控制在 y 行等等。在如今力大砖飞的大模型面前,单文件区区 2000 行的代码根本不是个事,相反,过于细致的拆分会降低同一个 session 里的上下文正确性,又或者要触发多次文件加载,反而降低效率。
大模型吐出代码的速度已经远远超过人类的理解和消化速度了,每行代码的价值接近于零,尽可能的写一些独立的、不被其他代码依赖的、容易被删除的代码,能让迭代的效率最大化。而不是过于担心代码的复用性和可维护性,毕竟现在存在的代码很可能下个 session 就被替换掉了。
比如在前端的代码里,我注意到大模型给不同但类似的 UI 组件里写了一些重复性极高的子结构,诚然这在理想世界里很不合理,因为按照此前的经验,抽象出一个可复用更公用的组件是更好的做法,但是如果要做这件事,就需要能够确保后续大模型也会正确的去复用这个组件,否则这次抽象很有可能是白费力气的增加未来冗余代码的风险,因为同样的做抽取合并的事情如果还发生多次,就会出现多份看似相似但又不完全相同的组件,反而在指数增加实际维护成本。而保持在组件内部,它永远不会被其他组件依赖,随时可以被重写或者删除,反而是更好的选择了。
在探索出能让大模型稳定输出去复用了已有功能的工程方式之前,保持代码的独立性和可删除性是更好的选择了。
Read the summary, not the code
我在尝试让大模型在每次写完代码以后,再输出/维护一份文档,来总结当前的进度和坑,因为它们真的很容易事情只做一半然后问你是否还要xxx,(omg,经常感觉自己就像个被 AI 牵着鼻子走的傀儡一样,甚至这句也是 AI 补全出来的)。所以一个多轮对话的 session 快结束的时候,输出一份总结性文档,作为起点交接给下一个 session ,也是方便人类在第二天打开这个窗口还能回忆起你打算干什么。
又或者先去和 Gemini 讨论一下设计思路,多轮交互之后对好方案细节后再让它写一份初稿作为 prompt 的输入,比直接写几行其实过于粗糙的提示词的效果好很多。
Know what you want, and know how to achieve it
确实,在真的动手做这件事之前,我就知道自己可以做到,去年已经写过了一个类似的桌游。以至于被吐槽,怎么总是做这种“无聊”的项目,感觉不太有挑战性。
但是很明显目前的通用 AI 的智能程度也没有强大到你只需要说一句“帮我做个xxx桌游的在线版本”,就能得到一个完整的、可玩的、没有任何 bug 的桌游了。虽然我确实很想见识下不计成本的让 🦞 去尽情的烧token来试试结果,看个乐子。
所以我初始就给自己定了一个额外的目标,让这个项目吃掉原来的项目且未来能够快速横向拓展其他桌游,继续把这件事追加一个项目重构的安排强行增加意义感,roadmap 直接写进了第一个 plan.md 里,基础框架 -> 迁移之前的桌游 -> 新增这个桌游。(虽然这个这个目标在执行的时候被我先跳过了第二步,结果来看不然这个月 token 不够用了)
基础框架反而是最费人力时间的部分,因为这里没有想清楚就开始做的话,大概率会出现一堆无用的文件和函数,功能和设计都不合理,而这个第一块地基就烂了的话,后面只能是 Garbage in, Garbage out 了。
大模型输出太快了真的很容易让人放弃思考,想清楚自己想要什么,去引导这个高效率的工具帮你实现,愿不在数据洪流中迷失,共勉。