摘要

1) 一句话总结 在AI编程时代,开发者的核心职责已从手动编码转向代码审查,必须掌握“代码坏味道”等软件工程概念,以引导AI生成符合业务上下文且可维护的生产级代码。

2) 核心要点

  • 角色转变:开发者的日常工作已转变为指导AI编程助手,需具备高级开发者的架构视野,而非盲目复制粘贴。
  • 三大核心概念:要引导AI创建高质量代码,开发者需掌握代码坏味道(Code Smells)、抽象(Abstraction)和设计模式(Design Patterns)。
  • 坏味道一:发散式变化(Divergent Change):指一个模块或类违背单一职责原则,处理过多事务。盲目让AI在复杂代码库中添加新功能极易加剧此问题。
  • 解耦职责:应对发散式变化的方法是将不同阶段(如数据获取、数据工程、模型训练)的逻辑分离到独立类中,以提高代码的可测试性和架构灵活性。
  • 坏味道二:夸夸其谈未来性(Speculative Generality):指为尚未发生的未来需求过度设计。给强大的AI提供模糊提示词,极易生成大量不必要的模块和代码。
  • YAGNI原则:应对过度设计应遵循“你不需要它(YAGNI)”原则,从最简单的可行方案开始,有机地迭代代码库。
  • 上下文决定一切:代码的正确性取决于业务场景(如MVP阶段与生产环境对代码结构的要求完全不同),而AI缺乏完整的业务背景认知。
  • 核心竞争力:数据科学家的价值已从编写样板代码转移到培养架构直觉、解决复杂问题以及引导AI契合独特业务场景。

3) 风险/缺口

  • 操作风险:当类承担多种不同职责(如耦合数据工程与机器学习)时,每次修改代码引发崩溃的风险会成倍增加。
  • AI上下文污染风险:AI容易将耦合在一起的不同领域代码(如数据清洗和训练)视为同一问题,从而在修改时引发不必要的逻辑变更。
  • AI放大错误风险:AI能在瞬间重写数百行代码,若涉及多个领域,极易引入单元测试无法捕获的Bug。
  • 代码库失控风险:若任由AI进行“夸夸其谈未来性”的过度设计,开发者将失去对代码库的控制,导致未来修改极其困难。
  • 效率权衡风险:试图通过编写极其详尽的“背景备忘录(Prompt)”来让AI了解所有业务细节是不可扩展的,可能导致写代码的体力活仅仅变成了写提示词的体力活,并未真正提升效率。

正文

AI 可以编写代码,但你必须掌握方向。本文不探讨如何构建提示词(Prompt)来让 AI 施展魔法,而是关注如何在现代 AI 编程生态中保持你作为开发者的核心竞争力。

如今,开发者的主要职责已从手动编写代码转向审查代码。每个人实际上都成了指导“初级开发者”(AI 编程助手)的“高级开发者”。为了脱颖而出,不再盲目地按 Tab 键或复制粘贴,你需要具备高级开发者的远见,掌握现有的软件工程实践。

核心概念

要引导 AI 助手创建可维护、可扩展的生产级代码,你需要了解以下高级概念:

  • 代码坏味道(Code Smells)
  • 抽象(Abstraction)
  • 设计模式(Design Patterns)

对经验丰富的开发者来说,这些概念是第二天性,是通过多年的代码审查和调试刻在脑子里的。而在 AI 代劳了手动编码的今天,即使是初级从业者也必须具备“审查”代码的能力。本文将首先深入探讨第一个主题:代码坏味道。

什么是“代码坏味道”?

“代码坏味道”就像发酸的牛奶,直观地提醒你喝下去是个坏主意。几十年来,开发者通过试错了解到哪些代码能长期有效。“发臭”的代码通常很脆弱、容易隐藏 Bug,且让人类或 AI 代理难以理解其确切的运行逻辑。

在过度依赖 AI 编程助手构建项目时,通常会出现两种典型的“坏味道”:发散式变化(Divergent Change)和夸夸其谈未来性(Speculative Generality)。

坏味道一:发散式变化(Divergent Change)

当一个模块或类同时处理太多事情时,就会出现发散式变化。代码的目的“发散”到了多个方向,试图包揽一切,而不是专注于做好一项任务(违背了单一职责原则)。这会导致代码经常崩溃,并需要为了各种独立的原因进行反复修复。

AI 为何会加剧这一问题?

如果你不熟悉代码库并盲目接受 AI 的输出,就极易陷入此陷阱。当你要求 AI “添加处理 X 的功能”时,它通常会完全照做,将新代码硬塞进现有的类中,尤其是在现有代码库已经很复杂的情况下。如果你不从全局角度考虑代码的角色和职责,最终很可能会得到一堆发臭的代码。

机器学习工程中的例子

假设有一个“全能型”的模型流水线类,它同时负责数据获取、数据工程和模型训练。将平台、数据工程和机器学习工程的关注点耦合在一个地方,会带来以下问题:

  • 操作风险: 每次修改都有引入 Bug 的风险。类承担了三种不同的职责,崩溃的风险就增加了三倍。
  • AI 上下文污染: AI 会将数据清洗和训练代码视为同一个问题的一部分。例如,它可能会为了适应数据工程的改变而进行不必要的训练逻辑修改。
  • AI 放大风险: AI 能在一秒钟内重写数百行代码。如果这些代码涉及多个不同领域,AI 引入单元测试无法捕获的 Bug 的几率也会随之增加。

如何修复?

将职责解耦。例如,让模型流水线仅负责“编排”不同的建模阶段,而将每个阶段的复杂逻辑干净地分离到各自独立的类中。

  1. 降低操作风险: 职责清晰后,你可以放心地重构数据加载逻辑,而不必担心影响机器学习训练代码。只要输入和输出(“契约”)保持不变,影响下游的风险就会降低。
  2. 代码可测试性: 测试范围更小且定义明确,编写单元测试变得容易得多。
  3. 乐高般的灵活性: 架构变得易于扩展。无论是从 S3 迁移到 Azure,还是尝试新的 LightGBM 模型,只需替换相应的模块即可。

坏味道二:夸夸其谈未来性(Speculative Generality)

“发散式变化”通常出现在庞大复杂的代码库中,而“夸夸其谈未来性”则多见于新项目的起步阶段。这是指开发者试图通过猜测未来的发展来“面向未来”编程,结果引入了不必要的功能,徒增复杂性。

你可能想构建一个支持所有模型、交叉验证和超参数调优的完美流水线,结果却发现工程量巨大、代码脆弱、耗时过长,而你最初真正需要的只是一个简单的分类模型。

AI 为何容易陷入此陷阱?

最新、高性能的 AI 编程助手最容易出现这种坏味道。如果给强大的 AI 提供一个模糊的提示词,你很快就会得到过多的模块和数百行新代码。这些代码乍一看可能很合理,但实际上 AI 是在为你尚未规划的未来做设计选择。这会让你失去对代码库的控制,未来一旦需要修改将变得非常痛苦。

核心原则:有机地发展代码库

在审查 AI 输出时,请牢记“YAGNI”(You ain’t gonna need it,你不需要它)原则。只实现你当前需要的代码,而不是你预见的代码。从最简单的可行方案开始,然后不断迭代。这是一种更自然、有机的代码库发展方式,既能完成任务,又能保持精简,减少 Bug。

核心启示:上下文决定一切

这两种代码坏味道揭示了一个道理:软件工程很少有绝对“正确”的代码,一切都取决于上下文

例如,前面提到的“全能型”类在生产环境中是“发散式变化”的坏味道;但在 MVP(最小可行性产品)或研发阶段,如果你只需要考虑单一数据源或单一模型,提前构建多个独立的类和编排器反而成了“夸夸其谈未来性”的坏味道。

AI 可以写出功能和语法都完美的 Python 代码,但它不了解你的完整业务背景。它不知道这段脚本是一次性的实验,还是价值数百万美元的生产流水线的核心。

效率的权衡

你或许认为可以把所有业务细节都喂给 AI,但在实践中这无法扩展。如果你要花半小时写一份“背景备忘录”才能换来 50 行干净的代码,你真的提高了效率吗?还是仅仅把写代码的体力活变成了写提示词的体力活?

如何脱颖而出?

在 AI 时代,数据科学家的价值已经发生了根本性的改变。编写样板代码、格式化和单元测试的体力活已被移除。

要从盲目复制粘贴的同行中脱颖而出,你需要培养架构直觉,引导 AI 助手朝着符合你独特业务场景的方向发展。通过掌握代码坏味道等概念,你将能产出更可靠、性能更好的成果。最终,这将为你腾出更多精力去专注于解决问题和架构方案——这才是数据科学真正的乐趣所在。

关联主题