突破CRUD | 簡單優雅的代碼生成工具誕生記(萬字長文慎入)


 

0、學習本文你或許可以收獲

1、一個需求從產生、分析到解決的全過程思考
2、簡單的面向對象分析實踐
3、UML類圖實踐
4、設計模式的實踐應用
5、最后收獲一款還算不錯的代碼生成工具實現思路和源代碼

本文將從上面第一點提到的全過程 需求->目標->思路->設計->實現->總結 逐一展開。

本文為了盡量還原真實場景下如何從無到有實現一個需求,所以全文會假設大家都不動代碼生成這個東西。是需要從零開始研究的。

下面開始正文。

1、先看需求

某日,風小南(年輕時的自己)代碼寫的正酣,技術經理突然走了過來,拍拍了風小南肩膀。

“小南啊,你看咱這個系統里面這么多增刪改查的功能,雖然拷貝復制可以,但是效率還是不夠高”。

風小南心想

"都CV模式了效率還不高,你咋不上天呢 ?"。

緊接着,技術經理說道

你看,現在這個用戶管理模塊做完了,我做其他角色、機構管理時,代碼的規范、基本的增刪改查結構是一樣的對吧,確實可以快速復制實現其他兩個功能,但是這中間有幾個問題仍然影響效率

 

第一:文件重命名問題,一個基本的模塊從前台到后台大概7-10個左右的代碼文件,在復制的同時均需要重新命名,文件數量這取決於每個公司的開發體系和標准。文件數量也可以更少,或者更多

 

第二:實體屬性肯定有存在不一樣的吧,需要修改或新增,這有一部分工作量

 

第三:類上,方法上,字段上的備注都需要調整吧,比如用戶管理類的備注是用戶管理,那你拷貝成角色管理得改成角色管理吧。方法字段都一樣得調整下吧

 

第四:類中的屬性、方法名、局部變量等也會需要跟着變化,比如,UserController 注入的UserService,方法內部聲明的userList變量,那拷貝成角色管理對應的名稱均需要調整為 roleXXX

 

第五:多余不用的方法需要一個個刪除

 

第六:還有個嚴重的問題,就是拷貝完后經常會有人忘了改上面說的幾點內容,導致代碼可讀性降低。

風小南結合自己實際寫代碼時的情況還真是存在這樣的問題,不禁感到CV大法在復制整個模塊時,還真是不太方便快捷,那怎么解決呢? 風小南心生疑惑。

“你這兩天給咱研究一下,看行業內還有沒有更有效的解決方案。你先嘗試着弄,有什么問題咱們隨時溝通(話外音,有什么進展問題要及時主動匯報)

說完,技術經理轉身就走了。

哎,故事寫的不好,湊合着看看,核心需求表達到就OK了。

2、初步探索

研究新技術那可是風小南最喜歡的事情了,只不過現在還沒有明確的方向,自己之前也沒有這方面的經驗,這時候能給自己指明道路的就是前輩或搜索引擎了,作為愛折騰技術的風小南,那必然是先自己搜索研究一番,短期內沒結果的話在請教下前輩。總之原則就是,不耽擱公司的事情,任務按時完成就OK。

打開搜索引擎,咋搜呢? 風小南發現不知道該輸入什么關鍵字才能找到想要的東西,得先確定下關鍵字。既然是代碼拷貝相關問題,那假設有相關工具或解決方案之類的東西,應該也會叫 “代碼XX” 吧。

既然跟效率有關,先來個 “代碼效率” 搜一波吧。截圖部分圖,結果如下



大概看了下內容,發現都是跟代碼調優加快執行效率相關,並非提升代碼開發效率,那就關鍵字不對,還得調整。

風小南又想了想,代碼拷貝工具? 代碼復制工具 ?仔細想想應該都不對,但還是嘗試了一波,果然沒有找到想要的結果。

效率不就是要速度快么,“代碼快速開發” 這個咋樣呢,再試試。搜索結果如下

列表出現了一系列快速開發平台,而且頻繁出現了「代碼生成」這個詞,直覺告訴風小南這不就是自己心里想要的那個但不知怎么表達的那個關鍵詞嗎。風小南又補充了一點既然公司用的是Java,那搜「Java代碼生成」肯定更准確一點。至此,關鍵字確定了就是「Java代碼生成」。

操作激動顫抖的雙手,在搜索引擎敲下了「Java代碼生成」,點擊搜索。

風小南迫不及待點開幾篇大致瀏覽了下內容,隨后又調整了幾次關鍵字,「Java代碼生成工具」、「Java代碼生成器」搜索查看了一波資料后,看了相關的實現思路,不禁大喜 “這不正是我們需要的東西嗎,自主生成、模板定制、一步到位”。什么改變量名,重命名、備注問題統統不存在,風小南心里大致有譜了。

實現方式大致兩種,一種借助現成的代碼生成平台,第二種就是自主實現,需要借助模板引擎技術,這里就存在技術方向的確定,需要跟領導匯報了。

風小南將查閱到的資料和自己的理解整理成文檔,發給技術經理(主動及時溝通、匯報很重要),並到技術經理的工位旁進行簡要匯報,技術經理聽完又大致瀏覽了風小南整理的資料,說道:

做的不錯,咱們公司有自己的研發平台,代碼生成工具最好是能直接跟咱們現在的平台融合起來,我看了下現成的代碼生成工具跟咱現在的平台不好融合,而且功能太多,使用的技術標准也不太一樣,我們自己實現一套簡單的吧,解決當下核心問題就行,不用太復雜。還是交給你來做吧。

風小南聽到這,那個高興啊。天下還有比擼代碼更開心的事嗎?有,那就是擼自己不會的代碼。哈哈。

至此,前期方案的初步探索就完成了。

探索階段的工作往往容易不好把控,原因在於探索那一定是未知的領域、未知的問題,任務本身不具體,不知道最終會做成什么樣,時間周期可能還長,這時候需要注意的就是自己工作的方式方法。要點就是及時溝通匯報進度。

3、工作任務書

任務有了,大致目標有了,但是還不夠具體,為了防止最后做出的東西跟技術經理想要的不一樣,我還是把剛才談話的內容梳理一下,形成一個明確的工作目標,再找經理確認一下達成一致,再開始。

目標基本上清晰了,用什么技術,領導說了要容易融入公司的開發平台,那是要求跟公司現有的技術框架一致,規范一致,哦對,還提到了要簡單易用。於是有了下面的內容。

代碼生成工具工作任務書

 

工作目標
(1) 核心解決現在代碼拷貝復制效率低下的問題
(2) 通過自主研發的方式實現一套代碼生成工具並能夠與公司平台集成

 

技術選型
(1) springboot
(2) thymeleaf

 

使用方式
(1) 命令行方式使用,不依賴web服務即可使用

風小南把整理的簡要工作目標文檔,發給了技術經理,過了一會,技術經理回復了過來,加了幾項工作目標。

工作目標
(1) 核心解決現在代碼拷貝復制效率低下的問題
(2) 通過自主研發的方式實現一套代碼生成工具並能夠與公司平台集成
(3) 增加新代碼模板時要易於擴展
(4) 可按需生成,如可以只生成Controller文件,而不是非得全模塊代碼生成

至此,工作目標已確定,下來就是具體干活了。

領導很忙的時候,如果沒有幫你梳理出具體的任務項,我們需要學會自己梳理,並找領導確認。這也是幫助自己逐步積累的一個過程,以后自己帶人帶團隊這些套路是可以復用、擴展的,面向對象嘛,另一方面還能幫領導減壓。領導不會討厭這樣的員工。

5、技術設計

本來風小南都想好了怎么實現,很快就能做出來,無奈技術經理加了兩條要求,讓這個事情又變得不是那么簡單,還需分析分析,好好設計一下子。

核心原理圖

既然如此,那還是先把大致的原理圖畫出來吧,這個是核心的實現思路,風小南大致畫了這么一個圖。


核心原理圖大致是上面這么一個結構。簡單解釋一下,就是通過讀取數據庫表元數據和代碼模板,通過thymeleaf引擎將代碼模板和數據庫元數據進行合並,即將模板表達式替換為具體的數據,最后輸出文件。

有了這個核心原理后,就需要基於這個結構進行展開設計,來達到后續兩點要求。

(3) 增加新代碼模板時要易於擴展
(4) 可按需生成,如可以只生成Controller文件,而不是非得全模塊代碼生成

風小南解讀這兩點要求后,得出一個結論:實際上第(3)說的就是要滿足開閉原則,第(4)條是程序要能夠自由組合生成方式,支持個性化自定義。

類圖設計

首先那就需要簡單設計下基本的類圖和關系,怎么做呢?之前沒有這方面的經驗,想一步到位顯然不太可能,那就得拆解步驟一步步來,分析上面的原理圖,先不用考慮類之間的關系把能想到的類先全部列出來,就是窮舉法,然后逐步優化調整,這是第一步。

做的多了,有了一定經驗可能就用不到窮舉,窮舉法適用於當下沒什么太好的思路或不知道怎么開始的情況,相當於在做事的過程中尋找靈感和方法,逐步將自己的思維帶入場景。

以讀取表元數據這個過程舉例來說,要能讀取表元數據,是不是需要一個數據庫連接的類,鏈接是不是需要配置文件,讀取配置是否需要個類,讀回來后的表元數據往哪放,是不是也需要表信息和字段信息的類,先不管合理不合理,先列出來。依次類推,其他步驟過程也這么分析。

簡單普及下元數據
什么是元數據?即描述數據的數據就叫做元數據,怎么理解?還是舉個例子簡單點
比如說有個用戶表User,有兩個字段 id(int) name(String)
那么描述User表信息和字段信息的數據,就叫做元數據,看下圖


左邊的這條數據表達了右邊用戶表的相關信息,如這個表叫什么,什么類型的,用的什么存儲引擎,版本等等,這些表述User表信息的數據就叫做User表的元數據。
同理,字段也一樣,描述字段名、字段類型、字段長度等等的數據就是字段的元數據。

 

以Mysql為例,Mysql中創建完成后存在個Schema叫 「information_schema」,這個庫就為mysql的元數據庫,存儲了一些列mysql數據庫實例、表、字段、索引等等的元數據信息,里面就有Tables、Columns表存放表和字段的元數據。

最終基於代碼生成工具的核心原理過程,風小南列出了下面自己能想到的類清單

類名 用途 步驟過程
Table 表元數據信息 讀取元數據
Column 字段元數據信息 讀取元數據
DbConnection 獲取數據庫鏈接 讀取元數據
YamlRead 讀取YAML配置 讀取元數據
CodeTemplate 模板文件 讀取模板信息
Command 生成命令 生成代碼
TypeMapping 數據庫與Java類型映射類 生成代碼
GenCode 代碼生成 生成代碼
CodeOutput 代碼輸出 輸出
GenCodeRunner 開發人員使用的入口類 啟動運行

有了基本清單,下來就借助UML工具進行具體設計,風小南所在公司所有設計均使用的是PowerDesign。

類圖初版

風小南認為既然是初版那定然是把大的邊界,基本關系先勾勒出來,起到鎖住邊界和找出關鍵要素的作用,基本上來說就是把上面列出的類先畫出來標上簡單的關系,於是有了下圖

 

 

類圖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類進行調整,還有一處就是代碼生成完后的輸出方式,現在可能輸出到文件,未來如果想輸出到數據庫、命令行也不是不可能。經過上面的思考,風小南對上面提到的幾處內容分別進行了抽象設計,形成了下圖。

幾個關鍵點設計

1 、Command
Command設計成了接口,對於不同模板的生成,提供不同的生成命令,可提供組合生成命令,即一次生成模塊所有代碼。

2、CodeOutout
Codeout調整為接口,針對不同輸出形式提供不同的實現類。

3、CodeTemplate
CodeTemplate設計為基類,針對不同的模板文件提供不同的擴展子類。

如此設計對於GenCode核心類來說,它操作的相關類都是接口或基類,那么這個層面就可以做到基本穩定,不管實現層如何變化,該層都不會受到影響。

類圖0.3版

總體結構已經成型,但是風小南突然發現,Command類的位置貌似放的不太合適,命令應該是有用戶觸發,而不是GenCode,那么用戶如何觸發,唯一入口在GenCodeRunner,那么,Command是不是在GenCodeRunner處更合適。於是風小南再次調整了Command類的位置。

Command可以是單個生成命令,可以進行多個生成命令進行組合形成一個命令,如此就滿足了技術經理要求的第4條,程序要能夠自由組合生成方式,支持個性化自定義。最終得到的結果如下圖。

 

 

幾個關鍵點設計

1 、GenCodeRunner
GenCodeRunner 根據用戶的輸入,會實例化對應的Command對象,調用GenCode的gen方法。

2 、GenCode
GenCode中原理的gen方法是無輸入參數的,調整后,gen方法接收一個生成命令,進行具體的代碼生成。

類圖0.4版

類關系都處理妥當,但是還有一個點遺漏掉了,風小南突然想到,像TypeMapping這種類,如果初始默認值無法滿足要求,那得允許用戶自己定義呀,嗯,還缺個全局層面的配置類。

目前是只有TypeMapping一個,倒是可以讓用戶直接通過該類方法進行擴展自定義,但是后面可能會有其他配置項,如果將這些配置接口都拋出給用戶,用戶使用復雜度不就增加了,那么多配置接口他哪記得住,所以提供一個全局配置的入口類還是很有必要的,不管什么層面的配置自定義,都可以通過該配置類實現。用戶只需記住這個全局的配置類就可以了。

就叫它GenCodeConfiguration吧,類圖新增成員,最終完整設計如下。

 

 

設計完結

至此設計工作結束,下面就可以依據類圖設計,進行實現了,或許你感覺這么簡單個玩意,折騰這么多類,累不累,我兩三個類就可以搞定了,沒錯,可以搞定,但是要解耦、可擴展、易維護,怎么實現每個過程可被替換?這就需要更多的接口、抽象類、面向對象的設計思想、設計模式的應用才能實現。其實上面的類設計還可以更復雜,只是當下我們的需求就這么多,目前的設計足矣。

如此,是不是有點感覺spring為什么會整的那么復雜,一些開源框架實現的功能可能明明很簡單為什么搞那么多接口,繼承,目的就是為了解耦、可擴展、易維護,內部實現可自定義替換。

或許你還是感覺沒啥必要,那你要這么想,不從這些小的工具、代碼中去一點點磨煉自己的編程思維,加深對面向對象設計的理解,那什么時候去練,沒有前面小的積累,你能一步去實現個Mybatis嗎? 不積跬步無以至千里,所以,經過小場景的鍛煉,不斷積累,不斷突破嘗試,才有可能設計出更完善更好的工具或框架。

6、實現過程

核心原理清楚了,設計有了,對風小南來說剩下編碼就是最容易的事了。當然對於剛入行的年輕人來說,可能實現也存在一定的障礙,這個障礙主要是見的少,寫的少,純代碼的編寫能力還不能夠駕輕就熟,缺少代碼經驗。解決辦法就是帶着腦子多練。

需要注意一點的是,上面的設計並非最終版,因為具體實現的過程中可能還會發現一些設計時考慮不到的內容,所以設計跟實現是一個相互促進完善的過程,畢竟不動手,有些細節情況是考慮不到的,更何況本文並非是作者提前准備好才寫的,而是為了盡量還原真實過程,邊實現,邊輸出文章。

代碼實現首要做的就是定義項目包結構。實際上就是對設計中的類進行歸類建代碼包。經過分析后基本形成包結構如下


剩下的事情就是對每個類進行分別實現。從哪開始呢,可以順着實際代碼執行的過程一步步實現。到哪一步需要哪些類配合,再對需要的類實現。風小南畫出了整體代碼執行過程如下圖。


實現部分就以包為單位講下大致的實現思路,關鍵位置的代碼簡要粘貼一點配合說明,其他內容就不一行行代碼進行粘貼了,完整代碼隨后會上傳至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

命令包,用於實現各種代碼的生成實現,看下整個包的類圖結構



整體分為單命令和組合命令兩種,目前單命令實現了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(nullnull, 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

輸出包主要實現最終生成代碼的輸出形式,目前實現了控制台輸出和文件輸出,看下類結構。

 

 


比較簡單,簡單的繼承結構,大概看下實現代碼
// 摘自 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

生成代碼的模板定義類,沒有多余的邏輯控制,就是模板屬性和模板對應最終生成文件相關屬性的定義。



看個控制器代碼模板的定義
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、使用體驗

命令行交互方式

自定義調用

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) 搜索關鍵字很重要
(3) 設計先行,思路比實現重要
(4) 不知道怎么干的時候,特定場景下窮舉法試一試
(5) 步子不要跨太大,一步步迭代實現
(6) 總結,搞清為什么做?做什么?怎么做?后續演進空間?

9、完整代碼地址

https://github.com/yuboon/java-examples/tree/master/springboot-gencode

10、更多精彩

覺得還行,動動手指留個贊。
以上就是今天的內容,我們下期見。
更多優質內容,首發公眾號【風象南】,歡迎關注。




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM