小叶和同学想借助 AI 做一个社团器材预约工具。页面负责让同学选择器材和时间,预约处理部分负责判断能否借用,记录部分保存结果。大家分别把任务交给 AI,很快都有了能演示的功能。

第一次接在一起时,页面显示“预约成功”,记录里却没有生效的预约。负责页面的同学认为,收到“成功”就说明器材已经留好了;负责处理的同学却说,自己返回的成功只表示请求已经收到。另一处问题是,查询页面刚显示投影仪可用,小叶正式提交时却被告知时间冲突。有人因此怀疑,两个功能至少有一个算错了。

这些问题不能只靠统一字段名解决。大家还要约定:交来什么才算一项明确请求,某个结果究竟保证了什么,什么时候可以据此继续行动,哪些变化已经真正发生。本章要讨论的接口与协作约定,就在这些具体问题里。

以下器材工具、日期、编号和规则均为虚构教学情景。我们用它理解软件部分怎样合作,不需要先搭好整个系统;也不把这里的预约政策当作任何学校的实际制度。

一、接口让使用者知道,可以向这一部分要求什么

接口是一个软件部分对外提供能力的交接方式。函数的调用入口、服务接收的请求、两个程序共同读取的文件,都可以承担这种交接。使用者通过它提出要求,提供者按约定返回结果或产生相应作用。

接口通常会告诉我们名称、输入与输出,但合作需要的含义往往更多。例如,一个入口名叫“预约器材”,输入器材编号和时间,输出“成功”。仅有这几项,还不能判断成功以后器材是否已被占用,是否仍等管理员处理,或者是否只是表单填写正确。

小叶实际关心的是:自己现在能否按已经预约到器材来安排活动。这个行动需要一个明确承诺。如果接口只保证收到了请求,页面就应显示已提交或待处理;如果它保证预约已生效,页面才有依据显示已经预约到。两种能力都可能有用,但必须让使用者知道自己得到的是哪一种。

把输入含义、适用条件、结果以及可观察作用写清楚,就是在说明接口契约。这里的契约指技术上的共同约定:调用方需要按什么方式使用,提供方需要完成什么。它可以先是一段简短文字,并不要求大学生先学一套形式化语言。

例如,小叶可以先写:“申请预约一件指定器材的一段时间。返回预约成功时,预约记录已经生效,并会用于之后的时间冲突判断;若明确拒绝这次申请,则没有为它建立新预约。”这已经比“传入编号,返回成功”更能支持页面决定下一步。

接口契约也保护提供者的实现空间。页面需要知道预约是否生效,通常不需要知道记录存在哪个数组、用什么临时变量、先查哪张内部表。只要对外承诺仍得到满足,内部办法就有机会调整,而不要求所有调用者跟着学习新代码。

从这个角度看,约定的作用不是增加一份必须写得很厚的文档,而是把原先分别藏在各人脑中的理解放到同一个可讨论的位置。AI 生成代码时也会补入它认为合理的细节。如果几个任务分别补出不同含义,代码各自能运行,仍可能无法共同完成小叶的预约。

接下来,我们选一项具体申请,把这种约定逐步写出来。每多说明一层,都应让某个原先无法判断的问题变得可以判断。

二、字段能装下信息,还要说清信息代表什么

小叶这次要预约的是编号为 Q17 的一台投影仪,时间是 2026年10月16日14:00至16:00,北京时间。Q17代表一件具体器材,不是“投影仪”这一类器材,也不是还可借出的数量。本例一次申请只预约一件器材在同一天的一段时间。

可以把这次申请写成下面的JSON示意。它展示双方交换的信息,不是某项服务已经运行后留下的记录。

可复制模板
{
  "equipment_id": "Q17",
  "start_at": "2026-10-16T14:00:00+08:00",
  "end_at": "2026-10-16T16:00:00+08:00",
  "request_id": "req-041"
}

前面三项分别记录器材身份、开始时间和结束时间。时间文字中的+08:00说明这里采用的时区偏移,避免接收者把同一串钟表时间当成另一个地方的当地时间。日期也完整留下,否则“周五下午”随着阅读时点变化,就可能指向另一周。

最后的request_id是这一次申请的标识。这里把它记作req-041,是为了让后续回复和重复发送仍能与同一项申请对应,具体作用会在后面展开。它与器材编号不同:同一件器材可以在不同时段接受多项申请,不能拿Q17同时代替“借哪件”和“正在处理哪一次”。

当前案例从调用身份已经识别为小叶开始。身份识别由工具的登录入口处理,预约部分据此知道申请者是谁。上面没有让人随便填写一个姓名,再把这个姓名当成身份已核实的证据。输入正文与调用环境提供的信息可以不同,双方仍需要明确各自从哪里取得。

这里可以区分数据结构和数据语义。结构说明有几个字段、名称是什么、允许放哪种类型;语义说明字段表示的对象、单位、时点以及使用条件。Q17即使是合法字符串,若页面把它当器材类别,处理部分把它当某一台机器,两边仍没有交接同一件事。

时间也一样。“14”和“16”都能保存成数字,但双方必须知道它们是当天时刻、持续小时数,还是从某个起点累计的分钟。仅检查数据类型,不会自动补出这些含义。小叶应先说清预约哪一天、哪一段时间,再决定采用什么记录形式。

常见的API描述工具可以记录参数、数据结构、响应及行为说明,例如OpenAPI官方规范。这种形式便于共同维护和部分自动检查,但器材身份、预约生效等含义仍要由当前任务说明。即使一份请求完全符合规定格式,也不能单靠格式检查证明器材确实可借。

因此,字段表最有价值的一列常常是“对方可以怎样使用这个值”。页面拿到器材身份是为了指向同一件物品,拿到时间是为了约定占用范围,拿到请求标识是为了认出同一项操作。顺着用途写,容易看出还缺什么,也不容易为了显得完整塞入一堆暂时没人使用的字段。

三、把边界说清,比反复说“判断合法”更有用

有了起止时间,小叶还要决定两个预约怎样算冲突。这里先采用一条明确的教学规则:器材从开始时刻起被占用,到结束时刻释放;本例暂不额外加入归还检查、搬运或重新准备的间隔。

按这个规则,Q17若已在14:00至16:00被预约,另一项15:30至16:30的申请会与它共同占用一段时间,因此冲突。若另一项从16:00开始,则只是在前一项结束的位置接上,没有共同占用一段时间。这一判断依赖刚才约定的释放方式。

数学上常把这种时间范围写成左闭右开区间:包含起点,不包含终点。这种表示精确记录了“开始计入,结束释放”的规则,让页面和预约处理部分对前后接续的时刻作出同一种判断。

固定预约时段与前后相接、实际重叠的区别
图 S05-01|固定预约时段与前后相接、实际重叠的区别

图中的几项都针对同一天的同一件器材。13:00至14:00恰在小叶的申请开始时结束,16:00至17:00在小叶的申请结束时开始,按当前规则都不重叠。15:30至16:30则有一段共同占用时间。我们比较的是时段是否相交,并不是只比较两个开始时刻是否相同。

还需要把无效时段与冲突分开。若开始和结束都写14:00,这项申请根本没有满足“开始早于结束”的规则;若写16:00开始、14:00结束,本例又不支持把它自动理解为跨日预约。此时应先说明输入时间有问题,而不是把它当成已经查过器材安排后的冲突。

边界一旦清楚,就能形成有意义的检查例子:正好相接、确实重叠、开始等于结束、开始晚于结束。前两类检验占用关系,后两类检验输入是否有效。只重复检查几十组普通时段,仍可能漏掉接续时刻或无效输入的处理;小叶应让这些会改变判断的情况各有对应例子。

如果将来社团规定每次归还后还要留出15分钟检查设备,那么16:00直接接下一项就不再符合这条新规则:前一项使用虽然结束了,器材仍需完成检查,才能交给下一项使用。页面的可用提示、处理部分的冲突判断和约定示例都需要共同反映这条新要求。

这也解释了为什么接口里只写“传入合法时间”不够。合法可以指格式能解析,也可以指开始早于结束,还可能指满足使用规则;不同层次不能用一个词带过。把当前需要的边界说明白,比要求 AI 自行“完善所有校验”更容易获得可以核对的结果。

四、调用方负责提供什么,提供方负责保证什么

软件规格中常用前置条件和后置条件来表达双方责任。前置条件说的是,调用这项能力时需要满足什么;后置条件说的是,在规定前提下完成调用以后,结果及相关状态应满足什么。MIT关于规格的课程说明也用这两个概念说明调用者和实现者之间的责任。

先看一个很小的内部例子。预约程序可能有一个只负责比较两个时间段的函数,约定交给它的时间已经解析完毕,而且各段的开始都早于结束。调用这个函数的程序部分负责满足这些前提;比较函数则负责按约定判断是否重叠。它不必同时承担解释“周五下午”、识别登录身份和保存预约的工作。

这样的分工有用,是因为某些信息可以在进入内部能力前统一准备。时间解析入口处理一次,后面的比较便可以围绕已经清楚的对象工作。前置条件不是提供者可以任意推卸的口号,而是双方确实有办法共同遵守的边界。

对面向页面的预约入口,小叶需要更宽的约定。用户可能漏填结束时间,页面也可能传错字段。如果这些情况是工具要正常应对的输入,就应说明预约入口如何识别、如何返回问题,以及是否会产生预约记录。不能一面宣称工具会处理常见填写错误,一面又在约定里把所有错误都排除到“非法输入,行为不管”的区域。

因此,内部时间比较函数可以要求已经得到有效时间段;对外接收预约的入口则负责把缺字段、无法解析、起止不合当前规则等情况处理成明确的输入错误,并且不为这次错误输入新建预约。相同的“时间是否合法”,放在不同交接位置,可能对应不同的责任安排。

另一些条件不能让页面提前保证。例如,页面刚查过Q17可用,并不能保证真正提交时仍然可用。若预约入口把“调用者保证器材当时一定空闲”写成前置条件,而页面又没有控制其他申请的办法,这份契约就很难被正确使用。

更合适的安排是:页面提出器材和时间要求,预约处理部分依据处理时的有效安排判断是否接受。时间冲突是它需要明确回答的一种结果,不能因为出现冲突就说调用者不该发来申请。小叶由此可以区分“没有按约定提供可识别的信息”与“信息清楚,但业务条件不允许”。

当前案例中,申请身份已被识别,预约入口还要按借用规则判断该身份是否有资格。器材是否存在、是否可借、时段是否与有效预约重叠,也都应有明确的处理结果。资格不足与时段冲突的原因不同,页面需要据此说明是借用资格不符合要求,还是应重新选择器材或时段。

对于后置条件,仅写“返回一个字符串”同样太弱。预约入口若返回成功,应保证为哪件器材、哪段时间、哪位申请者建立了什么记录;若返回冲突,应保证没有为本次申请另建一条生效预约。完成后的结果与状态连在一起,调用者才有依据继续行动。

一份约定允许常见失败结果,并不等于它不可靠。恰恰相反,输入错误或器材已被占用时,明确说明原因并保持记录一致,往往就是正确履行了约定。真正需要追查的是承诺与实际行为不一致,例如已经返回冲突,却又留下了占用器材的新预约。

五、“成功”需要对应已经发生的事情

现在先看小叶这次申请成功的情形。设处理时器材可借、身份符合资格、时间合法且没有冲突,预约部分为它建立了编号R208的生效记录。双方可以约定,成功回复包含下面这些信息。

可复制模板
{
  "status": "reserved",
  "reservation_id": "R208",
  "equipment_id": "Q17",
  "start_at": "2026-10-16T14:00:00+08:00",
  "end_at": "2026-10-16T16:00:00+08:00",
  "request_id": "req-041"
}

这里的reserved表示预约已经生效,R208是这条预约记录的身份。它与req-041又不相同:一个识别业务中的预约,一个识别发来的那项申请。保留对应关系后,页面能够知道当前回复是针对哪次提交,也能够在以后查询或取消时指向正确预约。

开始、结束和器材身份再次出现在结果里,也有具体作用。页面可以核对处理方接受的是不是小叶实际选中的Q17及相应时段。如果输入经过了某种解释或转换,最终结果应让使用者能够看出接受了什么,不能让一个孤立的“成功”掩盖对象或时间已经改变。

成功的关键依据仍在于作用已经发生。假设程序先生成一个看起来很像预约编号的字符串,马上回复reserved,随后才尝试保存;保存失败时,这个编号仍显示在页面上。字段齐全、JSON正确,都没有兑现“预约已经生效”的承诺。

小叶需要把生效说明得足够可观察:按R208能够查询到对应记录;后续申请相同时段时,冲突判断会把这项有效预约算进去。若系统连这些行为都没有接上,就不能只靠界面出现一个编号来认定预约已经留好。

这种超出返回值本身的状态变化,在程序设计中通常叫副作用。建立预约、修改预约状态、写入文件,都是可观察的状态改变。“副”并不表示坏事;对预约操作来说,改变记录正是它要完成的主要工作之一。问题在于哪些作用应该发生、哪些不应该被顺带改变。

例如,取消R208可以把这条预约改成已取消,并使它不再占用对应时段。但不能因为两条记录使用同一件Q17,就把这件器材未来所有预约一并清空。接口应让调用者说明取消哪一条,提供者则保证修改范围与这次要求相符。

同样,查询预约通常只用于取得当前信息,不应因为“查看了R208”便重新占用一次或替小叶确认一项尚未确认的修改。查询与修改的作用不同,给它们清楚名称和约定,可以减少调用方对每次操作会发生什么的猜测。

预约已生效也有承诺边界。它说明系统中的这项安排已经建立,并不保证现实里的投影仪从此不会故障,也不自动完成领取、归还或现场交接。若产品要管理这些后续事情,就应另有对应状态和操作。此时需要把“完成了哪一件事”说准,而不是把成功二字越写越大。

六、查询时可用,为什么提交时仍可能冲突

上一节展示了申请被接受的情形。下面另看一次存在竞争的提交:小叶开始查询时,Q17在所需时段还没有有效预约;在他提交之前,另一位同学先完成了对同一时段的预约。

查询结果与正式提交之间可能发生的另一项预约
图 S05-02|查询结果与正式提交之间可能发生的另一项预约

小叶第一次拿到“可用”,描述的是查询所依据的当前安排。这个查询本身没有为他保留器材。因此,另一位同学随后成功预约,并没有违反查询原本的承诺。小叶再提交时,处理方根据已经变化的有效记录返回冲突,也可能是正确行为。

从前到后,两个结果看起来不同,但回答的问题及所处时点也不同:查询回答“现在查到什么”,提交回答“现在能否建立这项预约”。若把前者解释成“无论接下来发生什么,这件器材都已为我保留”,才会把没有承诺的保证加到查询之上。

页面因此可以把查询结果写成“当前可预约,提交时再次确认”,并在提交回复前保留等待状态。收到正式成功后显示预约详情;收到冲突则说明所选时段已不可用,并让小叶重新选择。这样安排不是掩饰系统错误,而是让页面表现符合它真正取得的信息。

有人可能提出,把查询按钮和提交按钮放得近一点,就能避免这个问题。操作更快或许会缩短两次动作之间的间隔,却没有阻止另一项申请在其间生效。若任务要求的是确定保留,需要改变实际操作及其承诺,例如另设有明确有效期的临时保留能力;按钮位置本身不能替代它。

即使省掉前面的查询,直接提交也仍需要处理竞争。假设两个申请几乎同时进入,两个处理过程都先读到了空闲,又各自写入一条生效预约,就会违背“同一件器材的重叠时段不重复接受”的约定。仅仅在代码里出现一次“检查可用”,不足以证明并发时这个约定得到满足。

这里可以认识原子性的一项用途:某些相互依赖的判断和状态变化,需要作为受保护的整体完成,不能让竞争操作利用中间空隙得到互相冲突的成功结果。具体可以采用哪种存储和并发控制办法,要根据实现决定;本章先把对外必须保持的结果说清。

这不表示小叶必须先掌握所有并发算法才能让 AI 做预约工具。他已经能够提出一项有内容的检查要求:“让两个申请竞争同一件器材的重叠时段,检查有效记录和返回结果,不能两项都被接受。”实现者再说明用什么办法保证,以及测试实际观察到了什么。

查询与提交的区别还可以迁移到其他场景:看到某个文件存在不等于稍后读取时仍在,看到一批任务尚未被领取不等于已经分配给自己。每当一个查询结果将被用来支持后续修改,都应问清它描述哪个时点,以及修改发生时还需要确认哪些条件。

七、没有结果、明确拒绝和结果未知,需要不同的处理

小叶准备给页面增加提示。此时他遇到三个看似都没有预约详情的情况:查询完整执行后没有找到可用器材;提交申请后被明确告知时间冲突;提交后一直没有收到答复。它们不能统一写成“操作失败,请重试”。

先看空结果。假如一次查询的目标是列出某时段所有符合条件的器材,处理方已经完成查询,确实没有匹配项,可以返回这样的示意内容。

可复制模板
{
  "status": "ok",
  "items": []
}

空列表表示本次查询没有找到符合条件的项目,查询工作本身可以已经正确完成。页面可以说明当前条件下没有可用器材,让小叶换时间或改变选择。这与“没有成功读取器材记录,因此不知道有什么”是不同状态。

如果一次查询只完成了一部分,却把暂时没拿到的其他结果都省略,仍返回普通的空列表,调用者就会把不完整观察当成确定的没有。若产品支持部分结果,应给出相应含义;如果不支持,就应返回明确的查询错误。缺信息不能悄悄冒充业务事实。

再看明确拒绝。本例中,conflict可以表示处理方已经确认时段冲突,并且没有为本次申请新增预约;invalid_input表示字段或时间不符合约定;not_eligible表示当前申请身份不满足借用资格。具体标签可以由团队决定,但每种标签的事实依据和状态作用必须一致。

为什么值得区分这些原因?因为页面接下来的动作不同。缺少结束时间,应让小叶补充;时间冲突,可以提供重新选择;资格不符,则不能承诺随便多点几次就会成功。错误信息的作用是让调用者知道发生了什么、能做什么,而不仅是给程序员看一串代码。

最后是结果未知。请求发出后没有收到回复,可能是它根本没有到达,也可能是处理方已经保存预约,只是成功回复没有回来。仅凭页面等待超时,无法确定记录究竟有没有生效。这是调用者目前掌握的信息不足,不是一份服务端已经作出的拒绝判决。

因此,“明确拒绝且未建立预约”与“未收到回复,不知道是否建立”需要分开。前者可以支持重新选择或纠正输入;后者需要按约定查清原申请,或使用有保证的重发办法。如果直接换一个新请求再提交,可能把同一意图变成一项全新操作。

开头那个“成功只是收到请求”的问题,也可以放在这里判断。若接口只完成受理,便应返回待处理的含义,并给出以后怎样取得最终状态的办法。若当前契约承诺直接返回已经生效的结果,就不能为了省去等待而悄悄把受理改名为成功。要改变的是双方的合作方式,页面和后续流程都应跟着调整。

八、重复发送同一申请,需要怎样的约定

现在回到req-041成功建立R208的情形,另外假设成功回复没有到达小叶的页面。他看到的仍是等待,处理方保存的预约却已经生效。小叶再次发送时,怎样避免把它当成另一次预约意图?

这里会用到幂等性。在本章的操作场景中,它关注的是:同一项请求重复执行,不会因为重复次数增加而产生额外的业务作用。例如,重发已经处理的申请,不应再建立第二条预约。每次返回的文字是否逐字相同,是另一项需要分别约定的事情。

只有重复请求看起来一样,还不足以定义“同一项”。同一个人可能先取消预约,随后真的重新申请;也可能只是因为未收到回复而重发。若只靠器材和时间相同就把所有请求合并,便可能把不同意图混在一起。

因此,本例让调用方为一次申请分配req-041,并在重发这次申请时继续使用它。提供方把已识别的调用者、请求标识及当时参数共同对应起来。新的预约意图使用新的标识;重发原申请保留原标识,不能每点一次重试就生成一个新号。

我们为这个教学工具再定一个范围:从服务端首次受理起,至少24小时内保存这次申请的调用者、请求标识、原参数和处理结果之间的对应关系。在这个保留期内,同一调用者用req-041和原参数重发已经成功的申请,系统不新增预约,而是让结果仍关联R208,并说明这条预约的当前状态。这里的24小时是本例约定,不是所有软件的统一期限。

如果这两次发送之间没有取消或修改,页面就可以再次取得R208仍已生效的信息,知道此前那次申请已经成功。如果期间R208被正式取消,重发旧请求也不应把取消撤销,或单凭旧成功回复让页面误以为器材仍被占用。对历史处理结果与当前业务状态的关系,也需要在接口中说明。

还有一个容易忽视的分支:小叶把申请从14:00至16:00改成15:00至17:00,却继续使用req-041。系统若只看编号就返回原来的R208,会让他误以为新时段也被接受;若把它当新申请保存,又破坏了重复标识的含义。当前可以约定,对同一标识但参数不同的请求,明确返回参数不一致,不修改原预约。

若小叶确实想改变预约,应走工具支持的修改流程,或者取消后以新的申请标识重新申请;具体采用哪种方式由产品要求决定。关键是别让“同一项请求”的标识同时表示原先要求和新的要求,仍期待双方自动猜中。

AWS关于幂等API的工程文章讨论过调用者请求标识、重复副作用、参数变化和保留期这些问题。我们借此理解一种合作约定,不需要为本章使用云服务,也不把某个平台的具体实现当作当前工具已经具有的能力。

增加一个request_id字段本身不会自动完成幂等性。提供方还需要让识别请求、保存作用和记录对应可靠地配合,不能预约已经建立,却忘记它属于哪次请求;也不能两个同时到达的重复请求都被当成第一次。调用方则必须按约定保留标识和参数。两边的责任实际接通,这项保证才成立。

超过保留期、无法查清旧请求、或者服务端根本没有提供这种保证时,页面不能据“理论上可以幂等”就无限自动重试。应按真实支持的查询或恢复办法继续处理,并保留结果尚未确认这一事实。重试间隔、恢复和持久化怎样具体实现,下一章再展开;本章先明确重发到底被允许依靠什么。

九、约定留出选择空间,变化时仍要照顾原有使用者

接口约定需要足够明确,却不一定把每个结果固定成唯一形式。只要使用者所需的保证已经给足,提供者可以保留有用的选择空间。MIT关于规格设计的课程也讨论了允许多种合法结果,以及改变约定时如何看待已有调用者的问题。

例如,在另一次尚未提交预约的查询情景里,符合条件的投影仪有Q17和Q21。若接口承诺返回全部匹配器材,但没有承诺排序,那么先列Q17或先列Q21都可以符合这份约定。页面可以展示这个集合,却没有依据直接把第一项标成“系统最推荐”。

如果小叶的使用目标确实需要优先推荐,就应进一步明确按什么推荐:距离最近、领取方便,还是某种规格更合适。这个要求涉及排序含义,应进入相应约定;如果只是页面想让显示稳定,也可以由页面按明确规则排列,不必让查询接口替它承担所有展示决定。

这里的区别是,允许多种合法结果可以给实现者自由,但不能省掉使用者完成任务必需的含义。省略了必要规则,不叫灵活;规定了没人依靠的内部步骤,也不会自动让接口更好。小叶需要从实际调用方式判断哪一种信息值得承诺。

再看接口变化。兼容性关心的是:已有调用者按原先允许的方式使用时,是否还能得到原来承诺的结果和作用。函数名没换、字段还是字符串,并不足以回答这个问题。

假设预约入口原本只需要已经识别的身份、器材、时间和请求标识,后来突然要求每次还必须提供一个新的部门编号。旧页面没有发送这项信息,原本有效的调用就可能被拒绝。即使新增字段很合理,也需要安排调用者怎样跟上,不能把“只是多一项信息”当成没有影响。

反过来,假如入口增加一种允许的时间输入格式,同时继续正确接收旧格式,且对旧请求仍给出原来承诺的结果,那么旧调用者可能不必改变。判断依据是原先有效的调用与保证得到了保留,而不是字段数量增加或减少。

输出变化也可能改变行为。原来的成功明确表示预约已生效,后来新增“待审核”,并把它也放进页面原先按成功处理的分支,旧页面便可能提前告诉同学器材已留好。这不是增加一点描述文字,而是改变了调用者可以据此采取的行动。

即使只新增一个看似可选的展示字段,也应看真实调用者怎样处理它。有的接收方允许忽略陌生字段,有的却要求收到的字段集合完全一致。前一种可能平稳继续,后一种可能报错。判断兼容性需要约定与实际使用证据,不能把“加字段通常没事”写成无条件规律。

小叶还可能发现,有些旧页面依赖了从未承诺的顺序,例如一直把查询第一项当作推荐。这说明调用方需要修正,但并不意味着可以完全忽略正在使用的产品。先识别这种依赖,再决定更新页面、补充必要排序约定或安排过渡,才能让用户的任务继续完成。

一份接口契约因此也是修改时的比较基准:哪些输入过去有效,哪些结果过去有明确含义,哪些作用一直被依靠。AI 提出“优化一下返回格式”时,小叶可以要求它按这些具体关系解释影响,而不是只看新格式是否更整齐。

十、用同一份约定协作,再用真实交接核对

现在,小叶可以重新安排最初的分工。他不必先独自写完全部代码,而是先拿Q17这项预约,把双方已经说清的约定放在同一处,附上成功、冲突、输入错误和等待未决的例子。页面与预约处理部分都以这份材料为共同依据。

页面任务可以具体到:收集同一天的起止时间并显示选择;提交后先进入等待;只有收到与本次请求对应、表示已经生效的结果才显示预约成功;明确拒绝时说明原因;尚未知道结果时,按提供的查找或重发约定继续处理。这里每一种页面表现都有对应事实。

预约处理任务则是:检查交来信息的含义与规则;根据处理时的身份资格和器材安排决定结果;成功时建立可查询、会参与冲突判断的有效记录;明确拒绝时不留下本次的新预约;重复请求按约定保持同一作用及正确对应。它并不需要知道页面按钮摆在哪一边。

两边可以先独立工作。例如,页面开发时使用一个测试替身,也就是暂时代替真实预约部分、可以按需要提供特定结果的简单程序。让它分别返回成功、冲突和迟迟没有结果,便能观察页面是否进入正确状态,不必等整个后台写完。

但这个替身承担的是特定检查。它能帮助确认“页面收到这种信息会怎样做”,不能证明真实预约记录已经保存,也不能证明两个竞争申请不会都成功。若替身永远返回reserved,页面演示再流畅,也只覆盖了一种事先安排的返回情景。

预约部分同样可以先围绕约定检查自己:合法且可借的申请是否建立记录,正好相接是否按现行边界处理,重叠时是否明确拒绝,重复请求是否仍指向同一项作用。这些例子来自已经说明的行为要求,不能只照着当前代码会返回什么来写预期。

两边接在一起以后,还需要完成一次真实交接。提交Q17及相应时间,核对返回对象与请求对应,再按返回编号查询记录,并查看下一项冲突申请会得到什么。页面显示、返回内容和实际记录共同对应,才支持预约成功这一结论。

如果检查失败,约定能够帮助定位修复责任。页面发送的时间没有遵守共同格式,先查调用侧的转换;处理方已接受清楚的请求却返回了另一件器材,查提供侧的对象对应;双方对“已经受理”都各有合理解释,则先修共同约定,再调整相关代码。不同原因需要不同动作。

这也是使用AI时值得形成的习惯:先让它面对一项明确交接和几种可判断的情景,再要求它说明自己的实现怎样满足约定。AI 写出的说明可以帮助检查,但最后仍要与实际输入、返回和状态变化核对。文字声称“已支持幂等”与两次请求没有产生重复作用,是不同证据。

十一、把这次预约写成一份真正能用的小约定

回到小叶的工具,现在可以把主要决定收在一张表里。它不是任何项目通用的完整模板,而是本章已经逐步讲清的这项预约交接。

约定内容 当前器材工具怎样解释
申请对象 一次申请预约一件具体器材,在同一天的一个时间段使用;调用身份已识别
时间范围 开始早于结束,开始计入占用、结束释放;当前规则不加交接缓冲
查询含义 表示查询所依据时点的匹配情况,本身不为申请者保留器材
成功含义 预约记录已生效,可以查询,并进入后续冲突判断;回复与本次对象、时间、请求标识对应
明确拒绝 说明对应原因,并且没有为这次申请建立新预约
未收到答复 调用者还不能确定处理结果,使用约定的查找或重发办法确认
已成功请求的重发 同一调用者、标识和参数,在规定保留期内不新增预约,关联原预约并说明当前状态
并发要求 竞争同一器材重叠时段的申请,不能同时成为互相冲突的有效预约

凭这些决定,开头的两件事便能分别判断。若处理方只收到了请求,没有让预约生效,页面就不能显示已经预约到;应修正返回含义或页面对含义的使用。若查询以后另一项申请先占用了器材,提交被拒不必然是错误,页面应把查询提示和正式结果分开。

接下来先做一项小规模的真实验证:用一件器材和一个时段,从提交走到查询已生效记录,再检查竞争申请与重复发送的结果。普通路径和会改变判断的分支都能对应共同约定以后,再扩展更多器材、跨日预约或管理员审核。新增功能带来的含义变化也有了可以比较的依据。

接口与协作约定给小叶的,不是一套必须先背完才能行动的术语,而是一种让合作逐步变得可靠的办法:交接时说清对方能依靠什么,修改时保留或明确调整这些依靠,验证时找到与承诺对应的实际结果。这样,AI 更快生成的各个部分才有机会共同完成一件明确的事。

练习与参考分析

练习一:已有编号,是否就能显示预约成功

处理方收到小叶的申请后,先给出一个“受理编号”,并说明稍后还需核对器材安排。页面看到有编号,就显示“已预约到Q17”。后来处理方返回冲突。问题一定在后面的冲突判断吗?应怎样修改交接?

**参考分析:**受理编号识别的是一项已经接收的申请,并不证明预约已生效。题面明确还要核对器材安排,因此页面把“已受理”扩大成“已预约到”,缺少所需依据。后来的冲突可能是正确结果,不能只因为它与页面先前显示不同就认定判断出错。

应让页面按实际收到的含义显示待处理,并明确通过什么方式取得最终结果。最终成功需要对应已生效预约,拒绝则显示原因。如果团队要改成一次调用直接返回最终处理结果,也需要双方共同调整,不能只把字段改名而保留原来含义。核对重点是编号代表什么、哪些作用已发生,不是编号看起来是否完整。

练习二:没有匹配项,还是没有查到完整数据

一次查询本应查看全部可借投影仪。处理方只读到了部分记录,其他记录读取失败,于是返回status为ok、items为空列表。页面据此提示“所有投影仪均不可借”。这个结果是否足以支持页面结论?

**参考分析:**不足。部分记录读取失败意味着缺少一些信息,不能据此证明那些器材都不符合条件。普通空结果的含义是查询已按约定完成却没有匹配项,当前行为并未满足这一前提。页面虽然按既定空列表含义显示,提供方交出的结果却没有兑现该含义。

若当前接口不支持部分结果,应明确返回查询未完成或查询错误;若产品需要使用部分结果,则要同时说明范围和缺失情况,让页面能够避免作出“全部没有”的判断。不能让调用者仅靠猜测“也许空列表表示断网”来补救。这里先修结果含义与已完成工作的对应,再决定如何恢复读取。

练习三:调整排序以后,谁的约定出了问题

器材查询一直承诺返回全部匹配项,没有承诺优先次序。某页面把第一项自动标为“最适合你的器材”。后来查询部分改变内部读取顺序,匹配集合未变,页面推荐却换了。是否应直接要求恢复旧顺序?

**参考分析:**匹配集合未变、顺序没有被承诺,因此不能只据第一项改变认定查询违约。页面把位置解释成推荐,使用了接口没有提供的含义。恢复旧顺序可能暂时恢复原来的显示,却没有说明为什么第一项最适合,也没有形成可靠合作依据。

应先明确产品是否真的需要推荐及其标准。需要时,可以提供有清楚规则的排序或推荐能力;只需稳定显示时,页面也可自行排序。与此同时,已有页面的实际错误仍要处理,不能因为查询方没有违反书面约定就放任错误推荐。修复应同时考虑约定与正在发生的使用行为。

练习四:新增准备间隔后,16:00能否继续接下一项

原规则允许Q17在14:00至16:00的预约结束后,下一项从16:00开始。现在管理员决定,每次使用结束后必须留出15分钟检查器材。有人说只需把页面说明换掉,接口输入输出都没有改,所以处理逻辑和边界例子无需检查。怎样判断?

**参考分析:**新要求改变了器材什么时候重新可用。若14:00至16:00仍表示用户占用时段,另加的检查阶段延伸到16:15,那么紧接的16:00申请不再符合这条新规则;从16:15开始才不占用本次准备阶段。这里另设的是实际使用政策变化,不能继续沿用原来“结束即释放”的含义,却声称两套判断都来自同一规则。

应共同确定用户时间是否包含准备阶段、已有预约怎样处理、哪些入口显示和检查这一限制,再更新对应例子与实际处理。只改说明不改冲突判断,可能继续接受违反新规则的安排;只改内部判断不说明,页面又可能继续给出错误期待。至于既有记录是否需要改动,题面尚未给过渡政策,应先明确,不能自动全部取消。

练习五:重发返回已取消,是否破坏了幂等性

req-041成功建立R208,随后小叶正式取消R208。在约定的请求信息保留期内,旧页面重发相同标识和参数。系统没有新建预约,返回R208当前已取消。有人认为第一次返回已生效、这次返回已取消,结果不同,说明不幂等。这个判断成立吗?

**参考分析:**不能仅凭返回文字不同得出不幂等。需要检查重复发送是否又产生了不应出现的业务作用,以及回复是否符合当前契约。题面中旧请求没有重新建立预约,也没有撤销取消;返回的仍是同一条R208,只是它的当前状态已由正式取消操作改变。这符合本章关于关联原预约并说明当前状态的约定。

若系统为了让回复逐字相同,继续返回旧的已生效状态并让页面当成当前结果,反而会掩盖实际取消。也不能为凑第一次的结果而重新创建预约。这里要分清重发原请求、另一次正式取消、当前状态查询三者的关系,而不是把幂等简单等同为所有可见文字永远一样。

练习六:页面与替身都通过,预约能力是否已完成

页面连接测试替身后,能显示R208、Q17及正确时间。真实处理部分也能返回同样的JSON。但查询预约记录时找不到R208,另一个重叠申请仍被接受。团队认为双方返回格式都通过检查,可以先登记预约功能完成。这个结论缺什么证据?

**参考分析:**格式检查与页面替身检查只支持相应范围:字段能否读取,页面能否根据给定结果显示。当前契约还承诺预约已生效、能够查询并参与后续冲突判断。找不到记录、重叠申请仍被接受,已经给出这些作用没有接通的失败证据,不能按已完成放行。

应沿实际提交、保存、查询与冲突判断追踪,找出成功回复与有效记录脱节的位置。修复以后,再用真正接入的组件检查返回对象、记录内容及下一项申请的行为。这里没有必要先全面重写页面;应依据已经观察到的缺口决定范围。也不能把测试替身改成永远返回更漂亮的成功详情,当成实际记录已经建立的替代证据。