In certain circles, one of the main raisons d’être for object-oriented design, or encapsulation in the broadest sense, is that it makes it possible to later “swap out” implementations without disturbing the end-client whatsoever. I kind of tacitly accepted that for a long time, but I think it both oversimplifies the arguments in favor of encapsulation and diminishes its power.
Is there practical value in swap-able implementations? I’ve seen a few cases where it was incredibly valuable, usually in the context of using a third-party library. Here the need for encapsulation is driven by the fact that you don’t control the implementation — the third-party does — and you need to protect yourself from their future changes. It is a strong argument for encapsulation, but more as a protective measure than because you intend to swap out the implementation. (If you are planning to swap the implementation right off the bat you might want to look at your vendor-selection process…)
So given that it is sometimes desirable to enable “swapability”, is it really the case that you can do it without disturbing the end-client? Sometimes, but not always. Different implementations will have different performance characteristics; switching from an implementation that stays within the process boundaries to, for instance, a web-based service implementation, will most definitely result in changes in the performance profile that will be visible to your clients. It might not be a problem, but it will definitely be apparent.
So swap-ability is kind of nice, in some situations, but I don’t think in and of itself is a strong enough justification for OO or encapsulation.
I think there are three other rationales for encapsulation that yield far more significant benefits than swap-ability:
- Encapsulation helps you control the granularity of your designs. Designs accrete organically around the encapsulated lumps of functionality rather than spreading higgledy-piggledy throughout and yielding the dread spaghetti code monster.
- Encapsulation allows us to intellectually partition complexity into manageable units.
- Encapsulation isolates behavior to make it testable. (While this could be viewed as an argument for swap-ability, I don’t consider it to be a valid argument; I’m pretty firmly against the idea of wasting time writing mocks — but I talk about that elsewhere.)
So while the idea of swapping out implementations has a strong hold in the developer hive mind, I think it is important to look beyond that one simple, rather limited idea to the more powerful benefits of encapsulation.