摘要:新建字典必要的驗(yàn)證參數(shù)不能為空調(diào)用封裝數(shù)據(jù)到統(tǒng)一到結(jié)構(gòu)體異常處理包括中拋出到自定義異常和未知異常統(tǒng)一包裝到返回對(duì)象中這樣子的代碼在開(kāi)發(fā)接口的時(shí)候比比皆是。
基礎(chǔ)知識(shí)
在開(kāi)始之前 假設(shè)你從未了解過(guò)函數(shù)式編程,本文不會(huì)教你函數(shù)式里面的各種概念。而是用實(shí)際案例讓給了解到函數(shù)式編程的魅力,并且能夠在合適的場(chǎng)景中應(yīng)用。
## 重構(gòu)之前
基本代碼如下 很普通的 springboot http接口。
@RequiresRoles(roles = {RoleEnum.ADMIN_CENTER}) @ApiOperation(value = "新建字典") @PostMapping("save") public Response saveDict(@RequestBody SaveDictVO vo) { Response response; try { // 1 必要的驗(yàn)證參數(shù) if (StringUtils.isBlank(vo.getTypeValue())) { response = new Response(ResponseStatus.BAD_REQUEST.getCode(), "typeValue不能為空"); } else { // 2.調(diào)用service boolean b = dictTypeService.saveDictType(vo); response = new Response(ResponseStatus.OK.getCode(), ResponseStatus.OK.getMsg()); // 3 封裝數(shù)據(jù)到統(tǒng)一到結(jié)構(gòu)體 response.setData(b); return response; } } catch (Exception e) { // 4.異常處理 包括 service中拋出到自定義異常和未知異常統(tǒng)一包裝到 返回對(duì)象中 response = GlobalControllerExceptionHandler.resolveExceptionCustom(e); } return response; }
這樣子的代碼 在開(kāi)發(fā)http接口的時(shí)候比比皆是。本身寫(xiě)的不壞,沒(méi)有拗口的地方,邏輯很嚴(yán)謹(jǐn),讀起來(lái)很流暢。
美中不足的是,不夠通用化。 大量這樣的代碼容易讓編碼的人變成一個(gè)不會(huì)思考的機(jī)器...
對(duì)比之前寫(xiě)的每個(gè)http接口我們很容易發(fā)現(xiàn)它們有相似的特點(diǎn)
必要的驗(yàn)證參數(shù)
調(diào)用service
封裝數(shù)據(jù)到統(tǒng)一到結(jié)構(gòu)體
異常處理 包括 service中拋出到自定義異常和未知異常統(tǒng)一包裝到 返回對(duì)象中
只有第二步是不同的,其他步驟幾乎是重復(fù)的邏輯。
先做簡(jiǎn)單的我們可以抽取一個(gè)方法把 1,3,4做統(tǒng)一處理
public Response action(Object req) { try { String vstr = ValidatorUtils.validate(req); if (StringUtils.isNotBlank(vstr)) { return new Response(ResponseStatus.BAD_REQUEST.getCode(), vstr); } Object result = null; // 調(diào)用servcie 執(zhí)行結(jié)果 Response response = new Response(ResponseStatus.OK.getCode(), ResponseStatus.OK.getMsg()); response.setData(result); return response; } catch (Exception e) { log.error("", e); Response response = GlobalControllerExceptionHandler.resolveExceptionCustom(e); return response; } }用接口抽象service邏輯
public interface ActionCallBack { Object action(Object req); }
修改上面的action方法
public Response action(Object req, ActionCallBack action) { try { String vstr = ValidatorUtils.validate(req); if (StringUtils.isNotBlank(vstr)) { return new Response(ResponseStatus.BAD_REQUEST.getCode(), vstr); } Object result = action.action(req); Response response = new Response(ResponseStatus.OK.getCode(), ResponseStatus.OK.getMsg()); response.setData(result); return response; } catch (Exception e) { log.error("", e); Response response = GlobalControllerExceptionHandler.resolveExceptionCustom(e); return response; } }如何使用
@RequiresRoles(roles = {RoleEnum.ADMIN_CENTER}) @ApiOperation(value = "新建字典") @PostMapping("save") public Response saveDict(@RequestBody SaveDictVO vo) { return action(vo, new ActionCallBack() { @Override public Object action(Object req) { //業(yè)務(wù)邏輯 return dictTypeService.saveDictType(vo); } }); }引入函數(shù)式
當(dāng)我們重構(gòu)完上面的代碼,并在 saveDict方法中引入使用時(shí),一切看起來(lái)都很美好。但是IDE卻給出一些善良的提示.
nonymous new ActionCallBack() can be replaced with lambda less... (?F1) Inspection info: Reports all anonymous classes which can be replaced with lambda expressions Lambda syntax is not supported under Java 1.7 or earlier JVMs.
根據(jù)IDEA 提示將代碼修改成函數(shù)式風(fēng)格
@RequiresRoles(roles = {RoleEnum.ADMIN_CENTER}) @ApiOperation(value = "新建字典") @PostMapping("save") public Response saveDict(@RequestBody SaveDictVO vo) { return action(vo, req -> { //業(yè)務(wù)邏輯 return dictTypeService.saveDictType(vo); }); }引入原生函數(shù)式接口
public最終成果Response action(R req, Function
@Api(value = "指標(biāo)API", description = "指標(biāo)API") @RestController @RequestMapping(ConfigConstants.CURRENT_API_VERSION + "/indicators") public class IndicatorsController extends BaseController { @Autowired private IndicatorsService indicatorsService; @RequiresRoles(roles = {RoleEnum.ADMIN_CENTER}) @ApiOperation(value = "新增指標(biāo)") @PostMapping("/save") public Response小結(jié)save(@ApiIgnore @ModelAttribute DwSalaryEmpInfo empInfo, @RequestBody AddIndicatorsVO vo) { return action(vo, v -> { Indicators model = BeanCopyUtils.copy(vo, new Indicators()); Indicators record = indicatorsService.saveIndicators(empInfo, model); return BeanCopyUtils.copy(record, new IndicatorsVO()); }); } @RequiresRoles(roles = {RoleEnum.ADMIN_CENTER}) @ApiOperation(value = "刪除指標(biāo)") @PostMapping("/remove") public Response remove(@ApiIgnore @ModelAttribute DwSalaryEmpInfo empInfo, @RequestParam String id) { return action(() -> indicatorsService.removeIndicators(id)); } }
上面代碼來(lái)自我自己的實(shí)際項(xiàng)目一個(gè)縮影,實(shí)際上做一個(gè)上層的封裝要處理很多問(wèn)題,比如某些接口不需要參數(shù)驗(yàn)證,或者不需要返回值,就需要對(duì)action函數(shù)進(jìn)行重載。讓業(yè)務(wù)更方便的使用。
通過(guò)使用函數(shù)式變成對(duì)過(guò)程/對(duì)象混合代碼進(jìn)行重構(gòu),使得代碼更凝練而有表達(dá)力了。雖然函數(shù)式編程尚未廣泛推廣于大型工程中,只有一部分程序猿開(kāi)始嘗試使用,在理解上也需要一定的思維轉(zhuǎn)換,不過(guò)適度使用確實(shí)能增強(qiáng)代碼的抽象表達(dá)力。僅僅是“高階函數(shù)+泛型+惰性求值”的基本使用,就能產(chǎn)生強(qiáng)大而凝練的表達(dá)效果。 函數(shù)式編程確有一套自己獨(dú)特的編程設(shè)計(jì)理念。
現(xiàn)代軟件開(kāi)發(fā)已經(jīng)不僅僅是單純地編寫(xiě)代碼實(shí)現(xiàn)邏輯,而是含有很強(qiáng)的設(shè)計(jì)過(guò)程。需要仔細(xì)提煉概念、對(duì)象、操作,仔細(xì)設(shè)計(jì)對(duì)象之間的交互,有效地組合一系列關(guān)聯(lián)對(duì)象成為高內(nèi)聚低耦合的模塊,有效地隔離對(duì)象關(guān)聯(lián)最小化依賴關(guān)系,如此才能構(gòu)建出容易理解和擴(kuò)展、更容易演進(jìn)的長(zhǎng)久發(fā)展的軟件。編程即是設(shè)計(jì),從具象到抽象再到具象的過(guò)程。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/74753.html
摘要:譯文鏈接編程派有時(shí)候,利用語(yǔ)言簡(jiǎn)潔優(yōu)雅地解決問(wèn)題的方法,會(huì)隨著時(shí)間變化。隨著不斷進(jìn)化,統(tǒng)計(jì)列表元素?cái)?shù)量的方法也在改變。最后將字典中相應(yīng)鍵的值設(shè)置為新的計(jì)數(shù)。我們發(fā)現(xiàn)這種方法比之前的代碼更加簡(jiǎn)潔優(yōu)雅,所以提交了此次修改。 showImg(https://segmentfault.com/img/remote/1460000010723715); 文中如對(duì)專業(yè)術(shù)語(yǔ)的翻譯有誤,請(qǐng)Pytho...
摘要:用戶點(diǎn)擊改變?nèi)譅顟B(tài)崔然渲染整顆組件樹(shù)有沒(méi)有解決方案呢當(dāng)然有創(chuàng)建一個(gè)只接收的新組件,并將組件中的邏輯都移到組件中。最終的示例使用全局狀態(tài)和生成全局狀態(tài)和崔然完整示例見(jiàn)結(jié)論在和出現(xiàn)之前,缺乏自帶的全局狀態(tài)管理能力。 React 16.3 版本,正式推了出官方推薦的 context API —— 一種跨層級(jí)的數(shù)據(jù)傳遞方法。React 16.8 版本,推出了全新的 hooks 功能,將原本只...
摘要:所以一個(gè)網(wǎng),甚至是響應(yīng)式設(shè)計(jì),在兩個(gè)平臺(tái)上都會(huì)損害您整體的。三響應(yīng)式與如果把網(wǎng)站作為一個(gè)單獨(dú)的網(wǎng)站,如果網(wǎng)站的內(nèi)容與桌面版的內(nèi)容相對(duì)缺少,導(dǎo)致用戶回到桌面端的網(wǎng)站,會(huì)記錄這種選擇,使搜索排名降低,國(guó)內(nèi)百度就不知道會(huì)怎樣。 一、為什么需要響應(yīng)式設(shè)計(jì)(responsible web design) 1. 響應(yīng)式發(fā)展背景 1、屏幕尺寸的快速變化,iphone為320x480,分辨率在未來(lái)可以...
摘要:暴露接口如果是函數(shù),就擴(kuò)展,否則就是驗(yàn)證數(shù)據(jù)使用金額校驗(yàn)規(guī)則這樣運(yùn)行能正常,也有擴(kuò)展性性,但是對(duì)于代碼潔癖的來(lái)說(shuō),這樣寫(xiě)法不優(yōu)雅。 重構(gòu)不是對(duì)以前代碼的全盤否定,而是利用更好的方式,寫(xiě)出更好,更有維護(hù)性代碼。不斷的追求與學(xué)習(xí),才有更多的進(jìn)步。 1.前言 做前端開(kāi)發(fā)有一段時(shí)間了,在這段時(shí)間里面,對(duì)于自己的要求,不僅僅是項(xiàng)目能完成,功能正常使用這一層面上。還盡力的研究怎么寫(xiě)出優(yōu)雅的代碼,性...
閱讀 3561·2023-04-26 02:10
閱讀 1299·2021-11-22 15:25
閱讀 1668·2021-09-22 10:02
閱讀 907·2021-09-06 15:02
閱讀 3469·2019-08-30 15:55
閱讀 600·2019-08-30 13:58
閱讀 2775·2019-08-30 12:53
閱讀 3042·2019-08-29 12:38