In this short article Public versus Published Interfaces from 2002, Martin Fowler distinguishes between easily changeable "public interfaces" and harder to change "published interfaces":
The key difference is being able to find and change the code that uses an interface. For a published interface, this isn’t possible, so you need a more elaborate interface update process.
Back than his advices on publishing included:
- Don’t treat interfaces as published unless they are
- Don’t publish interfaces inside a team
- Publish as little as you can as late as you can
The article was written in 2002 before microservice-based architectures become popular. In my company, we are moving to microservices and also preparing to switch from a building from source model to versioning. The assumption is that it makes it easier to support the development in an organization with a growing number of developers, as versioning allows more control about when you want to apply code changes as you have to actively increase the version of the library that you depend on.
When I now read Martin Fowler's article, I find his arguments very convincing. On the other hand, microservice architectures and also internal versioning seem to be trends which lead to more published interfaces.
Maybe I am missing something, but I see some conflicting goals in recent trends and Martin Fowler's article from 14 years ago. For example, "Don’t publish interfaces inside a team" seems to be in conflict with the trend that each team tries hard to splits its project into lots of small, independent services with a well-defined "published" interface. Also introducing semantic versioning of all libraries and small API projects seems to be a violation of that advice and makes refactoring harder.
I am a bit confused, so I wanted to clarify under which conditions publishing an interface has more advantages than avoiding it at all costs. Here is my understanding of both sides, please correct me if I got them wrong.
Martin Fowler's argument in short:
- Avoid published interfaces because it prevents refactoring
- Split your system into little services with a well-defined interface, as it is easier to understand.
- Instead of refactoring a monolith, all services are so small that they can be easily anyway
The other argument "build from source" vs version management is not touched in the article and is also not strictly required in microservice architectures, but still I wanted to mention it because I see a similar trade-off:
- Having access to all the source code allows easier refactoring at the cost of having to work with more code; changes to some library immediately become visible to dependent projects (which can be an advantage or disadvantage)
- Internal version management allows to checkout only the code that is needed but makes refactorings harder unless the developers have great discipline in updating their dependencies regularly (otherwise, public interfaces become "published" similar to the strong code-ownership example in the article).
- If some projects do not want to update their code, you still can make non-backward compatible refactorings, but later you have additional work when you eventually upgrade the other projects.
My current conclusion is that the trend is to encourage publishing interfaces in order to separate services as much as possible. In other words, the recommendation in the article mostly no longer apply to today's preferred system architectures. It still applies to the implementation of one microservice internally, but when they are small enough there are not too many non-published interfaces left, anyway. So the advice was more relevant in 2002 where monoliths were more common.
Would you agree? (Disclaimer: As I said, I am quite a novice on this subject.)