Is this case an overuse of abstraction?
We are using a library provided by someone else. Of late due to changes in that library our project has 500 errors. When migrating to the new library we found that only 15 APIs are failing and 500 errors are repetitive (multiples occurrences of those 15 errors, as same calls are used at so many times).
So开发者_开发知识库, for migration I proposed creating another internal static wrapper class, that wraps those library API calls. Because if library were to change again we will have less code to change and thus code becomes easier to maintain in future. And also by wrapping calls we avoid human errors (or unintended(overloaded) API usages).
But some folks here, don't see the point in having another wrapper class, which they feel is totally unnecessary. Their sole point of argument is that as most API changes are just one liners we can always change them using CTRL+H (Find and replace). And they also say that this extra abstraction that I am suggesting, takes away the readability (as it hides the actual API call behind another method name (even though meaningful) ) for the coder/reader.
Whats the best approach here? Am I wrong with my suggestions?
This is actually known as the Adapter pattern, and it's specifically created with your exact problem in mind....
Adapter is specifically used to NOT add functionality, just to adapt an interface of an API to an interface expected by the caller. The interfaces are just a handy OO tool to implement the adapters function in a consistent and managable way, the pattern itself basically describes how to solve a problem.
It is a relatively common practice to wrap unstable APIs and libraries with custom wrappers. One common use, for example, is to translate exceptions of that library into your nomenclature of exceptions.
More generally these wrappers are known as an Adapter, though Adapters (IMHO) are more meant for providing functionality needed by one side while hiding the exact "language" of the other side, not because the other side is unstable.
You mentioned the use of statics though - I'm generally not a big fan of using these. IMHO it is better sometimes to have an interface represent the functionality you need, and then have subtypes of that interface, when one of these subtypes uses the third party library. The advantage of that is that can one day switch to another vendor without changing every call in your system.
Either way, you're generally on the correct track. IMHO anyone who thinks CTRL-H is a valid refactoring tool is asking for trouble. Are they at least using getters and setters (Where applicable) in their code?
Also, the readability part is unclear to me. An adapter with a readable name is just as good as an original API with a readable name.
If an API is changing, a wrapper is the only way to protect yourself. If you've settled on a API that is changing you've got some big risks to your project. Mitigating those risks with a wrapper also allows you to protect yourself if you want to switch to another library.
To implement the wrapper, you have to make the wrapper and do your search and replace.
Either way, you still have to touch all your calls due to the initial API change, so I don't see that the small extra investment is a problem.
Hard to say without knowing your code, but I feel like a facade/adapter is a good way to seprate api calls from your own code. I would not go so far to say it is necessary, but its clearer imho.
It depends on what the API is doing and whether adding another layer really adds insulation/encapsulation or if it's merely adding another layer of indirection. If a change in the API will necessitate a change in the public interface of your wrapper, it'll just get in the way.
A wrapper layer is best suited when you can expose the functionality at a level of abstraction that makes sense for your application, hiding the API flexibility that you don't need and standardizing how you access the functionality you do need. This can also involve using function and parameter names more specific to your problem domain, which can reduce the conceptual difficulty of understanding how the API is integrated into your application.
精彩评论