电竞比分网-中国电竞赛事及体育赛事平台

分享

你或許以為你不需要領(lǐng)域驅(qū)動設(shè)計

 黃爸爸好 2019-11-03

作者:鄒溪源,長沙資深互聯(lián)網(wǎng)從業(yè)者,架構(gòu)師社區(qū)合伙人!


猶記得剛剛參加工作時,是地圖廠商四維圖新集團旗下的一家子公司,主要從事規(guī)劃測繪相關(guān)軟件研發(fā)的公司。當時我的項目是為勘測設(shè)計院提供相對應(yīng)的應(yīng)用軟件,對地理信息和規(guī)劃相關(guān)的圖紙信息領(lǐng)域的認知,幾乎已經(jīng)專業(yè)水平。事實上,規(guī)劃設(shè)計大概和軟件設(shè)計類似,有規(guī)劃的設(shè)計、或無規(guī)劃的設(shè)計,造成的結(jié)果幾乎是天壤之別。
我們或許很容易就能設(shè)想到一個毫無規(guī)劃設(shè)計的城市,縱橫交錯的路網(wǎng)、雜亂無章式的建筑布局、各種凌亂的棚戶區(qū)設(shè)計,恰好象征著軟件設(shè)計的無序性,也恰好體現(xiàn)了軟件企業(yè)在經(jīng)費不足、組織缺乏管理、開發(fā)者能力不足、軟件隨時隨地想改就改時的行業(yè)現(xiàn)狀,只能說這樣的軟件是最能符合當時實際勞動生產(chǎn)力水平的產(chǎn)品。

圖一:巴西棚戶區(qū)
如圖一所示,巴西棚戶區(qū),層層疊疊、風格迥異、密密麻麻,如果作為一個外人貿(mào)然來到這樣的地方,大概很容易迷失期間、更不用說充斥在棚戶區(qū)的各類毒品和黑社會。雜亂無章的建筑和街區(qū),就像代碼中錯綜復雜的調(diào)用鏈;而借助貧民區(qū)搞事的黑社會就像是代碼中的異味或者bug,表面上看起來如此平靜、與世無爭、但是你永遠也不知道啥時候會來一冷槍。
不要以為離我們很遠,我們其實輕易就能寫出這樣的軟件工程項目。不一定是“大泥球”系統(tǒng),也有可能只是一些看似簡單的業(yè)務(wù)系統(tǒng),但內(nèi)部代碼邏輯,可能會復雜到令人窒息的程度。也許那個時候有個別開發(fā)者也許會試圖靠自己的能力來改變局面,但是往往也會礙于屎山太大,難以下咽。
大概只有最頂級的規(guī)劃設(shè)計師、耗費足夠多的資源,才能將這樣的軟件系統(tǒng)進行整改。然而,即便如此,如果以后沒有持續(xù)維護的手段、更好的設(shè)計、僅靠老程序員或個別架構(gòu)師、盲目相信將單體服務(wù)拆分成微服務(wù),幾乎不太可能實現(xiàn)軟件未來的可持續(xù)發(fā)展。
一個良好的軟件產(chǎn)品的一生、或許其實是一家企業(yè)一生的真實寫照。
在特定組織架構(gòu)下,缺乏技術(shù)基因的組織有時候期待技術(shù)變革,卻會開啟新的泥坑。而那些渴望靠技術(shù)改變一切的技術(shù)專家,雖然擁有某些大廠微服務(wù)式架構(gòu)、以及架構(gòu)改造的經(jīng)驗,他們也試圖通過自己的努力,為企業(yè)業(yè)務(wù)騰飛助力。而在他們過去的經(jīng)驗中,往往相信組織遇到的問題,用微服務(wù)一定能解決問題。然后大肆擴招,一年內(nèi)從幾個人的規(guī)模、擴招到數(shù)百人的規(guī)模,將原來的系統(tǒng)從單體服務(wù)、改良成為微服務(wù)。但是靠單槍匹馬根本無力拯救大勢,沒有更好的業(yè)務(wù)拆分策略,就只能按照數(shù)據(jù)庫的表名關(guān)系實現(xiàn)了最簡單的拆分。架構(gòu)改造并非每次都會百試百靈,有時甚至連原來的需求都包不住,畢竟只能看到用戶界面層外觀上的表面邏輯,而隱藏在業(yè)務(wù)中的那數(shù)十萬行代碼,哪怕包含了企業(yè)最有價值的經(jīng)驗財富,也由于代碼過于混亂,最終拋棄在源代碼管理器中,堪稱化神奇為腐朽。

老系統(tǒng)改造也好、新系統(tǒng)開發(fā)也好,毫無疑問,我們最容易相信的其實是老程序員經(jīng)驗,而程序員們掌控系統(tǒng)的方式,就是靠數(shù)據(jù)庫建模來驅(qū)動軟件開發(fā)的古老模式,而且?guī)缀醵际敲嫦蜻^程式的代碼,這些代碼的流程幾乎一模一樣,只需簡單的按照步驟,一步步套模式,輕易就能學會。
1、查看用戶界面,定義需要綁定到界面的模型和層級結(jié)構(gòu)。
2、設(shè)計數(shù)據(jù)庫,不管什么類型的項目,先根據(jù)客戶提供的業(yè)務(wù)表單、將其轉(zhuǎn)化成實體關(guān)系(ER圖)、然后建立對應(yīng)的代碼模型。有可能使用專業(yè)軟件設(shè)計ER圖,也有可能會使用Navicat軟件設(shè)計ER圖。
3、設(shè)計接口,然后把數(shù)據(jù)拼湊成用戶界面層所需的對象。
4、代碼層次結(jié)構(gòu)為傳統(tǒng)的三層架構(gòu),嚴格按照用戶界面層、業(yè)務(wù)邏輯層、數(shù)據(jù)訪問層進行設(shè)計,有時候會引入依賴注入框架,實現(xiàn)不同層次間的解耦。
但是有時候程序員不會嚴格區(qū)分需要編寫的代碼,究竟是屬于哪個層次應(yīng)該囊括的內(nèi)容。于是毫無疑問,如果代碼是為了實現(xiàn)用戶界面上某些數(shù)據(jù)綁定操作,代碼就往用戶界面層寫;或者代碼是為了實現(xiàn)從數(shù)據(jù)庫中抽取某些復雜數(shù)據(jù)、并構(gòu)造成滿足用戶表現(xiàn)層邏輯的查詢對象,那么就可以看到數(shù)據(jù)訪問層代碼中那些臃腫的SQL語句或查詢方法。
正如“羅馬不是一天建成的”,屎山也同樣如此。這樣的寫法在代碼剛剛編寫之初并沒有問題,只是隨著業(yè)務(wù)變化、時間的積累、程序員的水平、方法重構(gòu)、新技術(shù)新組件的引入,代碼將成為屎山。
這時,高級程序員們的價值,就在于他如何能夠在屎山中快速找到bug、并解決問題的能力,這大概是一種不能復用、不可再生的能力,因為永遠有讓人看不懂的垃圾代碼,而且每家企業(yè)都有自己的特點,不同企業(yè)間往往不能循環(huán)利用。我一位朋友經(jīng)常吐槽,他感覺自己的價值就是守住公司那份擁有8年歷史的古老代碼,以便其他程序員在進行代碼修改時,不會引發(fā)莫名其妙的bug讓系統(tǒng)無法運轉(zhuǎn)。

在現(xiàn)代軟件工程學的教科書中,都會指出面向?qū)ο笫墙鉀Q軟件復雜性的方法,但實際上掌握這種方法的開發(fā)者并不多。由于開發(fā)者普遍缺乏抽象化思維,所以面向數(shù)據(jù)庫、面向過程式的編程習慣能夠成為業(yè)界主流,并非時代的倒退,而僅僅只是在短期效率和長期維護性上,被迫做出的艱難選擇。
假設(shè)我們設(shè)計出的符合三層架構(gòu)的系統(tǒng)結(jié)構(gòu)圖簡化后,如下圖所示:

我們來看看這種數(shù)據(jù)庫建模的開發(fā)流程中的輸出成果:
1、會定義兩種對象,分別是是面向UI層的模型(DTO)和數(shù)據(jù)實體(Entity)。在領(lǐng)域驅(qū)動設(shè)計中,將這兩種稱為所謂貧血模型,貧血模型,只有賦值器Set和取值器Get,(在Java里面會使用POJO 這個名詞來定義)。貧血模型是為了作為保存狀態(tài)或傳遞對象而存在,他并非按照實際用例場景對某類具體事務(wù)的抽象、也沒有與對象相關(guān)的行為。
2、定義數(shù)據(jù)訪問層來實現(xiàn)數(shù)據(jù)的持久化、或者從持久層實現(xiàn)數(shù)據(jù)的創(chuàng)建過程。數(shù)據(jù)訪問層存在的目的是為了構(gòu)建上述貧血模型對象,這種訪問機制被成為“事務(wù)腳本”。事務(wù)腳本與對象行為割裂,而且容易導致異味產(chǎn)生。
3、與用戶行為相關(guān)的操作割裂的存放在不同層。有的可能放在用戶界面層、有的可能放在數(shù)據(jù)訪問層、有的可能放在業(yè)務(wù)邏輯層,造成了領(lǐng)域知識的丟失。
4、用戶界面層使用接口作為外觀或者一種行為、開發(fā)者會使用自己獨立的風格習慣來定義這種行為,就容易造成術(shù)語和規(guī)則不統(tǒng)一,也會為后期產(chǎn)品的維護迭代造成問題。
5、現(xiàn)在的軟件設(shè)計,往往要求輸出一份高保真的原型圖、也會按照敏捷項目管理的流程對這份原型圖建立持續(xù)更新的機制,確保原型圖是需求的具體表達,但是產(chǎn)品語言并非統(tǒng)一語言,也許產(chǎn)品語言具有業(yè)務(wù)含義,但是由于不能指導開發(fā)者進行接口、類、持久層的設(shè)計,造成了代碼與需求的割裂。在張逸老師的《領(lǐng)域驅(qū)動戰(zhàn)術(shù)實踐》提到他曾經(jīng)使用dimension和metric兩種不同的對象來定義一個維度對象,為代碼造成了不必要的麻煩。我也曾經(jīng)在一個項目,遇到過產(chǎn)品術(shù)語未能澄清,導致開發(fā)中使用style和theme兩種截然不同的定義來定義與“風格”相關(guān)術(shù)語,為代碼引入了不必要的糾結(jié)。

領(lǐng)域驅(qū)動設(shè)計引入了以下概念,但是我們無需在這篇文章中深刻理解這些概念的具體含義,我們只需知道,有這個東西。當我們開始按照領(lǐng)域驅(qū)動設(shè)計的方法設(shè)計一個系統(tǒng)時,按照前人整理的領(lǐng)域驅(qū)動的sample,往往就會將概念融匯貫通,達到更好的理解效果。
1、統(tǒng)一語言:定義好產(chǎn)品原型,需要建立統(tǒng)一語言。這是一種在內(nèi)部和外部都能使用的規(guī)范化用語,包括UML、適當?shù)膱D、一致性的描述、以及專業(yè)術(shù)語和術(shù)語對應(yīng)的英文描述。
2、實體:在領(lǐng)域中可以通過標識進行唯一值定位的對象。
3、值對象:在領(lǐng)域中,從其他領(lǐng)域或某個實體中分離出只包含某些特定屬性的對象。由于不具備唯一性特征,往往無需用于數(shù)據(jù)持久化。
4、聚合、聚合根:將具有相關(guān)性的對象聚合在一起,并以聚合根的形式統(tǒng)一對外提供訪問方法和屬性字段成員。
5、限界上下文:領(lǐng)域包含核心領(lǐng)域、子域和通用子域,而限界上下文則是一個具體業(yè)務(wù)的流程。每個限界上下文獨立于其他限界上下文而存在,獨立演進、功能完備。限界上下文的識別充滿技術(shù)含量。
6、領(lǐng)域服務(wù):包括倉儲服務(wù)和工廠服務(wù),前者負責實現(xiàn)對象與數(shù)據(jù)庫的操作過程、封裝了一系列數(shù)據(jù)庫操作的方法;后者則側(cè)重于對象的創(chuàng)建過程。個人認為從三層架構(gòu)演進到領(lǐng)域驅(qū)動架構(gòu)過程中,倉儲服務(wù)是最接近于數(shù)據(jù)訪問層的邏輯,也是讓大部分領(lǐng)域驅(qū)動架構(gòu)最終又回歸到三層架構(gòu)的一種通病。從對數(shù)據(jù)訪問層中抽出對象、行為、數(shù)據(jù)訪問,是戰(zhàn)術(shù)設(shè)計的關(guān)鍵步驟。
領(lǐng)域驅(qū)動設(shè)計引入了一堆新的架構(gòu)形式,包括經(jīng)典的四層架構(gòu)、EDA(事件驅(qū)動架構(gòu))、CQRS架構(gòu)(命令查詢職責分離)。而由于Evans的原書沒有過分討論如何識別領(lǐng)域,后來又有許多大佬在他的基礎(chǔ)上進行了完善,提出了許多方法,包括名詞、形容詞、動詞建模法、事件風暴、四色建模等方法,限于篇幅,且聽下回分解。

領(lǐng)域驅(qū)動設(shè)計,或許是解決這些問題的一劑良方,但也或許是開啟了暗黑世界的大門。
概念晦澀難懂、程序員們不愿意開始思維變革、技術(shù)上可能存在不預期的坑、都可能讓新方法的實踐陷入一灘爛泥。還有許多人以為自己看懂了領(lǐng)域驅(qū)動設(shè)計(包括筆者),在往項目中運用時,總是有意無意的會被過程式代碼的思維定式控制,讓架構(gòu)回退到三層架構(gòu)。
由于微服務(wù)架構(gòu)的興起,讓復雜系統(tǒng)的開發(fā)維護成為大家普遍關(guān)心的問題,使得Eric Evans于十五年前提出的這套理論,在今天綻放出了新的光芒。當然領(lǐng)域驅(qū)動設(shè)計僅僅只是眾多面向?qū)ο缶幊痰囊环N實踐,通過領(lǐng)域驅(qū)動設(shè)計將UML等方法靈活的運用其中,通過打破原有數(shù)據(jù)庫關(guān)系建模給代碼造成的桎梏,讓開發(fā)者能夠真正的實現(xiàn)面向?qū)ο缶幊獭?/span>
然而思維模式的轉(zhuǎn)換并非易事,從過程式代碼中,抽離出與對象有關(guān)的行為,遠比理解這幾個概念要復雜,這需要大量經(jīng)驗的積累。

毋庸置疑,數(shù)據(jù)庫建模驅(qū)動軟件開發(fā)具有速度快、學習成本低的顯著特點,在許多項目中,能在短期內(nèi)可以給開發(fā)者帶來許多便利;而應(yīng)用領(lǐng)域驅(qū)動設(shè)計,則可以在更長的維護周期內(nèi),給軟件維護帶來實質(zhì)性好處。
兩種不同類型的開發(fā)模式,根據(jù)企業(yè)實際出發(fā)進行選擇,還只是開始,但能真正運用好領(lǐng)域驅(qū)動設(shè)計或者UML、面向?qū)ο笤O(shè)計這種軟件工程的美學思維來改造我們的系統(tǒng),讓系統(tǒng)綻放出更加璀璨的光芒,這才是軟件設(shè)計的樂趣所在。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多