在專業環境中,很少有事物比留下持久的印象更重要;無論是建立信任還是傳達未被欣賞的品質,這往往是扼殺任何系統的關鍵:人們對其失去信心。想像一下,看到一個總是出錯的東西;一個利害關係人看到一個失敗的承諾。他們看不到,也無法看到,失敗的功能與其所依賴的基礎之間的區別。對他們來說,系統是單一的;如果任何部分失敗,整個系統都會受到懷疑。這種看法,儘管在技術上很天真,卻會產生技術準確性無法消除的社會壓力。

隨著失敗的累積,壓力不斷增加;必須有人負責,必須採取行動。組織要求的不是根本原因分析或針對性的修復,而是可見的行動、果斷的變革和儀式性的淨化。必須釋放這種緊張感。

接下來發生的事情,與人類社會本身一樣古老:壓力下的群體選擇一個犧牲品,將罪責歸咎於它,最後,犧牲品被摧毀。透過其毀滅,社會凝聚力得以恢復。阿茲特克人將俘虜獻祭在金字塔頂,以確保太陽升起。我們在會議室裡犧牲程式碼庫,以確保專案能夠交付。機制是相同的;只有祭壇改變了。

勒內·吉拉爾觀察到,陷入危機的人類社群經常透過「替罪羊」來解決內部衝突:選擇一個犧牲品來承擔集體罪責,其驅逐能恢復秩序。替罪羊不一定有罪;它只需要是可接受的目標即可。它的罪責是透過敘事建構的,而不是透過調查發現的(參見 [5]、[6])。

然而,一些危險的個人卻將這種儀式化的實踐制度化,我稱之為「Casus Belli 工程學」:利用感知到的失敗作為藉口,用個人偏好的世界觀取代正在運作的系統。故障的功能就是需要解決的危機。基礎架構成為替罪羊,選擇它並非因為它的脆弱性或方便替換,而是因為它方便替換。在大多數情況下,這會自然展開,由對敘事的真實信念所驅動。這些人內心真正是煉金術士;他們有能力操縱持久印象的幻象,為自己謀取利益 [14]。他們不等待危機,而是滋養它。他們不偶然陷入替罪羊,而是精心策劃。他們故意製造「casus belli」(戰爭藉口),利用古老的集體暴力機制,以自己的形象重塑系統。這些不是犯下誠實歸因錯誤的困惑工程師。他們是政治操盤手,發現技術失敗可以轉化為組織權力。

這裡的危險不在於替罪羊本身;人類總是會尋找替罪羊。危險在於那些學會策略性觸發機制的人,那些能夠可靠地將任何失敗轉化為摧毀現有事物並建立他們偏好事物的機會的人。他們是世俗宗教的祭司,他們的儀式比任何技術優勢更能塑造我們的技術格局。

在軟體組織中,這種模式遵循相同的儀式。以下是我對其展開的看法。

當失敗產生緊張感、要求解釋並威脅職業生涯時,組織會選擇一個替罪羊,而不是面對實際原因,這些原因可能涉及最近的決策、現任領導層或系統性功能失調。它必須與失敗有合理的接近性(依賴項、框架、架構模式),無法為自己辯護(因為它陳舊、不時髦,或由已離職的人倡導),並且可以被指控者偏好的事物取代。最後一個標準是關鍵:替罪羊的毀滅必須為指控者的替代方案掃清道路。

一旦選定,替罪羊就會被儀式性地譴責。它的罪責透過重複來確立(「我們不斷遇到 X 的問題」),而實際原因(錯誤處理、測試、營運疏忽)則退居幕後。X 成為問題,X 必須被摧毀。戰爭的聲明目標與其實際目的無關:在失敗的掩護下,用一個範式取代另一個。

這種進程是可預測的。一個功能反覆出現故障,無論是由於與外部系統整合不良、錯誤處理不足還是環境脆弱性,而它恰好依賴於某個功能正常且一直功能正常的基礎組件。失敗並非由基礎架構引起,但基礎架構存在於依賴鏈中,這種鄰近性足以構成起訴。

有人決定基礎組件是「問題」。不是實際的故障來源,而是架構、範式、做事的方式。真正的失敗成為彈藥:「我們不斷遇到 X 的問題」演變成「X 是建立在 Y 之上,而 Y 是問題所在」,而實際原因(外部依賴項、測試不足、錯誤處理差距)則被指責整個基礎架構的敘事所掩蓋。

提出了一個替代方案,並且它以可疑的精確度與提出者的偏好技術、方法論或架構信念一致。然後,故障的功能及其正常運作的基礎架構一起被拋棄;故障的功能追溯性地「證明」了基礎架構一直以來都是錯誤的,而基礎架構功能正常的這一事實被認為不相關,是「錯誤的方法」。

吉拉爾確定了替罪羊的三個先決條件:危機、無差別的競爭和集體模仿。軟體組織具備這三者(參見 [5]、[6])。危機是故障的功能、生產事件、客戶升級;是某件東西明顯失敗並要求問責的事情。無差別的競爭是多個工程師或同等地位的團隊爭奪影響力的熟悉狀況,沒有既定的權威來指導技術方向,許多意見並存而沒有決定性的力量。集體模仿是框架的傳播:一旦有人宣稱基礎架構是「問題」,其他人就會模仿這種判斷,懷疑會轉化為共識,最初是一個人的觀點會固化為組織的真理。

進入這個環境的是霍根、凱撒及其同事在黑暗面領導力文獻中廣泛記錄的一種人格特質(參見 [7]、[8]、[9]、[10])。這些人以敘事連貫性取代因果分析;他們不追溯失敗的機制,而是接受最能說服人的解釋,將相關性視為因果關係,不是因為他們不知道區別,而是因為他們不具備也不重視其所需的嚴謹性。他們同時高度投入、深度參與結果、聲音洪亮且堅韌不拔,賦予敘事一種力量,確保其被推動,直到成為正統。他們在技術上缺乏安全感,需要外部認可:他們無法僅憑優勢提出自己偏好的解決方案,而必須先使現有方法失去合法性,將倡導轉化為起訴。

這種特質非常適合啟動替罪羊機制,結合了識別目標的動機、建構敘事的修辭能力以及將犧牲進行到底的心理衝動。不安全感將單純的倡導轉化為破壞:替罪羊必須死亡,以便指控者的世界觀能夠被奉為解決方案。

精確地說,問題不在於迭代或增量開發本身。這些想法比敏捷更古老,已經確立,並且在技術上是合理的;對 IID 的明確倡導出現在敏捷品牌出現幾十年前,在主流軟體工程文獻中,認為大型專案設計必須逐步進行,因為需求永遠不會一次性完成(參見 [1]、[2])。

問題在於運動規模上發生的事情:敏捷論述成為軟體歷史上最成功的 Casus Belli 開發實例之一,吉拉爾式的替罪羊行為以工業規模進行。

危機足夠真實:軟體專案失敗、超預算、超進度、需求錯誤、品質低劣。替罪羊是「瀑布模型」、「重量級流程」、「前期設計」、「全面文件」,這些實踐被捆綁在一起並賦予一個集體名稱,以便進行儀式性譴責。

其巧妙之處在於選擇。「瀑布模型」這個詞很大程度上是一個稻草人;很少有組織實踐漫畫中所描述的純粹的循序開發。即使是 1970 年的 Royce 論文,通常被引用為瀑布模型的起源,也包含明確的迭代和回饋循環,而不是嚴格的單次排序(參見 [3])。但這個標籤足夠合理(專案確實失敗了,存在文件標準,存在階段門),這種合理性就足夠了。背景不如修辭的效用重要。社會壓力已經累積;敘事需要一個有罪的名字和一個淨化的替代方案。

Ron Garret 在另一個領域闡述了相同的動態。在他對 JPL 的 Lisp 描述中,這個詞本身變得無法言說,無論它所代表的技術優勢如何,這是一個術語而非想法成為替罪羊機制真正犧牲品的例子:

「看到這一切發生真是令人沮喪。我今天的工作(我現在從事軟體驗證和確認)是解決可以直接追溯到使用語義定義不清的純粹命令式語言(如 C 和 C++)的問題。(Java 的情況稍微好一些,但也好不了多少。)但是,當然,顯而易見的解決方案(使用語義定義良好的非命令式語言,如 Lisp)並非選項。我甚至不能說 Lisp 這個詞,而不將我塑造成一個認為 Lisp 是萬能藥的瘋狂的形象。所以我(大部分時間)保持沉默,無助地看著數百萬納稅錢被浪費。(我會寄希望於一波草根對這種明顯浪費金錢的憤怒能夠帶來救援,但可惜的是,在政府項目中經常發生的離譜浪費的規模上,這幾乎微不足道。)」

敏捷宣言為這次犧牲提供了儀式性語言。公平地說,該文件包含一個明確的警告:雙方都有價值,但左側價值更大。字面意思來看,這並非絕對拒絕流程、文件、合約或計劃。問題在於這種語言在社會上是如何運作的。

在實踐中,警告是蒸發的。持續存在的是基於不對稱的口號:

「個體與互動高於流程與工具」成為對流程本身的持續懷疑。

「可工作的軟體高於詳盡的文件」成為長期低估文件價值的藉口,直到知識崩潰為口頭傳統。

「客戶合作高於合約談判」成為將治理和合約紀律視為反客戶官僚主義的方式。

「響應變化高於遵循計劃」成為將計劃視為天真的修辭許可,即使嚴謹的計劃正是使適應變得連貫的原因。

問題不在於宣言文本逐字逐句地荒謬。問題在於它在修辭上是為運動政治而設計的:道德上清晰易懂,易於傳播,並且難以反對,否則聽起來就像倒退。每一對都提供了一個可重複使用的反派類別(「流程」、「文件」、「合約」、「計劃」)和一個現成的道德身份來代表替代方案。這就是為什麼即使底層工程思想已經為人所知(參見 [1]、[2]、[4]),它仍然能夠作為敘事力量擴展。

宣言並未發明迭代思維。它提供了一個「casus belli」,允許透過將現有流程框架化為失敗的根源來取代它們。實際問題(需求收集不當、客戶訪問不足、測試不足、計劃不切實際、管理功能失調)未得到解決。「瀑布模型」成為替罪羊,其毀滅成為解決方案。

敏捷在運動規模上的成功,並非因為它引入了前所未有的工程思想,而是因為它以非凡的忠實度執行了替罪羊機制:識別出一個看似合理的敵人,建構其罪責,並在同一姿態中提供救贖。事實上,「新」核心很大程度上是對現有迭代實踐的重新品牌化是無關緊要的(參見 [1]、[2]、[4])。儀式完成,替罪羊被吞噬,敘事取得勝利。

Casus Belli 開發以特別有效的方式利用了認知偏差和組織動態。最近的失敗生動且顯著,而基礎架構多年來正常運作的歷史則抽象且被遺忘;可用性偏差將事件變成「系統性缺陷」的「證據」。一旦有人得出結論認為基礎架構有缺陷,確認偏差就會確保後續的每一個問題都成為佐證;成功被認為是「儘管」基礎架構存在而發生的,而失敗則被視為固有缺陷的證據。狀態偏見,通常是一種保守的力量,一旦狀態被框架為「失敗」,就會反轉:事件證明了失敗,因此基礎架構必須被替換。在低信任的環境中,權威加劇了這種影響:反覆聲稱基礎架構有問題,取代了獨立調查,共識被誤認為真理(參見 [11]、[12])。最後,替換提供了一種逃避維修所要求的沉沒成本對抗的方式;人們不是在「修復錯誤」,而是在「採用更好的實踐」,將撤退重新定義為進步。

後果是重大且不斷累積的。經過驗證的基礎架構,可靠運作並體現了多年機構完善的系統,被拆除,因為它們鄰近於一次失敗,組織在這個過程中放棄了積累的知識和經過實戰考驗的解決方案。根本原因依然存在:故障的實際來源(不良的錯誤處理、測試不足、環境脆弱性)在轉換過程中完好無損,並將在替代方案中再次出現,因為它們從未被面對。

每隔幾年,一個新的事件就會提供一個新的「casus belli」,循環往復:基礎架構被替換,然後再次被替換,沒有什麼能夠穩定下來,因為對於從動盪中獲利的人來說,穩定與停滯無異。當替代方案未能解決它們聲稱要解決的問題時,信心會進一步惡化,但組織並沒有認識到這種模式,而是指責新的基礎架構並開始尋找下一個。與此同時,理解因果關係、能夠區分相關性與機制的工程師們感到沮喪並離開。剩下的是那些擅長將政治操縱偽裝成技術領導力的人。

Casus Belli 開發透過幾個標誌暴露了自己。提議解決方案的範圍超出了問題的範圍:一個因外部 API 超時而失敗的功能,並不一定需要用另一種語言重寫整個服務層,當補救措施遠遠超過疾病時,就應該審查其潛在動機。失敗被用來指責一個範式而不是一個特定的實現(「這個 OOP 程式碼難以維護」變成「OOP 是問題所在」,「這個微服務難以調試」變成「微服務是個錯誤」),這種從特定到一般的飛躍正是「casus belli」運作的地方。提議的替代方案以可疑的精確度與提出者的偏好一致;如果一直倡導 GraphQL 的人突然認為 REST API 的失敗證明了 REST 本質上有缺陷,那麼就應該懷疑。實際的根本原因沒有得到嚴格分析:調查終止於「X 是建立在 Y 之上,因此 Y 是錯誤的」,而不是繼續到「X 因 Z 而失敗,這與 Y 無關」。並且,修辭強調革命而非演進,「我們需要徹底重新思考我們如何做 X」而不是「我們需要修復 X 中這個特定的缺陷」。革命性修辭是診斷性的;它表明目標是替換,而不是修復。

抵抗需要自身的紀律。堅持根本原因分析:不是「系統有缺陷」,而是「這個特定的調用在這種特定的條件下失敗」;因果關係,而非相關性。將失敗與基礎架構分開,並詢問是否可以在不替換基礎架構的情況下修復失敗;如果可以,則替換的討論為時過早。要求提議解決已識別的原因,而不是僅僅將它們轉移到另一個層級。根據內在價值評估提議的替代方案,而不是將它們視為「失敗」前任的救星,因為新的方法必須依靠自身的價值,而不是從摧毀先前的事物中獲得合法性。並關注其中運作的心理模式:這個人是在尋求驗證自己的世界觀,而不是解決問題嗎?動機很重要(參見 [8]、[9]、[10])。

誠實倡導迭代開發會是什麼樣子?它會說:「我們發現,透過頻繁的客戶回饋進行迭代開發可以減少需求不匹配。這裡有案例研究。這裡有測量結果。我們建議採用這些實踐。」相反,我們得到的是:「傳統開發是破碎的。它重視流程而非人。它產生文件而不是可工作的軟體。我們建議採用一種新範式。」

前者是工程論證。後者是「casus belli」。前者可能導致對實質上已經知道的實踐的審慎採用。後者導致了開發方法論的全面替換為「敏捷」框架,這些框架經常保留了它們聲稱要取代的事物的最糟糕屬性(僵化的流程,現在稱為「儀式」;詳盡的文件,現在稱為「待辦事項」;詳細的計劃,現在稱為「衝刺計劃」)。

敏捷的成功並非因為迭代開發在其出現之前就有缺陷,而是因為敏捷品牌為那些渴望範式變革並需要政治上可接受的理由的人提供了一個「casus belli」。宣言提供了這種理由,失敗的專案提供了證據,「瀑布模型」提供了替罪羊,一旦敘事確立,替換就變得不可避免。這就是 Casus Belli 開發在規模上運作的方式。

吉拉爾指出,替罪羊需要集體失明;社群在機制運作時不能認識到它。一旦替罪羊被視為它本來的樣子,一個無辜的承載者,承載著被投射的罪責,儀式就失去了力量。但只要社群相信替罪羊確實有罪,機制就能完美運作(參見 [6])。

這就是為什麼 Casus Belli 開發得以延續。參與者並不認為自己在執行儀式。他們相信自己正在解決問題,做出合理的技術決策,改進系統。敘事感覺真實,因為周圍的每個人都同意。替罪羊的罪責感覺不證自明,因為它已被無數次斷言。

這種模式得以延續,是因為它成功地達成了它實際完成的事情:釋放組織的緊張感,驗證偏好的世界觀,在技術的掩護下實現政治變革。它未能解決潛在的技術問題,對其作為社會機制的有效性毫無影響(參見 [11]、[12]、[13])。

但一旦你察覺到它,這種感知就是不可逆轉的。下次當一個事件引發更換基礎架構的呼聲時,你將會辨識出其結構:危機、替罪羊、虛假的因果關係、在幕後等待的偏好替代方案、譴責的儀式性語言。

你將面臨一個選擇:參與儀式,還是拒絕它。

拒絕是艱難的。它要求在敘事更具說服力時堅持因果關係,捍衛已被標記為要摧毀的系統,接受那個「不理解」、「抗拒改變」、「固守現狀」的人的角色。

但拒絕是工程學。Casus Belli 開發不是。它是偽裝成工程學的政治,偽裝成分析的儀式,偽裝成解決問題的替罪羊。工程學是對理解實際因果關係的承諾,是對基於證據的針對性補救的承諾,是對嚴謹區分相關性與因果關係的承諾,尤其是在敘事誘人時。

我們應該選擇工程學。尤其是在其他人都已經選擇了敘事的時候。