Last summer, we installed solar panels on our roof. Living in California means conditions are excellent for generating electricity from golden rays of sunlight. I like watching the digital display on our power meter “spin” backwards.
It also means that it doesn’t rain much until the winter months. Last week it rained a lot, which exposed a small leak in the roof where the panels are. The dark, wet spot over the dining area makes my stomach sink a little. I am sure I considered the possibility of leaks, but now I can start to see the dollar signs to fix the damage.
That was a hidden cost of going green. Still worth it, but more than I had calculated.
Software is full of hidden costs. StoryTime runs in a browser, and it needs to remember details to show an accurate picture. Where you are in the story, where you have been, and so on. Every scene has to be fetched from a remote server, which might take a second or two. The next time you see the same scene, it is nice to use the copy you already fetched and skip the trip across the network.
What I am talking about is called client-side state. That’s the condition of things where the user is. The fact that you are logged in, user preferences, the story and scene you are reading, the fact that you dismissed an error message. All of the little things that make the user experience smooth and natural require having a handle on client-side state.
I am writing the StoryTime client using React, a popular open-source library for building user interfaces (UIs). React is based on the idea of components. With 100 lines of code or less, you can make a useful component that handles some aspect of the UI. Need to handle more kinds of things? Make more components. Then you can assemble the components into bigger and bigger components until you have the entire application as a single top-level component that holds all of the others.
Using React is like building with Legos, except that you get to invent the pieces yourself. And the fact that you cannot hold your creations or throw them at your siblings.
Every component has the ability to hold state. Components can remember from click to click how things were and change the state as the user interacts with the system. Without this memory, you would never accomplish anything, always stuck on step one.
Once you create a dozen components that span a few application “pages” or “screens,” managing the state of components gets tricky. For example, the view for an anonymous user might be restricted, while a user who is logged-in would see personal information. How will the components dealing with personal information know whether to show themselves?
One answer is to pass around the knowledge that the user is logged in. That gets tricky when components are nested 3, 6, 10 layers deep. And that’s just one bit of knowledge. A typical application will have dozens or hundreds of other facts to track and share and change.
A different answer is to assemble that knowledge in one place and tell each component where to look for it. That one place is called a data store. It’s where you store data on the client, e.g., in the browser window. When everything is wired up correctly to a local data store, components have a consistent view of the client-side state. Changes made in one place are reflected throughout the application. It’s like magic.
The standard way to do this in React is called Redux. I won’t go into Redux here. Let’s just say that “all you have to do” is install it and wire your components to it. Then all of your client-side state issues will be solved. Sounds great.
And then there are the hidden costs. First you have to learn a new way of thinking. The state is supposed to be immutable, which means you are not allowed to change things in the state. Instead, you create a new state with things the way you want them to be and swap out the old for the new. Second, you wire components to the state by wrapping them with a special component that maps the knowledge to the component properties. Third, to make changes, you need to have a set of actions that carry the new information. The actions are sent into reducers that process the information and set up the new immutable state.
Then you need to rework the navigation system, the authentication system, and the way you fetch that remote data.
While all of this is helpful for managing the complexity, it also makes the simple things harder. That’s another hidden cost.
After a week of coding and troubleshooting, I have StoryTime partially working with Redux. The library and reader are wired up and almost bug-free. Navigation is broken—it keeps dropping the store on every page change. And the reader gets confused sometime going into a new story.
I thought it would take a couple of days because I have used Redux before and already adjusted my thinking. It’s just a matter of applying it. Beware of any sentence that starts with “it’s just…”
I will find more hidden costs this week, and probably the next, and the week after that. By then it should be fine, and the improvement will keep StoryTime from collapsing as I expand what it does.
Still worth it, but more than I had calculated.