DEV Community

loading...
Cover image for The case against DRY, Micro-Frontends edition.

The case against DRY, Micro-Frontends edition.

Ruben Casas
👨‍💻 Dev. 🔈 Online Conference Speaker. ⚛️ Working on a React Microfrontend Framework for millions of users worldwide ❤️ Love helping others.
Originally published at infoxicator.com Updated on ・4 min read

We have been told again and again that one of the golden rules of software engineering is the famous “Don’t Repeat Yourself“; if you find code that is repetitive you should try to abstract it, however, how does a modular architectural approach affect the DRY principle?

Let’s imagine that you are building a new section of a modular frontend application, you have the freedom to release to production as many times as needed without needing intervention from other teams, however, you start noticing a pattern, some of the features you are building are so similar across all modules that you decide to abstract them into their own dependency.

What seems like a perfect application of the DRYprinciple quickly becomes a bottleneck.

Let me expand on that… if the code that you abstracted is rapidly changing and your main module’s functionality depends on it, you will have to ensure you deploy that code before it can be used in your module and instead of having the freedom of one deployment, now we have to deploy two different codebases to achieve a working feature.

Let’s add something else on top of it, the second team who wants to reuse the same library that you extracted have also added some “extra features” to adjust the library to their own use case and now you find yourself quickly maintaining more and more features that were not part of the original requirements.

Finally, we end up with larger codebases and more complex code to adjust for all edge cases or even worse we might end up with a smaller inferior solution because we had to settle for the minimum set of features that apply to both use cases but leaving personalised use cases behind.

Reusing is very difficult! in some cases the cost of reusing is higher than building the feature twice.

Alt Text

Source: Microfrontend Myths by Cam Jackson

Three strikes… reuse!

Ok, so that’s if you have only 2 similar features, but what about the “Rule of three“, surely that is when you should think about an abstraction, right? well, like in most things in software development, it depends…

One of the main benefits of a modular “Micro-Frontend” architecture (and one of the most difficult to apply) is to decouple different modules to allow for independent deployments. If we start adding abstractions that break this pattern and tightly couple the different modules back together we end up back on square one and we negate this benefit resulting in a “distributed monolith”.

It’s all about the simple things

So hold on, are you saying that we must reinvent the wheel again and again?… Of course not! reuse is very useful when you try to abstract small, atomic and static things. Component libraries and design language systems are the best examples of how to reuse code effectively without breaking the freedoms of independent deployments… so don’t worry I am not suggesting that you should re-create the same button 100 times.

Reusability is a nice “side effect” not the target

Features and user experiences that are not static or atomic are very different when it comes to reusing code and not repeating yourself. It is definitely possible but harder and it might come with a cost. The recommendation is not to force the reuse and let it naturally occur, having a clear contract between the reused features and the consumers and preserving the ability to deploy independently to avoid blockers.

A great example of code reuse in a Micro-frontend application is the header and the footer; they are features that contain an entire user experience that is present in most of the pages of the website. After transitioning to independent deployments and using a vertical slice approach, each team might find themselves building and providing the same header and footer. This could lead to multiple copies that are not synchronized, affecting consistency and creating issues because there isn’t a centralised place to update or manage each copy.

Alt Text

The key to reusing these user experiences is to allow for horizontal slicing of the application where an individual team can deploy the header and footer independently and other teams will just consume them, with a clear contract for required communication (like showing the login or logout button depending on the user session for example).
Alt Text

Conclusion

Reusing features or entire user experiences is very difficult! When approached by the temptation of abstracting an entire user experience I usually ask myself the following questions:

  1. Is the feature something that doesn’t change very often?
  2. Is this feature present in more than three places? (Rule Of Three)
  3. Is the code made up of simple atomic things like components?
  4. Can the feature be owned by an independent team?
  5. Can I deploy the feature independently without tightly coupling it to other features?

If the answer to most of the questions above is “Yes”! then “Don’t Repeat Yourself!”


This article was inspired by the “Microfrontend Myths” webinar by Cam Jackson.

Discussion (4)

Collapse
franiglesias profile image
Fran Iglesias

Hummm. DRY is about knowledge, not about code.

Code duplication can be even desirable, as you expose in the article. Knowledge duplication is another subject.

I would add a "0 question" => Does this duplication represent a unique concept? If the answer is no, leave the duplication in place.

Collapse
infoxicator profile image
Ruben Casas Author

Yeah so there are many types of things that you want to abstract, avoiding code duplication is usually a good idea, also applies to small static things like primitives and well-defined components. The context of this article was more around the reuse of entire user experiences in a "Micro-frontend" application and how the DRY principle might not be a good idea for that use case.

Collapse
tejanshrana profile image
Tejansh Rana

"Reusability is a nice “side effect” not the target" - This is great. 👏
Thanks for sharing this Ruben! I especially like "reuse is very useful when you try to abstract small, atomic and static things". This is exactly how DRY should be approached.

Collapse
infoxicator profile image
Ruben Casas Author

Thanks Tejansh 👍