- Event
#Learning
Get ready for Cloudbrew 2024!
- 24/09/2024
Reading time 1 minutes
One of the biggest challenges in software development is dependency management and software architecture tries to manage it. Different architectural styles try to handle dependency management in different ways. Microservices are the newest trend, where one microservice is trying to be as autonomous as possible and therefore has no coupling to other microservices.
The main benefit of having loose coupling and minimal dependencies is making it easy to change the system without fear of breaking something else.
When talking about coupling and dependencies, we are usually referring to backend code. However, the same principles apply to the frontend code as well. One of the most discussed frontend topics in the field is state management as it’s present in all frontend applications, especially single-page ones.
There are many blog posts, that compare different frontend state management solutions like redux or mobX. However, there are not so many blog posts that touch on fundamental problems that a shared state could lead to.
In this blog post, we will investigate how sharing state across the solution may lead to hidden dependencies, which will have a huge impact on system maintainability.
About the hidden dependencies; they are one of the nastiest dependencies. They are created when multiple features refer to the same data structure on external storage (https://martinfowler.com/bliki/IntegrationDatabase.html).
let’s have a quick look at the hidden dependencies on the backend side. Let’s have an example using three features A, B, and C:
Now we have a situation where we do not have any visible dependencies between Features A, B, and C (which even a static code analyzer cannot see). However, all those features are depended on data structures in Table T1. So, all those features are depended on each other.
Now if we’ll get a new requirement that forces us to change feature A’s data structure, features B or C may get broken because of this change. We also have the same problem in the frontend when our components are connected to a shared state (redux, mobX, or something else).
State management solutions are libraries like redux, mobX, and overmind. I won’t go through deeply why we want to use state management solutions. In general, we use those to share some data between components.
Many people argue that mobX is a lot better than redux. Usually, because it is simpler and doesn’t have so much boilerplate code. Because of this kind of discussion and comparison between the state management libraries, we usually miss the point; boilerplate code is not the real problem, dependencies are.
At the beginning of the project, you won’t even notice dependencies. With loose dependency management, you can develop the system faster. However, when time pass and the system grows, you start feeling pain. The growing spider web of feature dependencies will slow down the development pace due to added complexity and makes your system more fragile.
When we share data across components, we may quite easily end up in the same situation we described in the backend example.
You have two options:
So why am I raising the issue on the frontend side? In the backend, we usually have clearer boundaries between the features. That makes dependency management more explicit and easier.
In the frontend, this is usually harder, because our feature boundaries are more blurry. We have a lot of features on one page and they usually show the same or similar data. That leads very easily to a bad way of data sharing, which will cause poor maintainability.
So, as a conclusion, it is actually fine to use state management libraries. The challenge in using these libraries is the easiness to access some other feature’s state. By doing so, you will create a hidden dependency.
Usually, you don’t need those state management libraries at all and that makes your system’s architecture simpler. Simpler systems are always more maintainable, so think twice before adding this extra complexity to the system.
For the record: During the last two years I have coded using React I haven’t needed any state library. Having the react components handle their own states is usually enough. Also have a look at a library like react-query, that helps you to handle some use cases where you usually need a state management library.
Our newsletters contain stuff our crew is interested in: the articles we read, Azure news, Zure job opportunities, and so forth.
Please let us know what kind of content you are most interested about. Thank you!