More posts by Nelson Lee
Recently, I’ve been having trouble sleeping, and there have been two things keeping me:
- My one-year-old
- State management
I’ve come to realize that the common thread between the two of them has been that they are both in Flux.
I’ve been working with the Flux architecture for the past three years, and I absolutely love it. The loose coupling you get between components, predictability of state, and ease of testing have brought order to the chaos in the web Front-End Development world. It’s no surprise that Redux has had such an impact and meteoric rise. For me, it is the pièce de résistance pattern and brings an elegance to Front-End Development that I’ve been searching for. It’s no exaggeration to say that using Flux is like having a fine cup of morning coffee. It brings a certain kind of clarity and awakening. However, only recently, my beliefs were questioned when a colleague of mine asked me – Why shouldn’t my view have local state?
Why shouldn’t my view have local state?
Like everyone who’s discovered a great coffee, I proceeded to educate my colleague on the wonders of Flux. It will make your code testable! It will give you single responsibility! It will increase all your investments by 10%, no lie! And yet, he continued to ask – Why shouldn’t my view have local state?
I was shocked! Did my colleague not understand the benefits of Flux and how good it starts your day and lets you sleep at night? So, I told him to try it out, and just like me, I was hoping he, too, would enter the state of awakening. And yet, to my surprise, a week later he came back and asked the same question again – Why shouldn’t my view have local state?
For me, when someone asks me something three times, it’s usually a wakeup call. Was my view of global state management just a decaffeinated view and local state is the real deal? This question haunted me. I would lie awake at night hearing my colleague’s voice over and over again – Why shouldn’t my view have local state?
My first response was that it’s a team thing. Since each component of the Flux architecture is a single responsibility, it brings clarity through ease of testing, readability, and maintainability of the code. For new developers, it makes for an easier onboarding process as one is required to follow the responsibilities of each component.
My colleague shot back with – What if my local state is isolated? I jumped to the reactive defence with – Well, then you’ll just encourage bad practice! It was a weak argument, and I needed a better reason.
It was time to bring in the big guns, so I went to consult our local UI connoisseur. I asked, should our views have local state? and he replied, No, our view should not have local state. I was pleased that our visions aligned and it was a moment of relief. Unfortunately, I was so focused on living in the moment of confirmation that I completely ignored the next and most important sentence. The view should be a thin layer that we can easily replace.
Over the next few days, I deferred addressing the issue of local state. I thought my colleague would see the light; he just needed time to breathe and take it all in. He will come to realize that the Flux architecture is the most superior form of Front-End State Management. He, too, would enter the state of clarity and awakening.
My colleague’s team provided a code review session to share their new found knowledge. This was the chance, to have an outsider validate the world of the wonders and joys of Flux. The code was beautiful, and it had all the markings of a well-built React+Redux application. It made me so proud that I had to hold back the tears of joy. However, it wasn’t until after the code review session that I was shocked back into reality.
After the code review session, another colleague commented – It’s weird that Redux holds all the state. I think some components should be able to hold local state and make I/O calls. This was like drinking a cup of coffee after a poor night of sleep only to realize that it’s decaffeinated!
I went on the defence again and brought up my broken record reasoning: Testability! Predictability! It’s a pattern! On-boarding costs! I wrote a spinner where the state was in the store, and it was glorious! Unfortunately, no amount of reasoning could convince my other colleague that in Flux, avoiding local state is the way.
It’s all about isolation
I struggled to sleep for the next few days – both my one-year-old and my world view were in a state of disarray. I started pouring through the Redux source code in the hopes that the code would speak to me. All I found was beautifully written functional code. Testability, predictability, and code symmetry were moot points. Like Max Cohen in the movie π, I went on a mad journey to discover the truth. And it was in my state of madness, I came across the truth, Redux is a framework agnostic state management library. It was then, that the UI connoisseur’s words started to ring true – The view should be a thin layer that we can easily replace.
Want to scale a Vue project? Use Vue+Vuex. Want to scale a React project? Use React+Redux. Want to scale an Angular project? Use Angular+NgRx. Want to scale a Polymer project? Use Polymer+Redux. Want to scale a Cycle.JS project? Use Cycle+State. Want to scale a Choo.js project? Use Choo.js. Oh, by the way, Choo.js has Flux architecture built in. The Flux architecture is becoming the de facto standard in Front-End Architecture, and there is good reason why.
It allows you to isolate your business logic from your interfaces, be it API or UX. It affords you the capability to refresh your UX or API quickly and incrementally.
Refreshing your UX design is a fact of life and happens very often. When you can isolate your business logic from your view and simplify your presentation, it allows you to rebuild your UX quickly. Any complexity that gets added to your view, must be reflected in your new implementation. It’s no wonder why it was a challenge to move from AngularJS to Angular or to React. Components that have local state will naturally incur some complexity. Complex components don’t scale well. As the old saying goes, A stitch in time saves nine. A smart component gets paid as tax in the future.
Ironically, a side effect of creating this isolation is that it encourages collaboration. By having the team maintain a global store, modelling becomes a first-class activity. Without a modelling exercise, the store can quickly become a challenge to maintain. In the end, by having a global store, the code becomes more maintainable through isolation of concerns and through collaboration between developers.
I enjoy working at Intelliware because we have a strong developer community. We’re encouraged to challenge each other and ask hard questions. As an organization, it’s vital to challenge the status quo continually. Times change, technology changes, and by continually challenging our views, we have a deeper understanding of what we do and why we do it. It’s dangerous to become apathetic in this field. By persisting and asking hard questions often, it forces us to constantly reason about why we make the technical decisions that we make and to understand when it is time to change.
I realize now that I’d taken for granted the power of the Flux architecture. Its structure and simplicity make for more maintainable code. By reasoning and understanding when to create a future tax, we can communicate it effectively to the client to balance the need for time to market vs. long term maintenance vs. flexibility.
After much reflection, would I have local state in my views? Probably not, but I wouldn’t avoid it if the need would arise. After all, Flux is just a recommendation and not a law.
Now that I’ve finished writing this blog, I think I can sleep.