楊詠
摘 要
當(dāng)前的學(xué)生創(chuàng)業(yè)工作室擔(dān)負(fù)了比較多的功能,如果使用常規(guī)的三層設(shè)計(jì)管理系統(tǒng),會(huì)捆綁依賴較多。本文探討了使用領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)模式來(lái)進(jìn)行學(xué)生創(chuàng)新工作室管理平臺(tái)的設(shè)計(jì),基于實(shí)體模型的功能歸類,以使業(yè)務(wù)層的劃分更為清晰,從而提高了系統(tǒng)的可復(fù)用性。
關(guān)鍵詞
領(lǐng)域驅(qū)動(dòng);創(chuàng)新;管理系統(tǒng)
中圖分類號(hào): TP311.52 ? ? ? ? ? ? ? ? ?文獻(xiàn)標(biāo)識(shí)碼: A
DOI:10.19694/j.cnki.issn2095-2457 . 2020 . 14 . 42
0 前言
近年來(lái),隨著軟件行業(yè)的飛速發(fā)展,現(xiàn)在的軟件更多的更重視后期的運(yùn)維和產(chǎn)品根據(jù)需求再進(jìn)行迭代。從軟件(software)的英文單詞上來(lái)說(shuō),我們也可以理解,軟件必須保持soft,也就是必須保持靈活。軟件需要更容易被修改。因此,當(dāng)我們開發(fā)一套產(chǎn)品,如果按照傳統(tǒng)的數(shù)據(jù)庫(kù)設(shè)計(jì)模式,把業(yè)務(wù)放在邏輯層中,會(huì)容易造成業(yè)務(wù)上的重疊和混亂。你中有我,我中有你,模塊間的耦合性太強(qiáng),從而導(dǎo)致開發(fā)的人員比較難去對(duì)軟件進(jìn)行更新迭代。
DDD模式全稱是:Domain-Driven—Design。DDD模式是由Eric Evans 在2004年提出的,他發(fā)表了《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)——軟件核心復(fù)雜性應(yīng)對(duì)之道》(Domain-Driven Design –Tackling Complexity in the Heart of Software),簡(jiǎn)稱Evans DDD。[1]
領(lǐng)域驅(qū)動(dòng)模式是一種用面向?qū)ο蟮乃枷雽?duì)軟件進(jìn)行設(shè)計(jì)和建模,它拋棄了傳統(tǒng)的工程師對(duì)于數(shù)據(jù)庫(kù)的建模方式,在業(yè)務(wù)設(shè)計(jì)上,以實(shí)體領(lǐng)域來(lái)對(duì)業(yè)務(wù)的功能進(jìn)行封裝和設(shè)計(jì)。基于該模式設(shè)計(jì)的軟件產(chǎn)品,使得業(yè)務(wù)界限和功能分析相對(duì)很清楚,很好地實(shí)現(xiàn)了模塊之間的解耦??梢哉f(shuō),這些年來(lái)微服務(wù)的流行,其中很大部分也是得益于領(lǐng)域驅(qū)動(dòng)模式的設(shè)計(jì)理念。
1 項(xiàng)目背景
目前,在項(xiàng)目化進(jìn)程的教學(xué)體系下,我們高等職業(yè)院校的工科類學(xué)生幾乎都擁有相關(guān)的校內(nèi)實(shí)訓(xùn)基地,或稱為學(xué)生創(chuàng)新創(chuàng)業(yè)工作室。在日常的管理中,除了一些常規(guī)的管理活動(dòng)外,工作室還承擔(dān)了訂制一些需求的項(xiàng)目。學(xué)生通過(guò)加入這些項(xiàng)目,一方面鍛煉了自己的開發(fā)項(xiàng)目的能力,可以使自己的知識(shí)體系和能力做了一個(gè)深度融合,使得工作室能發(fā)揮最大的能動(dòng)性。通過(guò)構(gòu)建創(chuàng)新創(chuàng)業(yè)工作室管理平臺(tái),我們可以提供一個(gè)平臺(tái)給用戶去自行訂制自己所需要的項(xiàng)目,同時(shí)學(xué)生也可以根據(jù)自己的能力加入相對(duì)應(yīng)的項(xiàng)目開發(fā),達(dá)到知識(shí)能力和素質(zhì)能力的融合。
之前,我們普遍的項(xiàng)目都是采用了貧血模式的三層MVC架構(gòu)的開發(fā)。在簡(jiǎn)單的業(yè)務(wù)需求上,三層架構(gòu)也比較好的滿足了客戶的需求??墒?,我們發(fā)現(xiàn),三層架構(gòu)的項(xiàng)目后續(xù)更新,可擴(kuò)容性不強(qiáng)。比如說(shuō),在三層當(dāng)中的邏輯BLL層,因?yàn)闃I(yè)務(wù)的調(diào)整,我們添加了很多新的方法,但是這些方法與實(shí)體的關(guān)系不大。因此在邏輯分層中,不夠清晰,也因?yàn)殚_發(fā)的學(xué)生流動(dòng)性比較大,維護(hù)的團(tuán)隊(duì)上手業(yè)務(wù)需要比較長(zhǎng)的時(shí)間。創(chuàng)業(yè)工作室管理平臺(tái)業(yè)務(wù)過(guò)程比較復(fù)雜,為了能讓開發(fā)過(guò)程更規(guī)范,讓系統(tǒng)具有良好的維護(hù)性和滿足SOLID的設(shè)計(jì)原則,我們基于領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)思想設(shè)計(jì)了本系統(tǒng),更關(guān)注業(yè)務(wù)的面向?qū)ο蟮乃枷雭?lái)進(jìn)行重新封裝。在本系統(tǒng)中,我們基于領(lǐng)域模型的建立,把系統(tǒng)分析和設(shè)計(jì)做了良好的融合,使得系統(tǒng)的分層結(jié)構(gòu)更為清楚,提高了系統(tǒng)的擴(kuò)展性,讓產(chǎn)品能更靈活地根據(jù)需求進(jìn)行改動(dòng)。
2 系統(tǒng)架構(gòu)
2.1 系統(tǒng)功能設(shè)計(jì)
創(chuàng)業(yè)工作室管理系統(tǒng)功能主要包括:人員管理、圖書管理、資產(chǎn)管理、項(xiàng)目管理四六大模塊。功能模塊如圖1所示。
2.2 系統(tǒng)建設(shè)特點(diǎn)
(1)采用前沿技術(shù)。本系統(tǒng)是基于.net平臺(tái)的.netCore3.1版本進(jìn)行開發(fā),結(jié)合EFCore、 Docker、IdentityServer4,數(shù)據(jù)庫(kù)采用Mysql、MongoDB,項(xiàng)目部署在CentOS上。在對(duì)系統(tǒng)使用領(lǐng)域驅(qū)動(dòng)模型設(shè)計(jì)后,使系統(tǒng)的業(yè)務(wù)分割清楚,能夠有更大的自由度,提高系統(tǒng)的可擴(kuò)展性。
(2)高性能。本系統(tǒng)采取了B/S結(jié)構(gòu),用戶通過(guò)瀏覽器或手機(jī)API就可以直接進(jìn)行系統(tǒng)的訪問(wèn)。用戶的前端界面設(shè)計(jì)采用Vue框架來(lái)進(jìn)行數(shù)據(jù)渲染。本系統(tǒng)為了提高響應(yīng)性能,進(jìn)行了前后端分離,采用異步加Json數(shù)據(jù)加載的格式。數(shù)據(jù)庫(kù)采用Mycat中間件對(duì)Mysql進(jìn)行數(shù)據(jù)庫(kù)讀寫分離和主從復(fù)制,提高數(shù)據(jù)并發(fā)查詢能力。
(3)權(quán)限清晰。對(duì)于不同的角色,用戶可以擁有不同的操作權(quán)限。在權(quán)限分派上,分為普通用戶、管理員和超級(jí)管理員。
(4)低耦合。本系統(tǒng)中采用六邊形體系結(jié)構(gòu)對(duì)于不同的場(chǎng)景進(jìn)行邊界的劃定。在本項(xiàng)目的實(shí)際情境中,我們所有的功能基本上都是圍繞用戶的業(yè)務(wù)和項(xiàng)目的開展維護(hù)等來(lái)展開的。因此,在領(lǐng)域設(shè)計(jì)中,我們需要根據(jù)領(lǐng)域及語(yǔ)義邊界等因素確定限界上下文,將同一個(gè)語(yǔ)義環(huán)境下的一個(gè)或者多個(gè)聚合放在一個(gè)限界上下文內(nèi)。比如說(shuō),項(xiàng)目人員管理與用戶管理兩者業(yè)務(wù)關(guān)聯(lián)緊密,可以共同完成人員管理功能,兩者一起構(gòu)成人員管理限界上下文,創(chuàng)新項(xiàng)目發(fā)布則可以單獨(dú)形成項(xiàng)目發(fā)布限界上下文。
(5)信息安全。對(duì)于關(guān)鍵敏感數(shù)據(jù),比如密碼、金額,采用MD5加密算法對(duì)數(shù)據(jù)進(jìn)行加密,數(shù)據(jù)庫(kù)中存放密文或檢驗(yàn)碼,防止超級(jí)管理員進(jìn)行密碼泄露。由于在本項(xiàng)目中涉及金額的支付,因此需要采用OAuth2來(lái)對(duì)用戶進(jìn)行授權(quán)認(rèn)證。在用戶登錄部分,也結(jié)合發(fā)送手機(jī)驗(yàn)證碼方式來(lái)結(jié)合用戶的認(rèn)證。
3 領(lǐng)域驅(qū)動(dòng)架構(gòu)設(shè)計(jì)
3.1 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的優(yōu)勢(shì)
領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)區(qū)別于之前的MVC三層設(shè)計(jì)模式的地方在于:在這種開發(fā)模式下,我們必須先整理清楚系統(tǒng)的業(yè)務(wù)需求,整理好領(lǐng)域模型所包含的屬性和方法。領(lǐng)域模型相當(dāng)于可以進(jìn)行復(fù)用的Service層。對(duì)于新功能需求的開發(fā),都基于之前定義好的這些領(lǐng)域模型來(lái)完成。這樣可以保證系統(tǒng)可以準(zhǔn)確地基于業(yè)務(wù)需求的建模來(lái)實(shí)現(xiàn)。本文采用領(lǐng)域模型驅(qū)動(dòng)設(shè)計(jì)的思想,業(yè)務(wù)邏輯需要進(jìn)行分割,分析每個(gè)模塊所對(duì)接的實(shí)體設(shè)計(jì),把復(fù)雜的功能設(shè)計(jì)轉(zhuǎn)換為關(guān)注實(shí)體模型對(duì)接的業(yè)務(wù)功能并封裝到對(duì)應(yīng)的實(shí)體功能中。領(lǐng)域模型改為由更多細(xì)粒度的類組成?;陬I(lǐng)域驅(qū)動(dòng)設(shè)計(jì),可以保證系統(tǒng)的可維護(hù)性、擴(kuò)展性和復(fù)用性。
領(lǐng)域驅(qū)動(dòng)的核心應(yīng)用場(chǎng)景就是解決復(fù)雜業(yè)務(wù)的設(shè)計(jì)問(wèn)題,其特點(diǎn)與這一核心主題息息相關(guān)。對(duì)于復(fù)雜的系統(tǒng),它對(duì)代碼的復(fù)用性、易維護(hù)性要求就越高,因此,前期設(shè)計(jì)就顯得尤為重要。而基于領(lǐng)域設(shè)計(jì)開發(fā)模式,逼迫我們進(jìn)行大量的業(yè)務(wù)調(diào)研、領(lǐng)域模型設(shè)計(jì),從而更好劃分功能的界限。
3.2 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的開發(fā)流程
基于領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的開發(fā)流程顯得尤為重要。
首先,我們需要把相同業(yè)務(wù)的服務(wù)拆分成單獨(dú)的業(yè)務(wù)池,比如,在圖1中的系統(tǒng)項(xiàng)目管理模塊中,我們可以按照業(yè)務(wù)的維度拆分成項(xiàng)目情況池、項(xiàng)目分類池、評(píng)論池和搜索池。其中,每個(gè)業(yè)務(wù)依賴獨(dú)自的數(shù)據(jù)庫(kù)資源,不依賴其他業(yè)務(wù)的數(shù)據(jù)庫(kù)資源。如果當(dāng)某個(gè)業(yè)務(wù)接口出現(xiàn)兼容或發(fā)展問(wèn)題時(shí),我們只需要對(duì)業(yè)務(wù)池進(jìn)行擴(kuò)展即可,這樣就大大減少了擴(kuò)容的復(fù)雜度。
第二,根據(jù)業(yè)務(wù)接口的重要程度,可以把業(yè)務(wù)分為核心池和非核心池。比如,就項(xiàng)目情況池而言,發(fā)布項(xiàng)目、加入項(xiàng)目接口相對(duì)重要一些,可以放在核心池里面;項(xiàng)目完成情況查詢的操作就相對(duì)不那么重要,可以放在非核心池里面。通過(guò)核心接口和非核心接口的分類,我們可以對(duì)核心池的性能優(yōu)先進(jìn)行保證,從而保證整體系統(tǒng)的穩(wěn)定性。
第三,我們可以根據(jù)接入客戶端類型的不同做業(yè)務(wù)池的拆分。比如,服務(wù)于小程序或者APP頁(yè)面的業(yè)務(wù)可以定義為移動(dòng)端池,服務(wù)于內(nèi)部其他部門的業(yè)務(wù)可以定義為內(nèi)網(wǎng)池,等等。
4 創(chuàng)業(yè)工作室管理系統(tǒng)領(lǐng)域驅(qū)動(dòng)架構(gòu)設(shè)計(jì)
本系統(tǒng)中對(duì)領(lǐng)域模型驅(qū)動(dòng)進(jìn)行了具體設(shè)計(jì),其框架如圖2所示。
基于創(chuàng)業(yè)工作室管理系統(tǒng)的業(yè)務(wù)需求,對(duì)每層的設(shè)計(jì)進(jìn)行詳細(xì)說(shuō)明如下:
(1)數(shù)據(jù)訪問(wèn)層:采用MySql+MongoDB數(shù)據(jù)庫(kù)管理軟件,結(jié)合關(guān)系型數(shù)據(jù)庫(kù)和非關(guān)系型數(shù)據(jù)庫(kù)進(jìn)行業(yè)務(wù)擴(kuò)展。
(2)業(yè)務(wù)邏輯層:按領(lǐng)域模型人員管理和項(xiàng)目管理等業(yè)務(wù)進(jìn)行建模,減少業(yè)務(wù)之間的耦合成都,保證其獨(dú)立性。在實(shí)體模型中,按照領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的思想, 按實(shí)體對(duì)象中設(shè)計(jì)相關(guān)的屬性和功能設(shè)計(jì)。
(3)UI層:本系統(tǒng)前后端分離,后端曝露接口給前端調(diào)用。因此,切分APP端用戶、Web端用戶相對(duì)容易。在前端部分,采用Vue框架進(jìn)行頁(yè)面數(shù)據(jù)渲染,異步加載數(shù)據(jù),從而提高響應(yīng)速度。
5 系統(tǒng)部分實(shí)體模型設(shè)計(jì)
在實(shí)體Entity部分,主要分為UserInfo類和ProjectInfo類。本文羅列了UserInfo類的設(shè)計(jì)。
UserInfo類設(shè)計(jì)如下:
[Table("UserInfo")]
public partial class UserInfo{
/*用戶信息部分,包含消息驗(yàn)證以及角色校驗(yàn)*/
public UserInfo(){
UserInfoTokens = new HashSet
UserInfoLoginLogs = new HashSet
UserInfoRoles = new HashSet
}
public Guid Id { get; set; }
public string Account { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string MobilePhone { get; set; }
public string Password { get; set; }
public string Salt { get; set; }
public string Sex { get; set; }
public bool Enabled { get; set; }
public bool IsAdmin { get; set; }
public DateTime CreationTime { get; set; }
public int LoginFailedNum { get; set; }
public DateTime? AllowLoginTime { get; set; }
public bool LoginLock { get; set; }
public DateTime? LastLoginTime { get; set; }
public string LastIpAddress { get; set; }
public DateTime? LastActivityTime { get; set; }
public bool IsDeleted { get; set; }
public DateTime? DeletedTime { get; set; }
public DateTime? ModifiedTime { get; set; }
public Guid? Modifier { get; set; }
public Guid? Creator { get; set; }
public virtual ICollection
public virtual ICollection
public virtual ICollection
}
6 小結(jié)
本文基于領(lǐng)域驅(qū)動(dòng)設(shè)計(jì),根據(jù)創(chuàng)業(yè)工作室管理系統(tǒng)完成了整個(gè)系統(tǒng)的架構(gòu)設(shè)計(jì),并根據(jù)人員管理和項(xiàng)目管理模塊的具體業(yè)務(wù)邏輯進(jìn)行領(lǐng)域模型設(shè)計(jì)。運(yùn)用領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)可以解決復(fù)雜的業(yè)務(wù)邏輯問(wèn)題,領(lǐng)域?qū)ο蟮墓δ茉O(shè)計(jì)對(duì)接了實(shí)際的業(yè)務(wù),讓領(lǐng)域?qū)ο笥辛肆己玫穆氊?zé)劃分和功能體現(xiàn)。
對(duì)于領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)模式,更多應(yīng)用結(jié)合在微服務(wù)的場(chǎng)景下。對(duì)于功能性要求不高,投入不是很大的項(xiàng)目,一開始就上微服務(wù),反而會(huì)使得開發(fā)效率更慢。由于本項(xiàng)目設(shè)計(jì)受技術(shù)以及團(tuán)隊(duì)等因素影響相對(duì)較小,主要考慮職責(zé)單一性,因此暫時(shí)不考慮拆分微服務(wù)。以后隨著用戶數(shù)量的增加,以及更多的投入,在產(chǎn)品迭代和重構(gòu)中再進(jìn)行相關(guān)的功能拆分。
參考文獻(xiàn)
[1]實(shí)現(xiàn)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)[M].北京:電子工業(yè)出版社,2014.
[2]微服務(wù)架構(gòu)設(shè)計(jì)模式[M].北京:機(jī)械工業(yè)出版社,2019.
[3]梁小鷗.探析思維導(dǎo)圖輔助系統(tǒng)在高職計(jì)算機(jī)網(wǎng)絡(luò)專業(yè)學(xué)習(xí)中的應(yīng)用[J].現(xiàn)代計(jì)算機(jī),2019.
[4]張金松.領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)在航務(wù)海事系統(tǒng)中的應(yīng)用研究[D].2010.
[5]趙悅,杜俏俏.基于領(lǐng)域驅(qū)動(dòng)的專利申報(bào)系統(tǒng)設(shè)計(jì)[J].2017.
[6]王敬林.基于微服務(wù)架構(gòu)的鐵路企業(yè)年金系統(tǒng)的研究和關(guān)鍵技術(shù)實(shí)現(xiàn)[D].2019.