1. 从“干净代码”的信仰者到怀疑者

我职业生涯的前半段,几乎是在为“干净代码”布道。在每一次代码评审里,在无休止的架构讨论会上,在那些大家嘴上说着讨厌、心里却无比在意的命名规范辩论中,我都是一个坚定的卫道士。我相信可读的、结构良好的、尊重下一个接手者的代码,是软件工程文明的基石。这不仅仅是一种实践,更像是一种职业操守,一种对同行和未来自己的善意。但最近一两年,一种越来越强烈的怀疑开始侵蚀我的信念:我们为之奋斗的这一切,在AI大规模介入软件开发的今天,是否正在失去其根本意义?我讨厌这个想法,但我发现自己无法反驳它。

这种转变不是一夜之间发生的。它源于无数个微小的瞬间:当你让AI生成一段业务逻辑,它吐出了一堆能用但命名随意的变量时,你第一反应是去修正它,但下一秒你会想,修正给谁看?当你看到AI将一段本该拆分成三个函数的逻辑,用一百行代码一气呵成时,你本能地觉得“不优雅”,但AI在下一个提示词下就能毫无障碍地理解并修改它。我们过去二十年建立起来的、旨在降低人类认知负荷的种种最佳实践——描述性命名、单一职责、短小函数、清晰抽象——它们的服务对象正在悄然改变。代码的主要读者,可能不再是人,而是模型。

这引发了一个根本性的问题:如果代码的“消费者”变了,那么衡量代码质量的标准是否也应该改变?我们是在固执地维护一个即将过时的“人类中心主义”代码美学,还是在坚守某种更深层的、AI无法替代的工程价值?这篇文章,就是我对这个困境的梳理和挣扎。我没有答案,只有观察和不断加剧的困惑。

2. “干净代码”的本质:一套为人类设计的信息接口

要理解当前的冲击,我们得先回到原点,看看“干净代码”究竟解决了什么问题。剥开所有方法论的外衣,它的核心目标只有一个: 优化人类与代码信息之间的交互效率

2.1 所有规则都服务于人类认知

想想我们奉为圭臬的那些原则。 描述性的变量和函数名 (如 calculateTotalPrice 而非 calc )是为了让开发者无需深入上下文就能快速理解其意图,这节省的是“解码”时间。 函数短小、只做一件事 ,是为了将复杂的逻辑封装成一个个可独立理解的单元,降低大脑的短期记忆负担。 一致的代码格式和风格 (缩进、空格、括号位置),是为了消除视觉噪音,让开发者能专注于逻辑本身,而不是在混乱的排版中寻找结构。

更深层的,如 松耦合、高内聚 的模块化设计,其终极目的也是服务于人类的团队协作与长期维护。一个高度内聚的模块,意味着相关变化被局限在一处;松耦合的架构,意味着一个模块的修改不会像多米诺骨牌一样引发整个系统的崩塌。这都是在应对人类项目管理中的经典难题:如何让多人高效、并行地工作在一个复杂系统上,同时控制变更的风险。

注意 :这里的关键洞察是,干净代码的“好”,是一种 相对的好 ,是相对于人类大脑的信息处理模式而言的。它并非代码在数学或执行层面的绝对最优解。一个对人类来说清晰无比的抽象层,可能会引入微小的运行时开销;一个高度拆分的函数结构,可能会增加一些调用栈的深度。这些代价在过去被认为是值得的,因为换来的是开发效率和维护成本的巨大优势。

2.2 当“读者”从人变为AI

然而,AI模型处理代码的方式与人类截然不同。它不“阅读”代码,至少不像我们一样线性地、带有情感和认知负荷地去阅读。它更像是进行一种高维空间的信息检索与模式匹配。

  • 对命名不敏感 :AI并不依赖 userInputValidation 这个名字来理解这个函数在做什么。它通过分析函数体内的条件判断、函数调用和数据结构,同样能推断出其功能。一个名为 x 的函数,只要实现正确,AI理解起来并不比一个命名完美的函数更费力。
  • 无视函数长度 :人类面对一个500行的函数会感到恐惧,因为我们需要在头脑中构建并维持一个庞大的逻辑模型。AI可以瞬间解析整个函数,捕捉所有分支和依赖,它没有“工作记忆溢出”的问题。将长函数拆解,对AI来说,只是将信息存储在了不同的位置,并不显著降低其理解难度。
  • 穿透抽象层 :我们创建抽象(如接口、基类)是为了隐藏复杂度,提供简洁的契约。但AI可以轻易地同时查看抽象的定义和所有具体实现。抽象带来的“信息隐藏”好处,对AI而言几乎不存在;有时,过于复杂的抽象层次反而会成为它寻找直接逻辑关联的障碍。

我亲身经历的一个转折点是在一次代码评审中。我面对一段AI生成的、功能完全正确的代码,习惯性地留下了评论:“这个变量名 temp 太泛了,建议改为 processedImageBuffer ”,“这个函数有点长,可以考虑把日志记录的部分抽出去”。就在点击“提交评论”的前一刻,我停住了。我在给谁写评论?这段代码大概率不会由另一个人类开发者来修改。下一次迭代,我或同事会直接给AI一个新的、更精确的提示词,让它重新生成。我是在用人类的规则,去评判一个非人类创作过程的中间产物。这感觉就像在用作文评分标准,去评判一个数据库查询的结果——不是不对,而是有点错位。

3. AI编码范式的崛起与“英语优先”的工作流

我们正在经历开发工作流的根本性重构。传统的“构思-设计-编码-测试-评审”线性流程,正在被一个以自然语言为核心的、更加循环和动态的范式所取代。

3.1 新的工作闭环:描述、生成、精炼

典型的新流程变成了:开发者用自然语言(英语、中文等)描述需求或问题 -> AI生成代码、测试用例甚至文档 -> 开发者从功能正确性、性能、安全性等“结果层面”进行评审 -> 如果不满意,用自然语言给出反馈或新的指令,进入下一轮迭代。在这个闭环中, 代码本身变成了一个临时的、可随时丢弃和再生的中间产物

这带来了几个深远影响:

  1. 知识锚点的转移 :开发者的核心知识不再需要深度锚定在某种编程语言的语法或特定框架的API上,而是更需要锚定在如何清晰、无歧义地描述问题,以及如何设计有效的测试用例来验证AI的输出。
  2. 评审焦点的变化 :代码评审的重点,从“代码风格和结构”大幅向“业务逻辑正确性、边界条件、安全漏洞和性能特征”倾斜。我们更关心代码“做了什么”和“做得怎么样”,而不是“长什么样”。
  3. 工具链的融合 :IDE、代码生成工具、测试运行器、调试器正在与AI深度集成。你可以在一个界面里对话、生成、运行测试、看到错误,再对话修改。编码环境正在变成一个“意图执行环境”。

3.2 自然语言成为最高级编程语言

这引出了一个有趣的推论:如果AI能流畅地将自然语言意图转化为代码,那么 自然语言本身就成为了事实上的最高级编程语言 。我们过去说Python是高级语言,C是低级语言,指的是它们离机器指令和人类思维的远近。现在,这个光谱的顶端是英语、中文、西班牙语。

代码,无论是Python、Java还是Rust,都降格成了“编译目标”。我们从写机器码(0101),进化到写人类可读的高级语言( if-else , for-loop ),再进化到直接说“给我创建一个用户注册的API,需要邮箱验证和密码强度检查”。每一层进化,都让我们离机器的“金属”更远,控制力更抽象,但开发效率的潜力也呈指数级增长。

一个必须面对的权衡是 :当执行效率成为终极追求时,我们可能会看到一种“返祖”现象。既然AI不惧怕复杂度,那么为了榨取最后一滴性能,开发者可能会更倾向于选择C、Rust甚至汇编这类低级语言作为生成目标,让AI去处理其中令人生畏的细节(如内存管理、并发安全)。人类可读性将彻底让位于机器执行效率,因为“可读性”的服务对象——人类——已不在关键路径上。

4. 失守的阵地:从代码到架构的全面让渡

危险之处在于,让渡的不仅仅是代码编写权。这种让渡正在向软件生命周期的上下游蔓延,侵蚀着我们作为工程师的核心决策领域。

4.1 架构设计与技术决策的“外包”

现在,开发者不仅用AI写一个函数,还会用它来“头脑风暴系统架构”、“比较微服务与单体应用的优劣”、“设计数据库表结构”。我们把问题抛出去,然后评估AI给出的方案。这些方案往往逻辑清晰、表述专业,引用着看似合理的模式(如“根据CAP定理,你的系统更关注一致性,因此建议……”)。它们的“说服力”极强。

但这里存在一个巨大的陷阱: AI的“推理”是基于模式统计的幻觉,而非真正的理解 。它可能组合出一个语法完美、引用正确但前提错误的方案。例如,它可能为你一个日活只有100的小型应用设计出一个过度复杂、包含十几个微服务和Service Mesh的架构,仅仅因为它在训练数据里看到很多“现代”、“可扩展”的系统都这么描述。

我曾掉进这样的陷阱。在为一个数据管道选择技术栈时,我让AI分析几个选项。它给出的回答结构工整,利弊分析表格一目了然,最终推荐了一个特定的流处理框架,理由听起来非常充分。我几乎就要采纳了,直到我凭直觉去查了一下该框架最近两年的社区活跃度和版本更新情况,发现它已近乎停滞。AI给出的分析是基于历史数据的“普遍真理”,却无法感知技术社区动态这个至关重要的“上下文”。它缺乏那种基于经验的、对技术生命周期的“嗅觉”。

4.2 “说服力陷阱”与直觉的退化

这是最令我担忧的部分:AI输出的那种流畅、自信、结构化的表达,具有极强的认知催眠效果。它会让我们不自觉地降低批判性思维的强度。当一个人花几天时间调研、画图、思考得出的结论,被AI在几秒内以一个更工整的格式呈现时,我们很容易产生“它比我懂得多”的错觉。

长此以往,我们那些通过踩坑、调试、深夜救火而磨练出来的 工程直觉 ——那种“感觉这个地方以后会出问题”、“这个设计闻起来不对”的模糊判断力——会逐渐退化。因为我们已经很少经历从原始需求到最终代码那个充满摩擦和不确定性的完整过程了。我们成了AI方案的评审者,而非创造者。而评审者的直觉,远不如创造者的直觉来得深刻和敏锐。

实操心得 :我现在强制自己执行一个“双通道验证”流程。对于任何AI给出的重要建议(尤其是架构和方案选择),我必须要求它同时提供 理由和反方观点 。例如:“请为使用Kafka作为消息队列提供三个主要理由,再模拟一个反对者,提出三个最有说服力的反对理由。” 这能帮助我打破AI答案的单向说服力,被动地激活自己的批判性思维。同时,对于关键决策,无论AI的答案看起来多完美,我依然会进行最低限度的独立信息检索,比如查看GitHub stars趋势、最新的Release Note、社区讨论热度,以获取AI所不具备的“实时上下文”。

5. 在AI时代重新定义“手艺”与掌控力

那么,这是否意味着软件工程师的手艺就此终结?我认为恰恰相反,手艺的内涵正在发生一次深刻的迁移。价值重心从“熟练编写代码”转向了“精准定义问题与掌控生成过程”。

5.1 从“写代码”到“定义标准”

如果AI是强大的代码生成器,那么我们最重要的角色不再是生成器本身,而是 生成器的校准者与质量控制器 。我们的“手艺”体现在我们为AI设定的标准、约束和审美上。

这意味着,你需要将你过去积累的、内化的“工程品味”外化、显式化。例如:

  • 不要只说“写一个安全的用户认证函数”。你要能清晰地表述你的安全哲学:“认证函数必须采用参数化查询防止SQL注入,密码必须使用bcrypt加盐哈希,失败登录需有延迟和日志但避免信息泄露,令牌需有可配置的过期时间和刷新机制。”
  • 不要只满足于AI生成一个功能。你要有对错误处理的偏好:“我倾向于使用Result/Either模式而非异常来处理已知的业务错误,所有不可预知错误应在顶层边界被捕获并转换为用户友好的消息。”
  • 你需要定义你对代码结构的审美:“对于数据转换层,我偏好纯函数式风格,避免副作用;对于API层,我接受轻度的事务脚本模式,但逻辑必须清晰分层。”

这个过程,本质上是在 构建你自己的、可执行的工程原则数据集 。你不再是代码的生产线工人,而是生产线的设计师和质检标准的制定者。

5.2 打造属于你的AI工作流与“智能体”

幸运的是,当前的工具生态使得个人化这一过程前所未有地便捷。你不需要一个庞大的团队,利用现有的AI平台和API,你就可以组装属于自己的“编码智能体”。

一个简单的实践路径如下:

  1. 知识库构建 :将你认可的优秀代码片段、设计文档、架构决策记录整理成文档或代码库。
  2. 原则提炼 :从上述材料中,总结出成文的、具体的开发规范、模式偏好和禁忌清单。越具体越好(例如:“状态管理优先使用Zustand而非Redux Toolkit,因为项目规模小,需要更简单的抽象”)。
  3. 工具集成 :利用像Cursor、Claude Code、甚至是自定义的ChatGPT提示词链,将这些原则作为系统提示词(System Prompt)或上下文的一部分。你可以创建不同的“智能体配置”:一个用于快速原型开发,规则宽松;一个用于生产代码生成,规则严格且包含安全检查。
  4. 持续迭代 :在评审AI输出时,将不符合你标准的案例作为反例,反过来补充和修正你的原则库。这是一个让AI与你共同进化的过程。

通过这样的设置,AI生成的代码将越来越带有“你的味道”。它生成的不仅仅是能运行的代码,而是符合你特定审美和标准的代码。你的杠杆率由此大幅提升:你能以一人之力,驾驭过去需要一个团队才能完成的代码产出量,同时保持统一的质量和风格。但这有一个绝对的前提: 你必须牢牢坐在驾驶座上 。你必须是那个提出关键问题、做出最终判断、决定采纳与否的“首席工程师”。一旦你退化为被动的接受者,你的手艺和判断力就会迅速贬值。

6. 常见困境与应对策略实录

在与AI协作编码的实践中,我遇到了许多具体而微的挑战。以下是一些典型场景和我的应对思路,或许你也会遇到。

6.1 场景:AI生成的代码“能用但很丑”

这是最常见的冲突。AI给出了一段逻辑正确、但命名随意、结构混乱的代码。

  • 传统反应 :立即动手重构,提取函数、重命名变量,使其符合干净代码规范。
  • 新思维下的反应 :先问三个问题:
    1. 这段代码的预期生命周期有多长? 如果只是一个临时性的、一次性的脚本,花费时间重构的性价比极低。直接使用即可。
    2. 谁将是这段代码的主要维护者? 如果未来维护极有可能还是通过AI(由你或他人给出新指令来修改),那么可读性对AI不是问题,重构的必要性下降。
    3. “丑”的代码是否隐藏了更深层的设计问题? 有时代码混乱是因为职责不清。这时,重构的重点不应是代码风格,而是通过给AI更精确的指令(如“请将数据获取、清洗和验证逻辑拆分成三个独立的模块”),从设计层面解决问题。

策略 :建立一个新的决策树。将“代码美感”的优先级排在“功能正确性”、“性能”、“安全性”和“变更成本”之后。只有当代码需要长期由人类维护时,才将“人类可读性”提升到高优先级。

6.2 场景:AI提供了错误的架构建议

如前所述,AI可能基于过时或片面的信息,给出不合理的技术选型。

  • 应对流程
    1. 质疑信息来源 :直接询问AI:“你这个建议是基于哪些资料或版本的信息?请提供具体的来源或时间范围。” 这能暴露其知识截止日期的局限性。
    2. 要求多方案对比 :不要接受单一方案。指令应为:“针对这个问题,请提供三种不同的架构方案,并用表格对比它们在复杂性、性能、可维护性和社区支持度上的优缺点。”
    3. 引入现实约束 :AI缺乏对“组织上下文”的理解。你必须主动注入这些信息:“在我的团队中,我们只有三个人熟悉Java,而对Python更熟练。我们的运维能力有限,倾向于使用全托管服务。请基于这些约束重新评估你的方案。”
    4. 进行小型概念验证 :对于关键决策,让AI为每个候选方案生成一个最简单的、可运行的示例代码片段。亲自花半小时部署和测试一下,你的直观感受(如启动速度、配置复杂度)往往比长篇分析更有说服力。

6.3 场景:过度依赖导致自身技能退化

担心自己长时间不写代码,会忘记语法、API和调试技巧。

  • 主动学习策略
    • 刻意练习 :每周留出固定时间,关闭AI辅助,完全手动完成一个小功能或解决一个算法题。这就像飞行员在模拟器上训练手动飞行一样,是为了保持“手感”和底层能力。
    • 深度评审模式 :不要满足于AI生成的代码能跑通。选择一段复杂的生成代码,像老师批改作文一样,逐行分析其算法效率、边界条件、潜在异常。尝试在不运行的情况下预测其行为,然后通过测试验证。这个过程能极大地锻炼你的代码静态分析能力。
    • 教授AI :当你试图向AI解释一个复杂概念或纠正它的错误时,你本身就在进行最有效的学习。为了教得清楚,你必须自己先理解得透彻。

6.4 场景:团队协作中的标准混乱

当团队中有人严格遵循干净代码,有人完全依赖AI生成“能用就行”的代码时,代码库会迅速分裂,评审摩擦加剧。

  • 制定新的团队公约 :是时候更新你们的“团队契约”了。这个公约不应再是简单的代码风格指南,而应升级为 “AI辅助开发协作指南” ,内容应包括:
    • 生成代码的验收标准 :明确哪些场景下生成的代码可以直接提交(如简单的CRUD),哪些必须经过人工重构和优化(如核心业务逻辑、公共组件)。
    • 提示词编写规范 :鼓励分享高效的、能产出高质量代码的提示词模板。
    • 评审清单 :代码评审的重点检查项需要更新,增加对AI特有问题的检查,如“提示词是否准确反映了需求”、“生成代码中是否有幻觉引入的不存在的API调用”、“是否存在因训练数据偏差导致的不安全模式”。
    • 知识资产管理 :建立团队共享的“优质模式库”和“反面案例库”,用于持续训练和校准团队使用的AI工具。

7. 结语:在工具理性与工匠精神之间

我依然没有关于“干净代码已死”的确切答案。这是一个正在进行中的、充满张力的过渡期。我看到的是,一套基于人类认知局限而建立起来的完美规则,正面对一个无视这些局限的新兴力量的冲击。

技术史上,工具的进化从来不会完全消灭旧技能的价值,但会无情地重塑它们的价值形态。计算器没有消灭数学,但它让心算能力从必备技能变成了个人兴趣。汽车没有消灭行走,但它重新定义了“距离”和“出行”的概念。

AI编码工具也不会消灭编程。但它正在将“编写符合人类阅读习惯的代码”从一项核心职业技能,推向一个更偏向于审美、协作或特定维护场景的 情境化技能 。与此同时,它把“精准定义问题”、“设计健壮的系统”、“制定高质量标准”、“做出明智的工程权衡”这些更高阶的能力,推到了舞台的中央。

所以,或许“干净代码”作为一种普遍强制性的教条正在松动,但“干净代码”背后所代表的精神——对产出的认真,对协作的尊重,对复杂性的管理,对卓越的追求——不仅没有过时,反而变得更加重要。只不过,现在我们需要将这种精神,从主要灌注于“代码文本”本身,转向灌注于 驾驭AI生成代码的整个过程

我们不再是泥瓦匠,精心砌筑每一块砖。我们正在成为建筑师,用新的语言(自然语言)和新的工具(AI),指挥着智能的工程机械,去建造更宏大、更复杂的结构。这对建筑师的眼界、判断力和掌控力,提出了前所未有的高要求。这场变革令人不安,但也充满了新的可能性。唯一确定的是,停留在旧地图上,注定找不到新大陆。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐