反面模式

在軟體工程中，反面模式（anti-pattern 或 antipattern）指的是在實踐中經常出現但又低效或是有待最佳化的設計模式，是用來解決問題的帶有共同性的不良方法。它們已經經過研究並分類，以防止日後重蹈覆轍，並能在研發尚未投產的系統時辨認出來。

Andrew Koenig 在 1995 年造了 anti-pattern 這個詞，靈感來自於 GoF 的《設計模式》一書。而這本書則在軟體領域引入了 “設計模式”（design pattern）的概念。三年後 antipattern 因《AntiPatterns》這本書而獲得普及，而它的使用也從軟體設計領域擴充套件到了日常的社會互動中。按《AntiPatterns》作者的說法，可以用至少兩個關鍵因素來把反面模式和不良習慣、錯誤的實踐或糟糕的想法區分開來：

行動、過程和結構中的一些重複出現的乍一看是有益的，但最終得不償失的模式
在實踐中證明且可重複的清晰記錄的重構方案

很多反面模式只相當於是錯誤、咆哮、不可解的問題、或是可能可以避免的糟糕的實踐，它們的名字通常都是一些用反話構成的詞語。有些時候陷阱（pitfalls）或黑色模式（dark patterns）這些不正式的說法會被用來指代各類反覆出現的糟糕的解決方法。因此，一些有爭議的候選的反面模式不會被正式承認。

這個概念很容易推廣到工程學以及工程以外需要人們付出努力去爭取的領域。儘管在工程學以外很少用到這個術語，但其概念是通用的。

舉例

1.1 社會和組織結構

1.1.1 組織結構

分析癱瘓（Analysis paralysis）：花費太多精力在專案的分析階段
腳踏車棚（Bicycle shed）：對於一些不重要的事務花上不成比例的精力
超前沿技術（Bleeding edge，刀鋒）：採用一些未經測試和 / 或尚不穩定的前沿技術來運營，從而導致成本超支、表現 / 效能不佳，和 / 或交付延期。
（cash cow）：假如舊產品的盈利能力強，通常會導致企業沒有動力開發新產品
委員會設計（Design by committee）：很多人同時進行設計，卻沒有統一的看法
承諾升級（Escalation of commitment）：明知錯了還不能收回之前的決定
目標管理（Management by objectives）：透過數字管理，過於關注非本質而或不易取得的數字指標
道德風險（Moral hazard）：不讓做決定的人知道他的決定會帶來什麼結果
蘑菇管理（Mushroom management）：不通知或是錯誤地通知僱員資訊。僱員像蘑菇一樣在黑暗中吸取養分，自生自滅
海鷗管理（Seagull management）：只有當出現問題的時候管理人員才會跟僱員進行接觸和互動的管理模式。典型的場景就是，海鷗式的管理人員 “飛” 過來，嘁嘁喳喳，是人都批評一通，爾後 “飛” 走了！
（Stovepipe or Silos，豎井式 / 發射井式 / 穀倉式管理）：組織結構是由若干彼此孤立的團隊組成，並且整個組織結構的範圍內，上下溝通交流能夠有效進行，而水平 / 橫向的則不然。結構上支援資料主要在上下方面的流動，卻禁止跨部門的通訊。
（Vendor lock-in，供應商套牢，供應商陷阱，廠商泥潭）：使一個系統過於依賴於外部所提供的元件 / 部件。

1.1.2 專案管理

（Death march，死亡之旅）：除了 CEO，每個人都知道這個專案會成為一場災難，但是真相卻被隱瞞下來，以免專案被立即取消。（儘管 CEO 通常知道並且仍然繼續試圖最大化利潤。）然而，真相被隱藏起來，直到大限來臨（"Big Bang"）。另一種定義：僱員由於不合理的 deadline，被迫在深夜和週末加班。
團隊思維（Groupthink）：在團隊思維中，團隊成員避免提出在一致觀點之外的思維。
九九定律（Ninety-ninety rule）：當專案 “幾近完成” 時，低估完成專案所需時間的傾向。
過度設計（Overengineering）：花費資源完成比實際需要的還要複雜的工程
（Smoke and mirrors）：展示還沒實現的功能，就像它們已經實現了一樣

1.1.3 分析方式

旁觀冷漠（Bystander apathy）：一個需求或者設計是錯的，注意到這一點的人卻不指出，因為這影響的是其他人。

1.2 軟體工程

1.2.1 軟體設計

（Abstraction inversion）：不把使用者需要的功能直接提供出來，導致他們要用更上層的函式來重複實現
（Ambiguous viewpoint）：給出一個模型（通常是面向物件分析與設計，面向物件分析與設計）卻沒有指出用意何在
（Big ball of mud）：沒有清晰結構的系統
（Database-as-IPC）：使用資料庫進行程序間通訊，而不使用更輕量級的合適的機制。或者說，對於常規的程序間通訊，不是去採用輕量得多的合適機制，而是將資料庫用作訊息佇列。
（Gold plating）：在專案達到最高價值後還繼續工作。
（Inner-platform effect）：系統可自定義的太多，以至於成為一個軟體開發平臺的蹩腳的複製品。
（Input kludge）：無法確定和實現對異常輸入的處理
（Interface bloat）：把一個介面做得過於強大以至於極其難以實現
（Magic pushbutton）：直接在介面的程式碼裡實作功能，而不維持其抽象性。這可能導致軟體的耦合性增加，彈性與可重覆使用性下降。
競爭風險（Race hazard）：輸出結果受到事件執行順序和時機的影響，在多執行緒環境和分散式系統中可能發生
（Stovepipe system）：過度聚集資料和功能，忽視了與其他系統和模組的共享

1.2.2 面向物件設計

貧血的域模型（Anemic Domain Model）：僅因為每個物件都要有屬性和方法，而在使用域模型的時候沒有加入非 OOP 的業務邏輯
呼叫父類（Call super）：需要子類呼叫父類被重定義的方法
圓還是橢圓問題（Circle-ellipse problem）：基於變數的子類化關係進行子類化
迴圈依賴（Circular dependency）：在物件或軟體模組中，直接或間接引入迴圈依賴。
常量介面（Constant interface）：使用介面定義常量
上帝物件（God object）：在設計的單一部分（某個類）集中了過多的功能
物件糞池（Object cesspool）：複用那些不滿足複用條件的物件。物件池是一種管理物件的方法，在重複使用物件前，需要針對物件進行初始化，以避免上次使用後的狀態等資料影響下次的使用
不羈的物件（Object orgy）：沒有成功封裝物件，外部可以不受限制地訪問它的內部
幽靈（Poltergeists）：指這樣一些物件，它們唯一的作用就是把資訊傳給其它物件
順序耦合（Sequential coupling）：指這樣一些物件，它們的方法必須要按某種特定順序呼叫
悠悠問題（Yo-yo problem）：一個結構（例如繼承）因為過度碎片化而變得難於理解

1.2.3 程式設計

偶然複雜度（Accidental complexity）：向一個方案中引入不必要的複雜度
遠隔作用（Action at distance）：意料之外的在系統分離的部分之間互動
（Boat anchor）：在系統中保留無用的部分
忙等待（Busy waiting）：在等待的時候不斷佔用 CPU，通常是因為採用了重複檢查而不是適當的訊息機制
（Caching failure）：錯誤被修正後忘記把錯誤標誌復位
拜物程式設計（Cargo cult programming）：由於對模式的盲目崇拜，在不理解的情況下就使用模式和方法，企圖得到好的結果
（Coding by exception）：當有特例被發現時才新增新程式碼去解決
（Error hiding）：在顯示給使用者之前捕捉到錯誤資訊，要麼什麼都不顯示，要麼顯示無意義的資訊
硬編碼（Hard code）：將對系統環境的假設寫入實現中
熔岩流（Lava flow）：保留不想要的（冗餘的或是低質量的）程式碼，僅因為除去這些程式碼的代價太高或是會帶來不可預期的結果
（Loop-switch sequence）在迴圈結構中使用 switch 語句來編寫連續步驟
魔術數字（Magic numbers）：在演算法裡直接使用數字，而不解釋含義
（Magic strings）：直接在程式碼裡使用常量字串，例如用來比較，或是作為事件程式碼
自我複製（Repeating yourself）：透過不斷複製已有程式碼的模式或程式碼段進行編碼；而非採用 once and only once（抽取原則）
（Soft code）：在配置檔案裡儲存業務邏輯而不是在程式碼中
麵條程式碼（Spaghetti code）：指那些結構上完全不可理解的系統，尤其是因為誤用程式碼結構
（Shotgun surgery）：開發人員一次性在一個多個實現的程式碼基中增加功能

1.2.4 方法論

（Copy and paste programming）：複製（然後修改）現有的程式碼而不是構造通用的解決方案
（Golden hammer）：認為自己最喜歡的解決方案是到處通用的（參見：銀彈）
（Improbability factor）：認為已知的錯誤不可能發生
非我所創（Not invented here）：拒絕使用組織外的主意或方案，但這也可能是出於版權等原因
（invented here）：拒絕組織內部實現的創新或解決方案，通常因為對成員沒有信心
（Premature optimization）：在編碼的早期追求程式碼的效率，犧牲了好的設計、可維護性、有時甚至是現實世界的效率
（Programming by permutation）：也稱巧合程式設計，試圖透過連續修改程式碼再看是否工作的方式來解決問題
重新發明方的輪子（Reinventing the square wheel）：已經有一個很好的方案了，又再搞一個爛方案來替代它
銀彈（Silver bullet）：認為自己最喜歡的技術方案能解決一個更大的問題
（Tester driven development）：需求來自 bug 報告的軟體工程

1.2.5 配置管理

依賴地獄（Dependency hell）：所依賴產品的版本所導致的問題
DLL 地獄（DLL hell）：不同版本 DLL 所帶來的問題，包括 DLL 可見性和多版本問題，在微軟的 Windows 上尤為突出
（Extension conflict）：蘋果系統在 Mac OS X 版本之前的不同擴充套件的問題
（JAR hell）：JAR 檔案不同版本或路徑帶來的問題，通常是由於不懂類載入模型導致的