抽象未支持全部互補或相關的方法時,將致使這種壞味。程序員
一種重要的抽象實現手法是建立內聚而完整的抽象。抽象未支持相關的方法時,可能會影響抽象的內聚性和完整性。若是抽象只支持部分相關的方法,其使用者就可能不得不本身去實現其餘的功能。客戶程序可能嘗試直接訪問抽象的內部實現細節,此時帶來的反作用是違反封裝原則。編程
Min/Max | Open/Close | Create/Destroy | Get/Set |
---|---|---|---|
Read/Write | Print/Scan | First/Last | Begin/End |
Start/Stop | Lock/Unlock | Show/Hide | Up/Down |
Source/Target | Insert/Delete | First/Last | Push/Pull |
Enable/Disable | Acquire/Release | Left/Right | On/Off |
###禁止特定行爲c#
設計人員可能有意識地作出不提供堆成或配套方法的設計決策。例如在只讀集合中,包含Add()方法,而不包含Remove()方法。微信
例如用SetEnabled(bool)替換Enable()和Disable(),傳入true表明啓用,fasle表明禁用。框架
抽象被賦予不止一項職責時,將致使這種壞味。ide
##爲何不能夠有多方面抽象?工具
單一職責原則指出,抽象必須承擔單一而明確的職責,且必須徹底封裝該職責。抽象承擔了多種職責時,意味着它將受多種緣由的影響而須要修改,設計的修改頻率與其缺陷數之間存在很強的正相關關係。這意味着多方面抽象存在的缺陷可能更多。學習
引入使用通用名(如Item,Order,Product,Image)的抽象時,它經常會成爲佔位符,用於提供全部相關(但未必屬於它)的功能。抽象的命名錶明瞭這個抽象的職責,命名太通用,隨着系統的迭代,抽象會慢慢承擔多種職責。感同身受!!!ui
對類進行了大量修改而沒有按期重構,久而久之,可能就會在類中引入了額外的職責。spa
沒有對關注點分離給予足夠的重視。
類承擔了多種職責時,就不是內聚的。可使用「提取類」來進行重構。
建立的抽象未用(未被直接使用或繼承)時,將致使這種壞味。有如下兩種表現形式:
設計中的抽象未被使用,就沒有發揮任何做用,所以違反了抽象原則。未實現的抽象類和接口時多餘的或憑空想象出來的歸納,所以是不須要的。
##未用的抽象潛在緣由
試圖設計"永不過期"的系統或在其中包含"將來可能用得着"的抽象時,將致使這種壞味。
需求不斷變化,爲知足早期需求而建立的抽象可能已經再也不須要。若是將其留在設計中,它將變成未用的抽象。
維護或重構時,若是不清理舊的抽象,可能留下未引用的抽象。這點深有體會,因此一直要求組員在重構的過程當中,必定要把舊代碼刪除。若是不這樣作,過時的和未用的代碼將致使代碼庫急劇膨脹,重構的代碼和未重構的代碼糾纏在一塊兒,代碼的可理解性、閱讀體驗極差。並且若是你重構的舊代碼你不負責刪除,其餘人就更不知道如何下手了,長此以往這些舊代碼就會變成BUG的溫牀。註釋掉舊代碼也不是一個好的選擇,太影響閱讀體驗。其次,如今的代碼版本控制工具功能強大,即便刪除錯了代碼,也能夠經過版本控制工具找回。因此舊代碼必須死。
不肯定是否還有其餘代碼在使用想要刪除的舊代碼。
將未用的抽象從設計中刪除。對於可能還有客戶程序在使用的API,直接刪除不可行,可將這些抽象標記爲''過時的''或"已摒棄",明確地指出在新開發的客戶程序中不得使用它們。
[Obsolete] public class Report { }
類庫和框架一般以抽象類或接口的方式提供擴展點,這些抽象類可能在庫或框架中未被使用,但它們是供客戶程序使用的擴展點,所以不屬於未用的抽象。
兩個抽象的名稱、實現或二者相同時,將致使這種壞味。
名稱相同
兩個不一樣的抽象重名將影響可理解性。
實現相同
多個抽象的成員定義在語義上相同,但在設計上沒有捕獲並使用這些實現中相同的元素。在繼承層析結構中,若是多個兄弟抽象的實現相同,可能意味着存在的是"未歸併的層次結構"壞味。
名稱實現都相同
##爲何不能夠有重複的抽象?
重複代碼是軟件萬惡之首。因此咱們要極力避免重複。
若是多個抽象的名稱相同,將影響設計的可理解性:客戶代碼開發人員將不知道使用哪一個抽象。
若是多個抽象的實現相同(代碼相同),將難以維護:修改其中一個抽象的實現時,經常須要修改其它全部重複抽象的實現。這不只增長了修改負擔,還可能引入難以發現的微小BUG。爲縮小修改範圍,必須儘量避免重複。
CV程序員複製並粘貼代碼,而不該用合適的抽象。
通過多年的修復或改進後,軟件將包含"殘留",其中有大量重複的代碼。
不一樣時期一般由不一樣的人員負責維護軟件,他們對軟件的瞭解不完全,編寫了原來就有的類或方法,致使軟件包含重複的代碼。
###類被聲明爲不可擴展的
類被聲明爲不可擴展的,沒法重用代碼,只能複製代碼,建立修訂版本。
對於名稱相同的重複抽象,能夠將其中一個抽象改成不一樣的名稱。
對於實現相同的重複抽象,若是實現徹底相同,可將其中一個抽象刪除。若是實現稍有差別,可將相同的實現歸併到另外一個類中:這能夠是層次結構中的基類,也能夠是重複的抽象可引用或使用的既有類或新類。
致使重複抽象的一個緣由是,要同時支持同步和非同步變種。
對於大型系統,創建徹底統一的領域模型要麼不可行要麼不划算。領域驅動設計提供的一種解決方案是,將大型系統分紅多個"界限上下文"。採用這種方式,不一樣上下文中的模型可能包含同名的類型,可是這是能夠接受的。
在JDK中,有不少的重複的方法和類,這是由於沒有對基本類型提供泛型支持。可是在.Net中就不會有這麼多重複的方法和類,由於C#對基本類型提供了泛型支持。
參考:《軟件設計重構》
<strong> <div class="content"> <div>做者:<a style="color: red; font-family: 微軟雅黑; text-decoration: none" href="http://songwenjie.cnblogs.com/" target="_blank">擼碼那些事</a></div> <div>來源:<a style="color: red; font-family: "Microsoft YaHei"; text-decoration: none" href="http://songwenjie.cnblogs.com/" target="_blank">http://songwenjie.cnblogs.com/</a> <div>聲明:本文爲博主學習感悟總結,水平有限,若是不當,歡迎指正。若是您認爲還不錯,不妨點擊一下下方的<span onclick="Digg();">【<font color=red>推薦</font>】</span>按鈕,謝謝支持。轉載與引用請註明出處。</div> <div>微信公衆號: <img src="http://songwenjie.vip/blog/180511/AFdec5f65k.jpg?imageslim" title="關注公衆號,獲取最新更新"/></div> </strong> </div>