首頁>技術>

還記得上次我寫過一篇關於實際專案程式碼分層和規劃的文章《看完這篇,別人的開源專案結構應該能看懂了》, 在文尾處提到過一些注意事項,其中第一條就是:

Contorller層引數傳遞建議不要使用HashMap,推薦使用資料模型定義

私信裡竟然有很多小夥伴提問說,為什麼不能這樣做?

我心裡暗自尋思:難道這麼做的小夥伴都沒有被同事捶嗎?(滑稽)

得嘞,今天咱們就掰扯掰扯這件事,這是實際寫程式碼時常忽略的一個問題

是不是有人也這麼寫過?

我自己曾經接手過一個前人留下來的老專案,拿到程式碼,匯入IDEA的那一刻,我哭出了聲。

因為它的Controller層程式碼都是類似這樣寫的:

@RestController@RequestMapping("/index")public class IndexController {    // 獲取App首頁內容    @PostMapping("/getIndexContent")    public ResponseWrapper getIndexContent( @RequestBody Map<String, Object> paramMap ) {        ResponseWrapper res = new ResponseWrapper();        // 下面開始做傳參有效性的校驗        if (!paramMap.containsKey("article_id")) {            res.setCode(500);            res.setMsg("缺少 article_id 資訊");            return res;        }        if (!paramMap.containsKey("page")) {            res.setCode(500);            res.setMsg("缺少 page 資訊");            return res;        }        if (!paramMap.containsKey("size")) {            res.setCode(500);            res.setMsg("缺少 size 資訊");            return res;        }        if (!paramMap.containsKey("version")) {            res.setCode(500);            res.setMsg("缺少 version 資訊");            return res;        }        // ...... 此處省略    }    // ...... 此處省略}

別的咱先不說,居然明目張膽地在Controller層裡方法裡用Map傳參?!簡直喪心病狂了。幸虧下面還有一波傳參有效性的驗證,對於傳遞的引數,我好歹也能猜個大概,不然那真是喵了個咪了。

接下來,我們就好好嘮一嘮:為什麼不要在Controller層傳參時使用Map型別!

Map一時爽,維護爽歪歪

正好,這地方有一個咱小夥伴活生生的例子。

記得之前有個小夥伴提問,問過一個這樣的問題,說他接手了一個別人的老專案,問了我一個類似這樣的問題:

看到沒!

用Map傳參的第一個(也是最大的一個)弊端就是:這會導致後續接手和維護的人懷疑自己的人生,因為他根本不知道程式碼傳的啥引數,想要構造引數去除錯介面只能靠腦補、摸瞎、以及猜測了。

試想一下,其實我們程式碼裡任何一個地方的傳參都可以使用Map來傳,如果真的這麼做了,程式碼中連任何資料模型類都不需要定義了,果真如此的話,這樣的程式碼咱能看懂嗎?

而且這位小夥伴接手的專案居然還用的是LinkedHashMap引數,可以說很秀了。

除此之外,緊接著還會帶來下面這個問題。

好用的API工具與你無緣了

我之前寫過一篇文章《前後端都分離了,該搞個好用的API管理系統了!》,聊過現在市面上一些比較好用的、能極大提升前後端開發效率的API管理工具,這對於前後端開發來說,簡直是莫大的福音。

我們就以Swagger這個API工具為例,如果Controller傳參使用Map的話:

// 獲取App首頁內容@ApiOperation("獲取App首頁內容")@PostMapping("/getIndexContent")public ResponseWrapper getIndexContent( @RequestBody Map<String, Object> paramMap ) {    // ...... 此處省略}

則API工具無法讀取具體引數專案和引數型別,所以傳參什麼的也看不出來:

換言之,我如果將上面的Map傳參改為自定義資料模型類IndexQueryDto來傳參的話:

// 獲取App首頁內容@ApiOperation("獲取App首頁內容(改造後)")@PostMapping("/getIndexContent")public ResponseWrapper getIndexContent( @RequestBody IndexQueryDto indexQueryDto ) {    // ...... 此處省略}@ApiModel(value = "App首頁內容請求引數實體物件")class IndexQueryDto {    @ApiModelProperty(value = "文章ID號")    @NotNull(message = "缺少 article_id 資訊")    private Long article_id;    @ApiModelProperty(value = "頁面數")    @NotNull(message = "缺少 page 資訊")    private Integer page;    @ApiModelProperty(value = "每頁條目數")    @NotNull(message = "缺少 size 資訊")    private Integer size;    @ApiModelProperty(value = "App版本號")    @NotNull(message = "缺少 version 資訊")    private String version;    // ...... 此處省略set/get方法}

則類似Swagger這種API工具就非常方便地能幫助我們管理引數了:

這樣不管是自己除錯,還是前、後端對介面都會方便得多。

同理,除了Swagger這種API管理工具之外,像在我的前文《沒用過這些IDEA外掛?怪不得寫程式碼頭疼》中推薦過的一個非常好用的介面管理外掛RestfulToolkit也無法識別出Map型別所盛放的具體引數:

但是對於資料模型的定義引數,就能非常清晰的給出引數細節,並方便地提供介面測試:

優秀的註解沒法使用了

還是以文章開頭舉例的程式碼來說,不管怎麼樣,寫這段程式碼的哥們還是負責的,畢竟兢兢業業地用手工連環if()判斷完成了所有引數的有效性校驗:

但問題是,我們真的需要這種辣眼睛的手工連環if()判斷來做引數校驗嗎?

同樣在前文《啥?聽說你還在手寫複雜的引數校驗?》中也說過了,我們其實可以通過註解來方便地規避繁雜的引數校驗工作,但前提是不能使用Map型別傳參,需要使用資料模型的定義,就像這樣:

class IndexQueryDto {    @NotNull(message = "缺少 article_id 資訊")    private Long article_id;    @NotNull(message = "缺少 page 資訊")    private Integer page;    @NotNull(message = "缺少 size 資訊")    private Integer size;    @NotNull(message = "缺少 version 資訊")    private String version;    // ...... 此處省略get/set方法}

一個NotNull註解即可搞定,它不香嗎?

Map傳參真的一無是處嗎?

有些小夥伴表示用Map傳參的好處就是可以隨意擴充套件,後期變動靈活,想往裡面塞幾個引數就塞幾個引數;而且也省去了各種物件定義和命名的煩惱。

如果非要用Map傳參

如果實在不能避免用Map傳參,也麻請配備完備的測試用例吧,省得讓後來接手維護的人天天看著程式碼懷疑人生了。

通過測試用例,後來接手維護的人也能快速搞清程式碼間的引數傳遞和呼叫,不然真的只能靠腦補畫面去除錯了。

噓...

好了,說了這麼多,如果你專案的Controller層程式碼還在使用Map傳參的話,答應我,二話別說,趕快全部偷偷去改掉,快!速度!跑步前進!

166
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • laravel + vue + Element 後臺建立全過程