One of the omnipresent notion in computer science is the abstraction layer. You can find them everywhere, and a large fraction of computer science academia is about designing proper abstraction layer, and studying the existing ones. I find them similar to metaphors: powerful but also very dangerous, as they can trap you, and warp the way you think. Bad, broken or unnecessary abstractions are the root cause of some of the most horrible code I have seen.
I’m not saying there are no good abstractions, but first that creating the right one is far from trivial, and that even the best designed abstraction will have limitations, and will be based on some assumptions. Sooner or later those assumptions will change, and the abstraction will become more of a tradition than an useful tool – UI abstraction layers are a typical example of this: the expectations and capabilities of the hardware have evolved so much that then current abstractions make little sense.
Often people build an abstraction layer around an unfamiliar API, in that case they are building more of a shield to avoid thinking to much about that API. There will be arguments for doing so: this is a cleaner design, makes the code more portable. The result is, more often than not, a simple wrapper that somehow shifts the model to whatever the author prefers, with no real added value. It adds bugs, code burden, and make the code more complex. When code is passed to another person, she just adds another layer of abstraction on top of the previous crap, and so on.
For me, an abstraction layer is valid if one or preferably both of the following conditions are met:
- The layer adds some non-trivial property
- The layer abstracts at least two different implementations
Sockets are a good abstraction, they abstract two very different underlying systems (network streams and files). A layer that hides a SQL database to do read and write operations has little value. A layer than handles multiple url formats has value, in particular if it handles the difficult parts of the various protocols: compression, encryption, proxy handling.
I think writing an abstraction too soon is basically just a case of premature optimisation, only what one tries to optimise is code reuse instead of code execution…