Tag: api design

命名返回流的java方法

是否有返回Stream的方法的命名约定? 我发现唯一提到的就是关于SO的答案 (最后一段),但我不知道它的基础是什么。

为什么JavaMail Transport.send()是一个静态方法?

我正在修改我没写过的使用JavaMail的代码,并且在理解为什么JavaMail API的设计方式有点麻烦。 我觉得,如果我理解,我可以做得更好。 我们称之为: transport = session.getTransport(“smtp”); transport.connect(hostName, port, user, password); 那么为什么Eclipse警告我这个: transport.send(message, message.getAllRecipients()); 是对静态方法的调用? 如果我无法使用该对象发送消息,为什么我会获取Transport对象并提供特定于它的设置? Transport类如何知道用于发送消息的服务器和其他设置? 它工作正常,很难相信。 如果我为两个不同的服务器实例化了Transport对象,该怎么办? 怎么知道使用哪一个? 在写这个问题的过程中,我发现我应该真的在呼唤: transport.sendMessage(message, message.getAllRecipients()); 那么静态Transport.send()方法的目的是什么? 这只是糟糕的设计,还是有这样的原因?

用自上而下的方法用Java设计API – 写Javadoc是最好的起点吗?

每当我需要在Java中设计API时,我通常会先打开我的IDE,然后创建包,类和接口。 方法实现都是虚拟的,但javadocs是详细的。 这是最好的办法吗? 我开始觉得API文档应该是第一个被淘汰的 – 甚至在第一个.java文件被写入之前。 这几点没什么优势: API设计人员可以完成设计和规范,然后在多个实现者之间拆分实现。 更灵活 – 设计更改不需要在java文件中反弹,寻找编辑javadoc注释的位置。 还有其他人分享这个观点吗? 如果是这样,您如何开始使用API​​设计? 此外,有没有可能有帮助的工具? 甚至可能是某种基于注释的工具,它可以生成文档,然后生成骨架源(类似于模型到代码生成器)? 我遇到了Eclipse PDE API工具 – 但这是Eclipse插件项目特有的。 我没有找到更通用的东西。

改造void方法以返回其参数以促进流畅性:打破变化?

“API设计就像性:做出一个错误,并在你的余生中支持它” ( Josh Bloch在Twitter上 ) Java库中存在许多设计错误。 Stack extends Vector ( 讨论 ),我们无法在不造成破坏的情况下修复它。 我们可以尝试弃用Integer.getInteger ( 讨论 ),但它可能会永远存在。 尽管如此,某些类型的改装可以在不造成破损的情况下完成。 有效的Java第2版,第18项:首选接口到抽象类 :现有的类可以很容易地进行改进,以实现新的接口“。 示例: String implements CharSequence , Vector implements List等。 有效的Java第2版,第42项:明智地使用varargs :您可以改进现有的方法,该方法将数组作为其最终参数,而不是对现有客户端采取varags。 一个着名的例子是Arrays.asList ,它引起了混淆( 讨论 ),但没有破坏。 这个问题是关于不同类型的改造: 你能改造一个void方法来返回一些东西而不破坏现有的代码吗? 我最初的预感指向是,因为: 返回类型不会影响在编译时选择哪个方法 请参阅: JLS 15.12.2.11 – 不考虑返回类型 因此,更改返回类型不会更改编译器选择的方法 从void改造返回一些东西是合法的(但不是相反的方式!) 即使使用reflection, Class.getMethod东西也不区分返回类型 但是,我希望听到其他在Java / API设计方面经验丰富的人进行更全面的分析。 附录:动机 正如标题中所建议的那样,一个动机是促进流畅的界面风格编程。 考虑这个简单的片段,它打印一个洗牌的名单: List names = […]

使用注释确保不会丢弃方法返回的值

Java中的String是不可变的。 从广义上讲,以下片段是“错误的”。 String s = “hello world!”; s.toUpperCase(); // “wrong”!! System.out.println(s); // still “hello world!”!!! 尽管这是“错误的”,代码编译和运行,也许是许多初学者的困惑,他们必须被告知错误是什么,或者通过查阅文档找出自己。 阅读文档是理解API的重要部分,但我想知道是否可以通过额外的编译时检查来补充它。 特别是,我想知道是否可以使用Java的注释框架来强制执行某些方法返回的值不被忽略。 然后,API设计者/库作者将在其方法中使用此注释来记录不应忽略哪些返回值。 一旦API补充了这个注释(或者可能是另一种机制),那么每当用户编写如上所述的代码时,它就不会编译(或者通过严厉的警告进行编译)。 那么这可以做到,你会怎么做这样的事情? 附录:动机 很明显,在一般情况下,Java 应该允许忽略方法的返回值。 List.add ( 总是为 true ), System.setProperty (之前的值)等方法的返回值可能在大多数情况下可以安全地被忽略。 但是,也有许多方法的返回值不应该被忽略。 这样做几乎总是程序员错误,或者不正确使用API​​。 这包括以下内容: 关于不可变类型(例如String , BigInteger等)的方法,它返回操作的结果 ,而不是改变它被调用的实例。 返回值是其行为的关键部分且不应忽略的方法,但人们有时会做(例如InputStream.read(byte[])返回读取的字节数,不应假设为整个长度数组) 目前,我们可以编写忽略这些返回值的代码,并让它们在没有警告的情况下编译和运行。 静态分析检查器/ bug查找器/样式执行器/等几乎可以肯定地将这些标记为可能的代码味道,但是如果可以通过API本身(可能通过注释)强制执行它,它似乎是合适的/理想的。 一个类几乎不可能确保它总是“正确”使用,但它可以做些什么来帮助指导客户正确使用(参见: Effective Java 2nd Edition,Item 58:对可恢复的条件使用已检查的exception和编程错误的运行时exception和项62:记录每种方法抛出的所有exception )。 有一个注释可以强制客户端不要忽略某些方法的返回值,并且编译器在编译时以错误或警告的forms强制执行它,这似乎符合这个想法。 附录2:代码段 以下是初步尝试,简洁地说明了我想要实现的目标: @interface Undiscardable { […]

为什么原始Stream没有收集(collections家)?

我正在为新手程序员编写一个库,所以我试图保持API尽可能干净。 我的库需要做的一件事就是对大量的int或long进行一些复杂的计算。 我的用户需要从中计算这些值所需的大量场景和业务对象,因此我认为最好的方法是使用流来允许用户将业务对象映射到IntStream或LongStream ,然后计算收集器内的计算。 但是IntStream和LongStream只有3参数collect方法: collect(Supplier supplier, ObjIntConsumer accumulator, BiConsumer combiner) 并且没有Stream具有的简化collect(Collector)方法。 所以不是能够做到的 Collection businessObjs = … MyResult result = businessObjs.stream() .mapToInt( … ) .collect( new MyComplexComputation(…)); 我必须提供这样的供应商,累加器和合并器: MyResult result = businessObjs.stream() .mapToInt( … ) .collect( ()-> new MyComplexComputationBuilder(…), (builder, v)-> builder.add(v), (a,b)-> a.merge(b)) .build(); //prev collect returns Builder object 对于我的新手用户来说这太复杂了,而且非常容易出错。 我的工作是创建以IntStream或LongStream作为输入的静态方法,并为您隐藏收集器的创建和执行 public static MyResult […]