使用自顶向下的方法在Java中设计API - 编写Javadoc是最好的起点吗?

8
每当我需要在Java中设计API时,我通常会打开我的IDE,创建包、类和接口。方法实现都是虚拟的,但javadocs非常详细。
这是最好的方法吗?我开始感觉应该首先输出API文档 - 即使在编写第一个.java文件之前。这有一些优点:
1. API设计人员可以完成设计和规范,然后将实现分配给多个实现者。 2. 更灵活 - 设计更改不需要在java文件之间跳来跳去寻找编辑javadoc注释的位置。
还有其他人分享这种观点吗?如果是这样,你是如何开始API设计的?
此外,是否有任何工具可以帮助?可能甚至有某种基于注释的工具,可以生成文档,然后生成骨架源代码(类似于模型到代码生成器)?我遇到了Eclipse PDE API tooling - 但这只适用于Eclipse插件项目。我没有找到任何更通用的东西。

好问题。+1 给你先生。 - luis.espinal
5个回答

4
对于API(以及我认为许多类型的问题),自上而下的方法用于问题分割和分析是可行的。
然而(这只是基于我的个人经验,所以需要保持谨慎),专注于Javadoc部分是一个好的做法,但仍然不足以可靠地成为起点。事实上,这非常实现导向。那么在此之前发生的设计、建模和推理呢(即使它可能很简短)?
您必须进行某种建模来识别组成API的实体(名词、角色和动词)。无论有多么“敏捷”,这些事情都不能在没有清晰的问题陈述的情况下进行原型制作(即使只是10K英尺的视图)。
最好的起点是明确你要实现什么,或者更准确地说,你的API试图解决什么类型的问题。BDD可能会有所帮助(下面会详细介绍)。也就是说,你的API将提供什么(数据元素),提供给谁,执行什么操作(动词)以及在什么条件下(上下文)。然后需要确定哪些实体提供这些内容以及在什么角色下提供(接口,特别是具有单一、清晰角色或功能的接口,而不是方法的万能袋)。这就导致了对它们如何协同工作的分析(继承、组合、委派等)。
一旦你有了这些,那么你可能处于一个良好的位置,可以开始进行一些初步的Javadoc。然后你可以开始实现这些接口,这些角色。随后会有更多的Javadoc(除了其他可能不属于Javadoc的文档,例如教程,how-tos等)。
你可以从用例和可验证的要求以及每个事物应该独立或协同完成的行为描述开始实现。在这里,BDD将非常有帮助。
当你在工作时,你需要不断地重构,希望通过一些指标(圆形复杂度和某种类型的LCOM)来实现。这两个指标告诉你应该在哪里进行重构。
API的开发与应用程序的开发本质上并没有区别。毕竟,API是一个用户的实用应用程序(恰好有开发角色)。
因此,您不应将API工程视为与一般的软件密集型应用程序工程有所不同。使用相同的做法,根据您的需求进行调整(每个与软件相关的人都应该这样做),那么您就会做得很好。
谷歌已经在YouTube上上传了其“Google Tech Talk”视频讲座系列已经有一段时间了。其中之一是一个名为{{link1:“如何设计良好的API以及为什么它很重要”}}的长达一小时的讲座。您可能还想查看一下。
以下是对您有帮助的一些链接:

Google Tech Talk的“超越测试驱动开发:行为驱动开发”:http://www.youtube.com/watch?v=XOkHh8zF33o

行为驱动开发:http://behaviour-driven.org/

与书籍“实用API设计”的网站伴侣:http://wiki.apidesign.org/wiki/Main_Page

回归基础 - 结构化设计#内聚性和耦合性:http://en.wikipedia.org/wiki/Structured_Design#Structured_Design


1
嗯,我个人认为,不行,你不能将源代码文档与设计关联起来(更不用说那些适合文档编译的子集了)。这只是对“它”在特定时间的文档化描述以及如何使用“它”。源代码文档和源代码本身一样,都是设计的实现产出。事实上,我认为这样的文档是“好”的源代码的一个组成部分,应该被视为彼此的一部分。可以这样理解,假设代码中的所有注释都是有效且有价值的... - luis.espinal
1
恰巧,并非所有源代码注释都会出现在Javadoc中。方法内部的注释记录了内部决策,而不是用于解释如何使用“它”,因此不属于外部文档的一部分。因此,Javadoc及其在其他语言中的等效物并不能提供完整的图片。此外,它们也没有“建模”,也没有提供可以推理的模型。Javadocs解释了模型(或其具体系统实现)的实用和配置方面。听起来可能像我在玩词语游戏,但这是一个非常重要的区别。 - luis.espinal
1
我认为API是接口的一种实现形式,是可交付的本身。存在一个合同来展示如何独立使用这个可交付物(API),无论我们是否通过类或接口提供直接访问(或者接口是否明确)。我的意思是,显然可以尝试将Javadocs用作起始设计指南。问题是在一般情况下(特别是在复杂情况下)是否足够。它作为源代码注释子集的本质,作为实现输出,使我相信它不足以胜任此任务。 - luis.espinal
2
继续 - 记住,没有Javadoc的代码是糟糕的代码。Javadoc的存在是必要的,但不足以构成良好的代码(因为Javadoc可能是无用的)。良好的 Javadoc(与位于Javadoc之外的良好代码注释一起)仍然只是必要的,但不足以构成良好的代码。然而,当您除了足够正确和足够良好构建的代码之外,还具有这些条件时,那么我们就拥有了良好(或至少足够好)的源代码。这证明了(在我看来)Javadocs与代码本质上是耦合的(因为它是其固有部分)。 - luis.espinal
1
我倾向于同意你在这里的观点。你的回答结合这些评论,已经足够回答了我的问题。因此,我接受了这个答案。再次感谢你详细、有论据支持的回复 :) - curioustechizen
显示剩余2条评论

3

首先定义接口是编程契约风格的声明先决条件、后置条件和不变量。我发现这种方法与测试驱动开发(TDD)结合得很好,因为你首先编写的不变量和后置条件是你的测试可以检查的行为。

顺便说一句,行为驱动开发是测试驱动开发的进一步完善,似乎是由于那些不习惯先考虑接口的程序员提出的。


2
关于我自己,我总是更喜欢先编写接口及其文档,然后再开始实现。
过去,我采用另一种方法,即从UML开始,然后使用自动代码生成工具。我遇到的最好的工具是 Rational Rose,虽然它不是免费的,但我相信有很多免费的插件和工具可供选择。Rational Rose相对于其他设计工具的优点在于,您可以将设计与代码“连接”起来,然后在代码或设计上进行修改,另一个也会更新。

谢谢@LiorO。我已经使用了各种Eclipse和Netbeans插件,可以进行设计到代码和代码到设计的转换(尽管我无法回忆起它们中的任何一个是否是“实时”的 - 即更改一个会更改另一个)。我正在寻找一种将此概念扩展到API设计和javadocs的方法。因此,看起来您也是从接口开始的。 - curioustechizen
将UML转换为Java,您也可以使用MagicDraw。在我看来,它甚至比Rational Rose更好。但它也不是免费的。 - Dainius

2

我会立即开始使用原型进行编码。任何必要的接口很快就会出现,您可以将原型塑造成最终产品。如果可能的话,请一路上从将使用您的API的人那里获得反馈。

没有“最佳方法”来处理API设计,只要对您有效即可。领域知识也有很大作用。


我同意这种方法和“做适合自己的事情”的建议。我也喜欢花几个小时来组装原型,并在出现意外复杂性的时候进行重构(它们总是会出现的)。过一段时间,所有的东西都开始成形了,这就是开始考虑固定接口、文档等方面的时间——我总是觉得这比试图在一张白纸上指定接口更快、更有效率。 - strmqm

2
我非常喜欢使用接口编程。它为代码的实现者和使用者形成了一个契约。我通常不会直接开始编写代码,而是从系统的基本模型开始(根据复杂性,可能是UML图等)。这不仅可以作为良好的文档,还提供了对系统结构的视觉澄清。有了这个,编码部分就容易多了。这种设计文档也使得在6个月后回到系统或尝试修复错误时更容易理解系统 :) 原型设计也有其优点,但要准备好放弃并重新开始。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接