天畫-codeMaker低代碼平臺設計與實現(下)
天畫-codeMaker低代碼平臺設計與實現(下)

一、背景
最近沒有再更新DDD相關的技術文章了,因為到了實戰環節需要大量的代碼demo,由于精力和時間有限,因此便希望借助代碼生成來解決一些模板化的工作內容。之前已經在代碼生成領域做了一些嘗試,這里便希望花一些時間專門做幾次迭代來滿足DDD項目工程實戰的問題。
二、需求
2.1 支持dubbo框架的代碼生成 需要生成的代碼元素包括facade,impl,dto,service,serviceimpl,bo,do,convert,mapper,mapperxml
2.2 支持基于plantUML類圖的代碼生成(動態DDD) 需要生成的代碼元素包括bo,acladapter,enum,factory,gataway,repository,
2.3 支持cola應用架構的代碼生成 需要生成的代碼元素包括bo,dto,vo,do,convert,facade,controller,vo,facadeimpl,mapper,mapperxml,service,serviceimpl,acladapter,factory,repository,gataway等。
三、迭代計劃
本文背景中已經點名了迭代的需求背景,因此就要按部就班的實現,為了盡快達成目標。這里分為三步走的方式。
第一版實現支持dubbo框架的代碼生成
第二版實現動態DDD代碼的生成
第三版支持cola框架代碼生成
四、設計與實現
4.1 支持dubbo框架的代碼生成
4.1.1 工程設計
這里參考下codeMaker早期的設計理念,就是生成的代碼第一不跟著真正的項目工程目錄走,第二不放在codeMaker核心工程里,而是創建與codeMaker-core模塊平級的工程,基于此工程來檢查并使用生成的代碼。因此這里創建了maven多模塊父子工程。父級工程:codemaker-dubbo
子工程:
dubbo-api:定位是dubbo consumer或者client接口,存放facade,dto.
dubbo-core:定位是dubbo provider或者server端,存放facadeimpl,bo,convert,serviceimpl,service等。
4.1.2 模型設計
之前的模型只涉及到tableBean,columnBean來表示數據庫的元數據,為了支持一套接口生成dubbo或者springboot框架的代碼需要重構代碼元素生成入口,因此增加了一個bean模型(ClassContentBean):另外需要根據配置的框架名稱來動態切換因此需要定義一些頂層接口和實現,部分UML類圖如下:
4.1.3 代碼生成配置
這里參考了基于springboot框架生成代碼的思路,為dubbo應用框架的代碼生成單獨配了一個配置文件,叫projecttemplate-dubbo.properties,內容如下:
4.1.4 代碼模板配置
在之前的介紹中代碼生成依賴的核心模板是freemarker模板,并且針對極簡模式和極速模式分別做了定制,在dubbo框架層面依然做了一些定制化的代碼模板文件,這些目標文件包括:dto.ftl,facade.ftl,facadeimpl.ftl,service.ftl,serviceimpl.ftl,test.ftl,mapper.ftl,mapperxml.ftl,bo.ftl
4.1.5 發布版本和詳情
版本號:1.0.3-SNAPSHOT
發布分支: dubbo-arch
發布內容:
1.重構代碼生成邏輯核心服務,引入應用層,支持多應用類型代碼生成架構2.支持一套api操作接口生成dubbo,springboot應用代碼3.增加dubbo應用的代碼模板,支持maven多模塊4.引入bo,facade,facadeimpl,aop,dto等代碼類生成模板5.dubbo項目支持facade層和service層雙服務層業務架構6.application.properties增加application.type屬性,值為springboot,dubbo,cola7.增加projecttemplate-dubbo.properties屬性文件,支持dubbo項目代碼生成8.原有配置文件projecttemplate.properties改名為projecttemplate-springboot.properties9.修復若干其他bug
4.2 支持動態DDD的代碼生成
4.2.0 設計概要
在決定進行這一輪迭代的時候并沒有立刻去做,而是想了兩天,DDD代碼生成本身跟傳統的代碼生成有一定的區別,最根本的一點就是DDD的代碼模型很靈活,沒有固定的模式。這就導致了基于數據庫或者基于接口文檔等的形式去做根本無法覆蓋DDD的基礎模式,反而跟基于數據庫的極簡模式和極速模式生成的代碼一樣,比較死板,分層較少。在后期迭代中代碼生成器基本上無法提供幫助了,類似于一次性使用產品。那么就需要找一個媒介或者一個容器來更容易的表達DDD可以表現的東西,在我看來DDD的最核心的東西莫過于實體,值對象,接口,枚舉,服務類等元素。另外一方面這個媒介或者容器最好可以是文檔類的軟件或者模板。
之前已經做過了通過數據庫的元數據來生成e-r圖,生成的e-r圖是基于plantUML的。由于plantUML本身支持很多場景的類圖,流程圖文檔設計。因此便對plantUML做了一些調研。發現這個軟件結合編輯器的插件和語雀文檔等平臺可以發揮設計文檔類的作用。另外一個優勢就是plantUML的類圖結構完全兼容DDD的一些概念模式和文檔樣例,這剛好契合了動態DDD的需求。這也就意味著基于plantUML的類圖做出的DDD文檔可以方便的轉換為具體的實現類。所以只要有plantUML類圖就可以生成基本模式的代碼,也方便后續迭代新模塊或者調整重構,可謂DDD代碼生成落地的一大上等神兵利器。
后面就順著這個思路做了一些調研,打算找一款java 的plantUML類圖解析工具發現沒有,但是plantUML類圖的讀寫也不是很難,因此這個難點可忽略,自己實現一個簡單的也可以。
那話不多說,下面看一下設計過程。
4.2.1 工程設計
我們參考dubbo,springboot框架的代碼生成同樣在codemaker-core工程的平級目錄下創建一個工程名為codemaker-dynamicddd。該工程跟springboot工程一樣是一個單模塊工程,其定位是基于plantUML類圖生成的代碼會單獨存放在這個模塊,同時這個模塊的定位是模塊級的應用。另外一方面我也把springboot,dubbo,cola認為是應用級的應用。
如果plantUML類圖本身是比較規范的文檔,那么生成的代碼也會比較規范,同時可以在這個工程里查看生成的代碼大概長什么樣子,需要怎么樣的調整。這也為開發者提供了一種代碼預覽的可能,避免直接上手開放,如果設計不當可以及時發現問題。
4.2.2 模型設計
同樣的,在本輪迭代中也對模型進行了一些擴展,把諸如mapper,controller,dto,bo,factory,valueobject等的代碼當作代碼元素來看待,然后讓解析出的plantUML文件內容轉換到這些代碼元素中。這輪迭代將模型分為分為兩類,一類是解析plantUML類圖進行定義的模型,如類,接口,枚舉,方法,屬性。另一類是DDD的代碼元素,比如bo(busniess object),enum,gataway,repository,factory這種的。這些代碼元素是從plantUML類圖文檔里解析出來的,因此需要先定義plantUML類圖中的代碼元素,這里做了簡單的抽象,下面看一下當前的模型類圖:
4.2.3 代碼生成配置
這里同樣參考dubbo的應用代碼生成配置單獨創建一個配置文件,名為projecttemplate-dynamicddd.properties ,內容如下:
4.2.4 代碼模板配置
根據動態DDD代碼元素的內容,我們定義如下代碼模板:abstractexe.ftl,acl.ftl,bo.ftl,enum.ftl,exeimpl.ftl,factory.ftl,gataway.flt,msgbody.ftl,valueobject.ftl
4.2.5 發布版本和詳情
發布版本號:1.0.4-SNAPSHOT
發布分支:dynamic-domain
發布內容:
1.基于plantUML文檔生成代碼,基于ddd思想和模式生成模塊級的代碼內容2.增加makeddd接口,支持生成dynamicddd模塊的代碼3.引入支持ddd代碼生成的配置(projecttemplate-dynamicddd.properties)和代碼模板(template/dynamicddd)4.codemaker-core模塊resources目錄增加ddd-plantuml目錄存放plantUML類圖5.支持ddd的一些模式代碼生成:實體模式,值對象模式,聚合根模式,工廠模式,倉庫模式,防腐層模式,服務模式,模塊模式,CQE模式,領域網關6.產出部分公共代碼生成服務方法7.優化代碼生成核心鏈路代碼模型,針對ddd代碼生成做了分層處理8.修復若干其他bug
4.3 支持cola應用架構的代碼生成
4.3.0 設計概要
4.3.1 工程設計
這里跟codemaker-dubbo類似,新建一個父子類的項目工程,名為codemaker-cola,子工程列表如下:
cola-adapter:定位是cola的適配器模塊,或者也叫端口適配層,前身名為cola-controller.所以這里主要存儲controller,vo,voboconvert的代碼元素。
cola-client:定位是cola的sdk模塊,如果融合rpc框架如dubbo,那么這個子模塊相當于dubbo-api或者dubbo-consumer.這里主要存儲facade,dto的代碼元素。
cola-domain:定位是cola的領域層,在領域層中主要包括bo,valueobject,enum,msgbody,factory,gataway,repository。
cola-infrast:定位是cola的基礎設施層,這里做了簡寫。在這一層中主要包括mapper,do,bodoconvert,gatawayimpl,repositoryimpl,acladapter(防腐層或者適配層) 另外完整的cola應用架構會包含一個cola-start的子模塊,這里做了簡化,因為一些個性化的配置一般在真正的項目中都是不一樣的,所以cola-start就不會存放代碼了,如果存放也可以,畢竟本身cola-start里面實際上就是一個Application類用來啟動項目。
4.3.2 模型設計
在DDD的代碼元素中分為兩種代碼元素,一種就是在dynamic-ddd迭代過程中定義的bo,valueobject,factory這種的原生代碼元素,另一種就是派生的代碼元素,由于基于plantUML類圖+DDD的代碼文檔,因此文檔里應該不會包含controller,facade,dto這些代碼元素,因此這些應該需要通過BO或者gataway進行派生。具體的設計包括通過BO類來派生DTO,然后派生dtoboconvert,然后派生facade等。由于facade一般也不會在DDD中體現,包括controller里面的接口因此就從BO類上做了一些擴展,增加了一些擴展key來做派生類的處理。
這么做的一個原因就是COLA架構本身就是支持復雜系統復雜業務下的應用架構,如果太簡單或者不是很復雜那么就不需要用COLA來構建工程。因為如果基于數據庫表的方式來生成代碼那么生成的代碼元素放在cola不同的子模塊下就顯得有點零散而且顯得特別少。所以如果基于plantUML+動態DDD的方式來構建的話又少了一些邊緣化的代碼元素,比如xo2xoconvert,controller。所以如果希望支持復雜業務的代碼應用就需要通過原生的代碼元素來派生一些plantUML本身不方便表達的代碼元素。下面來看一下在本輪迭代過程中的模型變化:
4.3.3 代碼生成配置
這里同樣參考dubbo的應用代碼生成配置單獨創建一個配置文件,名為projecttemplate-cola.properties ,內容如下:
#數據庫名稱cola.global.dbName=school_managercola.global.applicationName=school-manager#目標工程輸出目錄,這里填寫對應的工程的絕對路徑cola.code.outpath.cola-adapter=E:\workspace\tianhua-workspace\code-maker\codemaker-cola\cola-adaptercola.code.outpath.cola-infrast=E:\workspace\tianhua-workspace\code-maker\codemaker-cola\cola-infrastcola.code.outpath.cola-app=E:\workspace\tianhua-workspace\code-maker\codemaker-cola\cola-appcola.code.outpath.cola-domain=E:\workspace\tianhua-workspace\code-maker\codemaker-cola\cola-domaincola.code.outpath.cola-client=E:\workspace\tianhua-workspace\code-maker\codemaker-cola\cola-client#應用服務的plantUML類圖文件,不配置則走基于數據表的方式生成代碼cola.domain.plantuml=SchoolManager.puml
4.3.4 代碼模板配置
根據cola應用場景+動態ddd的能力,我們定義如下代碼模板:basController.ftl,bo.ftl,controller.ftl,convert.ftl,dto.ftl,enum.ftl,facadeimpl.ftl,gataway.ftl,dto.ftl,dtoddd.ftl,controllerddd.ftl,facadeddd.ftl,facadeimplddd.ftl
4.3.5 發布版本和詳情
發布版本:1.1.0-SNAPSHOT
發布分支:cola-arch
發布內容:
1.支持cola應用架構代碼生成,增加cola應用的template代碼模板
2.增加基于plantuml類圖的領域服務代碼生成接口
3.精簡不同應用框架的代碼生成配置
在每個應用框架配置下增加dubbo.domain.plantuml配置項,配置plantuml類圖文件名稱,支持基于類圖-ddd的代碼生成 ,如果不配置則不能借助plantuml類圖生成基于領域服務ddd的代碼,而是生成基于數據庫表的常規代碼 去除以下三個配置, 集中到application.properties文件中*.global.package*.global.author*.global.applicationName
4.在springboot,cola,dubbo的代碼模板目錄下增加ddd元素的tempalte代碼模板
5.將dynamic-ddd的代碼生成服務整合到springboot,cola,dubbo的代碼生成服務中,支持基于DDD思想的代碼生成
6.擴展plantuml中類圖標簽,基于BO派生多個代碼生成對象 (vo,dto,facade,doboconvert,controller,voboconvert,dtoboconvert)
7.整合底層代碼支持一套api,一套服務支撐springboot,cola,dubbo應用級代碼生成和dynamic-ddd模塊級代碼生成
8.修復多個兼容性bug
9.整體上支持基于數據庫表結構的代碼生成和基于plantUML類圖文檔的代碼生成
4.4 將動態DDD的能力應用到dubbo,cola,springboot應用上
4.4.0 設計概要
在cola-arch分支中已經借助cola應用代碼融合了動態DDD的代碼能力,因此如果想在功能上更加炫酷風騷,就需要將動態DDD的代碼能力融合到dubbo和springboot應用代碼上面,同時不能影響dynamic-ddd本身生成動態DDD代碼的能力,這樣的話就需要將基于數據庫表字段的元數據模型向基于plantUML類圖的class元數據模型靠攏,同時也要兼容只基于數據庫表字段的代碼生成模式。那達到的最終效果就是可以使用一套api生成dubbo,cola,springboot+動態ddd的應用工程代碼。
4.4.1 模型設計
由于1.0.3之前的版本只支持了springboot應用的代碼生成,在一路迭代之后,服務層代碼和業務模型都發生了變化,基于數據庫表字段的元數據模型需要轉換到基于plantUML類圖的class元數據模型。
最核心的一點就是TableBean對象需要轉換成ClassBean對象,同時這個ClassBean代表的是DO類代碼元素。另外一方面通過plantUML類圖中對BO的擴展就可以將DO類與BO進行關聯,這樣兩種模型就可以融為一體。具體可以參考SchoolManager.puml中的BO包。
這里我貼出來專門介紹一下:上圖以extend info為分界,以上的內容是BO類本身的數據,比如屬性,方法這些。以下則是codeMaker自動擴展的信息。繼續看一下:
tableKey:plantuml bo中的特殊屬性-表示bo-table的對應關系
facadeKey:plantuml bo中的特殊屬性-表示facade接口名稱
controllerKey:plantuml bo中的特殊屬性-表示controller類名
dtoKeyList:plantuml bo中的特殊屬性-表示dto別名
voKeyList:plantuml bo中的特殊屬性-表示vo類名
獲取學生信息:定制化方法—rpc
4.4.2 代碼生成配置
這里通過整體的設計優化之后,代碼生成配置也做了一些簡化。三大框架的代碼生成配置都做了精簡,將通用的都放在核心配置里,暫時用不到的配置全部刪掉,理論上不需要用戶花太多時間在配置上。另外代碼邏輯也做了兼容,比如每個配置文件里都有plantuml的文件名配置,如果沒有這個配置也是可以的。
4.4.3 代碼模板配置
在cola-arch中做了相對較長時間的開發,就是為了一次性將動態DDD的代碼生成能力融合到三大應用框架和架構,所以這里在不同的代碼模板目錄下增加了統一的與dynamic-ddd相關的代碼模板,有些通過數據庫實體映射的bo,dto元素會與融合后的元素相互沖突,所以這里通過加后綴來識別,比如template/cola下有bo.ftl,也有boddd.ftl,有facade.ftl,也有facadeddd.ftl。在融合之后cola,springboot,dubbo都具有了生成動態DDD代碼的能力。整體上從配置和代碼生成服務源碼上看雖然顯得有點冗余,但是為了兼容不同復雜度的應用項目,同時也為了快速實現和迭代這么做還是有價值的。
4.4.4 發布版本和詳情
由于時間和精力有限,也為了盡快將DDD系列完結所以這里不會將動態DDD融合dubbo和springboot做分別的迭代,所以一次性發布了一個稍微大了一點的版本,整體上升級到了1.1.0。通過上面的介紹可以知道從1.0.3開始到1.0.4再到1.1.0是有個完善的迭代升級的過程,這樣對于想二次開發或者直接使用的開發者來說是非常友好的。
4.5 整體架構圖
在上一篇文章中可以看到1.0.3之前的架構圖還是相當簡陋的,只有一些基礎的功能,也只支持springboot。到目前為止,經過一系列迭代之后整個架構層面,功能模塊設計層面做了一個全面的更新。這里我簡單對codemaker-core項目工程的業務邏輯做了如下分層:
4.5.1 接口層
在接口層面依然保留了之前的代碼生成模式,同時增加了更多代碼元素生成的api。由于在接口層面上做了統一,很多接口都不需要參數就可以直接訪問,所以整個接口設計和實現上盡量保持一套api支持三大架構的代碼生成。
4.5.2 代碼元素層
在代碼元素層中代碼元素這個概念在1.0.4之前的版本中其實沒有突出出來,在動態DDD代碼生成版本的迭代之后這個概念被顯示的表達出來之后很多東西都變得非常明朗,很多工作也可以圍繞這些代碼元素展開。在這一層中主要表達在代碼生成業務中,核心的模型就是代碼元素,針對代碼生成就是生成這些代碼元素表達的代碼。那么如果我想新增代碼元素的話,就可以在這一層進行定制化。如果要二次開發就可以在從這一層開始開始。
4.5.3 應用框架層
應用框架層在1.0.3和1.0.4中被逐步抽象出來作為頂層接口來看,這樣的話整個代碼生成邏輯會變得非常清晰,通過配置路由到不同的應用代碼生成服務中,通過代碼模板枚舉標示來路由到不同的代碼元素寫服務中。應用層目前看其實也比較穩定,如果要二次開發的話針對自己公司的框架進行適配也是非常方便的,因為codemaker-core工程已經提供了多個實現,參考cola,dubbo的實現邏輯二次開發完全 沒有問題。
4.5.4 服務層
這里對codemaker整個項目做了一層歸納總結,服務層提供了一些基礎能力讓上層來使用,比如生成e-r圖的,整個能力可以越過應用框架層來獨立使用。
五、使用步驟
上面說了這么這么多,那下面來真正演示一遍這個代碼生成平臺到底怎么用。
1.基礎設備:eclipse,idea,maven,mysql,plantUML插件,電腦,網絡2.準備一個數據庫,在codemaker-core的resources目錄中的application.properties配置文件中配置數據源3.在application.properties中配置要生成的應用類型,可選值是cola,dubbo,springboot.4.在對應應用類型的配置里配置要工程目錄,數據庫名稱,plantUML類圖文件名,plantUML類圖文件存放在codemaker-core的resources/ddd-plantuml目錄下。
假設是dubbo類型的應用,配置內容參考如下:
5.啟動codemaker-core工程,啟動方式參考sprintboot項目。
6.打開瀏覽器訪問127.0.0.1:8099/makeall
7.執行完成之后查看codemaker-dubbo工程下是否已生成對應項目的代碼文件。另外一方面如果不配置dubbo.domain.plantuml則只生成基于數據庫表字段的代碼文件。
8.單獨使用dynamic-ddd的代碼生成能力則只需要配置projecttemplate-dynamicddd.properties文件,內容參考如下:
#目標工程輸出目錄,這里填寫對應的codemaker-dynamicddd工程的絕對路徑dynamicddd.code.outpath=/Users/sourceSpace/code-maker/codemaker-dynamicddd#領域plantUML 類圖dynamicddd.domain.plantuml=SchoolManager.puml
9.將SchoolManager.puml文件放在codemaker-core的resources/ddd-plantuml目錄下
10.啟動codemaker-core工程
11.打開瀏覽器訪問127.0.0.1:8099/makeddd
12.執行完成之后查看codemaker-dynamicddd工程下是否已生成對應plantUML類圖的代碼文件。
六、結語
代碼生成項目到現在可以告一段落了,未來有時間的話可以基于plantUML類圖和時序圖增加一些新的功能特性,比如:
1.支持多個plantUML類圖同時解析生成代碼2.解析plantUML代碼調用時序圖融入到極速模式中。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。