【问题标题】:Prevent Internals leaking into API防止内部泄漏到 API
【发布时间】:2017-06-12 08:39:10
【问题描述】:

我正在寻找不同的方法来防止内部泄漏到 API 中。这是一个巨大的问题,因为一旦这些内部结构泄漏到 API 中;您可能会遇到意外的不兼容问题或内部冻结。

最简单的方法之一就是使用不同的 Maven 模块;一个带有 API 的模块和一个带有实现的模块。这样就不可能从 API 公开实现。

很遗憾,并非所有人都同意这是最好的方法。但是还有其他选择吗?例如使用 checkstyle 或其他“架构检查”工具?

PS:Java 9 对我们来说是不可用的,因为我们即将升级到 Java 8,这将是未来相当长一段时间内支持最低的版本。

【问题讨论】:

  • 实际上,将 API 及其实现分成不同的模块是一种常见的做法。还有 OSGi,它可以让您公开特定的包,但不能公开其他包。关于 checkstyle 和类似工具,我想您可以确保某些包(API)不会导入不需要的包(实现)。如果需要,自定义规则很容易实现。违规将导致构建失败。

标签: java api-design


【解决方案1】:

按照您的 checkstyle 想法,应该可以设置检查源文件中的导入语句的规则。

Checkstyle 对此具有内置支持,特别是 IllegalImportImportControl 规则。

如果公共类和内部类可以通过包名轻松分隔,这当然效果最好。

IllegalImport 的想法是您在 checkstyle 中配置一个 TreeWalker,它只查看您的 API 源,并且排除来自内部包的导入。

另一方面,使用ImportControl 规则,您可以在单独的 XML 文件中为整个应用程序/模块定义非常详细的访问规则。

【讨论】:

  • 谢谢。我会看看这个。我已经预料到 Checkstyle 对此有一些支持
【解决方案2】:

使用接口定义 API 并使用类实现它们是 Java 的标准。这样您就可以随意更改“内部”,而 API 的用户不会有任何变化。

【讨论】:

    【解决方案3】:

    另一种方法是使用一个模块(Jar 文件)用于 API 和实现(但话又说回来,它是 API 还是任何类型的库?)。在其中一个通过使用包将类和接口分开,例如com.acme.stuff.apicom.acme.stuff.impl。在后一个包protected 或只是package-protected 中创建类很重要。 包名称不仅向消费开发者显示“嘿,这就是实现”,而且内部也不能使用任何东西(为了简单起见,我们在此省略反射)。

    但同样:这与 API 的想法背道而驰,因为通常可以更改实现。使用这种方法无法将 API 与实现分开,因为两者都在同一个模块中。

    如果它只是关于隐藏库的内部,那么这是一个(不是一个)可行的方法。

    如果您指的是库而不是 API,它只公开其“前端”(通过使用接口或抽象类等),请使用不同的包名称,例如com.acme.stuffcom.acme.stuff.internal。当然,同样的可见性规则也适用。

    另外:这样就不需要 Checkstyle 和其他负担。

    【讨论】:

      【解决方案4】:

      这是一个好的开始:http://wiki.netbeans.org/API_Design

      关键点:Do not expose more than you want 显然,API 中表达的实现越少,未来的灵活性就越大。有一些技巧可以用来隐藏实现,但仍能提供所需的功能

      我认为您不需要任何检查样式或类似的东西,只需一个好的旧实体设计和架构就足够了。多态性就是你所需要的。

      最简单的方法之一就是使用不同的 Maven 模块;一个带有 API 的模块和一个带有实现的模块。这 这样就不可能从 API 公开实现。

      是的,我完全同意,尽可能隐藏,将你的界面分离到一个独立的项目中。

      【讨论】:

      • 这本书还不错;但这不是问题。问题是关于编译时保证不会意外泄漏到 API 中的内部类。
      猜你喜欢
      • 2010-09-21
      • 2015-02-05
      • 1970-01-01
      • 1970-01-01
      • 2016-07-10
      • 2010-12-20
      • 2011-12-05
      相关资源
      最近更新 更多