2

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:

  1. Don’t treat interfaces as published unless they are
  2. Don’t publish interfaces inside a team
  3. 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.

I have to admit that I have no experience with microservices. When it comes to internal versioning, I also have not much experience expect for some smaller Javascript projects where we split our code in small projects and used npm to manage the dependencies. Most of my time, I worked in middle to large Java projects where you build from source and which had mostly a monolith architecture. Expect for RMI communication between components, most interfaces could be classified as public (not published).

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

Microservice argument:

  • 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.)

  • 1
    You had me until I read the last sentence of your post. Do you have a more specific question than that? Otherwise, this amounts to a request for an article review. – Robert Harvey Jun 3 '16 at 17:32
  • @RobertHarvey I tried to make my point clearer by summarizing my current understanding, which could be wrong in some parts, of course. – Philipp Claßen Jun 3 '16 at 18:18
  • It seems as if your question hinges on the word "publishing." if a microservice is only used internally, you don't have to publish it, and if an API is public, I would think the same principles that Fowler outlined would still apply, whether it's a microservice or not. – Robert Harvey Jun 3 '16 at 18:22
  • @Philipp, You are assuming that a micro service means that the data has been published. When in fact, it can be a private micro service which is only used by other services behind an API gateway. Such a service would not be published. A published API would likely not be well-served by a gaggle of microservices, as your consumers will want a more coherent interface into your system. – Kasey Speakman Jun 7 '16 at 23:16
1

Fowler's point is essentially that once you have 'published' an interface you are stuck with it. Essentially you've become a dependency of something outside of your control and the more popular your interface is, the harder it is to understand the impact of changing it. This is just a fundamental aspect of reality.

Ultimately here's what happens: you create some services. People find value in those services and build dependencies on them in their systems and move on to work on other things. Then, you decide that you want to change your service. You absolutely can but when you do you break these systems and most likely make them angry. The less you know about your consumers, the harder it is to mitigate this. So you have to figure out how much you care about creating problems for these users.

If you do care, you need to plan to be able to maintain multiple versions of the same service. This allows you to move forward.

Here is another Fowler article that addresses microservices directly and I think it's superior to the one you reference here. It's the most complete and well written explanation of microservices I've seen. As I see it, microservices are less about the structure of the interface than how they are deployed and the issue you are asking about is orthogonal to the question of monolithic service platforms vs. microservices.

1

In his article on microservices from 2014, Martin Fowler lists the refactoring aspect as a drawback but concludes that the advantages of microservices weigh more heavily:

There are certainly reasons why one might expect microservices to mature poorly. In any effort at componentization, success depends on how well the software fits into components. It's hard to figure out exactly where the component boundaries should lie. Evolutionary design recognizes the difficulties of getting boundaries right and thus the importance of it being easy to refactor them.

But when your components are services with remote communications, then refactoring is much harder than with in-process libraries. Moving code is difficult across service boundaries, any interface changes need to be coordinated between participants, layers of backwards compatibility need to be added, and testing is made more complicated.

... So we write this with cautious optimism. So far, we've seen enough about the microservice style to feel that it can be a worthwhile road to tread. We can't say for sure where we'll end up, but one of the challenges of software development is that you can only make decisions based on the imperfect information that you currently have to hand.

The topic of explicit versioning versus building from source might be a question of your tool support in the end. It seems to be consensus that managing your dependencies with explicit versioning has no implications on whether the APIs are considered published.


At work, moving to explicit versioning currently breaks tool support. For instance, refactorings like renaming methods or classes are no longer supported, as the IDE cannot track how the code is used. Unless it is used in tests, IntelliJ marks the APIs as dead code, now. Find-references only works if you apply it on the classes in the jar.

It can be mitigated by temporarily switching all dependencies to snapshot dependencies (we are using Maven). Then, the IDE again understands who uses the interface and thus can automatically apply the changes.

So, I would assume that it is technically possible to setup an environment were you have both (explicit versioning and support for refactoring). In that sense, it is a decision that is independent of the discussion about "public vs published" interfaces.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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