摘要:接口隔離原則是什么客戶端代碼不應當被迫依賴于它們不需要的方法。
這是理解SOLID原則,關于接口隔離原則如何幫助我們創建簡單的抽象接口,并使客戶端代與接口之間存在的更少的依賴關系。接口隔離原則是什么
Clients should not be forced to depend on methods that they do not use.客戶端代碼不應當被迫依賴于它們不需要的方法。
這個原則本身與單一職責原則關系十分緊密,它意味著當你在定義你的抽象層代碼時,不應當在客戶端代碼在實現抽象邏輯時,暴露一些客戶端代碼不需要使用或者關心的方法。
進一步說明的話,就是當你有意地在抽象層中暴露的方法時,這意味著所有實現這些抽象邏輯的客戶端代碼都必須要實現所有的抽象方法,盡管這些方法并不一定都對客戶端代碼有意義。
將你的接口的保持精簡和小顆粒度,并且不要在它們中間增加無用的抽象方法,當你在對新的抽象接口進行命名時,你就會擁有更好的選擇,因為你已有了若干小顆粒的命名類型。這樣做的意義在于當你在需要提供一個更加大顆粒度的抽象接口時,你可以擁有足夠的靈活性來將已有的小顆粒度接口進行組合。
如何實踐接口隔離原則這個例子是關于一個ATM用戶界面的抽象接口,這個接口會處理諸如存款請求、取款請求等邏輯,從這個例子中我們會了解到,我們如何對這個接口進行隔離,使其進一步劃分為多個獨立的、更加具體的若干接口。
首先我們應當有一個工具函數庫接口,這個接口會描述我們想要暴露的關于byte操作邏輯的方法,讓我們創建這樣一個接口,如下
type ByteUtils interface { Read(b []byte) (n int, err error) // Read into buffer Write(b []byte)(n int, err error) // Write into buffer Trim(b []byte, exclusions string)[]byte // Trim buffer by removing bytes from the exclusion chars }
它可以正常工作一段時間,但是很快我們就會發現以下兩個問題:
它的命名ByteUtils太過于通用,如果我們僅通過命名本身,基本無法獲取任何具體的信息
當使用它時,會有一些古怪的感覺,因為當你根據不同的優化場景來按不同邏輯實現trim方法時,你所實現的read和write幾乎沒什么差別,但是你卻需要重復地實現它們,同時在某些不需要讀或者寫的場景,仍然需要實現它們。
所以它雖然能夠正常工作,但是卻不夠好。
我們可以通過創建三個更精簡、更具體的接口來替代原先通用的接口:
type Reader interface { Read(b []byte) (n int, err error) } type Writer interface { Write(b []byte)(n int, err error) } type Trimmer interface { Trim(b []byte, exclusions string)[]byte }
這種顆粒度比較細的接口也可以稱為角色接口,因為它們更易于重構和改變,甚至對于已經定義好的角色和目的也可以很容易的進行重新部署和定義。
在這三個基礎上,我們可以通過組合它們來獲取一個更有關聯性的接口列表,比如:
type ReadWriter interface { Reader Writer } type TrimReader interface { Trimmer Reader }
這意味客戶端代碼擁有了可以根據它們各自的需求來組合抽象層接口的靈活性,這樣就會避免在實現抽象接口時不必要的麻煩(比如必須要實現某些無用的方法),比如上面的TrimReader的實現并未包含多余的Write方法的聲明。
總結正如你所看到的,通用的接口往往會無意識的將自己和類的實現耦合在了一起,所以你應當盡量的避免這種情況的發生。在設計接口時,你應當時刻提醒自己,我是否需要使用所有在接口中聲明的方法呢?如果不是的話,將接口細分為更多個更精簡、更具體的接口。
正如甘地曾經說過:
你的行動決定你的習慣,你的習慣決定你的價值,你的價值會決定你的命運。
如果在架構中,你每次都會經過仔細思考,會按照好的模式來進行設計,它將會成為一種習慣,自然慢慢會轉變為你的價值或者原則,最終則會成為你的命運,比如成為了一個始終給予完善解決方案的軟件架構師。
我的觀點是,始終通過挑戰自己來變的更好,在某些時刻,你可能會遇到問題,但是往往你可能已經擁有了答案。
Happy coding!
譯者注對于接口隔離原則的理解,我一直覺的它本身其實是單一職責原則的一個擴展,但是它們之間也有細微的不同:
單一職責原則往往面向實現層,比如具體的類或者某個方法
接口隔離原則往往面向抽象層,比如一些抽象類或者抽象方法
所以將兩個原則結合起來看的話,可以很容器得到當時提出這兩個原則的人的意圖,那就是一定要時刻保持簡單。
在實際工作中,我深知保持簡單是一件十分困難的事情,因為工程師本身的使命便是解決問題,而問題往往充滿了未知性,而未知性往往代表著改變,這還沒有考慮到在項目實施過程中,產品經理天馬行空的設計思路,客戶們五花八門的需求等等。在這些外界條件下,我們的代碼往往會變得復雜無比,充滿了各種反模式和冗余代碼,最終會使自己陷入無盡的bug修復和維護工作中,怎么還會有時間進行自我提升呢?
所以,為了能夠按時下班,為了能夠及早回家,為了能夠讓我們的擁有更多的時間來提升自己和陪伴家人,在軟件設計之初,盡可能地針對將來所面臨的改變,在設計層面降低軟件抽象模塊間的耦合程度,在項目實施時,提高每個具體實現模塊內部的內聚程度,同時使它們保持簡單,這樣便是一個好的開始。
關注公眾號 全棧101,只談技術,不談人生
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107333.html
摘要:什么是里氏替換原則某個對象實例的子類實例應當可以在不影響程序正確性的基礎上替換它們。除了在編程語言層面,在前端實際工作中,你可能會聽到一個叫作的概念,這個概念我認為也是里氏替換原則的一直延伸。 這是理解SOLID原則,關于里氏替換原則為什么提倡我們面向抽象層編程而不是具體實現層,以及為什么這樣可以使代碼更具維護性和復用性。 什么是里氏替換原則 Objects should be rep...
這是理解SOLID原則中,關于依賴倒置原則如何幫助我們編寫低耦合和可測試代碼的第一篇文章。 寫在前頭 當我們在讀書,或者在和一些別的開發者聊天的時候,可能會談及或者聽到術語SOILD。在這些討論中,一些人會提及它的重要性,以及一個理想中的系統,應當包含它所包含的5條原則的特性。 我們在每次的工作中,你可能沒有那么多時間思考關于架構這個比較大的概念,或者在有限的時間內或督促下,你也沒有辦法實踐一些好...
摘要:事件驅動模型對于一些復雜的事件驅動模型,比如拖拽,往往使用開閉原則會達到意想不到的效果。 這是理解SOLID原則,介紹什么是開閉原則以及它為什么能夠在對已有的軟件系統或者模塊提供新功能時,避免不必要的更改(重復勞動)。 開閉原則是什么 Software entities (classes, modules, functions, etc.) should be open for ext...
摘要:設計原則梳理,參考核心技術與最佳實踐敏捷開發原則模式與實踐,文章面向對象設計的五大原則設計模式原則單一職責原則定義特性僅有一個引起類變化的原因一個類只承擔一項職責職責變化的原因避免相同的職責分散到不同的類,功能重復問題一個類承擔的職責過多, PHP設計原則梳理,參考《PHP核心技術與最佳實踐》、《敏捷開發原則、模式與實踐》,文章PHP面向對象設計的五大原則、設計模式原則SOLID 單一...
閱讀 2953·2021-11-24 09:39
閱讀 2861·2021-09-29 09:34
閱讀 3555·2021-09-24 10:23
閱讀 1740·2021-09-22 15:41
閱讀 1693·2019-08-30 15:55
閱讀 3510·2019-08-30 13:58
閱讀 2617·2019-08-30 13:11
閱讀 1665·2019-08-29 12:31