API是关于血汗泪的

   |      

在Hibernate Search团队(尤其是Hardy)设计Faceting API的两周里,我们经历了紧张的时光。Hardy努力于实现(本身就不是一项简单的代码工作),但更困难的部分是我们为了使API尽可能用户友好而进行的迭代过程。

  • 尽可能用户友好
  • 足够强大
  • 与其他Hibernate Search API保持一致

我在这里这里这里谈到了流畅API,但我从未分享过背后的原因。

哲学

Hibernate Search以及其他Hibernate和JBoss产品的关键目标之一是易用性,我们努力在API和配置上实现这一目标。

一个好的API应该是

  • 为人类而设计,而不是为机器、克林贡人或者IDE向导屏幕
  • 可供初学者和专家使用(使简单用例变得容易,向高级用户提供高级功能)
  • 易于使用,易于阅读
  • 避免或限制在使用API时可能犯的错误

API应该展示使用功能的自然路径,而不仅仅是暴露一些没有实际粘合剂或指南的概念。从某种意义上说,你的API在讲述一个故事,这就是它可读的原因。通过引导你,API限制了你可以犯的错误数量。

这些目标是有代价的。

过程

我们经常在API及其实现的第一版上工作,以获得感觉,然后是细化过程。我们查看主要用例(简单或复杂),并检查API的行为。用新API编写代码以查看其缺点至关重要。我可以听到一些“当然”的声音,但你会惊讶地发现有多少人跳过了这一步骤。坦白地说,我并不怪他们,这很困难且耗时。

在Faceting API的例子中,我们研究了Amazon.com,并实际上重新实现了其分面功能,以查看

  • API(在功能方面)缺少了什么
  • 在实现网站时,哪些步骤笨拙或过于冗长

根据反馈,我们精炼或彻底废弃API,然后重新开始。

另一个技巧是编写如何操作风格的文档,甚至更好的是写一本书。在我编写《Hibernate Search实战》时,Hibernate Search API和功能得到了一些改进。有几个原因

  • 在编写示例时,我发现API或配置过于笨拙(=>修复它)
  • 在介绍一个功能时,我找不到合适的用例来展示它(=>废弃它)
  • 在编写示例时,我需要编写应属于框架的基础设施代码(=>添加它)

我称这种做法为“以书驱动开发”;请注意,(良好的)文档不能替代糟糕的API。你需要两者。理想情况下,用户开始使用API,然后查看文档以学习更高级的用例。

在发布它们之前,尝试将API视为永远固定不变,并使用Josh Bloch的口号,“当怀疑时,将其排除在外”。

这个整个过程非常痛苦,我们大幅度修改了分面API三到四次。我敢肯定,在某个时候,Hardy希望他没有志愿实现这个功能 :) 有人说,好的开发者做50%的实现和50%的测试。我会说,好的库开发者做25%的实现,25%的测试和50%的API(当然,为了编写API,你需要编写测试,但你知道我的意思)。

我们广泛使用同行评审(通过GitHub的拉取请求模式)。所有进入Hibernate Search的代码都由团队中的另一名成员进行评审。这就是另一双眼睛捕捉到错误或概念性错误的地方

  • 错误(或概念性错误)
  • 懒惰(缺少JavaDoc、接口与实现等 - 你通常会留到以后的小改动)
  • 潜在遗漏的用例或API改进

这种系统的同行评审真正提高了我们软件和文档的质量。当我们需要回到草稿时,这很痛苦,但最终结果是值得的。

更多

请注意,Hibernate Search并不是唯一一个认真对待其API的项目。在JBoss,有一个普遍的趋势。仅举几个例子

  • Seam 3
  • Arquilian
  • Shrinkwrap

它们都有易于编写和阅读的API。当然,这不仅仅限于JBoss,现在许多项目和规范都更加认真地对待它们的API。我认为这有几个因素

  • 人们对Java越来越成熟
  • RoR的影响已经过去
  • Java的新特性如泛型和注解开辟了可能性
  • 挑战者推动了尘封的Java API,并进行了改进

我衷心推荐Josh Bloch的《Effective Java》,以及他关于如何设计一个好的API及其重要性的演讲如何设计一个好的API以及为什么它很重要。顺便说一下,我并不声称我的API一定是伟大的,但你知道我尽力了。就像滑雪一样

如果你不摔倒,你就不会进步

我取得了很大的进步 :)


返回顶部