1. 程式人生 > >領域驅動設計,讓程式設計師心中有碼(八)

領域驅動設計,讓程式設計師心中有碼(八)

 回顧

  領域驅動是十五年前,由Eric Evans提出的解決軟體工程複雜性問題的方法,作者從自己多年軟體開發的角度出發,通過引入領域驅動設計的概念以及一系列戰略設計模式和戰術方法,為混沌的軟體開發領域帶來了一縷陽光。

  在過去的許多年,我經歷了從技術崗位到管理崗位的變化,也深深的意識到,每一個軟體的設計與實施過程之艱辛,缺乏一些科學的管理方法,只會讓人疲於奔命,毫無積累,尤其是對於開發過程而言,看似枯燥乏味的編碼過程,卻充滿了更大的變數。

  例如,在以前傳統企業開發中設計系統架構時,往往會使用三層架構,使用者介面層,業務層,資料訪問層上手就來,但是卻看似三層分立,但是由於開發者開發過程中出現的一些不規範問題,容易在使用者介面層和資料層中堆積大量的冗餘程式碼,而中間的業務層反而非常單薄,程式碼行很少,僅僅只是實現物件的輸出而已。使用者介面層和資料訪問層就很容易成為腐化程式碼,隨著需求的變更,容易變成大泥球系統。

  尤其是那些核心模組的使用者介面層程式碼,輕易就突破了上千行,甚至上萬行,這些程式碼並非完全都是由於不規範的操作造成的,一定程度上也是由於個別開發者的程式碼不規範,形成的破窗效應。不管發生了什麼,這些程式碼最終成為一座屎山。如果再加上古人寫的儲存過程,對不起,我選擇自閉。

  屎山的命運往往都是一樣的,要麼重構成功,得以逆天改命,要麼被公司拋棄,成為企業發展過程中的一座重要里程碑。然而,往往不少程式碼都是一種使用者需求的體現,無論是重構或拋棄,都意味著對於某些需求點的放棄。

需求控制或不控制?

  使用者需求就像一個關在籠子裡的獅子,控制或不控制,這是個問題。

  對於網際網路公司而言,一定程度上來說,需求來源於產品經理的靈感乍現,或來源於對競品(被抄襲品)功能的把握,不同產品經理對於產品的規劃總是不盡相同,以及老闆和使用者的反饋也是產品需求變化的原因,需求的累積也會讓開發者為了修改而疲於奔命,而且面向網際網路的產品往往比專案型軟體成品面向更大的群體,擁有更長的生存週期,開發者為了應對需求而不節制的更改,容易成為試錯,甚至會影響企業的生存。

  所以使用領域驅動設計方法對後端的結構進行改造甚至中臺化改造成為一種非常有效的解決方案,而對於面向使用者的前臺,以及為前臺而生的BFF則由於更側重於使用者資料互動,而被排除於領域控制之外,(即 Backend For Frontend)(當然,過度的依賴前端表現層,也容易造成前端程式碼的冗餘,事實上前端和客戶端程式碼也最容易成為屎山,這是後話,就不贅述了。)

  除網際網路公司需要領域驅動的方法外,傳統軟體企業也同樣需要,在企業發展過程中,積累的無數專案,大部分專案都存在一些普遍性的共性,那就是為了盲目追求實現,而忽略了軟體程式碼的健壯性和可維護性,能否把功能強推下去,取決於專案經理對於甲方的控制力,一旦掌握優秀溝通技巧的關鍵崗位離職,這些專案都將成為一個個不知何時會爆發的地雷。軟體企業專案的複雜性,有別於網際網路企業的面對業務快速裂變帶來的變化,往往更側重於業務層面的規模複雜,一個系統的大幾百個功能點,如何保證質量,時間,成本三者的平衡,這是個恆古不變的問題。

  需求讓軟體充滿變數、而規模、質量屬性也同樣會影響到軟體的變化,要打破僵局,或許,領域驅動看似是一種不錯的選擇。

看似破解之道

  然而,領域驅動的實踐過程卻充滿坎坷,主要在於 Evans的原書,知識密度之稠,遠甚於開發者熱衷的技術話題。要解決某些技術問題,依託網際網路的資源,或許能很快找到解決問題的方法,但是面對領域驅動設計,卻讓人望而生畏,許多人都說雖然聽說這個概念的時間不在短暫,但是卻總覺得沒有入門。

  單純的從概念上看,引入的統一語言,領域儲存庫,實體,值物件,聚合根,限界上下文,上下文對映等名詞,理解上似乎很容易,但是要付諸實踐卻並非易事。尤其還需要把這些東西引入到企業實戰過程,更是難上加難。領域驅動設計方法,並不像那些技術書籍一般,拿著書上的方法,總能在自己公司找到可以實踐的點。 Evans的書也好,其他書也好,都只是方法,而不是一套行之有效,馬上就能使用的方案,需要團隊花費大量時間去應用實踐。

  例如,一種最常見的領域驅動架構的實踐是簡單四層的領域驅動分層結構,在不能有效理解關注度分離的前提下,架構程式碼同樣能成為屎山,而且似乎由於開發者知識傳承的缺失,極其容易讓人難以理解和更不用說程式碼質量的提升,只能成為倡導者實現個人價值提升的練兵場。

個人想法

  我個人認為,領域驅動設計方法,作為一種解決複雜問題的應對之道,確實值得企業對其持續關注,但是否有一種能夠便捷的方法,讓參與者能夠更快的將這麼好的方法論在產品研發過程中融匯貫通,形成更高效的應用過程呢,下面是我根據一些討論和學習過程,形成的一點思考,希望能給大家帶來一絲啟發。

  1,如何開始改變企業文化?這是來自於《例項化需求》中提出的一個問題,作者的原意是認為要實踐TDD,需要進行文化變革,事實上實踐DDD或許同樣如此。康威定律指出:一個組織拿出的技術方案設計,實際上是一個組織溝通方式的體現。你的組織真的準備好開始接受這種思想的考驗了嗎?這是個問題。

  2、確保你得到管理層的支援。這也是來自於《例項化需求》中的原話,毫無疑問,如果缺乏管理層的認可和支援,過程變更成功的機率幾乎為零。

  3、忘掉敏捷、忘掉領域驅動、忘掉概念。由於領域驅動設計方法的看似晦澀難懂,容易讓組織實踐領域驅動的人陷入學院派或教條主義的誤區,這表現在:組織者更傾向於使用專家給出的標準術語對領域驅動設計的方法進行解讀而缺乏與企業實際相結合的形式。我個人認為,為了更好的推廣領域驅動設計的應用過程,不應該侷限於教條主義,不要過分關注於概念、框架或自動化的工具,而是把領域驅動設計過程,解釋成一種發現需求、解釋需求之間的相關性、收集例項、設計測試、以及形成可自解釋的開發程式碼的過程。

  4、從一個小專案和簡單專案開始,探索建立一套行之有效的方法。從一個業務結構清晰、容易細分出應用場景和業務活動的專案出發,避免陷入大專案難以控制邊界的過程,而且大專案如果沒能更好的實施,只會一發不可收拾。有網友說,由於專案需求的極度不確定性,所以他覺得有必要引入領域驅動設計的方法來解決這個問題,我個人認為,這樣的做法只會導致專案更加一發不可收拾,尤其是在一個學習能力並不好的組織中開展領域驅動設計實踐、且大家都對這套理論一知半解的前提下。

  5,從產品語言中提煉統一語言。axure軟體的流行,讓通過原型文件這種視覺化需求表達成為主流。原型語言與需求的高度貼近,也便於產品研發團隊從中形成統一語言。

  6,形成可用的產品術語表。從統一語言出發,形成可以指導程式設計的術語表,並形成對應的中英文對照表,可以便捷的為開發過程提供變數命名的規則,尤其是許多開發者本身的英語水平就不是特別好,如果形成這樣的規則,或許能為程式碼的開發過程帶來許多便利。

  7,從統一語言和需求中提煉用例圖。按照張逸老師的說法,用例或使用者故事應該滿足6w特性,可以嘗試站在用例的角度思考這樣的問題:

  • 到底誰是使用者?需要執行這一活動的角色到底是誰?
  • 為什麼需要查詢功能?
  • 究竟要查詢什麼樣的內容?
  • 為什麼需要了解分配給我的任務情況?

  8,從用例圖和業務流程中識別限界上下文。沒必要一開始就採用四色建模法,採用比較簡單的領域場景分析的用例分析方法進行分析,同樣是不錯的選擇,例如從分析業務活動間的語義相關性,也是一種值得嘗試的方法。

總結

  人生三境界:看山是山,看水是水;看山不是山,看水不是水;看山還是山,看水還是水。大概技術領域也同樣如此。

  回到一個古老的問題,有人問:如何給一個變數命名,詞窮了怎麼辦?專家的回答是,按領域驅動設計的方法對變數進行命名。這就是實踐領域驅動設計的大師高論,已經到了看山還是山的地步。而普通開發者們,總是看了幾篇領域驅動設計的文章,就會以為嗯,我遇到的這些問題,用領域驅動能解決,然後,就陷入一堆概念之中不可自拔。

  實踐是檢驗真理的唯一標準,唯有真的使用一個專案開始實踐,才能真正體會領域驅動設計的精髓。領域驅動設計思想,是一種充滿魅力的軟體理論方法,然而要把這套理論真的用起來,依然需要經歷一個從新手到高階新手,再到勝任者、精通者和專家的學習過程。本文也同樣屬於一位處於新手村學習者的個人見解,班門弄斧,期待能拋磚引玉,措辭多有不當,還望海涵。

  參考資料:1、Eric Evans《領域驅動設計·軟體核心複雜性應對之道》

          2、張逸 《GitChat講座:領域驅動設計實戰》

         3、Gojko Adzic《例項化需求》

  ps:我本不想打廣告,不過我覺得張逸老師的課程確實講得挺不錯的,有興趣可以關注一下。