API库解耦方法?
想象一组代表某些 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 越多,需要应用的更改就越多。这是我想避免的。
Imagine a set of libraries that represent some APIs. By using an inversion of control mechanisms, concrete implementations will be injected in a consuming project.
Here is a situation. I have some of the API libraries depending on other API libraries for certain functionalities - therefore the API libraries themselves are coupled at some point. This coupling can become an issue later, because changing one API will result in changes of the dependent APIs, and the corresponding implementations will also need to be changed, so in the worst case we end up with quite a number of projects that need to be modified to reflect a change form only one of them.
Now I have in mind two possible solutions for this:
Create a monolith API project that unites the related API libraries.
Further decouple APIs by making each library provide interfaces for all functionalities that are dependent on the other API, so the direct dependency is removed. This might result in a similar code in both libraries, but gives freedom to the implementations chosen via the IoC mechanisms and also allows the APIs to improve independently from each other (when an API is changed, the changes would affect only its implementation libraries, not other APIs or their implementatons).
The problem with the second approach is the duplicating of code, and the result might be of having too much api libraries that need to be referenced (for instance, in .NET application each API will be a separate DLL. In some scenarios, like Silverlight applications, this can be an issue with app size - download time and client performance overally).
Is there a better solution for the situation. When is it better to merge some API libs into one bigger and when not? I know this is a very general question I am asking, but lets ignore the due dates, estimations, client requirements and technologies for a moment, I want to be able to determine the right approach based on both achieving maximum scalability and minimum maintanance time. So, what could be a good reason to choose either approach, or another one you might suggest me?
Edit:
I feel like I must clarify something about the question. I have in mind decoupling APIs from each other, not the API from its implementation. So, for instance if I have security API for validating permissions of access, and user accounts API that uses (references) the security API, changing security API will bring the need of changing the user accounts API, and the implementations of both of them. The more APIs that happen to be coupled this way, the more changes will have to be applied. It is what I want to avoid.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
需要在几个大型图书馆和无数个小型图书馆之间进行选择。
尽管如此,单一职责原则也适用于包级别,所以我建议小型、集中的库而不是巨大的通用库。这也使得选择同类最佳库变得更加容易。
小库总是可以组合/编译成更大的库(在.NET中使用程序集链接器/合并/重新打包实用程序),而拆分大库要困难得多。
无论您做什么,要记住的最重要的事情是向后兼容性。您引入的重大更改越少,这些库就越容易管理。
The choice is between few huge libraries and a myriad of small libraries.
Still, the Single Responsibility Principle also applies at the package level, so I'd recommend small, focused libraries instead of huge general-purpose libraries. This also makes it easier to always pick best-of-breed libraries.
Small libraries can always be composed/compiled into larger libraries (in .NET with an Assembly Linker / Merger / Repacker utility), while it's much harder to split a big library.
No matter what you do, the most important thing to keep in mind is backwards compatibility. The fewer breaking changes you introduce, the easier those libraries will be to manage.
我真的不认为这是一个问题。
有些库会依赖于其他库,这对我来说很好:改进一个库将改进所有依赖库!库的“所有者”有责任在进行更改时不破坏现有代码,但这是正常的,如果代码设计良好,则可以轻松处理。
I don't see this as a problem, really.
Some library will depend on other libraries, and this is fine to me: improving one library will improve all the dependents! The "owner" of a library will have the responsibility not to break existing code, when making a change, but this is normal and can easily be handled if the code is well designed.
如果您的所有相关代码都发生了变化,您应该重新考虑您的设计。如果您的库提供了某个 API,那么它应该将其使用者与底层类或库的更改隔离开来。
更新 1:
如果您的应用程序使用 Library1 和 API1,则不必处理 Library1 使用 Lib2、Lib3、..、LibX 的事实。
例如,Moq 模拟库依赖于 CastleDynamicProxy。你为什么要关心这个?您将获得一个已合并 DynamicProxy 的程序集,并且您可以仅使用 Moq。您永远不会看到、使用或不必关心 DynamicProxy。因此,如果 DP API 发生变化,也不会影响您使用 Moq 编写的测试。 Moq 将您的代码与底层 DP API 的更改隔离开来。
更新2:
那么您构建的不是一个库,而是一个针对非常具体问题的帮助程序,该问题不应该永远强加给其他项目。共享库往往会退化为“在遥远的未来某个地方可能有用”的集合。不!这总是会咬你的**!如果您对在多个地方发生的问题(例如
Guard
类)有解决方案:分享它。如果您相信您可能会找到解决问题的方法:将其保留在项目中,直到您确实遇到这种情况。然后分享一下。永远不要这样做“以防万一”。If you have changes rippling through all dependent code you should reconsider your design. If your library surfaces a certain API it should isolate its consumers from changes to underlying classes or libraries.
Update 1:
If your application uses Library1 with API1 it should not have to deal with the fact that Library1 uses Lib2, Lib3, .. , LibX.
E.g. The Moq mocking library depends on CastleDynamicProxy. Why should you have to care about that? You get an assembly where DynamicProxy is already merged in and you can just use Moq. You never see, use or have to care about DynamicProxy. So if the DP API changes, that would not affect your tests written using Moq. Moq isolates your code from changes in the API of the underlying DP.
Update 2:
If that is the case you don't build a library but a helper for a very specific problem that should NEVER be forced upon other projects. Shared libraries tend to degenerate to a collection of "might be useful somewhere in the distant future". Don't! This will always bite you in the a**! If you have a solution for a problem that occurs in more than one place (like
Guard
classes): share it. If you believe that you might find a use for some solution to a problem: leave it in the project until you really have that situation. Then share it. Never do that "just in case".