news 2026/10/1 15:00:31

AI Agent上下文工程实战:从ReAct循环到上下文压缩的完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI Agent上下文工程实战:从ReAct循环到上下文压缩的完整指南

1. 为什么上下文工程成了 AI Agent 的分水岭

1.1 从提示词工程到上下文工程的认知跃迁

2023 年大家还在卷提示词工程,研究怎么把一句话写得让大模型听话。到了 2024 年下半年,尤其是 2025 年之后,圈子里聊的东西明显变了——上下文工程这个词开始频繁出现在各种 AI Agent 项目的讨论里。我自己从 2023 年开始做 Agent 相关的项目,踩了无数坑之后才慢慢意识到:提示词工程解决的是“怎么问”,而上下文工程解决的是“在什么信息环境下问”。

这两者的区别,打个比方你就明白了。提示词工程像是你给一个刚入职的实习生写了一份详细的工作指令,告诉他“你要做 A、B、C”。而上下文工程是你不仅要写指令,还要决定这个实习生每天上班时桌面上摆哪些文件、能看到哪些邮件、能查阅哪些历史记录、能调用哪些工具、以及他做完一步之后下一步该看到什么。前者是一锤子买卖,后者是一套持续运转的信息供给系统。

为什么这个转变如此关键?因为当你真正搭建一个 AI Agent 去完成复杂任务时,你会发现单次对话的提示词质量只占最终效果的很小一部分。真正决定 Agent 能不能跑通一个多步骤任务的,是它在每一步能不能拿到正确的上下文。我做过一个数据分析 Agent,提示词改了二十多版,效果提升有限;后来把精力转到上下文管理上——控制每步注入的历史信息、工具返回结果的裁剪策略、中间状态的持久化方式——效果直接上了一个台阶。

1.2 一个真实案例:为什么我的 Agent 第三步就崩了

说一个我自己的翻车经历。2024 年底我做一个基于 ReAct 范式的调研 Agent,任务是“帮我调研某个技术方向的最新进展并生成报告”。前两步跑得很好:Agent 先搜索,拿到一批结果,然后决定打开其中几个链接深入阅读。到第三步的时候开始出问题——它开始重复搜索已经搜过的关键词,或者打开已经读过的页面。

排查了半天,发现问题出在上下文管理上。ReAct 循环每一轮都会把之前的 Thought、Action、Observation 全部拼进 prompt 里。跑到第三、四轮的时候,上下文已经膨胀到接近模型窗口上限,早期的关键信息被挤到了边缘位置,模型对“我已经做过什么”的记忆变得模糊。这不是模型能力问题,是我没有做好上下文的压缩和结构化。

后来我做了几件事:第一,把每一轮的 Observation 做摘要压缩,只保留关键信息;第二,单独维护一个“已执行动作列表”,用结构化格式注入;第三,对工具返回的超长结果做截断加摘要。改完之后,同样的模型,同样的提示词,任务完成率从不到 40% 提升到了 75% 以上。这就是上下文工程的价值——它不改变模型本身,但改变了模型每一步能“看到”什么。

1.3 上下文工程到底包含哪些核心模块

根据我自己的实践和跟同行交流的经验,一个完整的上下文工程体系通常包含以下几个核心模块:

  • 系统提示词管理:定义 Agent 的角色、能力边界、行为规范,这是上下文的地基
  • 对话历史管理:决定保留多少轮历史、如何压缩、如何摘要
  • 工具描述与返回处理:工具的定义怎么写得让模型能正确选择,工具返回的结果怎么裁剪和格式化
  • 记忆系统:短期记忆(当前任务状态)和长期记忆(跨会话的知识积累)的读写策略
  • 动态上下文组装:根据当前任务阶段,动态决定注入哪些信息
  • 上下文窗口预算分配:在有限的 token 预算内,合理分配给系统提示、历史、工具结果、当前输入等各部分

这几个模块不是孤立的,它们之间会相互影响。比如你的工具返回结果特别长,那对话历史的预算就得压缩;你的系统提示写得特别详细,那留给动态注入的空间就少了。做上下文工程,本质上就是在有限的窗口预算下做最优的信息编排。

2. 上下文工程的核心原理与关键细节

2.1 大语言模型的注意力机制与上下文窗口的物理约束

要理解上下文工程为什么重要,得先理解大语言模型处理上下文的基本机制。当前主流的大语言模型都基于 Transformer 架构,其核心是自注意力机制。简单说,模型在处理每一个 token 时,会“关注”上下文中所有其他 token,计算它们之间的关联权重。这意味着上下文中的每一个 token 都会对其他 token 的处理产生影响。

但这里有个关键约束:注意力计算量随上下文长度呈平方级增长。这就是为什么模型的上下文窗口是有限的——不是不想做大,是算力和显存扛不住。目前主流模型的上下文窗口从 8K 到 128K 甚至更大不等,但在实际 Agent 场景中,你很快就会发现这个窗口根本不够用。

更麻烦的是“中间遗忘”现象。有研究表明,模型对上下文中间部分的信息关注度明显低于开头和结尾。这意味着即使你的上下文没有超出窗口限制,放在中间的关键信息也可能被模型忽略。这个发现对我的实践影响很大——我现在会把最关键的信息放在上下文的开头(系统提示区域)和结尾(当前任务指令区域),中间放辅助性的历史信息。

2.2 ReAct 范式下的上下文流转机制

ReAct(Reasoning + Acting)是目前 AI Agent 最常用的基础范式之一。它的核心循环是:Thought(思考)→ Action(行动)→ Observation(观察)→ 下一轮 Thought。每一轮循环,模型都会基于当前上下文生成一个 Thought 和一个 Action,然后执行 Action 得到 Observation,再把 Observation 追加到上下文中,进入下一轮。

这个机制看起来很简洁,但实际运行时会遇到几个上下文层面的挑战:

第一,上下文线性膨胀。每一轮都追加新的内容,上下文越来越长。一个复杂任务跑十几轮,上下文轻松超过窗口限制。

第二,错误累积。如果某一轮的 Observation 包含了错误信息或者无关噪声,它会一直留在上下文里,影响后续所有轮次的决策。

第三,状态追踪困难。模型需要从冗长的历史中提取“我已经做了什么、还没做什么”,这对注意力机制是很大的考验。

我在实践中总结的应对策略是:不要把 ReAct 的历史当成一个只增不减的日志,而要当成一个需要主动管理的状态机。每一轮结束后,除了追加 Observation,还要做一次轻量的状态更新——更新“已完成步骤列表”、“当前进度”、“待办事项”等结构化信息,并在下一轮注入时优先使用这些结构化状态,而不是让模型自己去历史里翻。

2.3 上下文压缩的几种主流策略对比

上下文压缩是上下文工程中最核心的技术之一。我实际用过并且觉得有效的策略主要有以下几种:

压缩策略核心思路适用场景优点缺点
滑动窗口只保留最近 N 轮对话短任务、对话式 Agent实现简单、延迟低丢失早期关键信息
摘要压缩用模型对历史做摘要长任务、调研类 Agent保留核心信息摘要本身消耗 token 和时间
结构化提取提取关键状态存为结构化数据流程类、工具调用类 Agent信息密度高、可精确控制需要设计提取规则
向量检索历史存入向量库,按需检索知识密集型 Agent可处理超长历史检索质量不稳定
分层记忆短期/长期记忆分离管理复杂多会话 Agent兼顾即时性和持久性架构复杂度高

我自己的项目里最常用的是“结构化提取 + 摘要压缩”的组合。具体做法是:每一轮结束后,用一个轻量模型调用做两件事——把 Observation 压缩成一句话摘要,同时更新一个 JSON 格式的任务状态对象。下一轮注入上下文时,用结构化状态替代原始历史,只在必要时才附上最近一两轮的原始记录。这样能把上下文长度控制在一个很稳定的范围内。

2.4 工具描述与返回结果的上下文处理技巧

工具调用是 AI Agent 的核心能力,但工具相关的上下文处理往往被忽视。我见过很多项目,工具本身的实现没问题,但因为工具描述写得不好或者返回结果没处理好,导致 Agent 选错工具或者被返回结果淹没。

工具描述方面,我的经验是:描述要像写给一个新员工的 SOP,而不是像 API 文档。API 文档写“参数 X 是 string 类型,必填”,但模型需要知道的是“什么时候该用这个工具、什么情况下不该用、参数 X 应该填什么样的值”。我现在写工具描述会包含:工具的功能一句话概括、适用场景、不适用场景、每个参数的含义和示例值、返回结果的格式说明。

工具返回结果方面,最大的坑是返回内容太长。比如你调一个搜索工具,返回了 10 条结果,每条都有标题、摘要、URL,加起来两三千 token。如果每轮都这样,上下文很快就爆了。我的做法是:在工具层面就做好裁剪,只返回最相关的 top 3 条,每条只保留标题和一句话摘要;如果 Agent 需要更多细节,让它再调一次工具去获取特定结果的详情。这样把“粗筛”和“精读”分开,上下文效率高很多。

3. 从零搭建一个上下文工程驱动的 AI Agent

3.1 整体架构设计与技术选型

这一节我拿一个实际项目来拆解——一个基于 ReAct 范式的技术调研 Agent,能够根据用户给定的调研主题,自主搜索、阅读、整理信息,最终生成一份调研报告。这个项目我用 Python 实现,核心依赖是 FastAPI + LangChain + LangGraph,模型层可以接本地部署的开源模型或者 API 调用的大模型。

整体架构分为四层:

  • 接入层:FastAPI 提供 HTTP 接口,接收调研任务,返回任务状态和最终报告
  • 编排层:LangGraph 定义 Agent 的状态机,管理 ReAct 循环的流转
  • 上下文工程层:这是核心,负责每一轮上下文的组装、压缩、状态管理
  • 工具层:搜索工具、网页阅读工具、报告生成工具等

为什么选 LangGraph 而不是自己手写循环?因为 LangGraph 提供了状态管理和条件分支的原生支持,你可以把上下文状态定义为一个 TypedDict,每个节点读取和更新这个状态,框架会自动处理状态的传递。这比自己在 while 循环里维护一堆变量要清晰得多。当然,如果你要极致控制上下文,手写循环也不是不行,但开发效率会低不少。

3.2 上下文状态的数据结构设计

上下文工程的核心是状态管理,而状态管理的第一步是定义好数据结构。我的项目中,Agent 的上下文状态定义大致如下:

from typing import TypedDict, Annotated from langgraph.graph.message import add_messages class AgentState(TypedDict): # 原始对话消息(用于兼容 LangChain 的消息格式) messages: Annotated[list, add_messages] # 调研主题 topic: str # 已完成步骤的结构化记录 completed_steps: list[dict] # 当前任务状态摘要 status_summary: str # 已收集的关键信息(压缩后) collected_facts: list[str] # 已访问的 URL 列表(用于去重) visited_urls: set[str] # 当前轮次 current_round: int # 最大轮次限制 max_rounds: int

这个设计的关键点在于:messages只保留最近几轮的原始消息,用于维持对话的连贯性;completed_steps和collected_facts是压缩后的结构化信息,承载了大部分上下文重量;visited_urls用于防止重复访问;status_summary是每一轮动态更新的任务状态概述。

每一轮注入模型的实际上下文 = 系统提示词 + status_summary + collected_facts + 最近两轮的 messages + 当前轮的工具描述。这样即使跑了十几轮,实际注入的上下文长度也能控制在一个可控范围内。

3.3 系统提示词的分层设计方法

系统提示词是上下文工程的地基,但很多人把它当成一坨文本随便写。我的做法是分层设计:

第一层:角色与目标。用两三句话定义 Agent 的身份和核心目标。比如“你是一个技术调研助手,你的目标是根据用户给定的主题,通过搜索和阅读,收集足够的信息,最终生成一份结构化的调研报告。”

第二层:行为规范。定义 Agent 的工作流程和约束。比如“每次搜索后,你需要评估搜索结果的相关性,选择最相关的 1-2 个链接进行深入阅读。不要重复访问已经访问过的链接。当你收集到足够信息后,调用报告生成工具。”

第三层:输出格式。定义每一轮输出的格式要求。ReAct 范式下,通常要求模型输出特定格式的 Thought 和 Action。我会在提示词里给出明确的格式示例。

第四层:动态注入区。这一层不是写在系统提示词模板里的,而是在每一轮组装上下文时动态插入的。包括当前任务状态、已收集信息、最近历史等。

这种分层设计的好处是:前三层是静态的,可以精心打磨和复用;第四层是动态的,根据任务进展灵活调整。两者分离,维护起来清晰很多。

3.4 ReAct 循环的完整实现与上下文注入

下面是一个简化但可运行的 ReAct 循环实现,重点展示上下文注入的逻辑:

import json from langchain_openai import ChatOpenAI from langchain_core.messages import SystemMessage, HumanMessage, AIMessage llm = ChatOpenAI(model="gpt-4o", temperature=0) SYSTEM_PROMPT_TEMPLATE = """你是一个技术调研助手。 ## 你的目标 根据用户给定的主题,通过搜索和阅读收集信息,最终生成调研报告。 ## 工作流程 1. 分析当前任务状态,决定下一步行动 2. 可选行动:search(关键词) / read(url) / generate_report() 3. 每次只执行一个行动 4. 不要重复访问已访问的链接 ## 当前任务状态 {status_summary} ## 已收集的关键信息 {collected_facts} ## 已访问的链接 {visited_urls} ## 输出格式 请按以下格式输出: Thought: 你的思考过程 Action: 行动名称(参数) """ def build_context(state: AgentState) -> list: """组装当前轮的上下文""" system_content = SYSTEM_PROMPT_TEMPLATE.format( status_summary=state["status_summary"], collected_facts="\n".join(f"- {f}" for f in state["collected_facts"][-10:]), visited_urls=", ".join(list(state["visited_urls"])[-10:]) ) messages = [SystemMessage(content=system_content)] # 只保留最近两轮的原始消息 recent_messages = state["messages"][-4:] if len(state["messages"]) > 4 else state["messages"] messages.extend(recent_messages) return messages def react_step(state: AgentState) -> AgentState: """执行一轮 ReAct 循环""" context = build_context(state) response = llm.invoke(context) # 解析 Thought 和 Action thought, action = parse_response(response.content) # 执行 Action,获取 Observation observation = execute_action(action, state) # 更新状态 state["messages"].append(AIMessage(content=response.content)) state["messages"].append(HumanMessage(content=f"Observation: {observation}")) state["current_round"] += 1 # 压缩和更新结构化状态 state = update_structured_state(state, thought, action, observation) return state

这段代码的核心在于build_context函数——它决定了每一轮模型能看到什么。注意几个细节:collected_facts只取最近 10 条,visited_urls也只取最近 10 个,messages只保留最近两轮。这些都是为了控制上下文长度。同时,status_summary是每一轮动态更新的,承载了“当前进展到哪了”的关键信息。

3.5 结构化状态更新的具体实现

update_structured_state是上下文工程的关键环节,它负责把每一轮的原始信息压缩成结构化状态。我的实现方式是调用一个轻量模型来做信息提取:

def update_structured_state(state, thought, action, observation): """用轻量模型更新结构化状态""" prompt = f"""根据以下信息,更新任务状态。 当前状态摘要:{state['status_summary']} 本轮思考:{thought} 本轮行动:{action} 本轮观察结果:{observation[:2000]} 请输出 JSON 格式: {{ "status_summary": "更新后的任务状态摘要(一句话)", "new_facts": ["从本轮观察中提取的关键信息,最多3条"], "should_continue": true/false }} """ response = lightweight_llm.invoke(prompt) result = json.loads(response.content) state["status_summary"] = result["status_summary"] state["collected_facts"].extend(result["new_facts"]) # 记录已完成步骤 state["completed_steps"].append({ "round": state["current_round"], "action": action, "summary": result["status_summary"] }) return state

这里用轻量模型(比如小参数量的本地模型或者便宜的 API)来做状态更新,而不是用主模型,原因是:这个任务相对简单,不需要太强的推理能力;而且每轮都要调用,用主模型成本太高。实测下来,用一个小模型做状态提取,效果完全够用,成本能降低一个数量级。

4. 上下文工程实战中的常见问题与排查技巧

4.1 Agent 反复执行相同动作怎么办

这是 ReAct Agent 最常见的问题之一。Agent 搜了一个关键词,看了结果,然后又搜同样的关键词。排查下来通常有三个原因:

原因一:上下文里没有明确的“已执行动作”记录。模型看不到自己已经做过什么,自然可能重复。解决方法是维护一个显式的已执行动作列表,并在每轮上下文中注入。

原因二:Observation 没有提供足够的新信息。如果搜索返回的结果跟上次一样,模型会觉得“我还没找到想要的信息”,于是再搜一次。解决方法是在工具层面做去重,已经返回过的结果不再重复返回。

原因三:状态摘要没有更新。如果status_summary一直停留在初始状态,模型无法感知进展。解决方法是每轮强制更新状态摘要,并在上下文中突出显示。

我现在的做法是三管齐下:显式动作列表 + 工具层去重 + 每轮状态更新。改完之后,重复动作的问题基本消失了。

4.2 上下文超长导致模型“失忆”怎么处理

上下文超长是另一个高频问题。表现是:Agent 跑到后面几轮,开始忘记前面的关键信息,或者做出与之前矛盾的决定。排查思路如下:

首先确认是不是真的超了窗口限制。不同模型的窗口大小不同,你需要根据实际使用的模型来计算。一个粗略的估算方法是:中文大约 1 个字等于 1.5 个 token,英文大约 1 个词等于 1.3 个 token。把你的上下文内容估算一下,看看是否接近窗口上限。

如果确实超了,或者虽然没超但接近上限,就需要做压缩。我的压缩优先级是:先压缩工具返回结果(通常占大头),再压缩历史对话(保留最近几轮),最后压缩已收集信息(做摘要合并)。系统提示词和当前任务指令一般不压缩,因为这是最关键的。

还有一个技巧是“分阶段注入”。不是所有信息都需要在每一轮都注入。比如在搜索阶段,不需要注入之前读过的文章全文;在报告生成阶段,不需要注入搜索过程的详细记录。根据当前阶段动态决定注入什么,能省下大量空间。

4.3 工具调用失败时的上下文恢复策略

工具调用失败是不可避免的——网络超时、API 限流、返回格式异常等等。关键不是避免失败,而是失败后如何让 Agent 正确恢复。

我的做法是:工具调用失败时,不要把原始的错误堆栈直接塞进上下文,而是转换成模型能理解的描述。比如“搜索工具调用失败,原因:请求超时。建议:稍后重试或更换关键词。”这样模型知道发生了什么,也知道该怎么应对。

同时,我会在状态里记录失败次数。如果同一个工具连续失败三次,就强制 Agent 换一个策略,而不是无限重试。这个逻辑写在编排层,不依赖模型自己判断。

还有一个细节:工具失败后,上一轮的 Thought 和 Action 仍然保留在上下文里,但 Observation 被替换成了错误描述。这样模型能看到“我尝试了什么、结果失败了”,而不是完全丢失这一轮的信息。

4.4 常见问题速查表

问题现象可能原因排查方法解决方案
Agent 重复执行相同动作缺少已执行动作记录检查上下文是否包含动作历史维护显式动作列表并注入
后期轮次决策质量下降上下文超长或关键信息被淹没估算 token 数,检查关键信息位置压缩历史,关键信息前置
工具选择错误工具描述不清晰检查工具描述是否包含适用场景重写工具描述,增加示例
状态摘要不更新状态更新逻辑未触发检查每轮是否调用状态更新强制每轮更新状态摘要
报告生成时信息不全已收集信息被压缩过度检查 collected_facts 内容调整压缩策略,保留更多事实
模型输出格式错误格式要求不够明确检查系统提示中的格式说明增加格式示例,强化约束

4.5 几个我踩过的坑和对应的心得

坑一:把上下文窗口当垃圾桶。刚开始做的时候,我觉得反正窗口大,什么都往里塞。结果模型被无关信息干扰,效果反而差。后来我学会做减法——每一轮注入前都问自己:这条信息对当前决策真的有必要吗?没必要就砍掉。

坑二:摘要压缩用主模型。一开始我用主模型做历史摘要,效果是好,但成本高、延迟大。后来换成小模型做摘要,主模型只负责核心决策,整体成本和延迟都降下来了,效果几乎没有损失。

坑三:忽略工具返回结果的格式。工具返回 JSON 和返回自然语言,对模型的理解难度完全不同。我现在尽量让工具返回结构化的、字段名清晰的 JSON,模型解析起来准确率高很多。

坑四:没有做上下文版本管理。上下文工程的策略是需要迭代的——今天用滑动窗口,明天可能换成摘要压缩。如果没有版本管理,改来改去就乱了。我现在会把上下文组装逻辑单独抽成一个模块,每次调整都记录变更和效果对比。

坑五:忽视冷启动问题。第一轮的时候,collected_facts是空的,status_summary只有初始值。模型面对一个几乎空白的上下文,容易做出奇怪的决定。我的做法是在第一轮注入一个“初始行动计划”,给模型一个明确的起点。

5. 上下文工程的进阶方向与个人体会

5.1 多 Agent 协作中的上下文隔离与共享

当你从单 Agent 扩展到多 Agent 协作时,上下文工程会变得更复杂。核心问题是:哪些上下文应该隔离,哪些应该共享?

我的经验是:每个 Agent 有自己的私有上下文(自己的系统提示、自己的工具集、自己的历史),同时有一个共享的全局上下文(任务目标、全局状态、关键事实)。私有上下文保证每个 Agent 专注于自己的职责,共享上下文保证协作的一致性。

实现上,我通常用一个中心化的状态管理器来维护全局上下文,每个 Agent 在每一轮开始时从全局上下文拉取自己需要的信息,结束后把自己的产出写回全局上下文。这样既保证了隔离性,又实现了信息共享。

5.2 上下文工程与模型能力的关系

有一个问题经常被讨论:上下文工程做得好,能不能弥补模型能力的不足?我的观察是:在一定程度上可以,但有上限。

对于中等复杂度的任务,好的上下文工程确实能让一个中等能力的模型表现得像高能力模型。因为很多错误不是因为模型“笨”,而是因为它“没看到该看的信息”或者“被无关信息干扰了”。把上下文管理好,模型的能力就能充分发挥。

但对于需要深度推理的任务,上下文工程只能锦上添花,不能雪中送炭。模型本身的推理能力是天花板,上下文工程是帮你逼近这个天花板,而不是突破它。所以我的策略是:模型选型上不将就,上下文工程上不偷懒,两者都做好。

5.3 我个人的上下文工程检查清单

最后分享一份我在每个 Agent 项目上线前都会过一遍的检查清单:

  • 系统提示词是否分层清晰,动态注入区是否独立
  • 每一轮注入的上下文总长度是否在窗口的 60% 以内
  • 关键信息(任务目标、当前状态)是否放在上下文开头或结尾
  • 工具返回结果是否做了裁剪和格式化
  • 是否有显式的已执行动作记录
  • 状态摘要是否每轮更新
  • 是否有上下文压缩策略,压缩后是否保留了关键信息
  • 工具调用失败时是否有降级和恢复策略
  • 是否用轻量模型处理摘要和状态更新等辅助任务
  • 是否有上下文组装的版本管理和效果对比记录

这份清单不是凭空来的,每一条背后都有至少一次翻车经历。上下文工程这个方向,理论看着简单,但真正做好需要大量的实践和调试。我的体会是:把它当成一个独立的工程问题来对待,而不是提示词工程的附属品,你才能真正把 AI Agent 的效果做上去。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 15:00:06

大学生开学必学——电脑必学的快捷键整理

大学生开学,电脑必学的快捷键整理 文章目录大学生开学,电脑必学的快捷键整理[toc]1. 最常用的那一批1.1 Windows / 系统1.2 浏览器2. 也很常用,但没到「闭眼就会」的程度2.1 文件资源管理器2.2 文字编辑与光标移动(写代码 / 写论文…

作者头像 李华
网站建设 2026/10/1 14:59:39

雨花台区沟槽支护箱出租 9米U型钢板桩 市政管道开挖支护方案租赁商

随着国内基建工程、城市更新项目的持续推进,市政工程、土方桩基、厂房建设等领域对临时施工配套周转材料的需求逐年增长。相较于传统自购施工配套钢材的模式,租赁服务凭借灵活适配、成本可控、省心省力的特点,已经成为越来越多工程方的优先选…

作者头像 李华
网站建设 2026/10/1 14:57:22

Java接口实战:从语法机制到设计原则与常见坑

接口在Java里的地位,我觉得怎么强调都不过分。很多初学者写着写着就发现,自己写的代码一旦要加需求,就像往行李箱塞衣服——硬塞能塞进去,但拉链快爆了。而接口,本质上就是你提前说好"行李箱能装多少、怎么分层&q…

作者头像 李华