国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Jumping with Try

Java3y / 2387人閱讀

摘要:解決思路或生產對象,扮演生產者的角色而消費對象,扮演消費者的角色。正常情況下它們生產對象,而異常情況下,則拋出異常。重構的思路在于將異常處理更加明晰化,讓生產者與消費者之間的關系流水化。容器化其中,與包內私有,對外不公開。

場景

以一個簡化了的用戶登錄的鑒權流程,流程大體如下:

首先嘗試本站鑒權,如果失敗,再嘗試twiter的方式恢復;

之后再進行Two Factor認證;

快速實現

按照流程定義,可以快速實現第一個版本。這段代碼充滿了很多的壞味道,職責不單一,復雜的異常分支處理,流程的脈絡不夠清晰等等,接下來我們嘗試一種很特別的重構方式來改善設計。

public boolean authenticate(String id, String passwd) {
  User user = null;    
  try {
   user = login(id, passwd);
  } catch (AuthenticationException e) {
    try {
      user = twiterLogin(id, passwd);
    } catch (AuthenticationException et) {
      return false;
    }
  }
    
  return twoFactor(user);
}
解決思路

logintwiterLogin生產User對象,扮演生產者的角色;而twoFactor消費User對象,扮演消費者的角色。

最難處理的就是logintwiterLogin可能會存在異常處理。正常情況下它們生產User對象,而異常情況下,則拋出異常。

重構的思路在于將異常處理更加明晰化,讓生產者與消費者之間的關系流水化。為此,可以將User對象,可能拋出的異常進行容器化,它們形成互斥關系,不能共生于這個世界。

容器化
public interface Try {
  static  
  Try trying(ExceptionalSupplier s) {
    try {
      return new Success<>(s.get());
    } catch (Exception e) {
      return new Failure<>(e);
    }
  }
  
  boolean isFailure();
  
  default boolean isSuccess() {
    return !isFailure();
  }
  
  T get();
}

其中,SuccessFailure包內私有,對外不公開。

final class Success implements Try {
  private final T value;
  
  Success(T value) {
    this.value = value;
  }
  
  @Override
  public boolean isFailure() {
    return false;
  }

  @Override
  public T get() {
    return value;
  }
}
import java.util.NoSuchElementException;

final class Failure implements Try {
  private final Exception e;
  
  Failure(Exception e) {
    this.e = e;
  }
  
  @Override
  public boolean isFailure() {
    return true;
  }

  @Override
  public T get() {
    throw new NoSuchElementException("Failure.get");
  }
}
生產者

JDK8標準庫中不一樣,它能處理受檢異常。

@FunctionalInterface
public interface ExceptionalSupplier {
  T get() throws E;
}
第一次重構
import static Try.trying;

public boolean authenticate(String id, String passwd) {
  Try user = trying(() -> login(id, passwd));
  if (user.isFailure()) {
    user = trying(() -> twiterLogin(id, passwd));
  }
 
  return user.isSuccess() && twoFactor(user.get());
}
鏈式DSL

上述trying的應用,使用狀態查詢Try.isFailure/isSuccess方法顯得有些笨拙,可以通過構造鏈式的DSL改善設計。

public interface Try {
  ......

   Try recover(Function> f);
}
final class Success implements Try {
  ......
   
  @Override
  @SuppressWarnings("unchecked")
  public  Try recover(Function> f) {
    return (Try)this;
  }
}
final class Failure implements Try {
  private final Exception e;
  
  Failure(Exception e) {
    this.e = e;
  }
   
  @Override
  public  Try recover(Function> f) {
    try {
      return f.apply(e);
    } catch (Exception e) {
      return new Failure(e);
    }
  }
}
第二次重構

使用recover關鍵字,進一步地改善表達力。首先試圖login生產一個User,如果失敗從twiterLogin中恢復;最后由twoFactor消費User對象。

public boolean authenticate(String id, String passwd) {
  Try user = trying(() -> login(id, passwd))
      .recover(e -> trying(() -> twiterLogin(id, passwd)));    
    
  return user.isSuccess() && twoFactor(user.get());
}
徹底鏈化
public interface Try {
  ......

  default T getOrElse(T defaultValue) {
    return isSuccess() ? get() : defaultValue;
  }
    
   Try map(Function f);
}
final class Success implements Try {
  ......
  
  @Override
  public  Try map(Function f) {
    try {
      return new Success(f.apply(value));  
    } catch (Exception e) {
      return new Failure(e);
    }
  }
}
final class Failure implements Try {
  ......

  @Override
  @SuppressWarnings("unchecked")
  public  Try map(Function f) {
    return (Try)this;
  }
}
第三次重構
public boolean authenticate(String id, String passwd) {
  return trying(() -> login(id, passwd))
    .recover(e -> trying(() -> twiterLogin(id, passwd)))
    .map(user -> twoFactor(user))
    .getOrElse(false);
}
應用Scala

Java8 Lambda表達式() -> login(id, passwd)中空的參數列表頗讓人費解,但這是Java8語言本身限制的,應用Scala表達力可進一步提高。

import scala.util.Try

def authenticate(id: String, passwd: String): Boolean = {
  Try(login(id, passwd))
    .recover{ case e: => twiterLogin(id, passwd) }
    .map(twoFactor)
    .getOrElse(false)
}
Try的本質

TryMonad的一個應用,使得異常的處理可以在流水線上傳遞。使用ScalaTry簡化實現版本是這樣的。

sealed abstract class Try[+T] {
  def isSuccess: Boolean
  def get: T
}

final case class Failure[+T](val exception: Throwable) extends Try[T] {
  def isSuccess: Boolean = false
  def get: T = throw exception
}


final case class Success[+T](value: T) extends Try[T] {
  def isSuccess: Boolean = true
  def get = value
}

object Try {
  def apply[T](r: => T): Try[T] = {
    try Success(r) catch {
      case NonFatal(e) => Failure(e)
    }
  }
}

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/65595.html

相關文章

  • 【譯】渲染Elements

    摘要:注不做翻譯是中最小的構建部件。在里渲染讓我們看一下在下面有在你文件中無處不在的標簽我們會把這元素成為元素因為的所有東西都會放在這個元素里面。通過方法,我們能吧渲染到我們根節點上。更新被渲染的是不可變的。 下面是react官方文檔的個人翻譯,如有翻譯錯誤,請多多指出原文地址:https://facebook.github.io/re...特別感謝Hevaen,同時也向豪大React群所有...

    LoftySoul 評論0 收藏0
  • Chrome 小恐龍游戲源碼探究八 -- 奔跑的小恐龍

    摘要:例如,將函數修改為小恐龍眨眼這樣小恐龍會不停的眨眼睛。小恐龍的開場動畫下面來實現小恐龍對鍵盤按鍵的響應。接下來還需要更新動畫幀才能實現小恐龍的奔跑動畫。 文章首發于我的 GitHub 博客 前言 上一篇文章:《Chrome 小恐龍游戲源碼探究七 -- 晝夜模式交替》實現了游戲晝夜模式的交替,這一篇文章中,將實現:1、小恐龍的繪制 2、鍵盤對小恐龍的控制 3、頁面失焦后,重新聚焦會重置...

    paulquei 評論0 收藏0
  • 【譯】JavaScript最全編碼規范

    摘要:在中已經澄清分號恩,這也是規范一部分閱讀更多類型分配強制轉換執行強制類型轉換的語句。對于整型值大于位的進行位運算將導致不可預見的行為。在范圍內使用進行對象查詢譯文出處 類型 基本類型:訪問基本類型時,應該直接操作類型值 string number boolean null undefined javascriptvar foo = 1; var bar = foo; bar ...

    afishhhhh 評論0 收藏0
  • ReactNative開發筆記(持續更新...)

    摘要:,已過期,請使用代替。解決方案安卓增加屬性并設置為官方解釋當圖片實際尺寸和容器樣式尺寸不一致時,決定以怎樣的策略來調整圖片的尺寸。 本文均為RN開發過程中遇到的問題、坑點的分析及解決方案,各問題點之間無關聯,希望能幫助讀者少走彎路,持續更新中... (2019年3月29日更新) 原文鏈接:http://www.kovli.com/2018/06/... 作者:Kovli - 如何在原生...

    浠ラ箍 評論0 收藏0
  • canvas之轉盤抽獎

    摘要:最近工作中重構了抽獎轉盤,給大家提供一個開發轉盤抽獎的思路需求轉盤根據獎品數量不同而有變化目錄結構由于業務需要所以開發了兩個版本抽獎,和,不過部分只能替換圖片,沒有功能邏輯。 最近工作中重構了抽獎轉盤,給大家提供一個開發轉盤抽獎的思路 需求 1、轉盤根據獎品數量不同而有變化 2、canvas 目錄結構 showImg(https://segmentfault.com/img/bVbwL...

    _ang 評論0 收藏0

發表評論

0條評論

Java3y

|高級講師

TA的文章

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