亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

利用函數(shù)式優(yōu)雅的重構(gòu)API

bergwhite / 3458人閱讀

摘要:新建字典必要的驗證參數(shù)不能為空調(diào)用封裝數(shù)據(jù)到統(tǒng)一到結(jié)構(gòu)體異常處理包括中拋出到自定義異常和未知異常統(tǒng)一包裝到返回對象中這樣子的代碼在開發(fā)接口的時候比比皆是。

基礎(chǔ)知識

在開始之前 假設(shè)你從未了解過函數(shù)式編程,本文不會教你函數(shù)式里面的各種概念。而是用實際案例讓給了解到函數(shù)式編程的魅力,并且能夠在合適的場景中應(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 必要的驗證參數(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)一包裝到 返回對象中
           response = GlobalControllerExceptionHandler.resolveExceptionCustom(e);
       }

       return response;


   }

這樣子的代碼 在開發(fā)http接口的時候比比皆是。本身寫的不壞,沒有拗口的地方,邏輯很嚴謹,讀起來很流暢。
美中不足的是,不夠通用化。 大量這樣的代碼容易讓編碼的人變成一個不會思考的機器...

簡單重構(gòu) 分析

對比之前寫的每個http接口我們很容易發(fā)現(xiàn)它們有相似的特點

必要的驗證參數(shù)

調(diào)用service

封裝數(shù)據(jù)到統(tǒng)一到結(jié)構(gòu)體

異常處理 包括 service中拋出到自定義異常和未知異常統(tǒng)一包裝到 返回對象中

只有第二步是不同的,其他步驟幾乎是重復(fù)的邏輯。

先做簡單的

我們可以抽取一個方法把 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ù)式

當我們重構(gòu)完上面的代碼,并在 saveDict方法中引入使用時,一切看起來都很美好。但是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 action) {

        try {
            String vstr = ValidatorUtils.validate(req);
            if (StringUtils.isNotBlank(vstr)) {
                return new Response(ResponseStatus.BAD_REQUEST.getCode(), vstr);
            }
            Object result = action.apply(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;
        }
    }
最終成果
@Api(value = "指標API", description = "指標API")
@RestController
@RequestMapping(ConfigConstants.CURRENT_API_VERSION + "/indicators")
public class IndicatorsController extends BaseController {

    @Autowired
    private IndicatorsService indicatorsService;

    @RequiresRoles(roles = {RoleEnum.ADMIN_CENTER})
    @ApiOperation(value = "新增指標")
    @PostMapping("/save")
    public Response 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 = "刪除指標")
    @PostMapping("/remove")
    public Response remove(@ApiIgnore @ModelAttribute DwSalaryEmpInfo empInfo, @RequestParam String id) {
        return action(() -> indicatorsService.removeIndicators(id));
    }
}
小結(jié)

上面代碼來自我自己的實際項目一個縮影,實際上做一個上層的封裝要處理很多問題,比如某些接口不需要參數(shù)驗證,或者不需要返回值,就需要對action函數(shù)進行重載。讓業(yè)務(wù)更方便的使用。

通過使用函數(shù)式變成對過程/對象混合代碼進行重構(gòu),使得代碼更凝練而有表達力了。雖然函數(shù)式編程尚未廣泛推廣于大型工程中,只有一部分程序猿開始嘗試使用,在理解上也需要一定的思維轉(zhuǎn)換,不過適度使用確實能增強代碼的抽象表達力。僅僅是“高階函數(shù)+泛型+惰性求值”的基本使用,就能產(chǎn)生強大而凝練的表達效果。 函數(shù)式編程確有一套自己獨特的編程設(shè)計理念。

現(xiàn)代軟件開發(fā)已經(jīng)不僅僅是單純地編寫代碼實現(xiàn)邏輯,而是含有很強的設(shè)計過程。需要仔細提煉概念、對象、操作,仔細設(shè)計對象之間的交互,有效地組合一系列關(guān)聯(lián)對象成為高內(nèi)聚低耦合的模塊,有效地隔離對象關(guān)聯(lián)最小化依賴關(guān)系,如此才能構(gòu)建出容易理解和擴展、更容易演進的長久發(fā)展的軟件。編程即是設(shè)計,從具象到抽象再到具象的過程。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/74753.html

相關(guān)文章

  • Python語言中計數(shù)方法演變

    摘要:譯文鏈接編程派有時候,利用語言簡潔優(yōu)雅地解決問題的方法,會隨著時間變化。隨著不斷進化,統(tǒng)計列表元素數(shù)量的方法也在改變。最后將字典中相應(yīng)鍵的值設(shè)置為新的計數(shù)。我們發(fā)現(xiàn)這種方法比之前的代碼更加簡潔優(yōu)雅,所以提交了此次修改。 showImg(https://segmentfault.com/img/remote/1460000010723715); 文中如對專業(yè)術(shù)語的翻譯有誤,請Pytho...

    sunsmell 評論0 收藏0
  • Hooks + Context:狀態(tài)管理新選擇

    摘要:用戶點擊改變?nèi)譅顟B(tài)崔然渲染整顆組件樹有沒有解決方案呢當然有創(chuàng)建一個只接收的新組件,并將組件中的邏輯都移到組件中。最終的示例使用全局狀態(tài)和生成全局狀態(tài)和崔然完整示例見結(jié)論在和出現(xiàn)之前,缺乏自帶的全局狀態(tài)管理能力。 React 16.3 版本,正式推了出官方推薦的 context API —— 一種跨層級的數(shù)據(jù)傳遞方法。React 16.8 版本,推出了全新的 hooks 功能,將原本只...

    tommego 評論0 收藏0
  • 響應(yīng)設(shè)計個人一些總結(jié)

    摘要:所以一個網(wǎng),甚至是響應(yīng)式設(shè)計,在兩個平臺上都會損害您整體的。三響應(yīng)式與如果把網(wǎng)站作為一個單獨的網(wǎng)站,如果網(wǎng)站的內(nèi)容與桌面版的內(nèi)容相對缺少,導(dǎo)致用戶回到桌面端的網(wǎng)站,會記錄這種選擇,使搜索排名降低,國內(nèi)百度就不知道會怎樣。 一、為什么需要響應(yīng)式設(shè)計(responsible web design) 1. 響應(yīng)式發(fā)展背景 1、屏幕尺寸的快速變化,iphone為320x480,分辨率在未來可以...

    LeoHsiun 評論0 收藏0
  • 重構(gòu) - 改善代碼各方面問題

    摘要:暴露接口如果是函數(shù),就擴展,否則就是驗證數(shù)據(jù)使用金額校驗規(guī)則這樣運行能正常,也有擴展性性,但是對于代碼潔癖的來說,這樣寫法不優(yōu)雅。 重構(gòu)不是對以前代碼的全盤否定,而是利用更好的方式,寫出更好,更有維護性代碼。不斷的追求與學(xué)習(xí),才有更多的進步。 1.前言 做前端開發(fā)有一段時間了,在這段時間里面,對于自己的要求,不僅僅是項目能完成,功能正常使用這一層面上。還盡力的研究怎么寫出優(yōu)雅的代碼,性...

    AlphaWallet 評論0 收藏0

發(fā)表評論

0條評論

bergwhite

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<