从实际需求形成抽象认识,再用语言、架构和代码表达

在《AI 辅助开发下,如何保持项目一致性》中,我强调过理解和架构的重要性。在《AI Coding is a framework, and...》中,我讨论了自然语言描述中的歧义,以及 AI 编程对规约和判断能力的要求。

继续思考这个问题,我觉得还需要说明,架构、规约和代码之前的认识过程是什么。

我们需要先理解实际需求,辨认其中的事物、关系和约束,形成抽象认识,才能决定怎样描述它、怎样设计系统、怎样实现。自然语言表达、架构设计和代码实现,都依赖于这个认识过程。正确的表达和设计,首先要求我们对问题形成恰当的抽象。

所以,我关心的并不只是怎样让 AI 更准确地执行指令,而是怎样利用 AI,让人更快地理解正在处理的事情。

从具体事物到抽象认识

人认识物理世界,并不是把接触到的每一个现象分别记住。我们会从具体经验中分辨事物的性质,理解事物之间的关系,形成概念,并据此解释和处理尚未遇到的情况。

毛泽东在《实践论》中区分了感性认识与理性认识。感性认识来自对具体事物的接触,首先表现为对现象、局部和外部联系的感受。理性认识则需要对这些材料进行思考,形成概念、判断和推理,进而认识事物的内部联系。两者不是相互独立的知识,而是同一个认识过程中的不同阶段。

我认为,这也是理解软件开发的一个重要出发点。

软件所处理的对象可能是物理过程,也可能是人的活动、组织中的规则,或者已有计算系统的行为。无论对象是什么,我们都需要从具体情况中形成能够用于设计的认识。

用户提出的要求、日常操作的顺序、发生过的问题,提供了最初的材料。知道这些情况,还不等于理解了需求。我们需要进一步判断,哪些情况属于同一个概念,哪些关系必须保留,哪些差异会影响结果,哪些细节与当前问题无关。

这个过程就是抽象。抽象不是先选一个设计模式,也不是给已有代码增加几层接口,而是对实际问题中的事物及其关系作出判断。

例如,一项工作可能需要多次尝试才能完成。“要完成的工作”和“某一次尝试”是否应该是两个概念,取决于实际活动中它们是否有不同的状态、记录和处理规则。它们被写成两个类,是后面的实现决定;认识到它们不是同一件事,才是更早发生的抽象判断。

同样,把两个名称不同的业务过程归入同一个概念,也需要理解它们是否具有相同的关系和约束。名称不同不一定意味着本质不同,操作看起来相似也不一定意味着可以使用同一个抽象。

正确的抽象,应当在当前问题所需的范围内反映这些关系。它的依据是实际事物,而不是概念本身是否常见、形式是否整齐。

表达、架构和代码,是认识的不同表现

我们通常把需求描述、架构设计和编码分成几项工作。这样的分工有实际意义,但容易让人忽略它们共同依赖的东西。

用自然语言说明一项业务,需要知道其中有哪些对象、关系和规则。设计模块和接口,需要知道这些关系应该由谁负责、哪些约束必须共同维护。编写程序,则需要把这些判断落实为数据、状态和操作。

它们的形式不同,但都在表达我们对问题的认识。认识中的错误,也可能同时出现在文档、架构和代码里。三者保持一致,只能说明它们采用了同一种理解,不能说明这种理解符合实际。

这也是我所说的“当你能正确表达自己想要什么时,已经很接近设计好架构”的含义。这里的正确表达,不是写出一篇流畅的需求说明,而是能够说明系统中的概念是什么,它们为什么这样划分,彼此有什么关系,哪些条件下应该发生什么行为。

到了这一步,架构中许多重要的决定已经有了依据。后续仍然需要技术选择和实现工作,但不能把前面的认识过程当作单纯的写作准备。

Dijkstra 在 On the foolishness of “natural language programming” 中反对把形式化语言视为编程困难的主要来源。他强调,形式化符号本身能够帮助人进行精确思考,改用自然语言并不必然减少人的工作。

我与这个判断相近的地方是:换一种表达方式,并没有免除理解问题的工作。我的关注点则更靠前。无论最后使用自然语言还是编程语言,我们都需要先辨认实际问题,形成可以被表达的抽象认识。

这种认识也不是必须在写作和编码之前一次完成。尝试描述一件事情,会暴露概念之间的矛盾;尝试实现,也会使原先没有注意到的关系变得明确。表达和实现既是当前认识的结果,也可以继续参与认识的形成。

实践的意义,在于形成和修正抽象

这正是《实践论》对这个问题的重要性。它不只是告诉我们,设计完以后应该进行测试。它还讨论了设计所依赖的认识如何产生:人在实践中接触具体事物,通过思考形成抽象,再用这种认识指导实践。

如果只强调最后的检验,就会把抽象的形成当作一项已经完成的工作,仿佛我们一开始就知道应该有哪些概念,只需要验证代码有没有写对。实际开发中,更困难的情况往往是,我们还不知道应该怎样理解这个问题。

最初的设计包含了已有经验,也包含了对当前问题的推测。在实现和使用过程中,我们会发现,有些原先认为相同的情况需要不同处理,有些被划为不同模块的行为却必须共同变化,还有一些复杂规则实际上来自同一个约束。

这些结果要求我们重新判断概念及其关系。这个判断发生变化,才意味着理解得到了修正。仅仅在每一种新情况出现时增加一段处理代码,并不意味着已经获得了更准确的认识。

在《人的正确思想是从哪里来的?》中,毛泽东也指出,由经验形成的思想、计划和办法,仍然需要回到实践中检验;正确认识往往需要经过实践与认识之间的多次反复。

放到软件开发中,我更愿意把这个过程理解为:我们不是拿着一个始终正确的抽象去完成实现,而是在实际工作中逐渐认识到,应该怎样抽象这个问题。

这并不要求所有经验都由自己重新获得。文档、已有系统和其他人的实践,可以帮助我们形成初步认识。但把已有概念用于当前问题时,仍然需要理解它所描述的关系,以及这些关系在这里是否成立。

为什么我说一件事情要做三遍

我经常说,当你把一件事情做三遍,基本上就理解了它,也能够把它做对。

这里重要的不是三这个数字,而是反复实践中认识的变化。

第一次做的时候,我通常只能按照已有经验和眼前的要求理解问题。哪些东西应该放在一起,哪些关系值得单独表达,很多判断并没有充分依据。实现使这些判断产生了具体结果,也让我获得了仅靠设想没有获得的认识。

再做一次时,我已经知道第一遍的哪些概念不合适。有些复杂性来自实际需求,有些则是自己理解错误造成的。此时重新设计,能够更明确地区分二者,不必继续沿用最初的划分。

继续做下去,才可能形成相对稳定的抽象,知道哪些关系是必要的,哪些结构可以去掉,以及每项设计决定所依赖的条件。

因此,重做的价值不在于得到更多版本,而在于每一遍都改变了对事情的理解。只是更换措辞、重新生成代码,而没有重新认识问题,并不能获得同样的结果。

这也解释了为什么有经验的人能够更快地完成设计。对他而言,其中一些认识过程已经在过去的实践中发生过。但面对不同的条件,这些认识仍然需要调整,不能因为过去做成过,就默认现在的问题与过去相同。

AI 应当帮助我们更快地完成这个认识过程

如果把 AI 的作用限定为执行已经完整确定的设计,就只使用了它在实现阶段的能力。对我而言,更值得利用的是,它可以帮助我们把尚不成熟的认识具体实现出来,让我们有机会检查这种理解是否成立。

我们可以让 AI 帮助构造实现,观察实际行为,比较不同划分所带来的结果。这里要验证的,不只是程序是否符合描述,还有描述所依据的概念和关系是否符合实际需求。

AI 也可以提出新的概念和方案,但接受一个方案之前,我们仍然需要理解它解释了什么、忽略了什么。不能因为代码能够运行,就把 AI 给出的划分直接当成自己已经掌握的认识。

人参与这个过程,不以亲手输入每一行代码为条件。更重要的是,能否从结果中认识到原先的判断哪里不充分,并据此形成新的判断。AI 可以承担一部分实现工作,却不能使人自动获得对实现对象的理解。

当认识发生变化以后,再利用 AI 进行整体重构,就有了明确的依据。我们已经能够说明原先的抽象有什么问题,新的概念怎样组织,系统应当保留哪些关系。重构是在代码中重新表达这些认识,而不只是整理旧代码。

我所期待的优雅,也来自这里:对事情理解得更准确,必要的关系得到明确表达,不必要的区分和重复得以去除。它不是在不充分的理解上增加更多设计技巧。

所以,AI 编程中值得追求的,不只是更快地把想法变成代码,而是更快地从实际问题中形成正确的抽象认识。自然语言描述、架构和实现,都是这个认识过程的具体表现。利用 AI 做实现和验证,再按照新的理解重构,最终服务的仍然是人对事物的理解。


AI 编程中,人的理解从哪里来
https://blog.wh1isper.top/2026/10/07/ai-coding-understanding-through-practice/
作者
Wh1isper
发布于
2026年10月7日
许可协议