做者 Kid 螞蟻金服·數據體驗技術團隊前端
隨着咱們解決的場景愈來愈專業化和複雜化,大型SPA應用的流行,前端承擔的職責愈來愈多。代碼的質量和系統的完整性愈來愈難把握。很容易致使迭代着迭代着發現代碼改不動了。最後只能新起爐竈,從新開發。歸根到底在於複雜度的失控
,本文會嘗試分析其中的問題以及從前端如何應用領域模型
開發的角度給出一些建議。vue
咱們的系統架構精心設計過,按照標準的系統分層來管理複雜度。邏輯層
,展現層
,數據層
。每一層都精心設計。咱們抽象出獨立的類來放通用邏輯。對着代碼不斷地重構,將有複用能力的點進行抽象。爲何需求的變更仍是能常常摧毀咱們的設計呢。react
緣由在於:git
軟件自己是爲了管理複雜度,咱們如今面對的問題域錯綜複雜。爲了建立真正好用的軟件,開發者必須有一整套與之相關的知識體系。爲此要知道的知識的廣度讓人生畏。一旦咱們不能理解問題域,咱們就無法作到控制問題域的複雜性。程序員
當複雜性失去控制的時候,開發人員就沒法理解軟件。當領域的複雜度沒有獲得解決時,基礎技術再好的構思也無濟於事。github
上面我所描述的設計都是技術層面
的設計。咱們很容易抽象出一個獨立的類來放通用邏輯,但是很難給它業務上的定義
!這個通用類只有技術維度上的通用。數據庫
問題在於技術維度上的通用很容易被業務摧毀
。需求上的變更或者膨脹,技術維度的通用很容易被摧毀。舉個例子,頁面變化了,某個視圖組件被複用了,他可能就要被提取到上層的common目錄。也就是技術模型馬上須要從新設計,而後就是重構,重構成工程師喜歡的簡潔的樣子。而後需求再變化,再重構....陷入了怪圈。編程
而且這個階段咱們很難保證重構的高效進行,有個理論叫破窗戶
理論。一幢年老的大樓,一旦第一扇窗戶破了,就會馬上給人一種年久失修,腐敗的跡象。就像是一輛車,一旦第一個車窗壞了,裏面很快就會遭到破壞。後端
裏面的根本緣由就是咱們設計的技術模型
與領域模型
不匹配。因而每次需求的改動,映射到技術模型的改動可能就是極大的工做量。甚至根本改不動,在業務壓力很大的時候,咱們只能告訴產品經理,這個能夠作,可是咱們須要2個月。結局極可能就是需求方的妥協,犧牲用戶的利益。致使產品愈來愈難用。架構
任何項目都會丟失知識,外包出去的系統可能只交回了代碼,知識沒有傳遞回來。離職了,轉崗了,一旦出於某種緣由人們沒有口頭傳遞知識,知識就丟失了。
丟失的知識也會致使系統愈來愈難維護,新同窗不知道對於通用邏輯的改動會發生什麼事情,代碼最終變成了「石油坑」,越陷越深,最終沒法自拔。
以上這三個問題歸根到底,就是咱們沒有在前端代碼裏把咱們業務描述清楚。咱們不少狀況下是視圖驅動
,而不是業務驅動
。不少時候只關心頁面長什麼樣子,發了什麼請求拿了什麼數據。因而在業務概念上每一個人理解的深度都不一樣。解這個問題可能採用新的領域驅動設計的開發方式會比較合適。
領域模型是跨前端-後端-產品-設計的統一的語言。統一的語言既能夠造成統一的理解,也能夠促進領域模型的不斷精化。也能迫使開發人員學習重要的業務原理,而不是機械的功能開發。產品經理也會不斷提煉知識,昇華自身理解。若是沒有一個統一的,有共識的結構化的模型,必定會讓項目很快的僵化,最後變成維護代價極高的遺留系統。
領域模型不少狀況下都是由後端同窗創建的,前端同窗如何指導開發呢?我對於咱們系統的演進過程進行了總結,但願能給你們一些靈感:
咱們在進行前端設計以前要搞懂咱們要開發的業務含義。除了本身理解創建模型以外咱們能夠尋求後端同窗的幫助。拿到他們的領域模型
,弄清他們的模塊劃分。他們實際上是業務邏輯的最終實現方,咱們能夠直接借鑑他們的模型,這樣也能夠保證先後端對於業務模型的理解一致。
咱們要繪製出前端的領域模型圖,這個圖與後端的領域模型圖一致程度很高,但毫不是同樣
的。一般比後端模型簡單。好比頁面須要進行一項任務的配置,這個配置在後端模型裏可能會被解釋的至關複雜(會被拿去作一些同環比之類的複雜操做),可是在咱們前端模型裏,他的業務功能就是簡單的任務配置而已~
如圖,這一點是必須落到代碼上的核心
!!必定要根據對應的前端領域模型在代碼中分離出單獨的領域層。模型必須與實現緊密結合,必定要指導設計,並落到代碼上成爲最終產品的一部分
。
還須要強調的是領域層的建設必定不是兩個頁面同時發了個請求,因而把這個請求抽出來,給與一個領域的名字。他必定被提早創建好
的。在開始進行前端設計以前就被設計出來的一層。
咱們要將全部頁面組件與模塊內的業務行爲都抽離出來,放在合適的領域模塊中。只要是業務行爲,必定有一個領域模塊能夠落
。若是不行就是領域模型設計的不合理。
要明白,驅動領域層分離的目的並非頁面被複用,這一點在思想上
必定要轉化過來。領域層並非由於被多個地方複用而被抽離。它被抽離的緣由是:
穩定
的(頁面以及與頁面綁定的模塊都是不穩定的)解耦
的(頁面是會耦合的,頁面的數據會來自多個接口,多個領域)極高複雜度
,值得單獨管理(view層處理頁面渲染以及頁面邏輯控制,複雜度已經夠高,領域層解耦能夠輕view層。view層儘量輕量
是咱們架構師cnfi主推的思路)以層爲單位
是能夠被複用
的(你的代碼可能會拋棄某個技術體系,從vue轉成react,或者可能會推出一個移動版,在這些狀況下,領域層這一層都是能夠直接複用)衍進
(模型存在的目的是讓人們聚焦,聚焦的好處是增強了前端團隊對於業務的理解,思考業務的過程才能讓業務前進)這裏想引用下咱們leader導演的話說,咱們的競爭力毫不僅僅只是前端,咱們的競爭力在於咱們是數據部門的前端,在於咱們對於數據業務的理解。只有對於業務有深層次的理解,才能將系統帶到正確的軌道上來。
接口約定儘可能由前端主導
,畢竟接口是給前端使用,前端來設計接口比較合理。並且在約定的過程當中,前端同窗又多了一次熟悉後端是如何分模塊的機會。必須經過看後端同窗的數據庫和總體的設計文檔來約定接口路徑和變量名稱,也可以讓先後端同窗對於系統的各部分的命名一致。
咱們在類,方法,模塊命名時要直指業務核心
,保持與領域模型的一致。好比一條員工數據記錄可能會被翻譯成 inputRec或者employeeData, inputRec其實就是一個計算機思惟的術語,而employeeData纔是直指問題領域。這個錯誤其實很容易犯,咱們開發的程序員思惟根深蒂固
。
確保團隊內部全部同窗都要熟悉系統的模型。尤爲是對於要熟悉並修改代碼的新同窗,先向他們分享咱們系統的領域模型以後再介紹技術架構。工做開展的重點的不一樣會致使編程世界觀的不一樣。這樣子會讓新同窗養成習慣,在進行技術決斷以前先判斷是否符合現有的模型。不斷的思考模型,纔可以幫助咱們業務成長。
領域驅動設計對於下降項目的複雜度上是明顯效果的,並且將前端的代碼業務邏輯和視圖邏輯解耦。能夠作到業務邏輯層的複用。加深了前端同窗對於業務的理解和思考,能夠促進業務發展。這種分層思想並不侷限在某個框架下,建議你們嘗試下~
對咱們團隊感興趣的能夠關注專欄,關注github或者發送簡歷至'tao.qit####alibaba-inc.com'.replace('####', '@'),歡迎有志之士加入~