如果“认为有害”的文章本身不被认为是有害的,则本帖标题为“认为有害的作废方法”。 哦,好了
无效方法在大多数面向对象的代码库中无处不在。 在运行时中某个地方发生可变状态或I / O的直接后果是,您可以包装功能编程狂热者称为impure的任何行为,该行为原则上没有有意义的返回值。 一个常见的示例是在应用程序引导期间,例如在Java中:
@Resource MyClass implements Runnable {// ...@PostConstruct
public void init() {if(this.enabled) {this.executorService.scheduleAtFixedRate(this,0,500,TimeOut.MILLISECONDS);}
}// ...
}
上面的代码据说不错,但是公共无效方法,尤其是它们在给定代码库中的扩散,显然是代码的味道。 即使以面向对象样式进行编码。
您的
公共方法供您的类合作者使用,它们是类功能的门户。 因此,它们应尽可能简洁,并提供实现类行为所需的最小表面积。 任何函数定义的一个主要的自记录部分自然就是其返回类型。
让我们从前面的示例开始:
@Resource MyClass implements Runnable {// ...@PostConstruct
public void init() {if(this.enabled) {this.executorService.scheduleAtFixedRate(this,0,500,TimeOut.MILLISECONDS);}
}// ...
}
我们的类可能在构造时收到某种executorService
实例,该实例可能是从某些依赖项注入粘合代码获得的,然后启动了工作计划。 客户代码需要显式调用init()
的可能性通常很小。 这表明我们的@PostConstruct
方法应该具有更严格的可见性,可能是private
或protected
,而这将是结束。
但是,真的吗?
可测性
假设我们要实际测试工作线程的关闭行为,这通常是一件棘手的事情。 您想做的事情大致如下:
// changed code from the original MyClass file:
@PostConstruct
public ScheduledFuture<T> init() {if(this.enabled) {return this.executorService.scheduleAtFixedRate(this,0,500,TimeOut.MILLISECONDS);}
}public testExecutorShutdown(){ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();MyClass c = new MyClass(service, true); // executorService, enabledScheduledFuture<T> scheduled = c.init();executorService.shutdown();scheduled.get(1, TimeUnit.SECONDS); // throws exception
}
上面的测试代码测试了计划的操作在执行程序关闭后的1秒(或两次计划的迭代)内终止。 这样的测试依赖于访问由init方法返回的将来的对象。
自我记录
人类的知觉被他们当前的意识视野所遮盖
– 埃利亚·怀斯
我们对init()
方法所做的更改启用了行为测试,但带来了一个重要的副作用: ScheduledFuture
对象现在是MyClass
公共接口的一部分,这意味着现在任何客户端代码都可以与其进行交互。 这是否是一个理想的属性,实际上取决于MyClass
旨在支持的用例,并且可能您希望将ScheduledFuture
封装在一个更友好的类中,例如,仅公开bool isDone()
类的东西。
无论如何,保持上述init
方法为空将始终导致您的客户端代码(或开发人员使用他/她的IDE浏览init
签名)而无视MyClass.init()
的实际作用。 只需看看不同的签名,然后想想自己针对每个签名进行编码:
public void init()
public ScheduledFuture<T> init()
后者将在您每次需要使用它时为您节省大脑周期,因为它清楚地说明了其产生的效果,而无需查看代码或更深层次的文档。
一件事做好
当函数一次执行多个操作时,坚持函数返回一个值以明确声明其行为的想法显然是不可能的。 幸运的是,它本身就是一种代码味道 ,并且通过将返回类型视为函数的存在目的,可以使违反该原则变得更加奇怪。
结论
对您自己的未来以及对使用您的代码的所有开发人员都是好事,永远不要再在公共API中隐藏诸如返回值之类的宝贵信息。
拥抱与亲吻c。
翻译自: https://www.javacodegeeks.com/2018/05/void-methods-as-behavior-black-holes.html