日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線(xiàn)咨詢(xún)客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

使用函數(shù)式編程可以減少代碼重復(fù),使代碼更易于理解。

JAVA編程語(yǔ)言以其面向?qū)ο蟮奶匦远劽惨蚱淙唛L(zhǎng)和繁瑣的異常處理機(jī)制而而廣受批評(píng)。當(dāng)Java語(yǔ)言在1.8版本引入函數(shù)式編程能力時(shí),人們并沒(méi)有馬上理解到這如何給程序員提供幫助。

圖片

本文給大家講解一個(gè)示例,以說(shuō)明函數(shù)式編程如何提高代碼的重用性和可讀性。

1 問(wèn)題

為了實(shí)現(xiàn)功能,第三方編寫(xiě)的通信客戶(hù)端使用了依賴(lài)注入和注釋。然而,該客戶(hù)端存在一些問(wèn)題,例如拋出已檢查異常、缺乏日志記錄和重試能力。因此,我們需要對(duì)該客戶(hù)端的功能進(jìn)行封裝,以添加重試功能、日志記錄和良好的異常處理。

如果沒(méi)有函數(shù)式編程,那么程序需要?jiǎng)?chuàng)建一個(gè)外觀,將每個(gè)客戶(hù)端功能都包裝在委托中,并添加日志記錄、異常處理和通信重試的邏輯??蛻?hù)端共有50個(gè)需要封裝的函數(shù),這將導(dǎo)致幾乎完全相同的50個(gè)副本的代碼,僅有調(diào)用的客戶(hù)端函數(shù)和傳遞的數(shù)據(jù)類(lèi)型有所不同。這樣會(huì)帶來(lái)大量的重復(fù)代碼問(wèn)題。

為了解決這個(gè)問(wèn)題,要使用函數(shù)式編程的方式對(duì)該客戶(hù)端功能進(jìn)行封裝,以實(shí)現(xiàn)重試能力、日志記錄和良好的異常處理。

2 使用函數(shù)式編程解決問(wèn)題

解決方案是添加1或2個(gè)專(zhuān)門(mén)用于處理異常、執(zhí)行日志記錄和實(shí)現(xiàn)重試循環(huán)的方法。但是,它們需要調(diào)用通信客戶(hù)端中的特定函數(shù)。

使用函數(shù)式編程,方法可以將函數(shù)作為其參數(shù)接收。該方法不需要在設(shè)計(jì)時(shí)知道哪個(gè)函數(shù)。Java(因?yàn)檫@與其他編程語(yǔ)言不同)所要求的是函數(shù)具有預(yù)期的簽名。

在我們的情況下,我們需要2種變體:BiFunction簽名和BiConsumer簽名。區(qū)別在于BiFunction返回一個(gè)值,而B(niǎo)iConsumer則不返回。

2.1 示例代碼:委托

public final ActionResult<List<Order>>
    downloadOrders() {
    return get(
      ".downloadOrders()",
      (
        client,
        apiKey
      ) -> client.downloadOrders(apiKey.toString())
    );
  }

上面的示例沒(méi)有顯示錯(cuò)誤處理、日志記錄和重試循環(huán)。這是由get(String, BiFunction)方法執(zhí)行的。因此,我們不需要50個(gè)重復(fù)的錯(cuò)誤處理、日志記錄和重試循環(huán),而是有50個(gè)易于理解的委托。

get(String, BiFunction)方法回調(diào)傳入的BiFunction,我們?cè)谏厦婵吹搅诉@一點(diǎn):

(    
  client,
  apiKey
) -> client.downloadOrders(apiKey.toString())

我們可能會(huì)從JavaScript中認(rèn)識(shí)到這一點(diǎn)。語(yǔ)法是一個(gè)BiFunction的lambda表示法:它接受2個(gè)參數(shù),可能做一些事情,并返回一些東西。它是一個(gè)回調(diào)函數(shù),根據(jù)需要即時(shí)創(chuàng)建,并且因?yàn)樗鼪](méi)有名稱(chēng),所以它保持匿名(并由編譯器分配標(biāo)識(shí))。它的參數(shù)client和apiKey在方法get(String, BiFunction)內(nèi)生成,并在運(yùn)行時(shí)傳回回調(diào)函數(shù)中。它看起來(lái)像這樣:

2.2 示例代碼:接受函數(shù)作為參數(shù)的包裝器

private final <T>
    ActionResult<T>
    get(
      final String caller,
      final BiFunction<
        Client,
        ApiKey,
        T
      > callback
    ) {
    final Client client = Client.newInstance(caller);
    final ApiKey key = this.getKey();
    final MutableList<Exception> errors = Lists.mutable.empty();
    boolean mustRetry = true;
    for (
      int retryCount = 0;
      mustRetry && retryCount < MAX_RETRIES;
      retryCount += 1
    ) {
      try {
        return new ActionResult<T>(
          callback.Apply(
            client,
            apiKey
          )
        ).with(errors);
      } catch (Exception ex) {
        mustRetry = mustRetry(ex);
        if (mustRetry) {
          try {
            TimeUnit.SECONDS.wAIt(1 << (retryCount + 1));
          } catch (InterruptedException ie) {
            errors.add(ie);
          }
        } else {
          errors.add(ex);
        }
      }
    }
    return ActionResult.<T>empty()
      .with(errors);
  }

在那段代碼中,BiFunction通過(guò)聲明進(jìn)行回調(diào):

callback.apply(
  client,
  apiKey
)

請(qǐng)注意,get(String, BiFunction)不知道回調(diào)返回的數(shù)據(jù)類(lèi)型。在像Java這樣的強(qiáng)類(lèi)型和顯式類(lèi)型編程語(yǔ)言中,通常不可能。直到泛型引入Java編程語(yǔ)言之前,這是不可能的。這就是為什么代碼中存在:它是回調(diào)返回的數(shù)據(jù)類(lèi)型的占位符。

請(qǐng)注意,調(diào)用站點(diǎn)也沒(méi)有指定返回值的數(shù)據(jù)類(lèi)型。相反,它由客戶(hù)端函數(shù)的返回值和委托上指定的返回?cái)?shù)據(jù)類(lèi)型隱含。如果它們不匹配,編譯器將發(fā)出警告,保持?jǐn)?shù)據(jù)類(lèi)型良好且檢查過(guò)。

3 總結(jié)

  • 壞的抽象是面向?qū)ο缶幊讨性S多問(wèn)題的根源。我們希望將目前的兩個(gè)異常處理和重試循環(huán)包裝器減少到一個(gè)包裝器,但是由于一個(gè)接受BiFunction回調(diào),另一個(gè)接受BiConsumer回調(diào),還沒(méi)有找到合適的方法。因?yàn)閺母拍钌现v,它們執(zhí)行不同的操作:發(fā)送和接收。使用相同的包裝器可能會(huì)破壞這種概念上的區(qū)別。總之,對(duì)于現(xiàn)在來(lái)說(shuō)值得高興的是避免了重復(fù)使用50個(gè)包裝器的情況。

  • 當(dāng)然,有些優(yōu)秀的編譯器可能會(huì)檢測(cè)到代碼重復(fù),并采取一些技巧將它們減少為具有不同回調(diào)的單個(gè)包裝器。然而,這并非我們當(dāng)前關(guān)注的重點(diǎn)。我們的目標(biāo)是消除重復(fù)代碼并提高代碼的可讀性。

  • 從理論上講,使用這個(gè)包裝器和函數(shù)委托可能會(huì)導(dǎo)致程序變慢。然而,根據(jù)經(jīng)驗(yàn),由于與遠(yuǎn)程通信伙伴進(jìn)行通信時(shí)遇到的網(wǎng)絡(luò)延遲,潛在的幾毫秒延遲相對(duì)微不足道。盡管如此,如果在您的環(huán)境中這導(dǎo)致了明顯的性能下降,請(qǐng)測(cè)量吞吐量并進(jìn)行相應(yīng)的調(diào)整。

  • 靜態(tài)代碼分析工具若能提供有關(guān)消除重復(fù)代碼的建議,將對(duì)代碼優(yōu)化非常有益。這樣的工具可以幫助開(kāi)發(fā)人員識(shí)別和消除重復(fù)的代碼段,從而提高代碼的可讀性、可維護(hù)性和性能。

分享到:
標(biāo)簽:函數(shù) 編程
用戶(hù)無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定