反面模式
? ?在軟件工程中瓢姻,一個(gè)反面模式(anti-pattern或antipattern)指的是在實(shí)踐中明顯出現(xiàn)但又低效或是有待優(yōu)化的設(shè)計(jì)模式尝艘,是用來解決問題的帶有共同性的不良方法修己。它們已經(jīng)經(jīng)過研究并分類抡句,以防止日后重蹈覆轍整胃,并能在研發(fā)尚未投產(chǎn)的系統(tǒng)時(shí)辨認(rèn)出來角溃。
? ?Andrew Koenig在1995年造了anti-pattern這個(gè)詞拷获,靈感來自于GoF的《設(shè)計(jì)模式》一書。而這本書則在軟件領(lǐng)域引入了“設(shè)計(jì)模式”(design pattern)的概念减细。三年后antipattern因《AntiPatterns》這本書而獲得普及匆瓜,而它的使用也從軟件設(shè)計(jì)領(lǐng)域擴(kuò)展到了日常的社會(huì)互動(dòng)中。按《AntiPatterns》作者的說法,可以用至少兩個(gè)關(guān)鍵因素來把反面模式和不良習(xí)慣驮吱、錯(cuò)誤的實(shí)踐或糟糕的想法區(qū)分開來:
- 行動(dòng)茧妒、過程和結(jié)構(gòu)中的一些重復(fù)出現(xiàn)的乍一看是有益的,但最終得不償失的模式
- 在實(shí)踐中證明且可重復(fù)的清晰記錄的重構(gòu)方案
? ?很多反面模式只相當(dāng)于是錯(cuò)誤左冬、咆哮桐筏、不可解的問題、或是可能可以避免的糟糕的實(shí)踐拇砰,它們的名字通常都是一些用反話構(gòu)成的詞語梅忌。有些時(shí)候陷阱(pitfalls)或黑色模式(dark patterns)這些不正式的說法會(huì)被用來指代各類反復(fù)出現(xiàn)的糟糕的解決方法。因此除破,一些有爭(zhēng)議的候選的反面模式不會(huì)被正式承認(rèn)牧氮。
? ?這個(gè)概念很容易推廣到工程學(xué)以及工程以外需要人們付出努力去爭(zhēng)取的領(lǐng)域。盡管在工程學(xué)以外很少用到這個(gè)術(shù)語瑰枫,但其概念是通用的踱葛。
舉例
社會(huì)和組織結(jié)構(gòu)
組織結(jié)構(gòu)
從天而降的責(zé)任(Accidental Ownership):雇員們接手了一個(gè)與當(dāng)前系統(tǒng)完全無關(guān)的系統(tǒng),在沒有合適的訓(xùn)練光坝、學(xué)習(xí)或關(guān)心下就得維護(hù)它
分析癱瘓(Analysis paralysis):花費(fèi)太多精力在項(xiàng)目的分析階段
血刃(Bleeding edge尸诽,刀鋒):采用一些未經(jīng)測(cè)試和/或尚不穩(wěn)定的前沿技術(shù)來運(yùn)營,從而導(dǎo)致成本超支教馆、表現(xiàn)/性能不佳逊谋,和/或交付延期。
搖錢樹(cash cow):盈利的老產(chǎn)品通常會(huì)導(dǎo)致對(duì)新產(chǎn)品的自負(fù)
委員會(huì)設(shè)計(jì)(Design by committee):很多人同時(shí)進(jìn)行設(shè)計(jì)土铺,卻沒有統(tǒng)一的看法
承諾升級(jí)(Escalation of commitment):明知錯(cuò)了還不能收回之前的決定
獨(dú)裁管理(Management by perkele):用完全聽不進(jìn)異議的獨(dú)裁作風(fēng)進(jìn)行管理
目標(biāo)管理(Management by objectives):通過數(shù)字管理胶滋,過于關(guān)注非本質(zhì)而或不易取得的數(shù)字指標(biāo)
道德風(fēng)險(xiǎn)(Moral hazard):不讓做決定的人知道他的決定會(huì)帶來什么結(jié)果
蘑菇管理(Mushroom management):不通知或是錯(cuò)誤地通知雇員信息。雇員像蘑菇一樣在黑暗中吸取養(yǎng)分悲敷,自生自滅
海鷗式管理(Seagull management):只有當(dāng)出現(xiàn)問題的時(shí)候管理人員才會(huì)跟雇員進(jìn)行接觸和互動(dòng)的管理模式究恤。典型的場(chǎng)景就是,海鷗式的管理人員“飛”過來后德,嘁嘁喳喳部宿,是人都批評(píng)一通,爾后“飛”走了瓢湃!
煙囪式管理(Stovepipe or Silos理张,豎井式/發(fā)射井式/谷倉式管理):組織結(jié)構(gòu)是由若干彼此孤立的團(tuán)隊(duì)組成,并且整個(gè)組織結(jié)構(gòu)的范圍內(nèi)绵患,上下溝通交流能夠有效進(jìn)行雾叭,而水平/橫向的則不然。結(jié)構(gòu)上支持?jǐn)?shù)據(jù)主要在上下方面的流動(dòng)落蝙,卻禁止跨部門的通信织狐。
廠商陷阱(Vendor lock-in暂幼,供應(yīng)商套牢,供應(yīng)商陷阱移迫,廠商泥潭):使一個(gè)系統(tǒng)過于依賴于外部所提供的組件/部件旺嬉。
項(xiàng)目管理
雪崩模型(Avalanche):不合理地混搭或者說混合使用瀑布模型與敏捷開發(fā)方法。
死亡征途(Death march厨埋,死亡之旅):除了CEO邪媳,每個(gè)人都知道這個(gè)項(xiàng)目會(huì)成為一場(chǎng)災(zāi)難,但是真相卻被隱瞞下來荡陷,以免項(xiàng)目被立即取消悲酷。(盡管CEO通常知道并且仍然繼續(xù)試圖最大化利潤。)然而亲善,真相被隱藏起來,直到大限來臨("Big Bang")逗柴。另一種定義:雇員由于不合理的deadline蛹头,被迫在深夜和周末加班。
團(tuán)隊(duì)思維(Groupthink):在團(tuán)隊(duì)思維中戏溺,團(tuán)隊(duì)成員避免提出在一致觀點(diǎn)之外的思維琳水。
九九定律(Ninety-ninety rule):當(dāng)項(xiàng)目“幾近完成”時(shí)间坐,低估完成項(xiàng)目所需時(shí)間的傾向。
過度設(shè)計(jì)(Overengineering):花費(fèi)資源完成比實(shí)際需要的還要魯棒和復(fù)雜的工程
障眼法(Smoke and mirrors):展示還沒實(shí)現(xiàn)的功能,就像它們已經(jīng)實(shí)現(xiàn)了一樣
軟件膨脹(Software bloat):允許系統(tǒng)的后續(xù)版本使用更多的資源
分析方式
旁觀冷漠(Bystander apathy):一個(gè)需求或者設(shè)計(jì)是錯(cuò)的纺棺,注意到這一點(diǎn)的人卻不指出,因?yàn)檫@影響的是其他人俊卤。
軟件工程
軟件設(shè)計(jì)
抽象倒置(Abstraction inversion):不把用戶需要的功能直接提供出來顶瞒,導(dǎo)致他們要用更上層的函數(shù)來重復(fù)實(shí)現(xiàn)
用意不明(Ambiguous viewpoint):給出一個(gè)模型(通常是OOAD,面向?qū)ο蠓治雠c設(shè)計(jì))卻沒有指出用意何在
大泥球(Big ball of mud):沒有清晰結(jié)構(gòu)的系統(tǒng)
數(shù)據(jù)庫式進(jìn)程間通信(Database-as-IPC):使用數(shù)據(jù)庫進(jìn)行進(jìn)程間通信闰围,而不使用更輕量級(jí)的合適的機(jī)制赃绊。或者說羡榴,對(duì)于常規(guī)的進(jìn)程間通信碧查,不是去采用輕量得多的合適機(jī)制,而是將數(shù)據(jù)庫用作消息隊(duì)列校仑。
鍍金(Gold plating):在項(xiàng)目達(dá)到最高價(jià)值后還繼續(xù)工作忠售。
內(nèi)部平臺(tái)效應(yīng)(Inner-platform effect):系統(tǒng)可自定義的太多,以至于成為一個(gè)軟件開發(fā)平臺(tái)的蹩腳的復(fù)制品迄沫。
輸入問題(Input kludge):無法確定和實(shí)現(xiàn)對(duì)異常輸入的處理
接口膨脹(Interface bloat):把一個(gè)接口做得過于強(qiáng)大以至于極其難以實(shí)現(xiàn)
魔力按鍵(Magic pushbutton):直接在接口的代碼里編寫實(shí)現(xiàn)稻扬,而不使用抽象
競(jìng)爭(zhēng)風(fēng)險(xiǎn)(Race hazard):輸出結(jié)果受到事件執(zhí)行順序和時(shí)機(jī)的影響,在多線程環(huán)境和分布式系統(tǒng)中可能發(fā)生
煙囪系統(tǒng)(Stovepipe system):過度聚集數(shù)據(jù)和功能邢滑,忽視了與其他系統(tǒng)和模塊的共享
面向?qū)ο笤O(shè)計(jì)
貧血的域模型(Anemic Domain Model):僅因?yàn)槊總€(gè)對(duì)象都要有屬性和方法腐螟,而在使用域模型的時(shí)候沒有加入非OOP的業(yè)務(wù)邏輯
(BaseBean):繼承一個(gè)工具類的功能愿汰,而不是委托給它
調(diào)用父類(Call super):需要子類調(diào)用父類被重定義的方法
圓還是橢圓問題(Circle-ellipse problem):基于變量的子類化關(guān)系進(jìn)行子類化
循環(huán)依賴(Circular dependency):在對(duì)象或軟件模塊中,直接或間接引入循環(huán)依賴乐纸。
常量接口(Constant interface):使用接口定義常量
上帝對(duì)象(God object):在設(shè)計(jì)的單一部分(某個(gè)類)集中了過多的功能
對(duì)象糞池(Object cesspool):復(fù)用那些不滿足復(fù)用條件的對(duì)象衬廷。對(duì)象池是一種管理對(duì)象的方法,在重復(fù)使用對(duì)象前汽绢,需要針對(duì)對(duì)象進(jìn)行初始化吗跋,以避免上次使用后的狀態(tài)等數(shù)據(jù)影響下次的使用
不羈的對(duì)象(Object orgy):沒有成功封裝對(duì)象,外部可以不受限制地訪問它的內(nèi)部
幽靈(Poltergeists):指這樣一些對(duì)象宁昭,它們唯一的作用就是把信息傳給其它對(duì)象
順序耦合(Sequential coupling):指這樣一些對(duì)象跌宛,它們的方法必須要按某種特定順序調(diào)用
悠悠問題(Yo-yo problem):一個(gè)結(jié)構(gòu)(例如繼承)因?yàn)檫^度碎片化而變得難于理解編程
偶然復(fù)雜度(Accidental complexity):向一個(gè)方案中引入不必要的復(fù)雜度
遠(yuǎn)隔作用(Action at distance):意料之外的在系統(tǒng)分離的部分之間交互
盲目信任(Blind faith):缺乏對(duì)bugfix的校驗(yàn)或?qū)ψ雍瘮?shù)返回值的正確性檢查
船錨(Boat anchor):在系統(tǒng)中保留無用的部分
忙等待(Busy waiting):在等待的時(shí)候不斷占用CPU,通常是因?yàn)椴捎昧酥貜?fù)檢查而不是適當(dāng)?shù)南C(jī)制
緩存失敗(Caching failure):錯(cuò)誤被修正后忘記把錯(cuò)誤標(biāo)志復(fù)位
拜物編程(Cargo cult programming):由于對(duì)模式的盲目崇拜积仗,在不理解的情況下就使用模式和方法疆拘,企圖得到好的結(jié)果
靠異常編程(Coding by exception):當(dāng)有特例被發(fā)現(xiàn)時(shí)才添加新代碼去解決
隱藏錯(cuò)誤(Error hiding):在顯示給用戶之前捕捉到錯(cuò)誤信息,要么什么都不顯示寂曹,要么顯示無意義的信息
硬編碼(Hard code):將對(duì)系統(tǒng)環(huán)境的假設(shè)寫入實(shí)現(xiàn)中
熔巖流(Lava flow):保留不想要的(冗余的或是低質(zhì)量的)代碼哎迄,僅因?yàn)槌ミ@些代碼的代價(jià)太高或是會(huì)帶來不可預(yù)期的結(jié)果
循環(huán)-switch序列(Loop-switch sequence)在循環(huán)結(jié)構(gòu)中使用switch語句來編寫連續(xù)步驟
魔術(shù)數(shù)字(Magic numbers):在算法里直接使用數(shù)字,而不解釋含義
魔幻字符串(Magic strings):直接在代碼里使用常量字符串隆圆,例如用來比較漱挚,或是作為事件代碼
自我復(fù)制(Repeating yourself):通過不斷復(fù)制已有代碼的模式或代碼段進(jìn)行編碼;而非采用once and only once(抽取原則)
軟代碼(Soft code):在配置文件里保存業(yè)務(wù)邏輯而不是在代碼中
面條代碼(Spaghetti code):指那些結(jié)構(gòu)上完全不可理解的系統(tǒng)渺氧,尤其是因?yàn)檎`用代碼結(jié)構(gòu)
霰彈槍手術(shù)(Shotgun surgery):開發(fā)人員一次性在一個(gè)多個(gè)實(shí)現(xiàn)的代碼基中增加功能方法論
拷貝粘貼編程(Copy and paste programming):拷貝(然后修改)現(xiàn)有的代碼而不是構(gòu)造通用的解決方案
黃金大錘(Golden hammer):認(rèn)為自己最喜歡的解決方案是到處通用的(參見:銀彈)
不可能因素(Improbability factor):認(rèn)為已知的錯(cuò)誤不可能發(fā)生
非我所創(chuàng)(Not invented here):拒絕使用組織外的主意或方案旨涝,但這也可能是出于版權(quán)等原因
這里發(fā)明的(invented here):拒絕組織內(nèi)部實(shí)現(xiàn)的創(chuàng)新或解決方案,通常因?yàn)閷?duì)成員沒有信心
不成熟的優(yōu)化(Premature optimization):在編碼的早期追求代碼的效率侣背,犧牲了好的設(shè)計(jì)白华、可維護(hù)性、有時(shí)甚至是現(xiàn)實(shí)世界的效率
轉(zhuǎn)換編程法或巧合編程(Programming by permutation or programming by accident):試圖通過連續(xù)修改代碼再看是否工作的方式來解決問題
重新發(fā)明方的輪子(Reinventing the square wheel):已經(jīng)有一個(gè)很好的方案了秃踩,又再搞一個(gè)爛方案來替代它
銀彈(Silver bullet):認(rèn)為自己最喜歡的技術(shù)方案能解決一個(gè)更大的問題
測(cè)試人員驅(qū)動(dòng)開發(fā)(Tester driven development):需求來自bug報(bào)告的軟件工程
殞石式驅(qū)動(dòng)開發(fā)(Meteorite driven development):需求來自任性的不具備專業(yè)知識(shí)及尊重的上層衬鱼,以犧牲底層員工生活品質(zhì)及削弱精神為主軸的開發(fā)方式,需求如隕石一般來自天上而不可回避配置管理
依賴地獄(Dependency hell):所依賴產(chǎn)品的版本所導(dǎo)致的問題
DLL地獄(DLL hell):不同版本DLL所帶來的問題憔杨,包括DLL可見性和多版本問題鸟赫,在微軟的Windows上尤為突出
擴(kuò)展沖突(Extension conflict):蘋果系統(tǒng)在Mac OS X版本之前的不同擴(kuò)展的問題
JAR地獄(JAR hell):JAR文件不同版本或路徑帶來的問題,通常是由于不懂類加載模型導(dǎo)致的
學(xué)習(xí) 設(shè)計(jì)模式 中無意 看到消别,覺得比較有意思抛蚤,故摘要于此,以上內(nèi)容摘自維基百科