编程小TIPS:使用函数式风格Either来编程

2021-12-27 13:27:57 浏览数 (1)

编程TIPS:分享简短,实用的编程小知识

最近在一些国外的技术博客中见到一个以前自己没太见过的编程风格,那就是Either,觉得非常有意思,稍微了解了下。分享给大家。

同时,我会基于最流行的后端语言Java来简单的演示下如何使用Either。

什么是Either

在英语中,Either是的意思,这也是函数式编程风格中Either的意思。

Either是一个对象,它代表有两种可能,或是left,或是right。通常left表示错误或异常,而right代表成功

一个典型的Either代码是这样的(基于Java)

代码语言:javascript复制
//保存一个用户,返回Either,有两种可能,或是UserError出现某种错误,或是User表示保存成功
public Either<UserErrorCode,User> createLocalUser();

这个写法是不是某种程度上,是不是可以替换了Java原来的异常及try..catch?

挺有意思的。

一个简单的实例

不使用Either的做法 (基于myddd-java)

代码语言:javascript复制
    public User createLocalUser(){
        if(Strings.isNullOrEmpty(name))throw new UserNameEmptyException();
        if(Strings.isNullOrEmpty(password))throw new PasswordEmptyException();
        if(Strings.isNullOrEmpty(userId))throw new UserIdEmptyException();

        this.created = System.currentTimeMillis();
        this.encodePassword = getPasswordEncoder().encodePassword(password);
        return getUserRepository().save(this);
    }

用Either重写上述方法

代码语言:javascript复制
 public Either<UserErrorCode,User> createLocalUser(){
        if(Strings.isNullOrEmpty(name)) return Either.left(UserErrorCode.USER_NAME_EMPTY);
        if(Strings.isNullOrEmpty(password))return Either.left(UserErrorCode.PASSWORD_EMPTY);
        if(Strings.isNullOrEmpty(userId))return Either.left(UserErrorCode.USER_ID_EMPTY);

        this.created = System.currentTimeMillis();
        this.encodePassword = getPasswordEncoder().encodePassword(password);
        var created =  getUserRepository().save(this);
        return Either.right(created);
    } 

有什么好处?

避免抛出异常带来的不可预知性

我们都知道,在Java中,处理类似场景我们大多会使用异常,但抛出异常会使方法返回变得不可预测,就是你不确定这个方法究竟是成功了还是抛出异常了。

所以,我们得在代码中,使用try...catch来捕获或处理成功或失败的不同场景。

但是如果使用Either返回,这意味着方法返回的是一个可以确定的Either对象。

这样本身代码会简洁很多,也会减少处理不同场景的代码复杂度。

保持函数式风格的优雅

相信大家都使用过Java 8之后的Stream等一些函数式风格,这会让你的代码更简洁与优雅。而有了Either之后,这意味着你可以保持这种简洁与优雅。

示例如下:

代码语言:javascript复制
computeWithEither(9).left()
  .map(FetchError::getMsg)
  .forEach(System.out::println);

Either有简洁的left以及right方法,通过这些方法结合流,这样处理业务时,比try...catch是不是优雅很多?

Either来源于何处?

我不是非常确认,但从我搜索的资料来看,似乎Scala语言中自带了这个特性,考虑到Scala比Java更具有函数式编程的能力,也许Either是从Scala中发展而来

Java如何使用Either?

Java有一个非常好的函数式风格的类库https://www.vavr.io/,里面就包含了Either这个小功能。

vavr还有其它许多对JDK的函数式风格的补充,如果你喜欢函数式编程风格,我想也许你不会想错过它。

0 人点赞