UDN-企业互联网技术人气社区

板块导航

浏览  : 599
回复  : 2

[讨论交流] Java 8的API设计原则

[复制链接]
胭脂粉的头像 楼主
发表于 2016-10-21 11:24:35 | 显示全部楼层 |阅读模式
  掌握的JavaAPI8设计,才能确保客户端代码可以使用lambda表达式访问API。一个好的API的设计需要仔细思考和大量的经验。因为一旦一个API公布,从一开始就贯彻坚定的承诺是非常重要。公共API,就像钻石,永远留传。你只有一次得到它的机会,所以给她最好的。

  API结合平衡了两个世界:坚定的和精确的承诺;以及具有高度的灵活性。下面是清单:

  如果一个值缺了不要返回Null

  不一致的空值处理(导致无处不在的NullPointerException异常)是Java应用程序历史上最大错误的唯一来源。一些开发者认为引进null的概念是在计算机科学领域有史以来最严重的错误之一。幸运的是,解决Java空值处理问题的第一步是Java8中引入的Optional。确保可以返回一个可选的对象,而不是null。

  这样做:

  publicOptional<String>getComment(){returnOptional.ofNullable(comment);}

  不要这样做:

  publicStringgetComment(){returncomment;//commentisnullable}

  不要用数组将值在API之间传递

  Java5引入枚举Enum类型,其方法values()是返回所有枚举元素值数组,每次进行values()调用会在内部复制一份数组,这导致差性能和客户端代码差可用性。

  如果返回的是一个不可修改的List就好得多,比如Stream,如果API返回元素集合,最好返回的是只读类型。

  可以这样做:

  publicStream<String>comments(){

  returnStream.of(comments);

  }

  不要这样做:

  publicString[]comments(){

  returncomments;//Exposesthebackingarray!

  }

  提供静态接口方法实现对象创建的单一入口

  避免客户端代码直接选择接口实现类,这会造成紧耦合。

  这样做:

  Pointpoint=Point.of(1,2);

  不要这样做:

  Pointpoint=newPointImpl(1,2);

  使用函数接口和Lambda而不是继承实现组合

  为了避免继承API造成客户端代码与API紧耦合,考虑使用静态接口方法实现组合。

  这样做:

  Readerreader=Reader.builder()

  .withErrorHandler(IOException::printStackTrace)

  .build();

  不要这样做:

  Readerreader=newAbstractReader(){

  @Override

  publicvoidhandleError(IOExceptionioe){

  ioe.printStackTrace();

  }

  };

  确保增加@FunctionalInterface元注解到函数接口中

  使用@FunctionalInterface可以让API用户使用Lambda实现你的函数接口。

  这样做:

  @FunctionalInterface

  publicinterfaceCircleSegmentConstructor{

  CircleSegmentapply(Pointcntr,Pointp,doubleang);

  //abstractmethodscannotbeadded

  }

  不要这样做:

  publicinterfaceCircleSegmentConstructor{

  CircleSegmentapply(Pointcntr,Pointp,doubleang);

  //abstractmethodsmaybeaccidentlyaddedlater

  }

  避免使用函数接口作为参数过载方法

  如果有多个函数有相同名称,都是将函数化接口作为参数,那么会造成客户端创建lambda混乱。

  不要这样做:

  publicinterfacePoint{

  add(Function<Point,String>renderer);

  add(Predicate<Point>logCondition);

  }

  这样做:

  publicinterfacePoint{

  addRenderer(Function<Point,String>renderer);

  addLogCondition(Predicate<Point>logCondition);

  }

  后者客户端可以使用point.add(p->p+“lambda”)调用。

  避免过度使用接口中默认方法

  默认方法有应该是短和“根本”的功能,不要加入太多内容。

  不要这样做:

  publicinterfaceLine{

  Pointstart();

  Pointend();

  defaultintlength(){

  intdeltaX=start().x()-end().x();

  intdeltaY=start().y()-end().y();

  return(int)Math.sqrt(

  deltaX*deltaX+deltaY*deltaY

  );

  }

  }

  这样做:

  publicinterfaceLine{

  Pointstart();

  Pointend();

  intlength();

  }

  确保API方法在被执行前检查参数不变性

  不要这样直接调用:

  publicvoidaddToSegment(Segmentsegment,Pointpoint){

  segment.add(point);

  }

  增加必要的检查:

  publicvoidaddToSegment(Segmentsegment,Pointpoint){

  Objects.requireNonNull(segment);

  Objects.requireNonNull(point);

  segment.add(point);

  }

  不要简单调用Optional.get()

  Optional.get()其实是Optional.getOrThrow(),在get之前检查一下,这样不会抛出exception

  这样做:

  Optional<String>comment=

  //某个Optional值

  StringguiText=comment.map(c->"Comment:"+c).orElse("");

文章来源:JDON

相关帖子

发表于 2016-10-24 09:40:42 | 显示全部楼层
厉害了我的哥,学习了
使用道具 举报

回复

发表于 2016-10-28 11:19:23 | 显示全部楼层
学习了
使用道具 举报

回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部