成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

讀懂 SOLID 的「開閉」原則

awkj / 3735人閱讀

摘要:事件驅(qū)動模型對于一些復(fù)雜的事件驅(qū)動模型,比如拖拽,往往使用開閉原則會達(dá)到意想不到的效果。

這是理解SOLID原則,介紹什么是開閉原則以及它為什么能夠在對已有的軟件系統(tǒng)或者模塊提供新功能時,避免不必要的更改(重復(fù)勞動)。
開閉原則是什么
Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.

軟件實體(類、模塊、函數(shù)等)都應(yīng)當(dāng)對擴(kuò)展具有開放性,但是對于修改具有封閉性。

首先,我們假設(shè)在代碼中,我們已經(jīng)有了若干抽象層代碼,比如類、模塊、高階函數(shù),它們都僅做一件事(還記得單一職責(zé)原則嗎?),并且都做的十分出色,所以我們想讓它們始終處于簡潔、高內(nèi)聚并且好用的狀態(tài)。

但是另一方面,我們還是會面臨改變,這些改變包含范圍(譯者注:應(yīng)當(dāng)是指抽象模塊的職責(zé)范圍)的改變,新功能的增加請求還有新的業(yè)務(wù)邏輯需求。

所以對于上面我們所擁有的抽象層代碼,在長期想讓它處于一成不變的狀態(tài)是不現(xiàn)實的,你不可避免的會針對以上的需要作出改變的需求,增加更多的功能,增加更多的邏輯和交互。在上一篇文章,我們知道,改變會使系統(tǒng)復(fù)雜,復(fù)雜會促使模塊間的耦合性上升,所以我們迫切地需要尋找一種方法能夠使我們的抽象模塊不僅可以擴(kuò)大它的職責(zé)范圍,同時還能夠保持當(dāng)前良好的狀態(tài)(簡潔、高內(nèi)聚、好用)。

這便是開閉原則存在的意義,它能夠幫助我們完美地實現(xiàn)這一切。

如何實踐開閉原則

當(dāng)你需要對已有代碼作出一些修改時,請切記以下兩點:

保持函數(shù)、類、模塊當(dāng)前它們本身的狀態(tài),或者是近似于它們一般情況下的狀態(tài)(即不可修改性)

使用組合的方式(避免使用繼承方式)來擴(kuò)展現(xiàn)有的類,函數(shù)或模塊,以使它們可能以不同的名稱來暴露新的特性或功能

這里關(guān)于繼承,我們特意增加了一個注釋,在這種情況下使用繼承可能會使模塊之間耦合在一起,同時這種耦合是可避免的,我們通常在一些預(yù)先有著良好定義的結(jié)構(gòu)上使用繼承。(譯者注:這里應(yīng)該是指,對于我們預(yù)先設(shè)計好的功能,推薦使用繼承方式,對于后續(xù)新增的變更需求,推薦使用組合方式)

舉個例子(譯者注:我對這里的例子做了一些修改,原文中并沒有詳細(xì)的說明)

interface IRunner {
  run: () => void;
}
class Runner implements IRunner {
  run(): void {
    console.log("9.78s");
  }
}

interface IJumper {
  jump: () => void;
}
class Jumper implements IJumper {
  jump(): void {
    console.log("8.95,");
  }
}

例子中,我們首先聲明了一個IRunner接口,之后又聲明了IJumper,并分別實現(xiàn)了它們,并且實現(xiàn)類的職能都是單一的。

假如現(xiàn)在我們需要提供一個既會跑又會跳的對象,如果我們使用繼承的方式,可以這么寫

class RunnerAndJumper extends Runner {
  jump: () => void
}

或者

class RunnerAndJumper extends Jumper {
  run: () => void
}

但是使用繼承的方式會使這個RunnerAndJumperRunner(或者Jumper)耦合在一起(耦合在一起的原因是因為它會因它的父類改變而改變),我們再來用組合的方式試試看,如下:

class RunnerAndJumper {
  private runnerClass: IRunner;
  private jumperClass: IJumper;
  constructor(runner: IRunner, jumper: IJumper) {
    this.runnerClass = new runner();
    this.jumperClass = new jumper();
  }
  run() {
    this.runnerClass.run();
  }
  jump() {
    this.jumperClass.jump();
  }
}

我們在RunnerAndJumper的構(gòu)造函數(shù)中聲明兩個依賴,一個是IRunner類型,一個是IJumper類型。

最終的代碼其實和依賴倒置原則中的例子很像,而且你會發(fā)現(xiàn),RunnerAndJumper類本身并沒有與任何別的類耦合在一起,它的職能同樣是單一的,它是對一個即會跑又會跳的實體的抽象,并且這里我們還可以使用DI(依賴注入)技術(shù)進(jìn)一步的優(yōu)化我們的代碼,降低它的耦合度。

反思

開閉原則所帶來最有用的好處就是,當(dāng)我們在實現(xiàn)我們的抽象層代碼時,我們就可以對未來可能需要作出改變的地方擁有一個比較完整的設(shè)想,這樣當(dāng)我們真正面臨改變時,我們所對原有代碼的修改,更貼近于改變本身,而不是一味的修改我們已有的抽象代碼。

在這種情況下,由于我們節(jié)省了不必要的勞動和時間,我們就可以將更多的精力投入到關(guān)于更加長遠(yuǎn)的事宜計劃上面,而且可以針對這些事宜需要作出的改變,提前和團(tuán)隊溝通,最終給予一套更加健壯、更符合系統(tǒng)模塊本身的解決方案。

在整個軟件開發(fā)周期中(比如一個敏捷開發(fā)周期),你對于整個周期中的事情了解的越透徹、越多,則越好。身為一個工程師,在一個開發(fā)沖刺中,為了在沖刺截止日期結(jié)束前,實現(xiàn)一個高效的、可靠的系統(tǒng),你不會期望作出太多的改變,因此往往你可能會“偷工減料”。

從另一個角度來講,我們也應(yīng)當(dāng)致力于在每一次面臨需求變更的情況下,不需要一而再,再而三的更改我們已有的代碼。所有新的功能都應(yīng)當(dāng)通過增加一個新的組合類或方法實現(xiàn),或者通過復(fù)用已有的代碼來實現(xiàn)。

插件與中間件

充分貫徹開閉原則的另一個例子,便是插件與中間件架構(gòu),我們可以從三個角度來簡單分析這種架構(gòu)是如何運作的:

內(nèi)核或者容器:往往是核心功能的實現(xiàn)的前提,一般會成為整個系統(tǒng)最核心的部分

插件:在實現(xiàn)容器的基礎(chǔ)上,往往一些核心功能都是以內(nèi)置的插件實現(xiàn)的,并且,通過實現(xiàn)一套通用的網(wǎng)關(guān)類接口,我們可以使插件具有可插拔性,這樣在需要新增特性和功能時,只需要實現(xiàn)新的插件并添加到容器即可,比如支持插件擴(kuò)展功能的瀏覽器Chrome。

中間件:中間件我們可以通過一個例子來說明,比如我們擁有一個請求 - 響應(yīng)周期,我們可以通過中間件,在周期中添加中間業(yè)務(wù)邏輯,以便為應(yīng)用程序提供額外的服務(wù)或橫切關(guān)注點,比如Reduxexpress還有很多框架都支持這樣的功能。

總結(jié)

希望這篇文章能夠幫助你學(xué)會如何應(yīng)用開閉原則并且從中收益。設(shè)計一個具有可組合性的系統(tǒng),同時提供具有良好定義的擴(kuò)展接口,是一種非常有用的技術(shù),這種技術(shù)最關(guān)鍵的地方在于,它使我們的系統(tǒng)能夠在保持強(qiáng)健的同時,提供新功能、新特性,但是卻不會影響它當(dāng)前的狀態(tài)。

譯者注

開閉原則是面向?qū)ο缶幊讨凶钪匾脑瓌t之一,有多重要呢?這么說吧,很多的設(shè)計原則和設(shè)計模式所希望達(dá)成的最終狀態(tài),往往符合開閉原則,因此許多原則都可以作為實現(xiàn)開閉原則的一種手段,在原文的例子中,我們可以很明顯的體會到,在實現(xiàn)開閉原則所提倡的理念的過程中,我們不經(jīng)意地使用之前兩篇文章中涉及的原則,比如:

保持對象的單一性(單一職責(zé))

實現(xiàn)依賴于抽象(依賴倒置原則)

我之前一直是做后端相關(guān)工作的,所以對于開閉原則接觸較早,這兩年轉(zhuǎn)行做了前端,隨著nodejs的發(fā)展,框架技術(shù)日新月異,但是其中脫穎而出的優(yōu)秀框架往往是充分貫徹了開閉原則,比如expresswebpack還有狀態(tài)管理容器redux,它們均是開閉原則的最佳實踐。

另外一方面,在這兩年的工作也感受到,適當(dāng)?shù)氖褂煤瘮?shù)式編程的思想,往往是貫徹開閉原則一個比較好的開始,因為函數(shù)式的編程中的核心概念之一便是compose(組合)。以函數(shù)式描述業(yè)務(wù)往往是原子級的指令,之后在需要描述更復(fù)雜的業(yè)務(wù)時,我們復(fù)用并組合之前已經(jīng)存在的指令以達(dá)到目的,這恰恰符合開閉原則所提倡的可組合性。

最后再分享一些前端工作中,經(jīng)常需要使用開閉原則的最佳業(yè)務(wù)場景,

UI組件的表單組件:對于表單本身以容器來實現(xiàn),表單項以插件來實現(xiàn),這樣對于表單項如何渲染、如何加載、如何布局等功能,均會封閉與表單容器中,而對于表單項如何校驗、如何取值、如何格式化等功能,則會開放與表單項容器中。

API服務(wù):一般我們可能會在項目中提供自定義修改請求頭部的工具方法,并在需要的時候調(diào)用。但這其實是一種比較笨的方法,如果可能的話,建議使用攔截器來完成這項任務(wù),不僅會提供代碼的可讀性,同時還會使發(fā)接口的業(yè)務(wù)層代碼保持封閉。

事件驅(qū)動模型:對于一些復(fù)雜的事件驅(qū)動模型,比如拖拽,往往使用開閉原則會達(dá)到意想不到的效果。最近有一個比較火的拖拽庫draggable,提供的拖拽體驗相比其他同類型的庫簡直不是一個級別。我前段時間去讀它的源碼,發(fā)現(xiàn)它之所以強(qiáng)大,是因為在它內(nèi)部,針對多種拖拽事件,封裝了獨立的事件發(fā)射器(其內(nèi)部稱作Sensor),之后根據(jù)這些發(fā)射器指定了一套獨立的抽象事件驅(qū)動模型,在這個模型基礎(chǔ)上,針對不同的業(yè)務(wù)場景提供不同的插件,比如:

原生拖拽(Draggable)

拖拽排序(Sortable)

拖拽放置(Droppable)

拖拽交換(Swappable)

還有若干提高用戶體驗的其他插件,這一切均是以開閉原則而實現(xiàn)的。

能想到的大概就這么多,希望可以拋磚引玉,如有錯誤,還望指正。

關(guān)注公眾號 全棧101,只談技術(shù),不談人生

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/107223.html

相關(guān)文章

  • 讀懂 SOLID 「里氏替換」原則

    摘要:什么是里氏替換原則某個對象實例的子類實例應(yīng)當(dāng)可以在不影響程序正確性的基礎(chǔ)上替換它們。除了在編程語言層面,在前端實際工作中,你可能會聽到一個叫作的概念,這個概念我認(rèn)為也是里氏替換原則的一直延伸。 這是理解SOLID原則,關(guān)于里氏替換原則為什么提倡我們面向抽象層編程而不是具體實現(xiàn)層,以及為什么這樣可以使代碼更具維護(hù)性和復(fù)用性。 什么是里氏替換原則 Objects should be rep...

    vibiu 評論0 收藏0
  • 讀懂 SOLID 「依賴倒置」原則

    這是理解SOLID原則中,關(guān)于依賴倒置原則如何幫助我們編寫低耦合和可測試代碼的第一篇文章。 寫在前頭 當(dāng)我們在讀書,或者在和一些別的開發(fā)者聊天的時候,可能會談及或者聽到術(shù)語SOILD。在這些討論中,一些人會提及它的重要性,以及一個理想中的系統(tǒng),應(yīng)當(dāng)包含它所包含的5條原則的特性。 我們在每次的工作中,你可能沒有那么多時間思考關(guān)于架構(gòu)這個比較大的概念,或者在有限的時間內(nèi)或督促下,你也沒有辦法實踐一些好...

    Snailclimb 評論0 收藏0
  • [譯]每位開發(fā)者都應(yīng)該知道SOLID原則

    摘要:開閉原則軟件實體類,模塊,函數(shù)應(yīng)該是可以擴(kuò)展的,而不是修改。函數(shù)并不符合開閉原則,因為一旦有新動物出現(xiàn),它需要修改代碼。 By Chidume Nnamdi | Oct 9, 2018 原文 面向?qū)ο蟮木幊填愋蜑檐浖_發(fā)帶來了新的設(shè)計。 這使開發(fā)人員能夠在一個類中組合具有相同目的/功能的數(shù)據(jù),來實現(xiàn)單獨的一個功能,不必關(guān)心整個應(yīng)用程序如何。 但是,這種面向?qū)ο蟮木幊踢€是會讓開發(fā)者困惑或...

    go4it 評論0 收藏0
  • 面向?qū)ο蠡?em>原則(3)- 最少知道原則開閉原則

    摘要:六開閉原則開閉原則簡介開閉原則的英文名稱是,簡稱。開閉原則是面向?qū)ο笤O(shè)計中最基礎(chǔ)的設(shè)計原則,它指導(dǎo)我們?nèi)绾谓⒁粋€穩(wěn)定靈活的軟件系統(tǒng)。 面向?qū)ο蠡驹瓌t(3)- 最少知道原則與開閉原則 面向?qū)ο蠡驹瓌t(1)- 單一職責(zé)原則與接口隔離原則面向?qū)ο蠡驹瓌t(2)- 里式代換原則與依賴倒置原則面向?qū)ο蠡驹瓌t(3)- 最少知道原則與開閉原則 五、最少知道原則【迪米特法則】 1. 最少知道...

    HackerShell 評論0 收藏0

發(fā)表評論

0條評論

awkj

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<