设计具有多种实现相同结果的API的API是否令人困惑?例如,我有我自己的Date
库(这是Java围绕一个简单的包装Date
/ Calendar
班来区分年月日,Date
中,从即时的时间,Instant
并提供机制,在两者之间转换).我从一个方法开始创建一个实例Date
:
Date.valueOfYearMonthDay(int year, int month, int day);
但后来我发现使用API的结果代码不是很易读.所以我补充说:
Date.yearMonthDay(int year, int month, int day) Date.ymd(int year, int month, int day) Date.date(int year, int month, int day)
然后我开始流利了:
Date.january().the(int day).in(int year);
(我发现流畅的版本对于进行可读测试非常有用).所有这些方法都做相同的事情,并具有准确的JavaDoc.我想我已经读过,perl
每个程序员都可以选择他/她更喜欢解决某些问题的方法.而且一个优点Java
是通常只有一种做事方式:-)
人们的意见是什么?
在过去的10年里,我一直在研究与Java中的API可用性有关的不同问题.
我可以告诉你,关于用Java做事的一种方法的说法是不正确的.在Java 中,通常有很多方法可以做同样的事情.不幸的是,它们往往不一致或有记录.
使用便捷方法膨胀类的接口的一个问题是,您要使它更难理解类以及如何使用它.你拥有的选择越多,事情就越复杂.
在对一些开源库的分析中,我发现了冗余功能的实例,由不同的人使用不同的术语添加.显然是个坏主意.
更大的问题是名称携带的信息不再有意义.例如,像swingLayer和setLayer这样的东西,其中一个只是更新图层而另一个也刷新(猜猜哪一个?)是个问题.同样,getComponentAt和findComponentAt.在其他方面,做事的方式越多,就越混淆其他所有内容并减少现有功能的"熵".
这是一个很好的例子.假设您希望在Java中用另一个字符串替换字符串中的子字符串.你可以使用String.replace(CharSequence,CharSequence),它可以像你期望的那样完美地工作,文字的文字.现在假设您想要进行正则表达式替换.您可以使用Java的Matcher并进行基于正则表达式的替换,任何维护者都会理解您的所作所为.但是,您可以编写String.replaceAll(String,String),它调用Matcher版本.但是,许多维护者可能不熟悉这一点,并没有意识到后果,包括替换字符串不能包含"$"的事实.因此,用"$"符号替换"USD"可以与replace()一起使用,但是会使用replaceAll()引起疯狂的事情.
然而,也许最大的问题是"做同样的事情"很少是使用相同方法的问题.在Java API的许多地方(我相信在其他语言中也是如此),你会找到做"几乎相同的事情"的方法,但是在性能,同步,状态变化,异常处理等方面存在差异.例如,调用将直接工作,而另一个将建立锁,另一个将更改异常类型等.这是一个麻烦的方法.
所以底线:做同样事情的多种方式并不是一个好主意,除非它们是明确且非常简单的,并且你需要非常小心以确保一致性.
我会回应其他人所说的便利方法很好,但会更进一步 - 所有"方便"方法最终应该调用相同的基础方法.除了代理请求之外,便捷方法应该做的唯一事情是以不同方式获取或返回变量.
便利方法中不允许进行任何计算或处理.如果您需要在其中一个中添加其他功能,请加倍努力,并在"主"/"真实"中实现.