Hadoop 接口分类法:受众和稳定性分类

动机

此处提供的接口分类法分类是为接口的开发人员和用户提供指导。该分类指导开发人员声明接口的目标受众或用户,以及其稳定性。

  • 对接口用户的益处:了解哪些接口可以使用或不使用,以及它们的稳定性。

  • 对开发人员的好处:防止意外更改接口,从而避免对用户或其他组件或系统造成意外影响。这在拥有众多开发人员的大型系统中特别有用,这些开发人员可能并不都具有项目的共享状态/历史记录。

接口分类

Hadoop 采用以下接口分类,此分类源自 OpenSolaris 分类法,并且在一定程度上源自 Yahoo 内部使用的分类法。接口具有两个主要属性:受众和稳定性。

受众

受众表示接口的潜在使用者。虽然许多接口对实现是内部/私有的,但其他接口是公共/外部接口,旨在供应用程序和/或客户端更广泛地使用。例如,在 posix 中,libc 是外部或公共接口,而内核的大部分是内部或私有接口。此外,某些接口针对其他特定子系统。

识别接口的受众有助于定义破坏接口的影响。例如,破坏受众为少数特定子系统的接口的兼容性可能是可以的。另一方面,破坏数百万互联网用户依赖的协议接口可能是不合适的。

Hadoop 使用以下类型的受众,按可见性增加/更广的顺序

Hadoop 没有公司私有分类,该分类适用于公司内其他项目打算使用的 API,因为它不适用于开源项目。此外,某些 API 被注释为 @VisibleForTesting(来自 com.google.common .annotations.VisibleForTesting) - 这些 API 旨在严格用于单元测试,并且应视为“私有”API。

私有

私有接口供项目内部使用(例如 HDFS 或 MapReduce),不应由应用程序或其他项目使用。项目的大多数接口都是私有的(也称为项目私有的)。除非有意公开接口供外部使用,否则应将其标记为私有。

受限私有

受限私有接口由指定的一组项目或系统(通常是密切相关的项目)使用。其他项目或系统不应使用该接口。接口的更改将与指定的项目进行沟通/协商。例如,在 Hadoop 项目中,某些接口为 LimitedPrivate{HDFS, MapReduce},因为它们对 HDFS 和 MapReduce 项目是私有的。

公共

公共接口供任何应用程序通用使用。

更改兼容性

API 的更改分为两大类:兼容和不兼容。兼容更改是指满足以下条件的更改

  • 不删除任何现有功能,
  • 不以妨碍在更改之前构建为使用该接口的客户端使用的方式修改任何现有功能,并且
  • 不添加任何需要对在更改之前构建为使用该接口的客户端进行更改的功能。

不满足这三个条件的任何更改都是不兼容更改。简单来说,兼容更改不会破坏现有客户端。以下示例是兼容更改

  • 向 Java 类添加方法,
  • 向 RESTful Web 服务添加可选参数,或
  • 向 XML 文档添加标签。
  • 使接口的受众注释更广泛(例如,从私有变为公共)或使更改兼容性注释更严格(例如,从不断发展变为稳定)

以下示例是不兼容更改

  • 从 Java 类中删除方法,
  • 向 Java 接口添加方法,
  • 向 RESTful Web 服务添加必需参数,或
  • 重命名 JSON 文档中的字段。
  • 使接口的受众注释不那么广泛(例如,从公共变为受限私有)或使更改兼容性注释更严格(例如,从不断发展变为不稳定)

稳定性

稳定性表示接口的稳定程度,以及何时允许对接口进行兼容和不兼容更改。Hadoop API 具有以下稳定性级别。

稳定

稳定接口作为首选的通信方式公开。预计稳定接口在主要版本中不会发生不兼容的更改,因此可作为安全的开发目标。稳定接口可以在次要版本之间兼容地演进。

允许的不兼容更改:主要(X.0.0)允许的兼容更改:维护(x.y.Z)

不断发展

通常公开不断演进的接口,以便用户或外部代码可以在其稳定之前使用某个功能。但是,接口应该“最终”稳定并提升为稳定接口的期望并不是将接口标记为不断演进的接口的要求。

仅在次要版本中允许对不断演进的接口进行不兼容更改。

允许的不兼容更改:次要版本 (x.Y.0) 允许的兼容更改:维护版本 (x.y.Z)

不稳定

不稳定接口是指不提供任何兼容性保证的接口。不稳定接口不一定是不稳定的。通常公开不稳定接口是因为用户或外部代码需要访问不打算供其使用的接口。该接口公开为不稳定接口,以明确说明即使该接口已公开,但它也不是首选的访问路径,并且不提供任何兼容性保证。

除非有理由对接口提供兼容性保证(无论是否公开),否则应将其标记为不稳定。在大多数情况下,私有接口也应该是 不稳定的。

随时允许对不稳定接口进行不兼容更改。

允许的不兼容更改:维护版本 (x.y.Z) 允许的兼容更改:维护版本 (x.y.Z)

已弃用

已弃用的接口将来可能会被移除,不应使用。即便如此,已弃用的接口仍将继续发挥作用,直到其被移除。已弃用的接口何时可以被移除取决于它是否是稳定的、不断演进的还是不稳定的。

如何记录分类?

如何为 Hadoop API 记录分类?

  • 每个接口或类都将使用 org.apache.hadoop.classification 包中的注释记录受众和稳定性。

  • 由 Maven 目标 javadoc:javadoc 生成的 javadoc 仅列出公共 API。

  • 可以通过其所属包的受众来推导出 Java 类和 Java 接口的受众。因此,将每个 Java 包的受众声明为公共或私有(以及私有受众变体)非常有用。

如何为其他接口(例如 CLI)记录分类?

常见问题解答

  • 为什么 Java 作用域(私有、包私有和公共)不够好?

    • Java 的作用域不太完整。人们常常被迫将类设为公共,以便其他内部组件使用它。它也不像 C++ 那样有朋友或子包私有。
  • 但是,如果它是 Java 公共类,我可以轻松访问私有接口。保护和控制在哪里?

    • 此分类方案的目的是不提供绝对访问控制。其目的是与用户和开发人员进行沟通。人们可以访问 libc 中的私有实现函数;但是,如果他们更改内部实现详情,应用程序将中断,并且人们将得不到提供 libc 的人员的同情。在使用非公开接口时,风险是已知的。
  • 为什么费心声明私有接口的稳定性?私有接口不总是处于不稳定状态吗?

    • 私有接口并不总是处于不稳定状态。在它们处于稳定状态的情况下,它们捕获系统的内部属性,并且可以将这些属性传达给其内部用户和接口的开发人员。
      • 例如,在 HDFS 中,NN-DN 协议是私有的但稳定的,并且可以帮助实施滚动升级。稳定性注释传达了此接口不应以不兼容的方式更改,即使它是私有的。
      • 例如,在 HDFS 中,FSImage 的稳定性指定提供了更灵活的回滚。
  • 应用程序使用稳定的私有接口有什么危害?它与公共稳定接口有何不同?

    • 虽然标记为稳定的私有接口的目标是在主要版本中才更改,但如果该接口的提供者也愿意更改该接口的内部使用者,它可能会在其他时间中断。此外,公共稳定接口即使在主要版本中也不太可能中断(即使允许破坏兼容性),因为更改的影响更大。如果您使用私有接口(无论其稳定性如何),您将面临不兼容的风险。
  • 为什么费心使用有限私有?这不是对某些项目给予特殊待遇吗?这不公平。

    • 大多数接口应该是公共的或私有的。除非明确用于一般用途,否则接口应该是私有的。
    • Limited-Private 适用于并非用于一般用途的接口。它们向需要特殊挂钩的关联项目公开。此类分类对接口的供应商和消费者来说都是有成本的。如果将来需要中断接口,两者都必须共同努力;例如,供应商和消费者必须共同努力,以协调各自项目的发布。此合同不应掉以轻心——如果可能,请使用 Private;如果接口确实适用于所有应用程序,则使用 Public。始终记住,使接口成为 Public 会带来巨大的责任负担。有时 Limited-Private 恰到好处。
    • Limited-Private 接口的一个好例子是 BlockLocations。此接口是一个相当低级别的接口,它向 MapReduce 和 HBase 公开。该接口很可能在未来发生更改,届时发布工作必须与 MapReduce 开发团队协调。虽然 MapReduce 和 HDFS 现在总是同步发布,但此策略可能会在未来发生更改。
    • 如果您有一个 Limited-Private 接口,其中列出了许多项目,那么该接口可能是一个成为 Public 的良好候选者。
  • 让我们将所有 Private 接口都视为 Hadoop 的 Limited-Private。如果 Hadoop 系列中的项目可以访问私有类,那有什么危害?

    • 在代码中曾经有很多情况,一个项目依赖于另一个项目的内部实现细节。为清理这些问题付出了巨大的努力。将所有接口作为 Limited-Private 向所有 Hadoop 公开将为重新引入此类耦合问题打开大门。
  • 所有 Public 接口不都是稳定的吗?

    • 在早期,人们可能会将 Public 接口标记为 Evolving。在这里,人们承诺努力进行兼容性更改,但可能需要在次要版本中中断它。
    • 不稳定的 Public 接口的一个示例是,当人们提供基于标准机构的接口的实现时,该接口仍在开发中。例如,许多公司为了抢占市场先机,在 IETF 尚未完全完成协议时,就提供了新 NFS 协议的实现。实现者无法以造成最少中断的方式演化接口,因为稳定性由标准机构控制。因此,将接口标记为 Unstable 是合适的。