關於組件的思考

同步cnblogs:關於組件的思考
同步知乎博客:關於組件的思考
同步github:關於組件的思考html

寫在前面的話

  前端寫了好多年,用過了各類各樣的組件庫,也曾本身寫過各類組件。可是對組件這個概念一直都沒有過一個很深刻了解,因此參考了不少資料,以及結合本身的理解,作概括和總結。so,纔有了這一篇,從什麼是組件,到什麼是軟件中的組件化設計,再到組件設計中有什麼優點和挑戰,到最後如何構建一套出色的組件系統。每一個人的想法都不是同樣的,我概括的可能也並不完善,僅做爲你們的參考,也歡迎你們補充。
前端

什麼是組件?

這就是咱們現實生活中,最形象最貼切的物品了。git

  圖一:是一堆齒輪驅動的系統,每一個齒輪都是單獨存在的,若是一個齒輪壞了,咱們只要替換下來換一個好的就能夠了,這個系統又能夠運轉起來了。程序員

  圖二:是我的PC的主板,你們也特別熟悉,對於插在主板上的每個單獨功能的組件(例如顯卡、CPU等等),若是壞了一個,能夠換一個好的,經過插槽替換上去,也能夠運轉起來。github


因此生活中有不少組件的實體,咱們看看這些關於組件的定義:編程

  1. 供裝配整臺機器、構件或元件的零件組合瀏覽器

  2. 在電子或機械設備中組裝在一塊兒造成一個功能單元的一組元件安全

  3. 組裝產品(如書櫥或碗櫥)時所組合的一般或多或少重複的部分架構

  4. 可被組裝或被從新組裝的幾個部件之一模塊化


這些都是咱們看獲得,摸獲得的,下面咱們再跳出現實表象,上升到一個更高的層面去看問題(這樣的說法也叫抽象)

  圖三:是一個完整的公司的職能部門圖。這個架構由各個職能負責人組成各個部門帶動公司運轉。咱們能夠將這個抽象一下。由每一個最小的職能負責人都是一個最小組件,由這些小組件組裝成了一個部門組件;再由這些部門組件共同驅動了公司這個系統運轉。


咱們將信息進行彙總和整理,得出以下結論:

  1. 從外觀和功能上來說,他們都是一個獨立的部分,多是零件或者是原件

  2. 從行爲上來說,他們擁有組裝這個屬性,能夠和其餘組件相互組合

  3. 能夠被從新組裝,重複利用


  固然咱們作軟件設計的,也是經過參考現實,抽象到軟件設計中,而後根據落地環境,去實現組件化設計思想,前人已經走在了路上,去摸索這塊土地,也得到了一些實用的理論,好比基於組件的軟件工程(Component-based software engineering,簡稱CBSE)基於組件的開發(Component-Based Development,簡稱CBD)的軟件開發範型等等,有興趣的能夠本身去看下。


這些是在軟件領域前人對組件的定義:

  1. 一個不透明的功能實體,可以被第三方組裝,且符合一個構件模型。 — 卡耐基梅隆大學

  2. 是軟件系統中具備相對獨立功能、接口由契約指定、和語境有明顯依賴關係、可獨立部署、可組裝的軟件實體。 — 計算機百科全書

  3. 是一個組裝單元,它具備約定式規範的接口,以及明確的依賴環境。構建能夠被獨立的部署,由第三方組裝。 — 軟件構件著做

  4. 爲自包含的、可編程的、可重用的、與語言無關的軟件單元,軟件組件能夠很容易被用於組裝應用程序中。 — 百度百科

  5. ......


每一個結論針對的都是各自穩定軟件領域的抽象,咱們還能夠看到更多對於組件這個概念的定義。因此咱們針對這些結論,作一個總結

組件具備什麼樣的特性?

  1. 高度內聚,不透明 — 不須要關心這個東西怎麼搞出來的,知道怎麼用就行了

  2. 對外以接口契約 — 有說明書,知道這個東西給了須要的就變成你想要的

  3. 功能相對獨立 — 相對歸納的指明這個東西的使用途徑

  4. 環境依賴 — 對環境的依賴比較重要

  5. 可重用 — 能夠屢次使用

  6. 可組裝 — 能夠和其餘東西組成其餘的玩意


組件系統中應該有哪些組件?

  原子組件:原子級別組件,單一功能,不能繼續拆分。

  複合組件:多組件組合,組成的能完成某一功能的組件。

  插槽組件:爲組件的組裝完成一個功能而提供的基礎設施。

  拓展組件:在原有組件上派生出一個新的組件,爲原有組件增長新的性能或者更改原有組件的功能。

  適配組件:經過適配組件去封裝不一樣組件,保證對外契約一致


  有了組件的定義,知道什麼是組件,組件有什麼特性,以及最後系統中的組件分類大概有哪些。咱們認識了組件這個概念,可是接下來,咱們怎麼去運用組件化的設計思想,去設計咱們的系統?

什麼是組件設計思想?

  將需求場景領域化,將場景領域模塊化,以符合系統需求爲衡量,以穩定領域最大複用爲目的,使其能夠經過組合拆分來構建整個系統的獨立解決方案


如圖:


案例(用前端系統舉例):

  好比咱們須要作一個簡單的前端的活動系統,需求要有登陸系統、查看活動、建立活動、修改活動、刪除活動。


第一步:將需求場景領域化

  登陸功能 -- 表單提交、查看活動 -- 數據展現、建立活動 -- 表單提交、修改活動 -- 表單提交、刪除活動 -- 用戶行爲。咱們將這些功能抽象成3個領域分別爲:表單、數據展現、用戶行爲3個領域。


第二步:將場景領域模塊拆分

  簡單拆分一個表單領域中的例子,咱們能夠將表單領域拆分出不少模塊,好比文本輸入模塊、密碼輸入模塊、單選模塊、多選模塊、下拉選擇模塊等等


第三步:歸納共性和分析差別性

  用文本輸入模塊和密碼輸入模塊作例子。下面咱們須要歸納共性:他們都能作輸入。分析差別性:一個輸入文本可見,一個輸入文本不可見。最後得出結論:設計一個輸入文本的組件,對外開放契約,若是你告訴我你須要把輸入不可見,我內部就作處理將這些東西遮住。


產出組件:

  組件:輸入組件

  契約:是否須要遮擋輸入

  功能:輸入文本的

  領域:表單輸入使用


設計意義:

  以這樣的方式作組件設計,若是整個系統都有這樣的穩定領域,那麼這些組件的意義就是針對該系統是最好的,不只知足了需求,還能夠最大功能複用。


組件化設計的好處

  1. 可重用,對於一個功能獨立且單一的組件,不須要花費其餘資源,能夠直接使用組件達到效果

  2. 拓展和替換,對於系統的維護和更新來講,能夠經過基礎組件進行拓展,而後能夠經過替換組件去爲系統進行更新

  3. 複雜合做可能性,獨立拆分模塊和組件,已組件拆分組合構建完整系統,使大型項目合做成爲可能。

  4. 提升效率,這包括對軟件複雜性更有效率的管理,快速地推向市場,以及更高的生產力(迭代效率),更高的質量等等


組件化設計的挑戰

  1. 開發組件所須要的時間和精力。

  開發組件不是單獨完成一個功能或者一個頁面,若是開發成組件,所須要的時間和精力成本是遠遠大於只是純粹完成一個功能的成本的。

  1. 不可描述需求的開發。

  對於軟件的需求階段,在現實開發中,不多是全部需求都特別明確的,因此對於這些不定性,不可描述需求的開發,對於組件的挑戰是很大的,由於領域不穩定,最終可能抽象的組件也是不定且變化的,這樣致使的組件變化成本是急劇上升的。

  1. 可用性和可重用的衝突。

  對於系統中最後造成的組件的衡量,不是一個固定標準的。可能組件對於現階段的可用性已經徹底知足,可是對於將來變化和爆發是否須要前瞻性的作預留和拓展,以達到更高一層的可複用的衝突,須要開發者本身衡量的。

  1. 組件維護。

  組件的維護在小型項目還能夠忽略,可是在大型項目中,若是維護須要本身一個代碼一個代碼的去尋找痕跡,那麼這樣的組件設計開發不理想,反而違背了組件設計最初的夢想。

  1. 可靠性以及容錯機制。

  由於組件內部是相對獨立的,咱們不知道內部的變化,因此衡量一個組件除了是否知足個人需求之外,是否可靠,以及組件不可靠,出現意外的反應機制是否可以準肯定位和降級容錯(損失一些功能,保證其餘功能完善)。

  1. 持續增加的挑戰。

  組件開發是爲了更高的減輕開發中的各類負擔,可是在組件持續的增加中,組件自己也會成爲一種負擔,對於自己的負擔是否有完善的處理機制,能夠在持續增加中hold住。

  1. 組件的規範。

  每一個攻城獅的開發風格都有各類差別,組件的規範,在這樣的合做中就是重中之重,減小多套理解成本。

  1. 解析組件的「內核」。

  對於核心大腦的健壯是整個系統的靈魂。這個很少說,掛了就直接game over!
有挑戰,是真實存在的,可是咱們能夠經過一系列的方法和規範去解決這些挑戰,讓組件化設計更好的服務咱們的系統。


如何設計一套出色的組件系統?


構建組件系統有2個方向:
  設計一套符合系統需求的組件
  設計一套能夠通用的組件


羅列一些無論哪一個方向都要考慮的因素:

1.統一收口和管理組件

  對於任何一個系統來講,快速迭代和增加中勢必會帶來組件的爆發式增加,若是不能將組件統一收口,可能會帶來組件的重複開發利用率低下(可能和一個組件功能80%相同,只須要拓展一個原子組件就能夠解決問題。或者無收口不知道其餘地方有個相似能夠知足的組件致使二次開發)。其次管理也同樣,好的管理能夠最大化發揮組件式開發的優點,不善的管理就會帶來這樣的疑問,"這樣的組件化開發,增長了更多的複雜度,還有什麼意義?"


2.組件升級和更新,乃至替換作到可控

  忘本式迭代,拋棄舊包袱,迎接新時代這是一種很爽的開發體驗。可是也會帶來,開發一時爽,xxxxx(你們本身體會)。組件每次的升級,在沒有完整的方案前,勢必要考慮組件的兼容性,不然我每次迭代一個新的組件,使用的組件都不兼容,都須要從頭返工手把手替換使用的組件。那就呵呵了。可是有完整灰度方案之後能夠實施,好比組件總體升級2.0版本,才能使用新特性,且有足夠的組件升級遷移方案保證升級無影響。這樣的可控,能夠最大化組件開發的優點。


3.容錯,核心與非核心組件的容錯方案的處理。

  容錯式,也分不少種方式,在傳統window大型系統中,對於核心組件的容錯式就特別的低,由於有些是核心組件,好比CPU,丟了這個就不能玩了。可是對於USB插槽,音頻輸出插槽等等這些容錯率就很高,你壞了無所謂,我係統能跑。只是我會斷掉你的組件提供的功能。因此組件的容錯,須要針對系統自己去評估,無統一方案。


4.安全性,除對外暴露契約影響,對內應自成沙盒

  這個就跟瀏覽器同樣,我受影響的東西,只有我本身對外拋出的約定和契約,不然其餘東西都不能影響到我。這樣纔不會致使會有非自己的變更,而讓組件自身出現問題,解耦萬物,才能達到心裏的聚合和獨立。


5.文檔,組件的自描述,功能和對外契約

  沒有文檔就是沒有自我介紹,誰知道你是誰,能幹什麼,能不能勝任個人解決方案。


6.可信,組件開發授於任何開發者,必須減小風險的可能,以及全面的測試。

  組件設計最終的執行者是開發者,若是一個未受評估或者沒有全面測試的組件引入整個系統構建中,那麼就是引入了一個很大的風險,之後對於這個風險你可能會承受多餘自身的時間去把控這個問題。這也是一個合格的軟件開發工程師須要評估的問題。


7.適配器和膠水代碼:包裝更復雜複合通用組件,應經過適配器設計和膠水代碼組合,保證符合組件規範

  組件的重複利用和組件之間的組裝,確定會帶來更多組件的出現和更復雜的組件出現,天然而然會獲得更高的複雜度。可是基於本系統的組件規範和開發規範,可使用更多的膠水代碼去適配成和本系統組件一致的模型,這樣你我都同樣,學習和使用成本都不高。業內不少都是建立一個組件的原始類,定義組件的基礎功能和契約,全部的組件都會去繼承這個原始類,達到組件的一致性。


8.友好,對開發者更友好,學習成本和使用成本更低廉

  在軟件開發中,下游消費的是程序員,是將你建立的東西發揚光大的信教徒,你的佈道須要更多的友好。不然程序員心裏就會出現這樣粗俗的聲音,「你上來就給老子一棒子,寫着寫着又給老子一棒子,還玩個蛋!」


9.穩定,一切以穩定爲重,遠離危險代碼

  相信每一個公司都會安利這樣的思惟,生產代碼是能經歷風吹雨打,是能扛得住大山的。你的組件同樣必須這樣,太多的問題,最終會致使沒法維護,成本過高,問題千奇百怪等等,而後你被幹掉了。


10.特點,獨特的系統有本身的特點和亮點

  通常這個都是可選項,畢竟你想的輪子,可能前人都造了N個,你有什麼特點去讓別人去選擇你,使用你。是由於愛嗎?仍是由於愛嗎?


11.更符合使用者習慣

  站在別人的角度去思考問題,才能知作別人須要什麼,才能讓別人離不開你。


設計一套符合系統經需求的組件(面向需求的組件開發)

第一要素:以需求爲中心,以知足需求爲衡量標準

1.挖掘符合本系統的組件作基礎組件和樣本組件。

  一個系統的組件系統不多是本身從頭搭建,由於成本問題。在業務的快速迭代中,通常都會選擇一些提供原子組件的第三方的庫和包,經過包裝第三方的組件,造成符合本系統需求的組件系統。


2.構建需求組件,適應現有系統的組件模型和需求規範

  不一樣組件定義了本身不一樣的對外接口契約,變幻無窮的契約會帶來雜、亂、差。無論哪一方的組件,乃至本身的組件,都須要遵照本系統的組件模型規範。


3.可選拓展,在需求可伸縮範圍支持拓展和收縮

  在需求組件的開發中,對需求的發展,乃至回滾都有很清楚的認識。在這樣的基礎之上,能夠在組件開發中留有可選拓展項,需求伸縮和回滾都能把控。


4.適可而止,不過多設計

  一切以需求爲準,知足便是最好。


5.自描述性更高,組件設計對需求的耦合性更高,須要更多的描述

  因業務的複雜度耦合更多的獨特的規則,這樣的組件更須要更高的自描述性內容。


設計一套能夠通用的組件(面向複用的組件開發)

第一要素:以通用爲中心,以抽象共性解決同類問題爲衡量標準

1.關聯穩定的領域抽象

  通用,便是穩定的,造成共識的領域。因此通用組件,也是穩定領域抽象出的組件


2.將組件通常化

  通常組件都是爲了解決特定問題而產生的應用,將這個應用進行通常化,關聯更廣泛的業務對象


3.控制複雜度和可讀性

  越通用的組件,可複用性越高,可是複雜度性對也越高,可讀性也越差


4.一致性

  統一的接口和契約,乃至統一的對外異常暴露,只有你們越一致,更通用纔會成爲可能


5.適應性

  爲組件增長一個配置接口,爲組件伸縮提供一種可能


針對組件設計的挑戰,咱們從未由於有挑戰就中止前進的步伐,因此結合前人探索和本身開發中的經驗和理解,對於想構建一套出色的組件系統的各位攻城獅提供一個指南和參考。

後記

  關於市面上全部前端組件作過度析,確實在通用的場景下解決了咱們很高的效率,可是咱們瞭解了組件這個東西自己,再去客觀的看全部組件,下面是我發現的一些問題:

  1. 底層能力不足。基於場景化的組件,只有在適配的場景下去找適當的場景組件,可是一個場景變幻無窮,雖然最後終究能窮舉出全部場景,可否在一種方式中可知足這種變化。
  2. 組件的替換能力,在市面上的場景組件中不少都是由好多小場景組件組裝而成,是否能夠在契約相同的方式裏,不改動組件自己,經過對外暴露方法,直接替換其中的小組件。
  3. 拓展和衍生能力,最小的場景組件,是否能夠經過一種方式去衍生變種。好比按鈕,是否能夠暴露「可控補丁」,我能夠變成任何形狀,直的,方的,圓的,橢圓等等,而不是直接寫死,等待迭代。
  4. 等等.......
相關文章
相關標籤/搜索