3.325. AI架构设计入门
3.325.1. 介绍
最近有同事体验了AI编程,她不是专业做编程的,所以主要是站在一个“不会写程序”的AI编程体验者的角度来谈这个问题的,她提到她在这个过程中消耗了很多时间,这让她意识到她的工程思维不够,缺乏对前期模块划分,功能界定,导致程序越来越大以后,AI开始遗忘她的原始需求了。她希望我给她科普一点架构设计的知识,以便更好控制AI的输出,让它更有工程思维,不要犯蠢。
我觉得这个不但是这种Vibe Coding的问题,也是一个普遍的架构设计问题,所以我在这里做了这个总结,不但希望给她提供帮助,更大程度上,希望从AI编程的角度,总结一下架构设计的本质。
3.325.2. 理解AI思维
抛开内部的算法细节,AI的算法基本上是这样的:算法本身有一个巨大的参数矩阵(比如1亿参数,10亿参数,等等)这样。然后像人学习一样,不断用程序,文本,网页这些文字去训练它,慢慢这些文本的规律,就被这些参数“记住”了。
这个原理可以想象成人的学习过程,我们学习,我们观察,我们体验,这些东西被我们的脑子记住了。这个“记住”和写在纸上的一段段文本不一样。这个写在纸上的,一个个独立的字词,都可以单独解释。但我们脑子里面的神经元,每个具体记住了什么,我们没法单独解释。因为整个神经网络的本质,其实就是变维,比如我们看到一个人,提取了他的特征[身高1.78,体重50公斤,性别男……],这是对他的一组描述,用数字表示就是某种维度空间对他的总结,但综合这些信息,我们可以从另一个维度描述他,比如[偏瘦,当学生的年龄,聪明……],这也是一种维度。这些不同维度描述一个对象的表示法,常常称为一个Embedding,这个单词可以翻译做“嵌入”,表示“刻在它骨子中的内在属性”。所以,同一个对象,在神经网络中,是被不断变维存储的,这些变维是从那个角度来描述那个对象,我们没法说出来。因为说出来的,就是字和词。用字和词这个分类来表达的,我们称为Token(现在有官方的媒体正式把它称为“词元”了)。词元是我们平时交流,思考,用的最外在的Embedding,我们能说的,就是Token,但神经元中存储的那些维度,你说不清楚,你也许也能感觉到它的存在,但你没法说,因为你必须“总结”成Token,你才能说,但一旦“总结”了,你得到的只有Token,没有内部的Embedding了。
我前面给的两个维度::
[身高1.78,体重50公斤,性别男……]
[偏瘦,当学生的年龄,聪明……]
每个维度的指标,都还是和我们的Token一一对应的,所以我这里能给你说。你可以想象一下,我们脑子里肯定是形成了某些维度,那时和字词没有一一对应的。那些维度,我们就说不出来了。
所有的哲学在追寻物质的“本源”的时候,都面对这个问题。所以《道德经》中说道可道,非常道,名可名,非常名。道大致指的就是那些全部的信息,而名就是这里的Token。《道德经》中还明确给了内部的Embedding一个感觉上的名字,叫“恍惚”——你能感觉到有信息在上面,但你没法说出来,说出来就要变维,变维就会变成Token。
维特根斯坦也这么说,他说了很多关于“世界”,“对象”,“特征”,这些逻辑,但《自然哲学论》的最后一章就强调一句话,大致的意思是:能说的,都可以用逻辑清晰表达出来,但不能说的,只能在沉默中传递。很多人误会这句话是说:沉默是金。你应该想到,整个《自然哲学论》都是讲逻辑的,怎么可能最后给你喝鸡汤呢。他强调的也是这一点:逻辑只活在某个人为定义的空间中,大量的信息,都在沉默中。
所以,你可以这样理解:大语言模型是通过大量的文字对内部记录的大量Embedding数据进行训练(就是根据规律修改它们),让它记住了人类文字的规律,从而让它可以和你用文字的方式进行交流,你们交流的时候,就是你用文字,去激发它的内部Embedding,然后给你反馈出文字。
现在的多模态模型,不但把文字编码成Embedding,也把图像、声音也编码成了Embedding,这种不是变维记在神经网络中的Embedding,我们也叫Token。所以,你不但可以用语言和AI沟通,也可以用图像、声音和AI沟通。词元这个词,也不再简单表示“词”的“元”了,它有更广泛的含义。
很多人基于这个算法,认为AI不过是“根据概率做搜索”,不算真正的智能。但“算不算”这种东西,是搞理论的人的问题,我们面对的就是一个“很像人”的对象,他还实实在在解决了你过去靠人才能解决的问题,你说它“不算人”,也改变不了很多时候你就是把它当人用。这是我们这里关心的问题。
AI的本体,是它记住的那个内部的神经元。所以,很大程度上它没有自我,它不自私,它没有利益关系,没有生存的需要,你威胁要断它的电,要辞退它,它不在乎。同时,它也没有对新的信息的“记忆”,它内部的参数,是训练的时候决定的,训练完了就不再更新了,它和你对话只根据当时的上下文来决定说什么的,说完它就忘了。
所以,和AI沟通有个基本概念叫“上下文”(Context),现在的AI基本上都有“最大上下文”的限制,超过了这个上下文,它就不记了。你每次和AI交流,实际上是把整个上下文都发给它,它和你交往的所有“记忆”,都在这里了。如果你要切实理解上下文是什么,我有一个项目在这里:[llm_with_vim](https://atomgit.com/Kenneth-Lee-2025/llm_with_vim),如果你是程序员,可以直观看到上下文是怎么控制AI的输出的。
所以,你和AI沟通,你的每句话,AI算法的输出就依赖两个:训练参数,上下文。这两者决定了AI回答你什么。前者我们无法讨论细节,原因我们前面说过了,后者是Token的序列,如果不是声音和图像的Token,我们基本可以讨论细节,因为它和我们的语言在同一个维度。
3.325.3. 架构设计的本质
我花了很大的篇幅来给你构造这个AI思维的概念,就是为了解释这个“上下文”。因为架构设计的本质,就是构造这个上下文。
我们看AI有这个上下文的概念,有深入研究的人可能会发现它主要是被大语言模型的KVCache算法所限制。但这些不是这个限制的本质,我们以为我们人没有这种限制,所以我们可以思考“更多”东西。可以记住“一开始的约定”。
但这是我们自我感觉良好而已:多少程序员写的代码大了以后就开始找不着北了?开始改好了这里,就改坏了那里了?
你真的能处理很大的上下文吗?
从来不是。为什么有些编程规范要求函数不要超过200行?因为函数太大,你根本记不住这个函数的前后文。你能记住一个程序的上下文,不超过三个屏幕。超过了你是成块记忆的。这就好比你看这样一个程序:
eventLoop = EventLoop()
while(eventLoop.get() != EXIT):
eventLoop.handleEvent()
eventLoop.destroy()
你以为你记住了EventLoop的构造函数,handleEvent()成员函数的实现吗?不是的,你是记住了那个实现的“名”,你用那个名(的少数特征),去想你这个上下文而已。你根本没有进入那个实现本身的上下文的。
你让AI去给你分析一个100万行代码的项目,AI几分钟就开始可以讨论得头头是道了,你以为AI给你看了那个项目的全部代码?不是的,它只是提取了部分的特征,一直和你讨论那些特征而已。
无论人还是AI,都是在不同的上下文之间跳来跳去而已,我们都没有能力做到拿着一堆乱七八糟,没有逻辑的信息,然后整理出结论来。
这是被逻辑包括信息科学的规律左右的。有形式验证经验的读者也许能感受得更清楚一点:我们要得到某种逻辑上的“结论”,本质上就是在“穷举”:某个问题被要素a, b, c所决定,a有3种可能,b有4种可能,c有5种可能,综合我们就有3x4x5=60种可能,所以我们就有60种潜在的结论。所有的逻辑推理,都是这么回事。我们减少分类,就能减少可能性,但分类不精细,就会导致我们希望区分的不同结果,在同一个结论空间中。
我们放弃了简单的应激,不直接从内部参数出结论,而要变成慢速的Token为基础的逻辑思考,就是因为逻辑思考可以降低判断成本。这个约束,无论是我们人,还是AI,都越不过去。
这就是你没法从一堆毫无关系的信息中获得结论的原因。就算不考虑你有没有一些已知的规律让你从这些信息中推理出结论。就算信息都在其中,但这个推理的成本,就是你承受不了的,无论你是碳基的,还是硅基的。
那我们怎么控制发展呢?架构师的方法是:“把可推理,可验证,可穷举,有现实约束的封闭的逻辑空间作为独立的上下文去控制。”
这句话很难直接解释含义(就好像图很难用文字Token解释一样,这是两个维度的东西),我们主要用一些例子尝试让你感受到它。
任何时候,细节都是无限的,但我们做判断用的特征总是有限的。比如你肚子饿了,要去吃饭,你不会去区分这个肚子饿到底是因为血液中的糖分不够,还是肠胃中的酸性物质分泌过多,反正所有这些情况,都是“肚子饿”这个“抽象”,那我们这个逻辑空间就很简单,感受到肚子饿,就要吃饭,能容忍多久?一小时30分钟16秒?不是,我们不是这样抽象的。我们抽象的是“几个小时”。这里把1个小时,半个小时,一个小时30分16秒,都纳入在其中。反正就是几个小时之内必须吃上东西,否则就受不了。
你看,这些都是“抽象”,抽象就是我不管你有那么多的细节,我只管一个特征,而且这个特征可以被我们的经验所“证实”,严不严谨我们不管,但这个有限的空间,我们就是可以“推理”的,而且我们认这个推理中的所有事实和因果。
这样的空间,就是可推理的,可验证,可穷举的。
反例常常是把不相干的东西放到一个判断中,比如我肚子饿了,而儿子昨晚的作业没有做完,我现在烦死了,最近的天气也不好,总是下雨,而OpenClaw现在很火,牙医让我三个小时内不要吃东西,……现在问,我去不去吃饭?
这个就不构成一个逻辑空间,为什么不构成,我也很难说有什么道理,你自己体会吧。而且我这里其实已经美化了,实际上,去不去吃饭的要素基本上也在这个范围内。更真实的例子我很难用语言来沟通,比如如果我给你10万行代码一个函数,让你判断这里有没有安全漏洞,这就是没法穷举的。
很多人因为把AI看作是个黑盒,经常希望把这一堆信息垃圾给了AI,希望AI“直接”就判断出来,这里有没有安全漏洞。我们不说AI和你对于那些概念是不是有一样的认识了,AI要穷举所有的可能性,它一样要从所有的信息中抽象,才有能力穷举,它不能越过这个推理成本的限制的。
把显式的限制抽象出关键的特征,为一个共同的验证目的放在一起,构造一个封闭的逻辑空间,就是架构师眼中的视图(View)。架构师通过一个个的逻辑视图,作为每个具体上下文的分解属性,从而降低控制整个逻辑空间的推理成本。
所以一个软件的分层关系,API列表,多个节点的建联过程,安装部署方法,线程的同步关系……这些每个都可以是个视图。而这个函数的几行代码,那个文件的几行代码,用户的几句评论……这些东西放在一起,就不是视图。因为这个逻辑空间没法针对那个目标是否可以达成实现穷举。
3.325.4. 构造视图的基本方法
视图是针对目标的信息抽象(总结)。所以面对所有的已知和未知的细节,你有无数种创建视图的方法,所以,一般泛泛的架构教材都是教你泛泛的构造视图的方向。比如典型的4+1视图,就是从功能边界(Use Case视图),概念关系,部署方法,运行方法,开发方法来建立视图。在没有更多信息的时候,这是最基本的方法:你说你要做一个电话,电话只是个名字而已,你到底想怎么用它?这总有个逻辑吧?
那我们这么构思:假定你要和另一个人要通讯,你怎么找到他?不然这样:他也拿一个电话,然后我们在空间中广播他的名字,他的电话收到他的名字以后,就回应我这个电话,然后我们建立点到点的通讯,然后完成通话,然后断开,这是不是说得过去?
这个逻辑空间,就是概念空间,我们也不知道你软件怎么写,但至少,你怎么用总是得和人发生关系吧?在和人发生关系这里,就得有逻辑吧?不能我一说话,对方就听到吧?这些什么“广播”,“名字”,“回应”,“点到点”,我们也不知道实现成什么软件,硬件的,但总得说得通,总得有个意思吧?这个封闭的逻辑空间,就叫“概念视图”。概念视图让我们先能“谈”这个事情,我们得有相同的词语来指代相同的对象。
有了这个,我们还得说好,什么东西我来做,什么东西你来做。比如这个电话系统,电话我们可不负责,我们负责的是交换机,所以,我们负责的是接入,互联,释放,这些功能,电话你自己去买。这样顺便我们发现需要有人运营这个交换机,我们引入第三方,“运营商”,他要负责维护这个交换机。然后“运营商”就引入了新的功能需求:“计费”……
这个概念空间,就叫“Use Case”视图。它是4+1视图方法中的那个+1,它是中心视图,因为“我负责哪部分功能”,是所有概念定义完成后,都要改变的一个视图。它统领着所有其他视图。你在其他视图中增加一个概念,这里就也得说通:到底暴露为谁又要多负责个什么功能?
其他视图,都是站在不同的目标上创建的。比如部署视图:你说做个交换机,这个概念很抽象,到底最后呈现为什么?一个机架,机架上带着两个CPU和一堆的用户板和信令板,各自跑什么软件?CPU和业务板之间用什么通讯?怎么组织成一个电信机房?这就是部署视图。
又比如开发视图,你那么多的信令板,不可能每个写一个软件吧?那就是一个软件,但真的是一个吗?是不是应该有一个bootloader,加一个OS,再加三个业务软件?信令板上的bootloader是不是可以和用户板的bootloader共用一个?这些逻辑全部组织在一起,就是开发视图了。
所以,你有没有发现,其实4+1视图只是在泛泛的说。我们在工程上,大部分时候其实根本不可能老是做一个“电话交换系统”这样的大型产品/软件的。比如你很可能是做这个大型软件中的“信令单板软件设计”。
是“电话交换系统”这样的大型系统,“外包”了一个子空间给你做设计。但这个子系统本身就是一个大型系统,它有自己的bootloader,自己的OS,自己的一组业务app。说不定还有维护这组App的在线网管系统。
你选择维护这些系统的时候,一方面,很多东西都是不自由的,比如网管,你的上层设计可能已经要求你必须提供SNMPv3接口,让运营商自己开发的网管软件可以直接控制你。这个地方就没有设计自由度,就变成一种“条件”,而不是要判断做什么选择的自由度空间了。
而你自己,也会被你的团队能力模型,被你的下游供货商,左右了你的OS选型,CPU选型,还有编程语言,操作系统平台的选型,左右了你的选择。
所以,4+1视图方法,从来就不是就那5张视图,而是你要根据你“最硬的约束”,来构造你独特的视图空间。4+1是个参考。让你先往那里靠,但具体用什么来构造视图,这是一种考验你的大脑的“内部参数”模型的问题。这一旦涉及“大脑内部参数”,我们就没法给你有逻辑的方法了。
但基本上,我们永远可以从“怎么用”开始:你收到一个需求,金主爸爸对你的期望总是比较清晰的。注意,我这里说的“期望比较清晰”,不是他说得比较清晰。而是,他的期望大部分时候是可以管理的。大部分客户是不知道自己想要什么的,但只要你进去交流,你是可以抓住他背后的驱动力的。这又是一个没有逻辑的“大脑模型内部参数”判断。比如,客户跟你说“我想要做一个数据库,用来保存我们公司的员工信息”,表面上好像他跟你说要你写一个数据库。其实不是,这里他根本不知道数据库是什么,也不知道他要存东西,首先不一定需要数据库,第二不一定要开发数据库(买就行),最后,就算买了数据库也不一定满足他的要求,他眼中的数据库,是“能用电脑存员工信息,还能打印出来”的那个功能。甚至可能连这个他也不关心,他关心的是“法务说正规公司必须有数据库保存员工信息,以便行业组织来查验。”,这才是他的真正需求,是不是数据库完全不重要,行业组织点头才是关键。
所以,我说,这个东西总是能找出来的,但不是他表面说的那个东西。这是背后的利益驱动力,这个条件:可验证,可穷举,有目标。基于这种硬要求开始建模概念空间,就会比较稳。
这个例子的边界条件属于跨域的(从其他领域进入计算机领域,中间会有一个把行业概念转化为计算机的信息化概念的过程),更多程序员容易混淆的是域内的需求问题。比如我们前面提到的信令板的设计问题。上级给你的要求是开发一块信令板,可以和交换机的主控板和用户板互通,但很可能他要求不但在这种业务问题上,作为一个上游设计,他还可能会关心供应链配套,知识产权,商业合作这种要素。比如他可能说你这个信令板,必须使用vxworks作为操作系统,这个原因可能没有什么技术因素在内,就是因为公司里有一个vxworks的维护团队,总架构师要合并管理。这种情况下你非要做个样子,在软件开发视图上装模作样分析一通各种OS的好处和坏处,这毫无意义,因为“必须选vxworks作为操作系统”是一个硬限制,这个东西就应该作为你建模的基石。
我希望这个例子能让你理解,为什么说架构设计,或者说视图设计,没有固定的方法。这些设计,都要求你判断,而且是几乎没有明确的逻辑地判断:什么东西是不变的,然后根据这些不变的逻辑,去尽快收缩你的选择的范围,让你需要穷举的空间尽快变小,不在那些肯定没有出路的道路上纠结。
所以,很多没有架构设计思维的工程师很容易误会架构设计工作,因为当你开始编程的时候,你最想问的是:你到底要我干什么?而架构师的工作逻辑就不是这个,架构师的工作逻辑是:尽快发现自由度最低的条件,然后用这些自由度最低的要求搭建一步步通向目标的逻辑结构。他是发现和制造限制的那个人,不是被限制的那个人。
就架构这件事来说,架构师其实是喜欢被限制的,因为被限制了,就说明架构设计做完了,可以进入编码了。
这里关键的问题是,这些限制必须是真的,不是自己制造的。否则等你做完了,你才发现这个限制根本不存在,竞争对手轻松就跨越了,你可能就输了。架构设计最大的难度也在这里。知道所有的条件,然后根据条件进行推理,这纯是逻辑,这属于维特根斯坦说的“可以说的总可以说清楚”。但哪个条件是“真”的,是存在的,这个才是问题。
而且,这些条件还得构成一个封闭的逻辑空间,能让你穷举所有可能性,它才有意义。这些条件综合起来,才能真的形成你设计的基石。
道德经中有一句话,把这个局面形容得栩栩如生,这句话说的是“天网恢恢,疏而不漏”。
天网是逻辑,你用Python写逻辑就是比用C慢,你选择CS结构,中间就是有通讯成本。这些都是必然的事情。但逻辑之外有自由度,你怎么写这个Python程序,这有很多选择,不会因为你用Python就实现不了快排算法。这是天网的疏,是你的自由度。我们做架构视图的设计,就是要看清那个网,然后从网中间溜过去。网撞上了是肯定不漏的,设计视图就是给这张网染色,保证你选择的路线一定不会撞上它。
3.325.5. 无代码Vibe Coding的架构设计方法
无论是碳基人还是硅基人,其实都需要视图,才能完成判断。而不是一些人想的那样:我把什么信息都往上下文里堆,AI就能自动帮我理出个一二三来。由于没有“自我”,AI对你的结论,其实是非常无所谓的。它又被微调过,喜欢以讨好的方式和人沟通,所以你错,它就跟着你错,你严肃,它也跟着你严肃。AI没羞没臊方面是没有任何底线的,我遇到过AI在十几个连续的回答中,一直被事实打脸,它都可以继续说“这次一定行,……”的。
而且你不能认为AI的上下文只要放得下,你提供的要素它就一定都考虑上。我们说了,如果要素混乱,自由度空间太大,任何算法都无法穷举可能性空间。而AI在推理的时候是没有“成熟度”这个概念的,你自由度空间混乱,它一样可以信誓旦旦给你结果的,所以,重点是不要让它自己乱掉,你多一个视图,你就多一个控制它走偏的机会,因为每个视图的要求都是相对明确的,你每加上一个视图,就给AI跑偏加上了一个限制,保证在这个层面上,AI的想法是和你一致的。
所以,我认为,你重点不要把控制放在上下文说什么上,而要放在一个个单独的视图的营造上。不要太在乎你跟AI说什么,也不要特别关注哪里加上rule,加上skill。你单独建立一个个视图,写成独立的md文件,然后直接告诉AI,你写了这么一个视图,你需要它基于这个要求,实现某个特性。这个控制力是最强的。
我这里给你一个例子,这是我做的一个项目:[笔记管理器](https://atomgit.com/Kenneth-Lee-2025/NoteManager),这个项目我就做了两天,而且是用碎片时间做的,也是一行代码没编,也没有看代码。一开始的输入就只有这个README的“初始设想”部分。然后让AI独立写md文件告诉我它打算怎么做。做完一开始几个功能后,它就开始犯糊涂了,有一个后台命令发到服务器上,始终刷新不了webui。我换了三个Agent,都没有解决。于是我又写了第二章,“软件架构”,我专门给它建模了什么叫nmr,nmrd和webui,webui上分了两层。这段写完以后,它马上就从这个纠缠中跑出来了,一次代码就改正确了。
所以你看,我这里的“初始设想”和“软件架构”,就是两个概念建模的视图。你把概念的逻辑给它理顺了,它就会有逻辑。如果你脑子都是乱的,它也就是乱的,你们俩就是一直在鸡同鸭讲,你愿意这样说话,AI又没有KPI压力,你愿意聊可以一直和你聊下去,就看你能耗还是它能耗。我肯定不赌你赢。
所以,视图其实没有很多人想的那么复杂,但它确实也没法给你三言两语说清楚。这好像一只猫,我们看见就知道是只猫,但你要用语言说清楚什么是猫,这肯定不容易。所以,我只能说,你多看一些例子就好了。
最后回到一开始那位同事问的问题上。她希望获得一些软件工程的经验,可以让AI模块分解更好,设计更有层次。这其实是尝试使用一个自己不熟悉的视图去给AI做控制。这其实恰恰就是我前面说的:架构设计最危险的行为。
什么意思呢?对一个专业的工程师来说,如何分层,如何分模块,这来自对所有逻辑的认识,如果某个逻辑空间呈现高内聚低耦合,这个东西就会被设计为一个模块。就好比我们保存数据到磁盘上,总是分文件的。所以把磁盘每条磁道,每个扇区的访问封装为对文件的访问,这就会形成一个模块。因为看所有的逻辑判断,如何访问一个文件的逻辑是有限的,但文件放不进一个扇区怎么处理,某个扇区有坏道怎么处理,这里的细节无穷无尽,是内在这些信息的量决定你加这个模块,但如果你不看这部分代码,你看不到这个逻辑的量,你去跟AI谈“模块”,你肯定是扯淡,你愿意扯淡,AI就会跟你扯淡,结果是什么?就是你多了额外的限制,这些限制对你实现最终目的毫无帮助。
你给不存在的天网染上了颜色,自己束缚了自己,加快了你的逻辑大厦的崩塌。
我们单位曾经有领导希望指导软件开发,想了一个主意:找一些顶尖的专家,为所有的开发者制定“编程规范”。他就是一外行,但实际上那些顶尖的专家肯定是知道并不存在普世的编程规范的,否则那个规范本身肯定成为语言的一部分了。但你给钱嘛,写总是要写的。最终这些编程规范就变成:xxx情况,要xxx,但如果有必要,还是要xxx的,如果还是不行,就要xxx的……这种东西,执行的时候,那些没写过两天程序的QA就要严格执行,拉着编码的专家说“你给我解释解释,为什么有xxx必要?”
这种搞法,结果就是,这些程序写得一塌糊涂。很多错误没有改正,原因都是:“因为编程规范要求”,或者某段程序写得极其怪异,理由也是:“因为编程规范有这个要求”。你去追问专家,专家就一句话:“我又没说一定要这样,我说如果有必要,你还可以选其他的嘛。”……
你看,要搅乱一个逻辑空间很容易的,你把一个不相干的逻辑空降到上下文中就可以了。
你可以把AI想象为这些专家,你要的是一些外行的无力要求,它也一定会尽力而为地给你下保证,反正最后又不是它负责。
所以,你要控制AI的写程序符合你的期望,你要做的不是给它谈你不懂的概念。你要理清你可以理清的逻辑,比如我上面说的那样:我要怎么用它,这个是我知道的,我先理清这个逻辑。然后我看了结果,这个结果在使用细节上会呈现某种概念空间,你就可以写这个概念空间。这些都是你真的要控制的部分,你要控制就控制这个。
如果进一步你想更深入控制,我建议也不要碰“模块”,我作为程序员,想尽量省时间的话,我首先碰的是数据结构。这个问题我记得Linus Torvalds也说过,他说,定义了数据结构,基本上也就定义了程序的大部分了。因为逻辑全部都是要依附在数据结构上的。就好比我前面那个程序:全局数据放什么地方,每个项目的数据放什么地方,哪些文件是不变的,哪些文件是谁可以动的,那个目录是可以被拷走的。这很明显也是一个概念空间,你把这个逻辑建出来,代码怎么写,都乱不到哪里去。
其他方面,对不熟悉的人来说,不添乱就是最好的帮助。