1. 如果接口的返回值有可能是null,请用Optional封装
public Optional<User> getUser() { return Optional.ofNullable(user); }
return getUser().orElse(defaultUser); return getUser().map(u -> u.getOrders()).orElse(Collections.emptyList()); |
---|
其他使用方法参考:http://unmi.cc/proper-ways-of-using-java8-optional/
好处:
- 优雅,下游不用写恶心的if-else判断
- 安全:告知接口的使用方返回值可能为null,需要处理,以避免代码缺陷
- 文档化:接口中可能为空的值文档化
2. 如果接口返回一个集合(list或set),可能一个Stream工厂是更好的选择
public Stream<UserBo> getUsers() { return userList.stream(); }
public Stream<UserDto> getUsers(Stream<UserBo> users) { return users.map(UserDto::new); }
public List<UserVo> getUsers(Stream<UserDto> users) { return users.map(UserVo::new).collect(toList()); } |
---|
优点:
- 封装:很好地封装了内部实现的数据结构,仅暴露一个Stream接口,不用纠结返回Set还是List
- 缓求值:减少占用的存储空间,有利于运行时产生更高效率的代码(中间不用产生List<UserDto>对象了)
3. 使用Either取代抛出Exception
public Either<ErrorDtoException, UserDto> addUser(String userName) { if (exist(userName)) { return Either.left(new ErrorDtoException("username is exist")); } UserBo UserBo = saveUser(userName); return Either.right(new UserDto(userBo); }
return addUser("myName").fold(e -> e.getMessage(), userDto -> userDto.getName()); |
---|
更多Either的API可参考源码
优点:
- 消除副作用:抛出异常的行为本身就是一种副作用,会导致程序路径偏离正轨(进入异常的流程)。
- 优雅:在返回值里表明错误并作出响应,这样就不需要打断程序的一般流程了。
4. 如果接口会抛出非受检异常或下游不那么关注的异常,可使用Try封装
public Try<Integer> divide(Integer a, Integer b) { return Try.of(() -> a / b); }
return divide(a, b).orElseMap(throwable -> defaultValue); |
---|
更多Try的API可参考源码
优点和Either类似
https://github.com/javadeep/common-functional/blob/master/functional-lang/src/main/java/com/javadeep/functional/lang/control/retry/Retrys.java以及https://github.com/javadeep/common-functional/blob/master/functional-lang/src/main/java/com/javadeep/functional/lang/control/validator/FunctionalValidator.java中的实现均用到了Try数据结构,可深入体会下。