Reasons for building microservices are often about using isolation as a means to handle change. Sharing code between services couples your services to each other and by this you are crossing the isolation barrier, reducing the effectiveness of the isolation and the ability to handle change, David Dawson writes questioning the Don’t Repeat Yourself (DRY) principle.
David, CEO at Simplicity itself, sees some common reasons for building microservices including:
- Independent scaling
- Service isolation
- Separate service life-cycles
David claims that these reasons are all about handling change, in the environment or in the codebase and he believes change is often also the main guidance used when splitting services apart.
The reasons among developers for sharing code across microservices are basically quite few, David has found, and include:
- Leverage existing technical functionality, e.g. through shared libraries.
- Sharing data schemas, e.g. by using the same classes.
- Sharing data sources, e.g. using the same data store by different services.
David emphasizes that all code sharing will attach your services together via the shared code. Creating a single source of truth, adhering to the DRY principle within a single service will create internal coupling but causes no problem in a service with a single responsibility. In contrast, when crossing a boundary, even though some things look the same, they are in a different context and must be different, implemented by different code and using a different data store. David urges that no matter how similar things look, we must resist attaching them because that means we are coupling across boundaries and across different contexts, a direct path to a big ball of mud.
David thinks the DRY principle has become one of the fundamentals of software development, comparable to design patterns but also that it has been transformed into a Don’t Repeat Anything principle and Copy and Paste is bad. Going back to the roots and the book “The Pragmatic Programmer” DRY was described as:
Every piece of knowledge must have a single, unambiguous, authoritative representation within a system."
David notes that the key term here is the concept of knowledge, not about copy and pasting. Although the principle is useful in certain areas he believes the term has been taken out of its context and applied too broadly. When applied at a higher level, e.g. sharing schemas, on a microservices architecture we will be left with the cost of maintaining the architecture but without the benefits, they have been short-circuited by DRY.
Community comments
This renders "micro" an impossibility
by Hermann Schmidt,
Re: This renders "micro" an impossibility
by Owen Rubel,
Shared IO State
by Owen Rubel,
Just examples of bad design
by Valentin Tudor Mocanu,
Service Boudaries is the Key
by Nabil Belakbir,
Re: Service Boudaries is the Key
by Richard Clayton,
hi all
by David Dawson,
Depends on the definition of "boundary" or "context"
by Ryan R,
Re: Depends on the definition of "boundary" or "context"
by Faisal Waris,
Interesting
by Rayna L,
Re: Interesting
by Vincent Fieldman,
Consider This
by Luis Espinal,
This renders "micro" an impossibility
by Hermann Schmidt,
Your message is awaiting moderation. Thank you for participating in the discussion.
A service with only a couple of code lines, which is the original 'micro' in microservice, cannot be independent in a non-trivial network of data structures. It must share knowledge because it is collaborating with other services to work on a bigger thing.
Only the most isolated small-scale problems like for example the calculation of PI or sending emails are really micro.
To me it looks like we have yet another silly term in the industry, not representing what it is really about (see NoSQL). The only real difference to the old SOA idea I can see is the stricter isolation in terms of lifecycle and infrastructure. Micro? Nah, not really.
Shared IO State
by Owen Rubel,
Your message is awaiting moderation. Thank you for participating in the discussion.
Gave a talk recently on how to fix alot of this through shared IO state making things more CPU bound and less IO bound by abstracting IO functionality/data from business logic and moving to a separate communication layer. This enables IO state to be shared with architectural tooling instead of being bound to controllers and thus binding IO state. See some of my slides here (www.slideshare.net/bobdobbes/presentations)
Re: This renders "micro" an impossibility
by Owen Rubel,
Your message is awaiting moderation. Thank you for participating in the discussion.
incorrect. All you have to do is share IO state. see this youtube video (www.youtube.com/watch?v=mZOs7oz0JOI)
Just examples of bad design
by Valentin Tudor Mocanu,
Your message is awaiting moderation. Thank you for participating in the discussion.
You cannot blame a design principle with examples of bad usages.
Microservices have some problems on respecting design principles like DRY and that will induce significant technical debt when copy-paste will be used on large scale. Putting the same business rule in 10 places it its also an invisible coupling that appear every time when that rule need to be changed.
Think further, if you have 500 of such repeated business rules, the system is already a big ball of mud.
A micro-service or a normal component/module, the effect will be the same. The micro-service has just a different type of deployment that bring no help in such cases. Does not count that deployment mode is "cool".
Just my opinion.
Service Boudaries is the Key
by Nabil Belakbir,
Your message is awaiting moderation. Thank you for participating in the discussion.
I am not agree with the conclusion .
if we are in the situation that two microservices need to use exactly the same code (For example the same bussiness rules) so there is here an opportuniy to create another Microservice ( Rules Microservices ) . Otherwise we will build just a modular Architecture and not a microservice one .
hi all
by David Dawson,
Your message is awaiting moderation. Thank you for participating in the discussion.
Hi there! Thanks to Jan and InfoQ for the write up.
Thank you to the commentors for the feedback (Owen's talk is worth checking out to broaden the mind), however I think that there is something of a misunderstanding (maybe coming from not reading the articles?)
At no point do I suggest massive duplication of code as Valentin and Nabil seem to suggest that I do. This is the 'copy and paste is baaaad' accusation that I actually discuss and deconstruct in the articles and it really, really misses the point (simple code duplication is not what DRY was originally about, even). There is a lot more going on than this.
The thrust of my articles is that DRY has been turned into a dogmatic position, an absolute truth. Dogma makes people do silly things without thinking things through for themselves.
It is somewhat ironic that the only way to defend an absolute truth against a reasoned argument is to portray the reason as another absolute to be opposed at all costs.
...
As an aside, Technical debt is an amorphous term that people seem to think means 'stuff I did wrong'. It originally meant 'stuff I chose to do a certain way, in the knowledge it needs to change again in the future'.
Technical debt is a choice, not an accident. If you have something wrong in in your system that you didn't intend to be there, then you made a mistake, you do not have technical debt.
Depends on the definition of "boundary" or "context"
by Ryan R,
Your message is awaiting moderation. Thank you for participating in the discussion.
Much of this depends on what you consider a boundary or context within your overall system. The problem (or business) domain should drive your system decomposition exercise. You should end up with nice logical groupings of functionality, data and terminology that will form your contexts. (Keep in mind that I have said nothing about technology yet.)
I would agree that you shouldn't apply DRY across boundaries defined this way. Each context should be free to evolve according to its own rules because this is what will happen naturally.
Interesting
by Rayna L,
Your message is awaiting moderation. Thank you for participating in the discussion.
I found this article very interesting, it is a good thing to challenge established wisdom every now. As a developer I have had it drilled into me that duplication of code is the ultimate horror, a complete taboo and most of us would never even consider this as an option.
I am currently wrestling with problems in our environment where we have centralised / re-used code and it sits in the middle of a web of other applications like a giant spider. One doesn't dare change it, as it will potentially involve regression testing numerous other applications. In response, people build layers over this or other independent components that do things that are 90% similar.
The real issue is trying to define where to draw the boundaries or domains and one's natural inclination is to make that domain limitless (which in my opinion is very bad). Unless you have shared business analysts, lock-step deployment cycles and very good collaboration between teams, shared code can quickly become a giant bottleneck and an anti-pattern, as it tries to be everything to everyone.
The only time I have seen shared code work is where the shared component has been very small and very specialised and where it can be configured for deployment to different environments and in different application contexts.
The other option that works for us is to copy the code into different branches (to be used by different applications/services) and then to merge any changes that can be shared between the branches. This allows independent evolution as well as code re-use, but it requires discipline to maintain.
Re: Interesting
by Vincent Fieldman,
Your message is awaiting moderation. Thank you for participating in the discussion.
Once you start having versioned services, you're talking 100+ deployment pipelines and branches to keep track of for a full featured application. I see it working for now... but there's more devops and developer overhead. just something to keep in mind.
Re: Depends on the definition of "boundary" or "context"
by Faisal Waris,
Your message is awaiting moderation. Thank you for participating in the discussion.
Well said.
In a large organization the natural boundaries are systems of records - each with potentially 100's of inter-linked tables. The associated services tend to be large as well.
I don't potentially see a benefit in creating 10's of services with duplicated code and partially repeated functionality in such a domain.
Re: Service Boudaries is the Key
by Richard Clayton,
Your message is awaiting moderation. Thank you for participating in the discussion.
Or the services should be combined. This goes either way.
Consider This
by Luis Espinal,
Your message is awaiting moderation. Thank you for participating in the discussion.
Let's consider the hypothetical scenario where many, if not most microservices used by a business are developed using a common language (say Java), and use the same build/dependency management mechanism (say, Maven.)
Do they share code?
Does sharing the same Xerces parser among microservices count as sharing code?
Let's get past the hypothetical of common 3rd party binaries, and into the realms of custom code.
What if a set of microservices use, for whatever reason (valid or invalid), a unique, propietary, in-house-developed serialization protocol? Are they sharing code?
My questions are tongue-in-cheek, but they exist to illustrate the problem with this article (yes, I read it).
What is code? Define code. What is the granularity of code that should not be shared? As it is typically attributed to Voltaire, "define your terms".
See, the thing is, I can see the argument when we are talking about business rules.
It is obvious then that we should not be sharing business rules (as a business rule should exist and be executed in one and only one place, irregardless of whether we have a monolith or a set of microservices.)
But from there, the article fails to sufficiently explain the argument, in particular about DRY.
Micro or monolith, it is very rare to see cases where it is better to ignore the DRY principle. Rare but not impossible.
A discussion about the discretionary use of DRY (or any principle for that matter) is best accompanied with concrete, elaborate examples. Otherwise, it falls into the realm of hand-waving.