iT邦幫忙

2026 iThome 鐵人賽

DAY 9
0

「他們兩個很熟」翻譯成工程語言是:這條介面的唯一一份規格書,存放在兩個人的交情裡——不可備份,也不可轉讓。


十秒鐘的介面會議

昨天結尾問了一個問題:需求沒寫清楚,可以靠一個人腦補;那兩個團隊之間的介面呢?今天就來看介面。案例照舊經過去識別化與合併改寫。

某個系統整合案裡有兩個子系統,一個管訂單,一個管帳務,分屬兩個團隊。每次改版,兩邊都要對介接的資料格式做調整。

照理說,這叫跨團隊介面變更,該有一場會、一頁定義、一次雙方確認。

實際上,它是一段十秒鐘的茶水間對話。訂單那邊的資深工程師,遇到帳務那邊的資深工程師——兩人是老戰友,從上上個案子一路打仗到現在:

「這次欄位跟上次一樣?」

「一樣,多一個 status。」

「行。」

會議結束。沒有文件,沒有範例,沒有錯誤格式,沒有時區、重送、空值的討論。

兩週後聯調,一次就通。PM 在週報上寫:「整合順利。」

年底,帳務那邊的資深工程師調往其他部門。

下一次改版,接手的工程師問了一句:「我們跟訂單那邊的介面文件在哪?」得到的答案是:「沒有欸,以前都是他們兩個講一講。」

於是他做了這個處境下唯一能做的事:翻程式碼,照上一版的樣子推測。訂單那邊也一樣,照著「上次的印象」改。

兩邊各改各的。聯調當天,資料對不上。

status 這邊當成三種值寫死了對應,那邊上一版已經悄悄加了第四種;時間欄位一邊帶時區、一邊不帶;對方重送的時候要不要擋重複,兩邊都以為是對方的事。

聯調炸了三天。兩邊都確定自己沒改壞,所以都確定是對方改壞的。

第三天,有人想起那句「以前都是他們兩個講一講」,打了通電話,把調走的那位請回來。他站在白板前講了二十分鐘,把當年談定的約定重講一遍——兩邊這才發現,自己手上的「印象」各缺了不一樣的角。

當天傍晚,介面通了。事後檢討,結論是:「交接不確實。」

注意這兩次的記帳方式。十秒對話換來一次就通,週報上叫「整合順利」;三天聯調換來一片狼藉,檢討會上叫「交接不確實」。兩個結論都沒提到同一件事實:

這條介面,從頭到尾沒有被定義過。


當時團隊怎麼理解這件事

當時兩個團隊的共識大概是:他們兩個那麼熟,開介面會議是浪費彼此時間;介面文件寫了也會過期,要看就看 code,code 不會騙人;我們敏捷,重視的是人與人的互動,不是流程與文件;而且事實勝於雄辯——一次就通,默契就是最好的介面管理。

每一句單獨看都有幾分道理。合在一起,它們把一份工程契約,換成了一段私人交情。

出事之後的解讀也很一致:「新人還不熟。」你可能發現了,這跟昨天那句「還好有他在」是同一種句型——把結構問題,讀成個人問題。


契約是寫給不熟的人看的

先替那段十秒對話平反:它的資訊量其實非常大。

「跟上次一樣」五個字,引用的是兩人多年合作累積出來的完整介面規格——每個欄位、每個狀態值的意義、出錯時的行為、誰該擋重複。這五個字是一個指標,指向只存在兩顆腦袋裡的共享記憶。要解開這個指標,兩個人都得在場。

所以那不是「沒有介面定義」。定義一直都在,而且相當精確。問題出在儲存位置。

換句話說,他們不是不寫契約。他們是用交情把契約內化了,內化到看起來不需要契約。

這就是為什麼「熟人合作不用契約」是一個危險的觀察:它是真的,但它推不出「契約沒有用」。介面契約(Interface Contract)本來就不是寫給熟人看的。

契約的意義,是讓不熟的人也能正確合作。

Waterfall 對這件事的處理很直白:介面定義是設計階段的產物,兩個團隊動工之前,交界處長什麼樣要先寫下來、凍結,要改就走 Change——因為 Predictive 的承諾是估算出來的,而交界沒定義,兩邊的估算就是兩份互相矛盾的猜測。

Agile 把它變輕,但沒有把它豁免:一頁 schema、一組雙方都跑得動的範例、一份跟著版本走的變更紀錄,形式隨你選。Individuals and interactions 的意思是「用對話把契約談出來」,不是「用交情把契約收進腦袋」。

兩套方法沒有任何一套主張:跨團隊的交界,可以只存在兩個人的關係裡。

因為交情這種儲存介質,有三個工程上的致命屬性:不可備份、不可轉讓,而且會隨人事異動自動刪除。


大神腦袋裡藏了什麼

那條介面能順跑好幾年,靠的是兩顆腦袋裡各存了一份規格:

欄位與型別
→ 他記得每個欄位當年為什麼長那樣,
   包括那個永遠是空的保留欄位

語意
→ status 前三種值的意思,是某次事故後兩人在白板前談定的;
   白板當天就擦掉了

錯誤格式
→ 他知道對方收到壞資料會回什麼,
   因為那段防禦寫法是他當年建議的

時序與重試
→ 「對方會重送,所以我這邊要擋重複」——
   這條規則只存在他的程式碼裡,而且沒有註解

版本與變更方式
→ 所謂變更管理,就是改之前打給對方

對照一下等一下的 Artifact 就會發現:最小介面契約需要的五行,一行都沒缺。全部存在,全部精確,全部不在紙上。

於是每次十秒對話,其實是兩份腦內規格在做差異同步——只傳 diff,因為全量版本雙方都有。旁人看到的是默契,實際上是一套高度壓縮、只有兩個人持有解碼器的通訊協定。

年底人事命令一發,解碼器少了一半。剩下那半份規格並沒有錯,只是再也沒有人能完整讀出它。


這次到底誰在吸收代價?

老規矩。這條介面多年沒出事,改版照跑、時程照走,那「跨團隊介面沒有定義」的成本,記在哪一格?

Scope       □   介接範圍一項沒少
Time        □   時程表上從來沒有「介面定義」這項;炸掉的三天記在「聯調」名下
Cost        □   沒有人為此追加預算
Quality     □   這次剛好炸在聯調——算走運,再晚一步就炸在帳務資料上
Risk        □   兩個人的交情是全案最大的單點故障,但風險清單上沒有這一條
人          ■   前期靠兩人的交情撐,後期靠三天聯調加班收   ← 又是這格

值得多看一眼的是「前期」那半句。這一格在爆炸之前就已經是 ■ 了——每一次十秒對話,消耗的都是那兩個人多年累積的共享記憶與信任。那是一種資產,一種從來沒出現在任何報表上的資產。組織用了它很多年,不用付費,也就從來不知道自己在用。

直到資產跟著人事命令一起離開,帳單才第一次寄到。


如果沒有大神,應該留下什麼

不是一份五十頁的介面規格書。是任何兩個團隊的交界處,至少有一頁東西,讓不熟的人拿著它就能正確介接。

判斷標準只有一條:

一個跟兩邊都不熟的工程師,只看這一頁,能不能不打電話就把介面接對?

能,這條介面才算被定義過。不能,那你們擁有的不是介面定義,是兩個人的交情——而交情的問題,我們剛剛才看過。


今日 Artifact|最小介面契約

把那一頁收成五行。任何跨團隊交界動工之前,兩邊一起填:

□ 欄位與型別:收/送哪些欄位、什麼型別、可否為空____
□ 語意:每個關鍵欄位(尤其是狀態值)代表什麼、由哪邊改變它____
□ 錯誤格式:出錯時對方會看到什麼(代碼、格式、一個實際範例)____
□ 時序與重試:誰先誰後、會不會重送、重複收到怎麼辦____
□ 版本與變更方式:現在第幾版、要改先告訴誰、記在哪____

寫在 wiki、repo 裡的一頁 markdown、甚至聯調前貼在群組的一則訊息,都可以。重點不是格式,是這五行從此有了人腦以外的副本。

順帶一提,第五行填「改之前打給某某」也行——至少你誠實面對了現況:這條介面的變更管理,目前建立在一個人的電話號碼上。


今日一句

默契是契約的一種儲存格式:讀取速度極快,但不可備份、不可轉讓,而且會跟著人事異動一起消失。

介面的洞,這次也被交情補完了。但第二部的盤點才過兩天,介面之外,還有一個更常被腦補的東西——一個功能做到什麼程度,算做完?

明天:沒有 Acceptance Criteria,資深工程師知道怎樣算完成。


上一篇
Day 08|需求沒寫清楚沒關係,大神看得懂
下一篇
Day 10|沒有 Acceptance Criteria,資深工程師知道怎樣算完成
系列文
你以為自己很敏捷,其實連瀑布都沒做好——30 天從錯誤承諾、大神救火,到沒有大神也跑得動的開發方法11
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言