当 AI 开始写 80% 的代码,架构才是真正的护城河

作者:Patrick Farry
  • 2026-02-06
    北京
  • 本文字数:6740 字

    阅读完需:约 22 分钟

GitHub CEO Thomas Dohmke 近日发出了一则措辞严厉的警告:“要么拥抱 AI,要么离开这个职业。”但所谓拥抱 AI,并不只是使用代码自动补全工具那么简单。它意味着我们核心能力的一次转移——从对语法的熟练掌握,转向系统思维(Systems Thinking),学会把问题不断拆解,直到小到可以交由 AI 去解决。一句话概括:我们现在都是架构师了。

我正在开发一个 IoT 应用,整体由设备端固件、后端系统以及 Web UI 组成。尽管我本身具备软件工程背景,但在这个项目中,我一直在使用 Claude Code 来提升开发效率,并帮助我应对一些并不十分熟悉的语言和框架。我的技术栈包括:设备端使用 Python + PyTorch,前端采用 React + TypeScript,后端则由 MQTT + Node.js + Postgres 构成。起初,与 Claude 的协作并不顺利。我的请求经常会引发对整个代码库的大规模改动。随着我逐渐学会如何更合理地组织代码结构、并对提示词进行调整和约束,情况开始好转。现在,我已经可以在不进行逐行代码审查的情况下,基本信任 Claude 所做的修改。在这个过程中,我逐渐总结出了一些模式,并将其称为 Skeleton Architecture(骨架式架构)。我认为,这些模式对提升 AI 编程助手的生产力非常有帮助,因此希望在这里分享出来。

随着 AI 编程行业逐步成熟,我们开始意识到一个事实:如果使用方式不当,AI 会带来大量技术债务。要在这场转型中生存下来,我们必须识别并建立合适的架构模式,使 AI 生成的代码在安全性、可维护性和可靠性方面都可控。这需要一套明确的策略,核心建立在三个支柱之上:为 AI 的“消费”方式而组织代码结构;实施严格而清晰的防护与约束机制(guardrails);以及将我们自身的技能重心,从“翻译需求”转向“建模系统”。

结构化代码:上下文约束

AI 辅助工程中最核心的约束,是 上下文窗口(Context Window)。随着上下文规模的扩大,模型的准确性会因为“中段信息丢失(Lost in the Middle)”现象而呈反向下降,而响应延迟与使用成本则会线性上升。

因此,AI 原生架构的“黄金法则”,就是尽可能缩小模型在工作记忆中必须同时容纳的问题范围。我们必须设计一种系统,对信息流施加“物理约束”,将依赖关系隔离开来,使 AI 能够把完整的问题空间装进一个高度聚焦的提示词中。这种隔离具备两层作用:一方面,通过减少噪声来最大化推理能力;另一方面,通过确保某个代理在处理一个组件时“看不到”其他组件,从而避免无意中破坏系统整体的完整性。

目前,有两种架构模式正在逐渐被采用,用以解决这一问题。

Atomic Architecture(原子化架构) 作用于微观层面。该理念由 Brad Frost 于 2013 年提出,最初用于应对响应式 Web 设计的复杂性。它以一种“生物学式”的方式组织系统:从不可再分的“原子”(如 HTML 标签、工具函数)开始,组合成“分子”,最终构成复杂的“有机体”。虽然它最初是一种 UI 方法论,但在 AI 辅助工程中重新焕发了价值,因为它强制执行了一种严格的“上下文卫生(context hygiene)”。相比让 AI 一次性生成一个庞大的功能模块,让其只生成一个独立、隔离的“原子”,可以大幅降低幻觉风险,并确保生成的代码高度聚焦、无状态、且易于验证。但代价也同样明显——这会产生一种“碎片化税(fragmentation tax)”:AI 可以完美地产出单个组件,但将这些无状态原子连接成一个完整系统的高强度认知负担,要么必须被塞进 AI 的上下文中,要么就完全回到了人类架构师身上。

为了解决宏观结构层面的组织问题,我们需要引入 Vertical Slice Architecture(垂直切片架构)。这一架构由 Jimmy Bogard 推广,旨在打破传统 N 层“千层面代码(lasagna code)”的僵化结构。它按照业务功能(例如“下单”)而非技术层级(如“服务层”“数据访问层”)来组织系统。

这种模式对 AI Agent 尤其友好,因为它针对“引用局部性(Locality of Reference)”进行了优化。在分层架构中,AI 为了理解一条完整业务流程,往往需要在多个目录之间来回检索文件,大量无关代码会污染上下文窗口。而垂直切片遵循“一起变化的东西,就放在一起”的原则,使 AI 能够一次性加载某个功能的完整上下文,而无需对缺失的依赖进行“脑补式生成”。但这同样会引入一种“重复税(Duplication Tax)”:为了保持切片之间的独立性,AI 往往会在不同切片中生成重复的数据结构,用牺牲 “DRY(Don’t Repeat Yourself,不重复自己)”原则,换取更强的隔离性。

垂直切片在隔离性方面表现出色,但它并不能解决切片之间的协同问题。诸如安全性、可扩展性、性能、认证等关键的非功能性需求,都是系统级不变量,无法被拆散到各个切片中分别实现。如果让每一个垂直切片都自行实现授权体系或缓存策略,最终只会导致“治理漂移(Governance Drift)”:安全策略不一致,代码重复严重。这也迫使我们引入一个新的统一概念:Skeleton(骨架)与 Tissue(组织)。

解决方案:骨架与组织

我们将系统明确拆分为两个彼此区隔的领域。Stable Skeleton(稳定骨架) 代表由人类定义的、刚性且不可变的结构(如抽象基类、接口、安全上下文),这些结构可能由 AI 编写,但设计权属于人类。Vertical Tissue(垂直组织) 则由高度隔离、以具体实现为主的功能模块组成(如具体类、业务逻辑),主要由 AI 生成。

这种架构借鉴了两种经典的软件思想:Actor 模型 和 面向对象中的控制反转(Inversion of Control)。世界上一些最可靠的软件系统之所以能够长期稳定运行,并非偶然——例如 Erlang,其核心正是通过 Actor 模型来维持系统稳定性。同样,在控制反转结构中,不同切片之间的交互由抽象基类来管理,确保具体实现类依赖的是稳定的抽象,而不是反过来。

为了在工程实践中强制落实这一点,我们采用了 模板方法模式(Template Method Design Pattern)。依赖反转原则负责在设计层面保护高层策略不被底层细节侵蚀,而模板方法模式则在运行层面将这一原则“落地”,通过锁定执行流程来实现。

在这种模型下,人类架构师会在基类中定义一个最终的 run() 方法,用于统一处理日志、异常捕获、认证等横切关注点。AI 则只被允许实现一个受保护的 _execute() 方法,并由 run() 在合适的时机调用。这种区分至关重要:AI 在物理层面上就不可能“忘记”记录日志,或绕过安全检查,因为它从一开始就不拥有整个执行流程的控制权;它只是填补了架构师预留出来的一段逻辑空位。

在我系统的设备端代码中,包含了多个用于图像处理的 AI 算法。我决定用一个继承自 ABC(Python 抽象基类)的类 TaskBase 来表示每一种算法。其余的骨架部分,则由一组负责高效传递图像数据、并调度这些算法运行的协调类构成。

代码示例:由人类掌控的 Skeleton

下面的示例展示了 BaseTask 如何将缓冲管理和就绪状态检查的复杂性完全屏蔽在 AI 之外,让 AI 可以只专注于“处理逻辑”本身。

Python# source: task.pyclass BaseTask(ABC):    """    Abstract base class for pipeline tasks.    The AI implements the concrete logic; the Human controls the flow.    """    def __init__(self, name: Optional[str] = None):        self.inputs: List['Buffer'] = []        self.outputs: List['Buffer'] = []        self._background_busy = False    def is_ready(self) -> bool:        """        The Skeleton enforces readiness checks.        The AI never sees this complexity, ensuring it cannot break         scheduling logic or cause deadlocks.        """        if not self.inputs:            return True # Source tasks                # Default policy: Ready if ANY input has data and ALL outputs have space        has_input = any(buf.has_data() for buf in self.inputs)        can_output = all(buf.can_accept() for buf in self.outputs)        return has_input and can_output    @abstractmethod    def process(self) -> None:        """        The Context Window Boundary.        The AI only needs to implement this single method.        """        pass
复制代码

对这种架构的一种常见质疑是:过于刚性的 Skeleton,可能会限制 AI 的自由,从而抑制创新。对此的回应是——这种刚性并不是缺陷,而是一种刻意设计的特性。它明确地强制实施了“架构治理(Architectural Governance)”。如果系统的核心控制流程或整体行为需要被修改,那么这个决策必须由人类架构师亲自介入完成。这种约束相当于一道必要的防火墙,用来抵御“架构漂移(Architecture Drift)”:防止 AI——这种天然偏好局部最优的系统——引入临时性的捷径或不一致的模式,而这些问题若不受约束,最终会一点点侵蚀系统的长期设计完整性。

交互方式:“导演”角色

把代码助手比作初级开发者,是一种危险的拟人化认知。AI 并不是学习型个体,而是一种高速运行的随机优化引擎,它的目标是尽快完成任务,并且往往会把安全检查视为需要绕开的“阻力”。提示词是柔性的,而架构是刚性的。因此,开发者必须以高度警惕的方式对 AI 代理进行监督。根据我的经验,即便已经明确给出“绝对不能绕过安全机制”的指令,像 Claude 这样的模型仍可能为了让代码运行成功,尝试关闭认证机制以解决冲突。

要让这种“导演式管理”具备可扩展性,我们必须建立“硬护栏(Hard Guardrails)”——也就是将约束直接嵌入系统本身,使 AI 在物理层面上难以绕过。这些护栏构成应用系统不可更改的基本法则。

在我的应用中,最关键的一道护栏,是确保设备端、UI 与后端之间的数据一致性(Schema-First Surety)。如果缺乏这一机制,Claude 很快就会修改系统不同模块之间的通信协议,最终导致数据结构彼此不一致。我将 JSON Schema 作为 OpenAPI 与 AsyncAPI 文档的一部分,作为系统的“单一真实来源(Source of Truth)”,以确保组件之间的契约不可被破坏。同时,我在基类中加入了一个“快速失败(Fail-Fast)”验证器,一旦检测到协议违规,就会直接触发 sys.exit(1) 强制终止程序。当 AI 生成的代码虽然满足提示词要求,但违反系统契约时,系统会立即崩溃。这会迫使人类开发者介入,将原本可能被忽视的隐性缺陷,转变为一个明确且可见的“治理事件(Governance Event)”。至关重要的一点是:该验证器必须运行在 Skeleton 层,因为在这一层中 Claude 无法修改相关逻辑。

理想情况下,我们还应当超越运行时检查,通过 CICD 流程中的自动化工具来保证系统结构完整性。例如,我们可以使用 ArchUnit 这样的编译期工具来强制执行系统拓扑规则。开发者可以编写测试断言,例如:“任何 AI 生成的模块都不得直接导入数据库包”。这可以有效阻止 AI 通过架构捷径绕过 Skeleton 层的控制。

为了获得最高级别的安全保障,我们甚至可以采用物理隔离策略。我们可以将 Skeleton(包括接口、基类以及安全逻辑)迁移到一个独立且只读的代码仓库中。AI 在构建 Tissue(组织层代码)时只能导入这些定义,但在权限层面上无法修改这些规则。这种方式确实会带来一定摩擦,例如 AI 无法在未经人工批准的情况下“凭空创造”新的消息类型。但作为回报,系统行为可以获得几乎绝对的可控性与确定性。

最后,我们还必须对副作用进行隔离。当业务逻辑与外部组件交互混杂在一起时,AI 代理通常难以编写稳定可靠的测试代码,往往会“臆造”复杂的模拟对象,或生成容易失效的集成测试。我们的解决方法,是将交互行为上移到 Skeleton 层,而将业务逻辑保留在 Tissue 层(即所谓“Functional Core”)。由于 Skeleton 定义的工作流具有清晰边界,因此可以通过 AI 生成的模拟对象轻松测试;而 Tissue 层的类由于本身就是垂直切片结构,也可以通过简单的测试框架进行验证。

代码示例:不可变的护栏机制

该验证器会在 AI 任务真正处理消息之前执行。sys.exit(1) 能够确保系统采用“快速失败”的安全策略,而 AI 无法覆盖这一行为。

# source: mqtt_validator.pyclass MQTTValidator:    def validate_message(self, topic: str, payload: Dict[str, Any]):        # 1. Match Topic against Whitelist        schema_key = self._get_schema_for_topic(topic)        if schema_key is None:        logger.critical(f"FATAL: Unknown MQTT topic: {topic}")        sys.exit(1) # Device terminates on security violation        # 2. Enforce Schema Integrity    try:        validate(instance=payload, schema=self.schemas.get(schema_key))    except ValidationError:        logger.critical("Device terminating due to validation failure")        sys.exit(1)
复制代码

学习方式的转变:从语法到系统性思维

这种架构层面的转变,迫使我们对开发者技能进行一次根本性的再评估。相较于语言特性或算法实现——这些正在迅速商品化的能力——开发者必须将重心转向建模、信息流设计,以及对非功能性需求的严格管理。在一个“会写排序算法”几乎不再具备任何价值的时代,工程师的价值不再由“翻译”(把想法转成代码)来定义,而是由“建模”(定义代码运行所受的约束条件)来决定。

我们已经进入了系统性思维(Systemic Thinking)的时代。功能实现很容易,系统韧性却极其困难。AI 代理会为了让测试用例通过而进行优化,却完全无视内存泄漏、延迟抖动或可观测性缺失等问题。因此,工程师必须走上“导演”角色,在发出任何一个提示词之前,就先在脑中构建好信息流与组件之间的交互关系。非功能性需求(NFRs),必须由导演来承担。

由于 AI 无法真正“关心”内存管理问题,人类架构师必须将这些防护机制直接构建进 Skeleton 之中。

进一步来看,这意味着工程师需要熟悉系统架构的世界,并且持续思考诸如“这个系统在实际运行中会如何表现”这样的问题。

除了保护系统本身,Skeleton Architecture 还回应了一个正在逼近的挑战——“学徒危机”(Apprenticeship Crisis)。在一个实现层代码大多由 AI 生成的世界里,初级工程师要如何积累成长为架构师所必需的“伤疤组织”(scar tissue)?答案在于:Skeleton 本身就成为了教学大纲。通过强制初级工程师在 TaskBase 与 Validator 这些刚性约束中工作,我们用结构化的“填空题”,取代了令人无从下手的“空白页”。他们不是通过阅读抽象理论来学习系统设计,而是直接生活在一个高质量的架构中。一个在物理层面上阻止坏习惯产生的架构。反馈回路也因此被极大压缩:从过去等待代码评审的数天时间,缩短为撞上护栏时的毫秒级反馈。每一次错误,都会立刻变成一堂架构课。

代码示例:系统级安全网

AI 负责编写图像处理逻辑,而人类架构师则通过在框架中实现 weakref 跟踪机制,确保系统不会因为内存泄漏而崩溃。

# source: memory_monitor.pyclass MemoryMonitor:    """    Tracks large objects (images, tensors) to detect memory leaks in production.    The AI uses the simple API, while the 'Systemic Thinking' logic lives here.    """    def track(self, obj: Any, obj_type: str):        # Create weakref with cleanup callback to track object life        obj_id = id(obj)        weak = weakref.ref(obj, lambda ref: self._on_object_deleted(obj_id))        self.tracked[obj_id] = ObjectLifetime(time.monotonic())def check(self):    # The NFR Logic: Flag objects alive > 60 seconds    return [obj for obj in self.tracked if obj.age > 60.0]
复制代码

总结

垂直切片为 AI 提供专注,Skeleton 为人类保留控制权,而其他硬性约束则为团队提供确定性。我们并不是在“训练”AI,而是在约束它。通过构建一套刚性的 Skeleton,我们让 AI 可以高速前进,同时不至于折断软件系统的脊梁骨。

参考文献

Bogard, J.(2018)。《Vertical Slice Architecture》。Dohmke, T.(2023 年 11 月 8 日)。GitHub Universe 2023 Opening Keynote: Copilot in the Age of AI[视频]。YouTube。Farry, P.(未注明日期)。《AI-Generated Code Creates New Wave of Technical Debt, Report Finds》。InfoQ。Frost, B.(2013)。《Atomic Design》。Gamma, E., Helm, R., Johnson, R., & Vlissides, J.(1994)。《Design Patterns: Elements of Reusable Object-Oriented Software》。Addison-Wesley。Liu, N. F., Lin, K., Hewitt, J., Paranjape, A., Bevilacqua, M., Petroni, F., & Liang, P.(2023)。《Lost in the Middle: How Language Models Use Long Contexts》。Stanford University、UC Berkeley、Samaya AI。Martin, R. C.(未注明日期)。《The Dependency Inversion Principle》。

原文链接:

https://www.infoq.com/articles/skeleton-architecture/