API库解耦方法?

时间:2012-02-02 14:00:44

标签: api dependency-injection decoupling

想象一组代表一些API的库。通过使用控制机制的反转,具体实现将被注入到消费项目中。

这是一种情况。我有一些API库,取决于某些功能的其他API库 - 因此API库本身在某些时候耦合。这种耦合可能会成为一个问题,因为更改一个API将导致依赖API的更改,并且相应的实现也需要更改,因此在最坏的情况下,我们最终需要进行大量的项目修改为只反映其中一个变更形式。

现在我想到了两个可能的解决方案:

  • 创建一个整合相关API库的整体API项目。

  • 通过使每个库为依赖于其他API的所有功能提供接口来进一步解耦API,因此删除了直接依赖关系。这可能会导致两个库中的代码类似,但可以自由选择通过IoC机制实现的实现,并且允许API彼此独立地进行改进(当API更改时,更改将仅影响其实现库,而不是其他API或其实现)。

第二种方法的问题是复制代码,结果可能是需要引用过多的api库(例如,在.NET应用程序中,每个API都是一个单独的DLL。在某些情况下与Silverlight应用程序一样,这可能是应用程序大小的问题 - 总体下载时间和客户端性能。

是否有更好的解决方案。何时将一些API库合并为一个更大的更好,何时不合并?我知道这是一个非常普遍的问题,但我们暂时忽略了截止日期,估算,客户要求和技术,我希望能够在实现最大可扩展性和最小维护时间的基础上确定正确的方法。那么,选择任何一种方法或者你可能会建议我使用另一种方法的理由是什么?

修改

我觉得我必须澄清一些关于这个问题的事情。我想到的是彼此解耦API,而不是其实现中的API。因此,例如,如果我有用于验证访问权限的安全API,以及使用(引用)安全API的用户帐户API,则更改安全API将需要更改用户帐户API以及这两者的实现。碰巧以这种方式耦合的API越多,就必须应用更多的更改。这是我想要避免的。

3 个答案:

答案 0 :(得分:4)

选择是在几个巨大的库和无数的小型库之间。

  • 如果你有一个庞大的库,其中的代码往往是紧密耦合,因为没有力量以松散耦合的方式设计各种元素。风险在于,进化该库变得越来越难,因为必须协调很多相互依赖关系。以.NET基类库为例。
  • 如果你有无数的小型库,你可能会冒险 dll hell 。是的,许多年前我们曾答应这已经结束了,但事实并非如此。只是尝试在应用程序代码库中使用大量细粒度的开源库,你就会明白我的意思。

尽管如此,Single Responsibility Principle也适用于软件包级别,因此我建议使用小型,集中的库而不是大型通用库。这也使得总是选择最佳库变得更容易。

小型库总是可以组成/编译成更大的库(在.NET中使用Assembly Linker / Merger / Repacker实用程序),而拆分大型库则要困难得多。

无论您做什么,最重要的是要记住向后兼容性。您引入的更改次数越少,这些库就越容易管理。

答案 1 :(得分:1)

我不认为这是一个问题,真的。 一些图书馆将依赖于其他图书馆,这对我来说很好:改进一个图书馆将改善所有家属!库的“所有者”有责任在进行更改时不破坏现有代码,但这是正常的,如果代码设计得当,可以轻松处理。

答案 2 :(得分:1)

如果您的所有相关代码都有变化,您应该重新考虑您的设计。如果您的库表面某个API,它应该将其消费者与基础类或库的更改隔离开来。


更新1:

如果你的应用程序使用带有API1的Library1,它不应该处理Library1使用Lib2,Lib3,..,LibX这一事实。

E.g。 Moq模拟库依赖于CastleDynamicProxy。你为什么要关心这个?你得到一个已经合并了DynamicProxy的程序集,你可以使用Moq。您永远不会看到,使用或不关心DynamicProxy。因此,如果DP API发生更改,则不会影响使用Moq编写的测试。 Moq将您的代码与基础DP的API中的更改隔离开来。

更新2:

  

查找对多个分支有效的问题会导致修改   所有这些

如果是这种情况,您不构建库,而是针对非常具体的问题的帮助程序,从不强制执行其他项目。共享库倾向于退化为“可能在遥远的未来某处可能有用”的集合。别!这将永远咬你**!如果您有针对多个地方(例如Guard类)发生的问题的解决方案:分享它。如果您认为可能会找到解决问题的方法:将其保留在项目中,直到您确实遇到这种情况为止。然后分享。永远不要“以防万一”。