Microservices are great. Containers are great. Packages are great. Objects are great. Functions are great. At each level they encapsulate functionality into re-usable modules. One place to make changes. One place to optimise. One abstraction to help you move to the best layer.
For the sake of argument though, I’m going to focus on microservices, specifically those accessed via an API, as that’s what I know best.
Interfaces and APIs are good for test harnesses, but isolating systems for your own benefit (to make modules open for extension but closed for change) bears no relation to making that module useful to other systems.
Sure, I could rip out the modules that contain business logic, and package it as a framework, but that doesn’t mean it’s useful for anyone else. It could well be an inner system. It may still be coupled to domain/architectural knowledge that make it too valuable to swap out. There could be an implicit dependency for just that one version of that one tool.
It is of course possible to make modules re-usable, but they have to be designed that way, whether up front, or evolved. And anything interchangeable has to be tested, in at least 2 conditions, to make sure it’s suitably robust.
Design an interface. Evolve the design. But don’t mistake solving one problem in one place for a general solution. And don’t think that adding an interface is all it takes to turn a local SQLite data store into a cloud file system repository.