突破 CRUD - 簡單優雅的代碼生成工具誕生記(萬字長文慎入)
0、學習本文你或許可以收穫
1、一個需求從產生、分析到解決的全過程思考
2、簡單的面向對象分析實踐
3、UML 類圖實踐
4、設計模式的實踐應用
5、最後收穫一款還算不錯的代碼生成工具實現思路和源代碼
本文將從上面第一點提到的全過程 需求 -> 目標 -> 思路 -> 設計 -> 實現 -> 總結 逐一展開。
本文爲了儘量還原真實場景下如何從無到有實現一個需求,所以全文會假設大家都不懂代碼生成這個東西。是需要從零開始研究的。
下面開始正文。
1、先看需求
某日,風小南(年輕時的自己)代碼寫的正酣,技術經理突然走了過來,拍拍了風小南肩膀。
“小南啊,你看咱這個系統裏面這麼多增刪改查的功能,雖然拷貝複製可以,但是效率還是不夠高”。
風小南心想
"都 CV 模式了效率還不高,你咋不上天呢 ?"。
緊接着,技術經理說道
你看,現在這個用戶管理模塊做完了,我做其他角色、機構管理時,代碼的規範、基本的增刪改查結構是一樣的對吧,確實可以快速複製實現其他兩個功能,但是這中間有幾個問題仍然影響效率
第一:文件重命名問題,一個基本的模塊從前臺到後臺大概 7-10 個左右的代碼文件,在複製的同時均需要重新命名,文件數量這取決於每個公司的開發體系和標準。文件數量也可以更少,或者更多
第二:實體屬性肯定有存在不一樣的吧,需要修改或新增,這有一部分工作量
第三:類上,方法上,字段上的備註都需要調整吧,比如用戶管理類的備註是用戶管理,那你拷貝成角色管理得改成角色管理吧。方法字段都一樣得調整下吧
第四:類中的屬性、方法名、局部變量等也會需要跟着變化,比如,UserController 注入的 UserService,方法內部聲明的 userList 變量,那拷貝成角色管理對應的名稱均需要調整爲 roleXXX
第五:多餘不用的方法需要一個個刪除
第六:還有個嚴重的問題,就是拷貝完後經常會有人忘了改上面說的幾點內容,導致代碼可讀性降低。
風小南結合自己實際寫代碼時的情況還真是存在這樣的問題,不禁感到 CV 大法在複製整個模塊時,還真是不太方便快捷,那怎麼解決呢?風小南心生疑惑。
“你這兩天給咱研究一下,看行業內還有沒有更有效的解決方案。你先嚐試着弄,有什麼問題咱們隨時溝通(話外音,有什麼進展問題要及時主動彙報)”
說完,技術經理轉身就走了。
哎,故事寫的不好,湊合着看看,核心需求表達到就 OK 了。
2、初步探索
研究新技術那可是風小南最喜歡的事情了,只不過現在還沒有明確的方向,自己之前也沒有這方面的經驗,這時候能給自己指明道路的就是前輩或搜索引擎了,作爲愛折騰技術的風小南,那必然是先自己搜索研究一番,短期內沒結果的話在請教下前輩。總之原則就是,不耽擱公司的事情,任務按時完成就 OK。
打開搜索引擎,咋搜呢?風小南發現不知道該輸入什麼關鍵字才能找到想要的東西,得先確定下關鍵字。既然是代碼拷貝相關問題,那假設有相關工具或解決方案之類的東西,應該也會叫 “代碼 XX” 吧。
既然跟效率有關,先來個 “代碼效率” 搜一波吧。截圖部分圖,結果如下
image.png
大概看了下內容,發現都是跟代碼調優加快執行效率相關,並非提升代碼開發效率,那就關鍵字不對,還得調整。
風小南又想了想,代碼拷貝工具?代碼複製工具 ?仔細想想應該都不對,但還是嘗試了一波,果然沒有找到想要的結果。
效率不就是要速度快麼,“代碼快速開發” 這個咋樣呢,再試試。搜索結果如下
image.png
列表出現了一系列快速開發平臺,而且頻繁出現了「代碼生成」這個詞,直覺告訴風小南這不就是自己心裏想要的那個但不知怎麼表達的那個關鍵詞嗎。風小南又補充了一點既然公司用的是 Java,那搜「Java 代碼生成」肯定更準確一點。至此,關鍵字確定了就是「Java 代碼生成」。
操作激動顫抖的雙手,在搜索引擎敲下了「Java 代碼生成」,點擊搜索。
image.png
風小南迫不及待點開幾篇大致瀏覽了下內容,隨後又調整了幾次關鍵字,「Java 代碼生成工具」、「Java 代碼生成器」搜索查看了一波資料後,看了相關的實現思路,不禁大喜 “這不正是我們需要的東西嗎,自主生成、模板定製、一步到位”。什麼改變量名,重命名、備註問題統統不存在,風小南心裏大致有譜了。
實現方式大致兩種,一種藉助現成的代碼生成平臺,第二種就是自主實現,需要藉助模板引擎技術,這裏就存在技術方向的確定,需要跟領導彙報了。
風小南將查閱到的資料和自己的理解整理成文檔,發給技術經理(主動及時溝通、彙報很重要),併到技術經理的工位旁進行簡要彙報,技術經理聽完又大致瀏覽了風小南整理的資料,說道:
做的不錯,咱們公司有自己的研發平臺,代碼生成工具最好是能直接跟咱們現在的平臺融合起來,我看了下現成的代碼生成工具跟咱現在的平臺不好融合,而且功能太多,使用的技術標準也不太一樣,我們自己實現一套簡單的吧,解決當下核心問題就行,不用太複雜。還是交給你來做吧。
風小南聽到這,那個高興啊。天下還有比擼代碼更開心的事嗎?有,那就是擼自己不會的代碼。哈哈。
至此,前期方案的初步探索就完成了。
探索階段的工作往往容易不好把控,原因在於探索那一定是未知的領域、未知的問題,任務本身不具體,不知道最終會做成什麼樣,時間週期可能還長,這時候需要注意的就是自己工作的方式方法。要點就是及時溝通匯報進度。
3、工作任務書
任務有了,大致目標有了,但是還不夠具體,爲了防止最後做出的東西跟技術經理想要的不一樣,我還是把剛纔談話的內容梳理一下,形成一個明確的工作目標,再找經理確認一下達成一致,再開始。
目標基本上清晰了,用什麼技術,領導說了要容易融入公司的開發平臺,那是要求跟公司現有的技術框架一致,規範一致,哦對,還提到了要簡單易用。於是有了下面的內容。
代碼生成工具工作任務書
工作目標
(1) 核心解決現在代碼拷貝複製效率低下的問題
(2) 通過自主研發的方式實現一套代碼生成工具並能夠與公司平臺集成技術選型
(1) springboot
(2) thymeleaf使用方式
(1) 命令行方式使用,不依賴 web 服務即可使用
風小南把整理的簡要工作目標文檔,發給了技術經理,過了一會,技術經理回覆了過來,加了幾項工作目標。
工作目標
(1) 核心解決現在代碼拷貝複製效率低下的問題
(2) 通過自主研發的方式實現一套代碼生成工具並能夠與公司平臺集成
(3) 增加新代碼模板時要易於擴展
(4) 可按需生成,如可以只生成 Controller 文件,而不是非得全模塊代碼生成
至此,工作目標已確定,下來就是具體幹活了。
領導很忙的時候,如果沒有幫你梳理出具體的任務項,我們需要學會自己梳理,並找領導確認。這也是幫助自己逐步積累的一個過程,以後自己帶人帶團隊這些套路是可以複用、擴展的,面向對象嘛,另一方面還能幫領導減壓。領導不會討厭這樣的員工。
5、技術設計
本來風小南都想好了怎麼實現,很快就能做出來,無奈技術經理加了兩條要求,讓這個事情又變得不是那麼簡單,還需分析分析,好好設計一下子。
核心原理圖
既然如此,那還是先把大致的原理圖畫出來吧,這個是核心的實現思路,風小南大致畫了這麼一個圖。
原理圖. png
核心原理圖大致是上面這麼一個結構。簡單解釋一下,就是通過讀取數據庫表元數據和代碼模板,通過 thymeleaf 引擎將代碼模板和數據庫元數據進行合併,即將模板表達式替換爲具體的數據,最後輸出文件。
有了這個核心原理後,就需要基於這個結構進行展開設計,來達到後續兩點要求。
(3) 增加新代碼模板時要易於擴展
(4) 可按需生成,如可以只生成 Controller 文件,而不是非得全模塊代碼生成
風小南解讀這兩點要求後,得出一個結論:實際上第 (3) 說的就是要滿足開閉原則,第 (4) 條是程序要能夠自由組合生成方式,支持個性化自定義。
類圖設計
首先那就需要簡單設計下基本的類圖和關係,怎麼做呢?之前沒有這方面的經驗,想一步到位顯然不太可能,那就得拆解步驟一步步來,分析上面的原理圖,先不用考慮類之間的關係把能想到的類先全部列出來,就是窮舉法,然後逐步優化調整,這是第一步。
做的多了,有了一定經驗可能就用不到窮舉,窮舉法適用於當下沒什麼太好的思路或不知道怎麼開始的情況,相當於在做事的過程中尋找靈感和方法,逐步將自己的思維帶入場景。
以讀取表元數據這個過程舉例來說,要能讀取表元數據,是不是需要一個數據庫連接的類,鏈接是不是需要配置文件,讀取配置是否需要個類,讀回來後的表元數據往哪放,是不是也需要表信息和字段信息的類,先不管合理不合理,先列出來。依次類推,其他步驟過程也這麼分析。
簡單普及下元數據
什麼是元數據?即描述數據的數據就叫做元數據,怎麼理解?還是舉個例子簡單點
比如說有個用戶表 User,有兩個字段 id(int) name(String)
那麼描述 User 表信息和字段信息的數據,就叫做元數據,看下圖
元數據. png
左邊的這條數據表達了右邊用戶表的相關信息,如這個表叫什麼,什麼類型的,用的什麼存儲引擎,版本等等,這些表述 User 表信息的數據就叫做 User 表的元數據。
同理,字段也一樣,描述字段名、字段類型、字段長度等等的數據就是字段的元數據。以 Mysql 爲例,Mysql 中創建完成後存在個 Schema 叫 「information_schema」,這個庫就爲 mysql 的元數據庫,存儲了一些列 mysql 數據庫實例、表、字段、索引等等的元數據信息,裏面就有 Tables、Columns 表存放表和字段的元數據。
最終基於代碼生成工具的核心原理過程,風小南列出了下面自己能想到的類清單
有了基本清單,下來就藉助 UML 工具進行具體設計,風小南所在公司所有設計均使用的是 PowerDesign。
類圖初版
風小南認爲既然是初版那定然是把大的邊界,基本關係先勾勒出來,起到鎖住邊界和找出關鍵要素的作用,基本上來說就是把上面列出的類先畫出來標上簡單的關係,於是有了下圖
image.png
類圖 0.1 版
基本雛形有了,下面就是對着雛形逐步思考每個過程,填充類的屬性、方法,檢查是否有遺漏,設計不合理的地方進行調整,調整後如下
1 、GenCodeRunner
GenCodeRunner 僅一個方法,就是 run,run 內部調用 GenCode 對象,爲什麼需要 GenCodeRunner,因爲任務目標中爲了簡化使用,該代碼生成工具會使用命令行方式。
那命令行控制這部分邏輯應該與核心業務剝離開,畢竟後面可能更換其他使用方式比如 http、gui 等都有可能,如果寫在覈心業務邏輯中,那就不方便更換使用方式了,那麼提供一個獨立的運行類來接收用戶輸入實現與用戶交互是有必要的。
2、MetaData
這個類在之前初版分析時,並沒有,新增這個類是覺得 GenCode 沒必要知道數據庫的相關細節,對於 GenCode 來說它需要的僅僅是元數據,怎麼鏈數據庫怎麼讀配置,它不應該關心,所以這些事情就交給了 MetaData。
3、Table、Column
這兩個類中分別添加了一個類屬性,Table 中添加了 className,Column 中添加了 attrName,由於數據庫大部分情況下命名標準爲下劃線分割形式,如 user_id,而類中爲駝峯式名,如 userId,所以爲了生成代碼的模板表達式足夠簡單,不處理什麼邏輯。
雖說模板表達式也可以實現這樣的轉化,但模板就該幹模板該乾的事,就是展示數據,因此將 user_id -> userId 這一過程消滅在 MetaData 中,所以分別提供了符合類和屬性命名規範的屬性。
按說應該分開,單獨定義類和屬性信息的類,但此處並不考慮留太多的可擴展空間,爲了避免引入過多的類,導致設計變得複雜,因此合併到一個類中。
類圖 0.2 版
經過 0.1 版的設計,風小南感覺整體結構基本清晰了,下來就是需要找到中間存在的變化點,將可能存在變化的地方進行抽象,這樣就能避免代碼修改或新增時帶來的內部調整。對修改關閉,對新增開放,開閉原則。即滿足技術經理的第 3 條要求。
風小南經過分析,發現就目前公司的實際情況來看,可能發生變化的地方主要在模板可能會隨時調整新增,那麼就會引調用類 GenCodeRunner 的變化,從而引起 Command 類進行調整。
還有一處就是代碼生成完後的輸出方式,現在可能輸出到文件,未來如果想輸出到數據庫、命令行也不是不可能。
經過上面的思考,風小南對上面提到的幾處內容分別進行了抽象設計,形成了下圖。
image.png
幾個關鍵點設計:
1 、Command
Command 設計成了接口,對於不同模板的生成,提供不同的生成命令,可提供組合生成命令,即一次生成模塊所有代碼。
2、CodeOutout
Codeout 調整爲接口,針對不同輸出形式提供不同的實現類。
3、CodeTemplate
CodeTemplate 設計爲基類,針對不同的模板文件提供不同的擴展子類。
如此設計對於 GenCode 核心類來說,它操作的相關類都是接口或基類,那麼這個層面就可以做到基本穩定,不管實現層如何變化,該層都不會受到影響。
類圖 0.3 版
總體結構已經成型,但是風小南突然發現,Command 類的位置貌似放的不太合適,命令應該是有用戶觸發,而不是 GenCode,那麼用戶如何觸發,唯一入口在 GenCodeRunner。
那麼,Command 是不是在 GenCodeRunner 處更合適。於是風小南再次調整了 Command 類的位置。
Command 可以是單個生成命令,可以進行多個生成命令進行組合形成一個命令,如此就滿足了技術經理要求的第 4 條,程序要能夠自由組合生成方式,支持個性化自定義。最終得到的結果如下圖。
image.png
幾個關鍵點設計:
1 、GenCodeRunner
GenCodeRunner 根據用戶的輸入,會實例化對應的 Command 對象,調用 GenCode 的 gen 方法。
2 、GenCode
GenCode 中原理的 gen 方法是無輸入參數的,調整後,gen 方法接收一個生成命令,進行具體的代碼生成。
類圖 0.4 版
類關係都處理妥當,但是還有一個點遺漏掉了,風小南突然想到,像 TypeMapping 這種類,如果初始默認值無法滿足要求,那得允許用戶自己定義呀,嗯,還缺個全局層面的配置類。
目前是隻有 TypeMapping 一個,倒是可以讓用戶直接通過該類方法進行擴展自定義,但是後面可能會有其他配置項,如果將這些配置接口都拋出給用戶,用戶使用複雜度不就增加了,那麼多配置接口他哪記得住。
所以提供一個全局配置的入口類還是很有必要的,不管什麼層面的配置自定義,都可以通過該配置類實現。用戶只需記住這個全局的配置類就可以了。
就叫它 GenCodeConfiguration 吧,類圖新增成員,最終完整設計如下。
設計完結
至此設計工作結束,下面就可以依據類圖設計,進行實現了,或許你感覺這麼簡單個玩意,折騰這麼多類,累不累,我兩三個類就可以搞定了,沒錯,可以搞定,但是要解耦、可擴展、易維護,怎麼實現每個過程可被替換?
這就需要更多的接口、抽象類、面向對象的設計思想、設計模式的應用才能實現。其實上面的類設計還可以更復雜,只是當下我們的需求就這麼多,目前的設計足矣。
如此,是不是有點感覺 spring 爲什麼會整的那麼複雜,一些開源框架實現的功能可能明明很簡單爲什麼搞那麼多接口,抽象類,目的就是爲了解耦、可擴展、易維護,內部實現可自定義替換。
或許你還是感覺沒啥必要,那你要這麼想,不從這些小的工具、代碼中去一點點磨鍊自己的編程思維,加深對面向對象設計的理解,那什麼時候去練,沒有前面小的積累,你能一步去實現個 Mybatis 嗎?
不積跬步無以至千里,所以,經過小場景的鍛鍊,不斷積累,不斷突破嘗試,纔有可能設計出更完善更好的工具或框架。
6、實現過程
核心原理清楚了,設計有了,對風小南來說剩下編碼就是最容易的事了。當然對於剛入行的年輕人來說,可能實現也存在一定的障礙,這個障礙主要是見的少,寫的少,純代碼的編寫能力還不能夠駕輕就熟,缺少代碼經驗。解決辦法就是帶着腦子多練。
需要注意一點的是,上面的設計並非最終版,因爲具體實現的過程中可能還會發現一些設計時考慮不到的內容。
所以設計跟實現是一個相互促進完善的過程,畢竟不動手,有些細節情況是考慮不到的,更何況本文並非是作者提前準備好才寫的,而是爲了儘量還原真實過程,邊實現,邊輸出文章。
代碼實現首要做的就是定義項目包結構。實際上就是對設計中的類進行歸類建代碼包。經過分析後基本形成包結構如下
包結構. png
剩下的事情就是對每個類進行分別實現。從哪開始呢,可以順着實際代碼執行的過程一步步實現。到哪一步需要哪些類配合,再對需要的類實現。風小南畫出了整體代碼執行過程如下圖。
執行流程. png
實現部分就以包爲單位講下大致的實現思路,關鍵位置的代碼簡要粘貼一點配合說明,其他內容就不一行行代碼進行粘貼了,完整代碼隨後會上傳至 Github。
GenCodeRunner
命令行交互類,核心作用一個是初始化全局配置和 GenCode,另一個作用是接收用戶輸入,通過交互確定用戶需要生成代碼的命令和輸出方式。關鍵代碼如下。
Scanner scanner = new Scanner(System.in);
scanner.useDelimiter("\n");
// 初始化代碼生成配置
GenCodeConfiguration genCodeConfiguration = new GenCodeConfiguration();
GenCode genCode = new GenCode(genCodeConfiguration);
// 控制用戶交互過程
Command command = this.selectCommand(genCodeConfiguration,scanner);
CodeOutput output = this.selectOutput(genCodeConfiguration,scanner);
String tableName = this.selectTableName(scanner);
// 生成
Console.log("\n");
Console.log("開始生成....");
genCode.process(tableName,command,output);
Console.log("生成完成....");
GenCode
核心類,協調各方資源獲取命令需要的相關參數,調用 Command 執行代碼生成。核心代碼如下。
public void process(String tableName,Command command,CodeOutput codeOutput){
Table tableInfo = MetaData.getTableInfo(tableName,configuration.getTypeMapping());
command.execute(tableInfo,springTemplateEngine,codeOutput);
}
此處實現與設計存在一點差異,設計中模板的獲取是在 GenCode 中,但實際實現時發現放在 Command 中更合適,此處做了調整,具體到 Command 包時再看。
command
命令包,用於實現各種代碼的生成實現,看下整個包的類圖結構
Command.png
整體分爲單命令和組合命令兩種,目前單命令實現了 Controller、Entity、Vo 三種,其他可以任意擴展實現,組合命令實現了一次性生成 Controller 與 Entity,同樣可以任意自定義擴展。
看個單命令的核心代碼
public class GenControllerCommand extends SingleCommand {
public GenControllerCommand() {
this.commandName = "Controller生成命令";
this.commandCode = "01";
this.template = new ControllerCodeTemplate();
}
@Override
public void process(Table table, Map map) {
// 留給用戶自定義處理過程,比如一些自定義參數的處理加一些控制等等,此處暫不需要
}
}
定義命令名稱,命名代碼(用於與用戶交互輸入的命令代碼對應),綁定對應的代碼生成模板。預留 process 函數的作用時在生成具體代碼前提供給用戶自行在對數據進行二次加工或處理些其他需要的邏輯。command 包結合使用了命令模式和模板方法。
在看下組合命令的核心代碼
// 摘自GenControllerAndEntityCommand
public GenControllerAndEntityCommand() {
this.commandName = "Controller & Entity 生成命令";
this.commandCode = "03";
singleCommands.add(new GenControllerCommand());
singleCommands.add(new GenEntityCommand());
}
// 摘自 ComposeCommand
// 執行命令
@Override
public void execute(Table table, SpringTemplateEngine springTemplateEngine, CodeOutput codeOutput){
for(SingleCommand singleCommand : singleCommands){
singleCommand.execute(table,springTemplateEngine,codeOutput);
}
}
組合命令是集多個單命令的集合體,執行過程即遍歷挨個調用每個單命令的執行方法,完全複用單命令。
configuration
全局配置類,提供默認參數配置和用戶自定義擴展配置。主要完成了命令註冊配置、輸出類型註冊配置、數據庫與 Java 類型映射配置。
所有配置的入口均在 GenCodeConfiguration 中,統一入口可以方便調用,減少用戶的記憶負擔。框架內部也能達到集中管控的目的。
db
此包較爲簡單,封裝了數據庫連接獲取的過程,主要包含一個配置類和一個連接獲取類,比較簡單,此處就不展開說明了。
exception
爲代碼生成模塊定義了統一的異常類 GenCodeException,代碼生成模塊的異常均會被包裝爲該異常拋出。
meta
數據表、字段元數據獲取包,主要處理邏輯是讀取數據庫元數據包裝爲 Java 對應的 Table、TableColumn 對象。
// 表元數據
Statement stmt = conn.createStatement();
String sql = "select table_comment from information_schema.tables where table_name = '"+ tableName + "'";
ResultSet tableResultSet = stmt.executeQuery(sql);
while (tableResultSet.next()) {
table.setComment(tableResultSet.getString("table_comment"));
break;
}
// 字段元數據
DatabaseMetaData metaData = conn.getMetaData();
ResultSet resultSet = metaData.getColumns(null, null, table.getCode(), "%");
List<TableColumn> tableColumnList = CollectionUtil.newArrayList();
while (resultSet.next()) {
TableColumn tableColumn = new TableColumn();
tableColumn.setCode(resultSet.getString("column_name").toLowerCase());
tableColumn.setType(typeMapping.getJavaType(resultSet.getString("type_name")));
tableColumn.setComment(resultSet.getString("remarks"));
tableColumnList.add(tableColumn);
}
table.setColumnList(tableColumnList);
output
輸出包主要實現最終生成代碼的輸出形式,目前實現了控制檯輸出和文件輸出,看下類結構。
CodeOutput.png
比較簡單,簡單的繼承結構,大概看下實現代碼
// 摘自 ConsoleOutput
@Override
public void out(Table table, String content, CodeTemplate template) {
Console.log("\n");
Console.log("-----------------------------");
Console.log(content);
Console.log("-----------------------------");
}
// 摘自 FileOutput
@Override
public void out(Table table, String content, CodeTemplate template) {
String fileName = "dist/" + table.getClassName() + template.getFileTag() + template.getFileSuffix();
File file = new File(fileName);
FileUtil.writeBytes(content.getBytes(),file);
Console.log("文件位置:" + file.getAbsolutePath());
}
template
生成代碼的模板定義類,沒有多餘的邏輯控制,就是模板屬性和模板對應最終生成文件相關屬性的定義。
CodeTemplate.png
看個控制器代碼模板的定義
public ControllerCodeTemplate() {
this.tplName = "控制器模板";
this.tplPath = "templates/Controller.tpl";
this.fileTag = "Controller";
this.fileSuffix = ".java";
}
tpl
具體的模板文件,使用的是 thymeleaf 的 text 模式,看個簡單的模板內容
/**
* [(${comment})]-實體
*
* @author yuboon
* @version v1.0
* @date [(${createDate})]
*/
@Data
public class [(${className})] implements Serializable {
[# th:each="column : ${columnList}"]
/** [(${column.comment})] */
@Column("[(${column.code})]")
private [(${column.type})] [(${column.attrName})];
[/]
}
7、使用體驗
命令行交互方式
gencode.gif
自定義調用
public class GenCodeTest {
public static void main(String[] args) {
GenCodeConfiguration genCodeConfiguration = new GenCodeConfiguration();
GenCode genCode = new GenCode(genCodeConfiguration);
genCode.process("sys_user",new GenVoCommand(),new ConsoleOutput());
}
}
基於此結構改造爲 GUI 方式獲取 Web 網頁方式均很容易。
擴展一個新模板
很簡單,定義個新的 Command、新的 Tpl 模板文件、CodeTemplate 模板定義文件,通過全局配置註冊新 Command,整個過程對已有代碼沒有任何改動。
8、總結
至此,一個簡易的代碼生成工具在風小南手中實現了。
還有優化空間嗎?當然有,比如說模板引擎是否可以隨意替換 ?代碼模板文件多版本時怎麼辦 ?Web 端實現,多模塊同時生成等等。
本文僅以代碼生成工具的核心功能爲案例,從需求到最終實現,較爲詳細的描述了工作過程和一些工作方法包括一些設計程序的思想和理念。
那以後自己搞個小工具需要完全按照上面的步驟來嗎,那不是,做的多了有經驗了,見的多了,這個過程是可以簡化的。
一些步驟自己腦子裏有個思考過程就行了,甚至可以直接動手寫代碼,不一定非得像本文這樣,一步一步搞這麼複雜,文章是爲了描述整個過程全貌,所以寫的比較詳細,只是表面上看起來複雜而已。
最後,再將全文中的一些關鍵點提煉一下:
(1) 及時主動溝通、彙報工作,及時主動很重要
(2) 明確工作目標,避免無用功
(3) 搜索關鍵字很重要
(4) 設計先行,思路比實現重要
(5) 不知道怎麼幹的時候,特定場景下窮舉法試一試
(6) 步子不要跨太大,一步步迭代實現
(7) 總結,搞清爲什麼做?做什麼?怎麼做?後續演進空間?
9、完整代碼地址
https://github.com/yuboon/java-examples/tree/master/springboot-gencode
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/ho6wJFvFKUG6fYlNDJPTIw