6

I'm curious if there's a series of tendencies or anti-patterns when programming whereby a developer will always locally re-wrap external dependencies when consuming them.

A slightly less vague example might be say when consuming an implementation of an interface or abstract, and mapping every touch-point locally before interacting with them. Like an overcomplicated take on composition. Given my example, would the interface not be reliable enough and any change to it never be surmountable any any level of indirection?

Is this a good or a bad practice? Can it ever go too far? Does it have a proper name?

  • 5
    The concept is certainly well-known (although I can't give you a canonical name): "All problems in computer science can be solved by another level of indirection" (David Wheeler) "...except for the problem of too many layers of indirection." (Kevlin Henney) – Kilian Foth Oct 17 '13 at 18:10
  • Lol great twist on that quote. God I hate indirection. – Sridhar Sarnobat Dec 27 '17 at 21:12
8

I've seen these things called "shearing layers" - which are specializations of "abstraction layers" for external dependencies.

Personally, I think it is a bad practice that often falls into YAGNI.

Yes, abstraction layers protect you from changing interfaces outside of your control, or if you change dependencies. But I've seen too often people go "but what if our database provider changes?!?" for an app that has a 6 month lifespan. I've also seen far too many bad abstraction layers. They leak through enough implementation details that you end up with a boat load of work to adapt it to your new implementation anyways.

If you know the extenal interface is going to change, abstraction may be prudent. If you know that you're going to need multiple implementations, abstraction is important. If you don't know, you're (probably) not going to need it.

4

I think most people just call it "wrapping an API." There are certain circumstances where it can be beneficial:

  • When you are only wrapping a small subset of the API. This enforces a smaller interface.
  • When your ABI isn't constant. Nvidia does this for their Linux drivers. The installation script compiles the wrapper and links it against their closed source binary.
  • When you're creating a useful abstraction, not just a function-for-function copy of the original API.
  • When you already have two implementations of the API you know you need to use. For example, different databases or operating systems or language versions. I have a project for both Android and desktop Java where I wrapped most of the UI functionality.

The mistake a lot of people make is wrapping an API on the off chance they might need to replace it someday, but if and when that day comes, their wrapper is too much like the original and needs rewriting anyway. Abstractions are only useful if they add some value to the layer below.

Not the answer you're looking for? Browse other questions tagged or ask your own question.