本文于2026-02-19作为付费文章发布在个人同名公众号,初次来生财分享,和大家交个朋友~
相信看到这篇文章的你,或许有过类似的体验 —— 装上 Cursor/Claude Code/Codex 之类的 AI Coding 工具,输入一个“一句话 Prompt”,比如:“帮我写一个贪吃蛇”,或者“帮我弄一个 TODO App”,又亦或是“帮我给我的 xxx 写一个 Landing Page”,再惊叹于它似乎真的给你撸出来了一个好像能玩/能看/能用的小 demo 级产品。
当然,你的 Prompt 可能会比这个更专业,结果可能会略好一些。但“玩具”、“一次性代码”的本质很可能并没有改变。
此时,你要是再往上去堆功能、加约束、开新页面、做数据存储、接入外部服务,你会发现 AI 它开始“顾头不顾尾”了,干脆就直接全部东西一股脑地丢到一个文件里面,最后就是一个好几千行的“乱麻文件”在那里。
随后,AI 也开始陷入“拆东墙补西墙”的模式。最后陷入改 bug 漩涡 —— 运气好的,抽卡抽对,还能凑合修了;运气不好的,这个项目到这也就结束了,功能也就停留于此。
如果你说“我这个东西我就写这一次,之后不会再改啦”,ok,那无所谓,一次性代码不需要考虑这么多,“玩具”是不需要维护和迭代的。但如果你希望它是可持续、可维护、可演化的系统,那就接着往下看吧,我想本文会对你有所帮助。
真正的门槛:工程化
非技术人的 Coding 思维,是「功能驱动」的,多表现为 —— “我要做一个 XXX 功能”。于是便让 AI 直接开始写代码,主打一个能跑就行,出 bug 我就打补丁。类似一种“黑盒式”的“功能堆叠式”开发,过程中通过不断的 Prompt 堆砌功能。
问题不在“黑盒”,而是在“视角”。茴字有四种写法,你怎么写都可以。但要写出可演进迭代的商业化系统,还需要注入「工程化思维」,这也是专业与否的分水岭所在。
《Google Software Engineering》中提到了几个要点:
-
Coding == 开发(生成新软件的方式,产生代码的直接行为)
-
软件工程 == 开发+修改+维护迭代(最大头)
-
软件是有生命周期的,必须考虑时间维度。 软件工程是随时间推移的 Coding。
-
软件工程不仅包括编写代码的行为,还包括一个组织用来长期构建和维护代码的所有工具、流程、策略。
这个部分对于非技术人员来说,可能是“我不知道我不知道”的东西,就很难带着一个时间尺度的视角来看代码这个东西,或者脑子里是没有这个概念的,这很正常,大家术业有专攻,难免会有视角缺失。
如果缺乏这份视角,写的 Prompt 难免侧重点会有不同,结果也会有不同,基本上全靠大模型本身的工程化能力了。目前软件工程化做的比较好的是 Claude。(虽然它有时会有点 Over Engineering)
耦合与解耦
工程化的核心特征之一,就是「解耦」。 专业的技术人员,知道什么时候该用接口,什么时候该抽象出配置,项目怎么分层。(后面的具体案例会有体现)
相反,“玩具”的核心问题,就是容易陷入逻辑「耦合」。 改 A 要动 B,于是就“拆东墙补西墙”了。因为 AI 完成任务,很可能并不会选择更工程化的那个更优解,它只知道要完成你当下给它的任务。
那「解耦」和「耦合」又是什么意思?我这里举个例子。
-
假如你笔记本电脑上的键盘或者触控板坏了,你需要带着整台电脑去专卖店把电脑拆开来修,这是「耦合」;
-
假如你电脑用的是外接的键盘、鼠标,走的是标准的蓝牙协议或者 Type-C 数据线,更换同样支持这些协议的外设即可,即使维修,也只需要带外设本身去就行,而不是整个电脑,这是「解耦」。
如果 AI 没有自发的工程化自觉性,你的 Prompt 又缺乏这种“适度的设计”,项目撑不过第二次、第三次需求变更,是必然的结果。
我们来做一下视角切换,站在工程师的角度,把 build 的出发点切换成“我要构建一个「可扩展」的系统,用来承载未来变化”,一起来想想这几件事儿:
-
我的项目有几个模块?分别在做什么?这个模块是否可以丝滑替换?(你不需要看懂代码,可以直接和 AI 聊)
-
未来如果来一个新模块,我要怎么迭代?如果是已有模块要加一个新功能,要怎么迭代?
-
如果某个模块的功能坏掉了,有缺陷,是否会影响到其他的正常功能?(隔离性)
-
几个模块之间的边界在哪?它们之间如何通信交互?
-
我改了 A,其他的 B、C、D 要变吗?为什么会变?能不能不变?
-
假如我要改掉 xxx,我改一个地方就行,还是多个地方?
-
我的数据实体/模型是否稳定?哪些是必须的、哪些是可选的?(这个后面的例子会提到)
我就不列更多了,上面提到的具体变更很可能也是由 AI 来做的,我主要是传递一种技术上的模块化思维给大家。这是一种结构优先的开发模式 。
模块化这个点我们往上拔一拔,它其实本质是门复杂度管理的艺术 ,相当于你把同类的概念和问题收敛到了一个域里面。我们这么做,其实对 AI 也是有好处的:
- 1.
它的上下文可以控制在更小的范围内,保证在上下文窗口支持的范围内;
- 2.
能力可复用,问题更聚焦,也符合“注意力机制”特征;
- 3.
拆分得当,也可以更省 token;
- 4.
方便 AI 更好找到对应的内容。
这个后面案例中有体现。
当技术实现本身不再是难题,困扰我们的下一个难题就在于“是否真正理解复杂度管理”这件事。
我承认,AI 非常擅长做局部生成、模式模仿,但在长期系统演进、跨版本一致性、隐性的复杂度控制、技术债预防方面,还是差点意思,需要我们人为地来把控。
身份转变
如果说此前我们在使用 AI Coding 时的身份,只是”产品经理“,看完我的这篇文章,我希望你还能带上”技术总监“的视角。别怕,这不是说你真的要懂技术、要看得懂代码,而是说你得懂得管理代码项目,并保证它在正确的方向上演进 :
-
你负责定义结构,AI 负责填充细节
-
你负责管理好文件目录,AI 负责写好单个文件代码
-
你负责定义接口标准,AI 负责实现接口实例
-
你负责制定规范、约束,AI 遵守于此
说的土一点,你需要是那个工头,给 AI 绘制工程图纸,并保证项目施工时是按照图纸来的。
你或许会问:”可是我也不会画图纸啊?那咋办?“别急,设计这事儿AI也能做,即所谓的定结构、接口标准、文件目录、规范、约束这些东西 。
设计和实现可以是分开的。在现实世界的工作中,我们也会存在 A 写设计方案, B 来实现的情况,这很正常。
所以你可以用不同的 AI 来做这件事,也可以直接在 AI 工具中使用 Plan Mode + Rule + Skills 去做这些事儿。我们后面来具体说。
具体案例
接下来,我将用更加具体的实战案例带你感受”工程化“,带你看看知我记物为什么从24年年底堆到今天 3w+ 行代码、100+ 个代码文件还能持续完全 AI Coding 迭代的原因。
下面的内容,我相信也是更有价值的、你能真正带走的东西。如果你只是想理解原理,其实看到这里已经够了。如果你想真正做出一个长期可迭代的软件系统,继续往下看。
知我记物并不是一个 demo,是正儿八经有收费模式的商业项目,它实实在在的帮我赚了五位数的钱。
项目结构:分层
我以我的 iOS App 项目为例,给大家看一下我的项目文件夹划分:
这密密麻麻的文件夹,可能就是劝退很多非技术人的第一道坎。但其实,这和我们去管理一个餐厅的逻辑是一样的。
在我的 App 代码里,没有“全能神”,只有各司其职的“员工”。AI 如果把所有代码写在一起,就会像是一个服务员既要负责点单、又要做菜、还要去菜市场买肉、最后还要洗盘子,最终崩溃是必然结果。
为了让 AI 不崩溃,我制定了严格的“岗位要求”(Rules):
-
数据层(Models):定义了“是什么”
-
这里就是数据结构/模型定义,这里不画任何界面,也不存在复杂的业务逻辑,专注于定义数据长什么样,规定了“番茄炒蛋”里要有“番茄”和“蛋”
-
比如:「物品」这个实体由 ID、名字(Name)、价格(Price)等字段组成,AI 读取了这个 Model,就会知道要怎么用这些数据模型
-
-
存储层(Stores):解决了“放在哪”
-
这里就是数据存储与状态管理,有的菜需要一直备着,那就把它放冰箱和仓库(持久化存储);有的调料经常要用到,就放在锅旁边(缓存);有的菜就正在锅里炒着(内存)
-
比如:App 里会有各种开关、设置,我就把它放在 AppStorage;物品数据我想要通过云端备份,我会同步到 iCloud;用户编辑到一半的表单打断了,再打开表单,我希望它能接着上次的继续编辑,我会放到缓存去
-
-
服务层(Services):搞定了“怎么做”
-
这一块就是放那些相对复杂的业务逻辑、API调用、外部集成,它就像是厨师,只负责把菜做好传递出去,而不会独自跑去前台直接跟客人说话
-
比如:知我记物需要去获取汇率,并做金额转换,还要计算出各个物品的总价,这是有一定复杂度的逻辑,还涉及外部调用和异常处理
-
再比如:我接了外部的图片搜索、 iTunes 搜索、AI 模型文本生成
-
还比如:我集成了 iOS App 分享的能力(可以分享进来,也可以分享出去)、提醒事项的能力、通知的能力
-
-
视图层(Views):决定了“长啥样”
-
这也就是SwiftUI 界面组件,即你眼睛能看到的那些东西及其交互,它只负责把厨师做好的菜(数据),漂亮地摆在盘子里给用户看
-
最好最好不要在餐厅里直接炒菜(在 View 层里写复杂的业务逻辑,比如直接在某个 Button 点击事件里面写数据库调用)
-
比如: App 下方的 tab 栏、物品的卡片视图、弹出的添加表单等等
-
-
工具层(Utils):负责打杂
-
各种工具、扩展、辅助函数
-
这里不展开说了,也就是比如什么时间转换、日期转换、金额小数点处理这种
-
我们来看个具体的 case,如果要做一个日记 App 的“记日记”的功能,非技术人可能会这么和 AI 表述:
“帮我写一个记日记的页面,可以输入标题和内容,点了保存就存到手机里,下面还能显示历史列表。”
于是乎,AI 就会吭哧吭哧生成一个 500 行的 DiaryView.swift,里面混杂了界面、数据存储、业务逻辑。你可能改了看似与数据存储无关的几行,然后保存功能就坏掉了。
但现在,我们可以尝试用更工程化的方式,分步地引导 AI 逐一实现(你可以写在一起,但是得要体现出不同的侧重点):
- 1.
先定义食材(Models):我现在要做日记功能。请在 Models 文件夹下写一个 Diary 结构(可以说中文,没关系),包含 id, title, content, createTime 字段(也可以说中文,没关系)。此外,打算每一步都分开实现的话,再补一句“只写结构体,不要写别的”。
- 2.
再找地方放 (Stores):接着,在 Stores 文件夹下写一个 DiaryStore(可说中文),并实现保存单篇日记的方法和读取全部日记的方法。数据存储使用 SwiftData/CoreData。注意:这里不要涉及任何 UI 代码。
- 3.
然后找厨师来炒 (Services):现在,在 Services 文件夹下创建一个 DiaryService。你需要写一个创建日记的方法,它接受用户输入的标题和内容,验证这两个字段不为空后,给这篇日记打上记录时间,再去调用刚才的 DiaryStore 的保存能力。如果有错,请把错误信息抛出来。(这里就是逻辑层。比如你想加一个“日记超过 500 字不能保存”的规则,就写在这,而不是写在界面按钮里。)
- 4.
最后再摆盘上菜(Views):最后再帮我画一个 xxx 样子的界面,需要包含 yyy 元素,点 zzz 按钮就保存日记。数据源就是 DiaryStore,保存时候去使用 DiaryService。如果 DiaryService 有错误,就给用户弹窗,说明错误。
你可能会问:“啊?要这么麻烦嘛?我一把梭哈,让 AI 自由发挥不是更快吗?”是可以,但这取决于你对这个工程的质量要求有多高。如果你只是想写个 10 分钟后就扔的玩具,确实可以一把梭哈,那更快。但如果你想做一个能持续迭代的产品,这么做的好处是巨大的:
-
当 Bug 出现时
-
如果是“保存了没反应”或者“数据错乱”或者“取不出数据”,你只需要在 AI 对话框中 @DiaryStore.swift 让 AI 改
-
如果是“输入框太丑”或者“按钮没反应”,你只需要在 AI 对话框中 @DiaryView.swift 让 AI 去调
-
-
当需求变更时
-
如果你以后想把“存到手机本地”改成“存到云端数据库”,你只需要让 AI 改 DiaryStore 里的代码即可,哪怕把整个 Store 层删了重写,都不会影响到界面(View)和逻辑(Service)一点
-
这就是“隔离”,这就是“低耦合” 。AI 不需要一次性读懂 1000 行代码,它只需要读懂它负责的那 100 行。这就是为什么我的项目写到 3 万行,AI 仍然在我掌控之下的重要原因之一。我的经验值是,单个代码文件最好不要超过500行代码,1000行是底线 ,多了就拆。
干说可能还是抽象了,我直接拿我近期迭代的功能中的用例出来说:
当我需要单独改置物墙的样式和交互,我只需要去 @WallView 就行。
当我要改网格视图的物品卡片样式时,我甚至可以单独 @GalleryItemCard 这一单一组件,这是粒度更细的,控制也就更加精准。(后面还会谈到)
当我要给我的物品加入独立的货币符号字段,也是 @ Model 中的 StorageItem 即可。(并且我在这里声明了它是可选字段,保证数据兼容性)
再比如,我要在数据加载流程中,异步触发汇率缓存刷新,也只需要 @ 数据 init 所在的 StorageBoxStore 就行。
我建议你按照一把梭哈和分层的这两种方式,分别去做同一个功能试试。你会亲眼看到两种项目在第三次需求变更时的差距。
慢即是快。地基打好了,后面盖楼才能又快又稳。 如果你感兴趣的话,可以顺着这个话题再和 AI 聊聊,建议你可以学一下:MVC、MVVM 这些软件框架中的概念,让 AI 通俗易懂地讲给你听就好。
如果你在想:“为什么我要会这么多啊?我就是功能驱动啊,AI 不就是负责工程化的嘛?”理论上是,但现阶段的 AI 做不到这么尽善尽美。倒也有个折中的办法,就是去使用 AI Coding 工具中的 Plan 能力,它能规划地相对好一些,还能反过来向你提问一些必要的问题,这样做出来的功能在可维护性上也能至少相对好一点。
但怎么说,这个问题就有点类似装修,选择全包,还是半包,还是自己一手包办,亦或是中间的某个状态值。
我下面放一个综合性示例。其中,@CapturedImagePreviewSheet 是 View 的一部分,算是 App 里面的表单,也算是样式+交互;而 @ProfileView 是我的个人设置页,也是样式+交互。除了 @ 具体的文件,我们也可以 @ 文件夹,比如我让 AI 把 DeepSeek 的接入部分放在 @Services 下,因为它是个外部服务的依赖。(里面还有一些其他的 case,这里不展开细说)
组件复用
在软件工程原则中,有一条叫 DRY 原则,即 Don't Repeat Yourself。我最近一期的周复盘公众号也在说这个问题。
为了避免总是造轮子、做重复性工作、拷贝代码,在工程设计上,我们倾向于去做复用(Reuse,也叫重用)。
我们回想一下上文说的。比如我要改知我记物 App 内的 logo icon,这个 icon 被 10 个地方用到了。
你是希望改一次,就所有地方生效;还是改 10 次呢?我想大部分人都会想只做一次工作吧。
事实是,我25年初那会儿写 logo icon 相关功能时候,只要我不说,AI 就不会去复用。然后生成了许多一样或者类似的代码,后来在某次偶然的 review 中被我发现了,便火速改掉了。
复用的真正威力在于“规模效应”,从经济学角度来看,就是边际成本逐渐递减。造第一个积木块可能很慢(要开模具),但一旦有了模具,造第 1000 个积木的成本几乎为零。软件开发的本质,就是把“捏泥巴”变成“拼乐高”的过程。
还是以我的知我记物 App 为例,知我记物有多种导入方式:
无论是哪种方式,最终都会拉起一个添加物品的表单:
而这个表单,就是一个可复用的组件。它正在被我代码中的多个地方引用着。
可复用组件,小到可以只是一个状态指示灯、胶囊型标签,甚至就是某种字体样式,大到一个添加表单、一个图片搜索的能力、一次 AI 分析处理。万物皆可复用。
而 AI Coding 工具中的 @,就很好地符合了复用这个特性。当我们让它去用 xxx 的时候,就直接 @xxx 就行。
比方说我最新版本刚迭代了一个,要在添加表单中调起图片搜索组件,我就可以直接这么说“在 xxx 地方,新加一个 yyy,点击后调起 @图片搜索组件,然后 blabla”。
即使不是@来复用,也可以是代码参考,@挺好用的。
总之,Don't Repeat Yourself. 做好复杂度控制与拆分的核心收益,就是好复用。
接口化思维
软件设计原则中,有一条很重要的,就是要「面向接口编程」。
问题来了,什么是接口?借用前面讲过的例子,假如你电脑外接的键盘、鼠标走的是标准的蓝牙协议或者 Type-C 数据线,如果他们坏了,你只要更换同样遵守这些协议的外设即可。目的,就是「解耦」。
换句话说,“黑猫白猫,抓到老鼠的就是好猫”中,“好猫”就是接口,协议标准就是“抓到老鼠”,我不管你具体是什么“猫”,能抓老鼠你就是“好猫”。
可能还是有点抽象了,还是来看一个我知我记物里边很具体的 case。
最新的版本中,我接入了 AI 模型的能力,来做购物订单的解析导入,这个过程中,就涉及我要用哪几家 AI 的模型 —— 我选择了去接入 DeepSeek 和 GLM。问题来了,它们其实都提供的是一个能力:根据 OCR 的结果,提取出商品信息(名称、价格、分类等等)。
但这时,我们会面临这样的问题:我们以后可能会在多个地方用到 AI 模型,难道我们要在每个地方都判断一下要用什么模型,然后通过逻辑分支去使用不同模型的能力吗?
换句话说,我如果有10个地方在用模型,我加了2个模型,就得改动 10 2 = 20 个地方,是个 O(m n) 的问题。而接口的存在正是为了解耦,将复杂度砍成 O(m + n),从而让你在每个地方的改动,都只需要感知接口(能力/行为)本身,而不是具体来做这件事情的模型。
这就好比你去买奶茶,你压根就不需要知道今天值班做奶茶的是张三还是李四,你只需要对着柜台喊一声:“给我一杯珍珠奶茶”。这里的柜台,就是接口。
或许还是抽象了,我们直接来看知我记物具体的案例。仍然是购物订单导入这个能力,如果我没说,即使我用了 Plan Mode,AI 就是会直接给你写一个具体的 DeepSeekService,而不是一个抽象的 AIModelService。(当然,我不确定如果我多给几个,它会不会就抽象了,我这里是只有一个)
因此,我让 AI 把这里边的能力给抽出来。(我已经说的很自然语言化了)
可以看到,多了一个 AIModel 的抽象,还有 DeepSeekModel 和 GLMModel 的具体实现。此外,还有一个 AISetting 驱动着这套模式。
这个,就是抽象出来的接口。目前只有解析订单为结构化数据这一个能力。
有了 AIModel 这层抽象,我们就不用主动地去做相关分支判断,而是让用户的配置去动态地驱动程序逻辑行为的改变。这边是「面向接口编程」的一个比较好的 use case。
如果下次再来一个 Gemini 的 model 要接,我只要把 Gemini 的接入文档丢进去,然后 @AIModelProtocol,让 AI 接入就完了。(为保证效果,可以 @DeepSeekModel 让 AI 参考,所谓 few shots)
这种设计模式的学名,叫做「策略模式」,感兴趣的可以让 AI 讲给你听,我在日常开发过程中经常会用到。
最后一块拼图:Rules
在结束之前,我想补充最后一点工程化建议,也是让 AI 变得更 smart 的技巧 —— 规则前置。
你在开发过程中肯定遇到过,AI 好像记不住你的说的话,一会儿这里用白色,那里用蓝色。或者生成的代码文件挂不到你想要的那个文件夹下。总之就感觉有些不对劲的地方。这是因为,我们并没有一套约束来控制AI生成代码的行为 。
硬的层面,我们可以去挑选一些技术框架,比如写前端工程,我们可以用 Next.js,写 Java 后端,我们可以用 SpringBoot。框架,可以保证整个项目规范的下限。 软的层面,可以去用 AI Coding 工具提供的 Rules 能力。
我这里以我使用 go-zero 开发的后端项目的其中一部分 Rules 为例,我们完全可以把我们的分层方式,以 Rules 的方式保存起来,告诉 AI。
比如你等会儿就可以把今天学到的“分层架构”、“复用组件优先”、“面向接口”写进规则里。
-
“Always use MVVM pattern.”
-
“Create separate files for data storage, logic and UI.”
-
“Prefer creating reusable components for UI elements.”
建议自己写完整一点,我这里简写了。最好按照我图片里的那种完整性来一遍。如果是已有项目,可以蹭 AI Coding 工具的 /init 用,基于 init 文件再改一改就行了。
这就相当于把你的“工头指令”贴在了墙上,AI 进场开工前必须来一遍,质量自然就上去了。
写在最后
在 AI 时代,Code,Syntax已经贬值了,但Structure,Pattern,Principle依然昂贵。
希望这篇文章能帮你打破“玩具代码”的魔咒。哪怕你完全不懂代码,只要掌握了这套“分层+复用+接口+Rules”的思维模型,你也能指挥 AI,构建出一个能迭代1年、乃至10年的长青项目~
如果你在实战中遇到了具体的 AI Coding 工程难题,或者想看更多关于“如何从 0 到 1 完成 App 上架商业化”的完整复盘,欢迎留言或者找我私下聊聊。
此外,本文针对的是尝试过 AI Coding 的非技术人,对于没尝试过的、不知道从何开始的,我还摸不太清楚具体的问题是什么。如果你有的话,欢迎与我交流。
Comments on "不懂代码也能指挥AI构建可迭代项目,我的AI Coding工程化实战经验分享" :