I Almost Got Fired for Choosing React in Our Enterprise App

Oaritis
8 min readJan 23, 2021

It’s summer 2018. My boss, Adrian, asks me to join him in a Skype call with James, the CTO of a big Canadian company.
While getting to know each other, I find out that James is a smart guy with big ambition. His vision is to migrate a massive desktop WPF application to the web in the cloud.
I like his friendly attitude and I can tell that he is eager to collaborate with us. He already has a development partner in India, but they lack experience in building web applications.
Adrian and I follow the standard approach for this situation. We have a few more calls and then we start the discovery phase in which we try to grasp the big picture and find the non-functional requirements. These are the main points we should focus on:
A big application — more than 220 pages, most of which are maintenance screens and around 20% of which are highly customized.
Display large amounts of data, especially in grids with all kinds of features: grouping, column freezing, row expand, custom columns, you name it.
Modular architecture allowing multiple teams to work on the project at the same time.
Multi-year project. New features will be added over time.
No offline support is required.
Quick onboarding for new team members, especially for the .NET developers working on the old desktop application.
As an architect, my role is to create a technical proposal that contains the architecture details, approach, roadmap, guidelines, and most importantly, the technology stack that will be used.
James mentioned multiple times that he wants a future-proof technology, and he is not in favor of Angular because it has a bad reputation after AngularJS got deprecated.
I had already successfully implemented a few small and medium-sized projects using both Angular and React, so I am not really attached to any of them. I feel that either could do the job.
For this project, I pick React with Redux… which I will regret two years later.
We assign a team of three developers to work on the proof of concept, and after two months, it’s a success. Super-responsive user interface, blazing-fast build time, and high development speed. Everyone is happy.
Roadblock #1: .NET Developers Join the Team
After the proof of concept, it’s time for the developers from the client’s outsourcing team to join in. We hadn’t started the knowledge-sharing sessions yet and the CTO sends me an email saying, “Hey, Răzvan. We really have to meet tomorrow with my outsourcing team.”
We have that meeting and the technical lead ambushes me with questions and solutions:
“Where is the dependency injection? What do you mean by ‘There is no need for one?’ Here is one: InversifyJS!”
“Functional components? No, no, no. We don’t like them. Let’s use class components!”
“Why do these functions just hang around and why aren’t they encapsulated inside service classes to make them static?”
“Where is the Retry Policy for the API? Let’s implement one using PollyJS.”
“Why are file names dash-case when class names are PascalCase? It should reflect the class name, so from now on, we will name them SomePageComponent.tsx.”
And, the one that annoys me most: “How can I run it using Visual Studio and not Visual Studio Code?”
It‘s’ clear to me. They want to use the .NET guidelines and design patterns in React. I have seen this happen many times — developers who have a hard time adapting to the new technology’s way of doing things. So I am not afraid of getting into a debate about why those are unusual patterns for React.
But in this case, the CTO is backing his team, which is normal. He had known me for just two months, while he had been working with his team for many years. I have to make compromises and agree with their proposals.
I just realized that React is not Java or .NET developer-friendly. Angular would have been a better choice in this case because of similar design patterns.
Roadblock # 2: There Is Never Only React
React is an unopinionated library, which means that it doesn’t have an opinion about how to implement cross-cutting concerns. So it is your and your team’s responsibility to develop an opinion about how to do it and especially what other libraries you want to use. Of course, you will use third-party libraries because you don’t want to reinvent the wheel. And there are so many options for everything in React.
For the proof of concept, I already had an opinion about how we should handle most of the cross-cutting concerns. Now they had to be revalidated with the new team members. This is a minimal list of topics to discuss:
Which router should be used?
Besides Redux, what should we use for async actions? Trunk? Saga?
Should we use Axios or the fetch browser API?
Redux-Forms, Formiq, or Final-Form?
Styled-Components, makeStyle, SASS, or plain CSS?
The Internationalization library?
So we spend another three weeks making those decisions. I can feel you screaming at me, “Come on, man! There is no way it takes three weeks to pick those libraries!”
Well… welcome to enterprise projects. There are many decisions. For each one, you have to create decision criteria, do research, validate findings by creating a proof of concept, present findings, document everything in the decision log, and keep libraries up to date. It takes a crazy amount of time, and it is not even fun.
And I am not even considering the time that each developer spends on learning all those third-party libraries. I never saw two React projects with the same dependencies, project structure, and guidelines. This means the knowledge is not transferable from project to project, as can be the case in Angular or Vue.
After those three weeks of not making any progress in implementing functional user stories, the CTO starts to worry.
Roadblock #3: React Hooks Gets Popular
After nine months, we have more than 50 pages created. The developers notice that function components are as good as class components and start using them. So, now the project no longer follows the original coding guidelines. It’s more like a personal choice for each developer. And for me, that is OK.
React Hooks is released and gets popular. The team has mixed feelings. Some developers are offended by the suggestion that classes confuse both people and machines, while others are enthusiastic about the new coding pattern.
All the third-party libraries that we are using have added support for Hooks, and it looks like the entire React world is going in that direction. So what should we do? Should we deviate from the original coding guidelines and add a third way of implementing components? There is no way of going back and migrating existing pages and components to Hooks!
The team is in favor of using Redux Hooks because there is no need to use Redux connect() and separate the dump components from the containers. This makes sense and we agree that from now on, new pages and components will use Hooks. We will leave the old ones as they are.
And that’s how we end up with three ways of doing things. There is no consistency anymore.
To make things even worse, some developers start to push the idea of not using Redux anymore but useState instead. This means that we will disrupt the idea of having a single global state.
Suspense is still an experimental feature. I am concerned about what will happen when it gets released.
Roadblock #4: Development Is Slowing Down
When we did the setup for Continuous Integration, the build took around three minutes, including npm install. But now, after a year, it takes around 15 minutes.
We also had to configure Node.js to extend RAM to 4GB because 2GB was no longer enough. This is not a big issue. What is concerning is that the developers have started complaining that the build takes so much time, the hot reloading stops working after 45–60 minutes of development, and a restart takes more than five minutes — especially for those with Windows machines (Linux systems apparently are much faster for Node.js). Sometimes, they have to delete node_modules entirely and download dependencies again because it simply won’t work otherwise.
What can you expect when there are 1,200+ dependencies in node_modules with a total of 600MB in size?
For an enterprise application, everything is about costs. Let’s say a developer has to restart six times a day with an hourly rate of $40 per hour. Six times/day x five minutes x 240 days/year x $40/hour x eight developers = $38,400/year. This is not a big amount for an enterprise, but it makes a nice annual bonus for the project sponsors. After all, it’s equal to a brand new Tesla Model 3.
Roadblock #5: Redux-Saga Is Slowly Dying
Most developers disagree with me, but I feel that a big part of the business logic is inside Redux async actions. Most of the time, it’s the only place where you can do the validation, API calls, error handling, trigger redux mutations, or trigger a notification toaster. If these are not considered business logic on frontend applications, then what is?
We use Redux-Saga, which was a poor decision because it adds unnecessary complexity. Thunk would have been good enough.
In enterprise applications, you have to upgrade and revalidate the dependencies once in a while. It is a good practice because you want security updates, performance improvements, and small incremental API changes while hoping for no breaking changes. It looks like Redux-Saga is being left behind. The last update was more than one year ago and the number of GitHub issues is still increasing without anybody fixing them.
Developers love React for three reasons: simplicity, flexibility, and ecosystem. React’s team enjoy experimenting with new ideas, but this is killing the ecosystem! They should be brave and take the blame for it!
Indeed, React is mostly backward-compatible, but the ecosystem around React is not. Developers and third-party libraries will always use the latest features and architecture patterns, while old experiments will be left behind to die. This should not be a problem for small and medium-sized projects because you can adapt much more easily. But for big multi-year projects, these experiments can be a deal-breaker.
It’s already September 2020 and I decide to include React-Saga in the risk assessment results for the technical steering committee.
Because 30% of the business logic was inside the sagas, I marked it as a high risk. That was when the CTO lost his temper and blamed me for making poor decisions when we started the project.
It was just the spark the product manager needed. He uses this as an opportunity to start asking questions like:
“Why do we have to spend so much time on upgrading libraries?”
“Why is the development slowing down?”
“Why did the application become buggy and unstable?”
Things escalate to the management level. I spend many hours looking for evidence to prove that we made the best decisions at the time — not the way I want to spend my weekend.
Several retrospective meetings later, we are sailing through calm waters again. After all, the project is almost done. It’s close to entering maintenance mode.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

--

--