This post is a mea culpa.
I’ve always believed that a software team must be led by someone who still knows how to code and keeps up with the latest developments in best practices. He or she must add technical value to the team, not just write status reports. In many cases, he or she should design and promulgate coding patterns and parameters.
That last thing is what I failed to do for the class of bugs I’ll now consider in this series on how to create fewer defects.
The class of bugs in question this time is caching bugs.
For those of us who grew up in a world of desktop applications, a web application can seem very slow, so on my team we do everything we can to make our web app faster. At the top of our list of techniques is client-side caching.
In my experience, there are two things you must do to avoid caching bugs.
The first is to encapsulate whatever caching pattern you want to use in one or more a general-purpose, reusable functions. That, we did.
The second thing is what we did not do and the oversight has led to a few bugs we’ve had to fix. You must ensure there is only one source for each type of data.
Probably like yours, our application has zillions of database tables, all relating to each other. When we pull a record down to the client, sometimes we bring the related records, and sometimes we don’t. This can lead to problems, as in this sequence that features two types of records, which I’ll call Parents and Children.
- The client app gets and caches a Parent record with all of its Children.
- The client app finishes whatever it was doing with that Parent and its Children, and the user goes off and uses another part of the app.
- There, the user retrieves and modifies a single Child record that happens to be one of the original Parent’s Children. This single Child record may or may not be cached.
- The user again retrieves the Parent and its Children. Happily, they are in the cache from step 1 and the app yields them from there.
- Surprise! The Child record modified in step 3 is not modified in the cached version returned in step 4.
The core problem is that there is more than one “source of truth” for the Child record: the cached list of related records from step 1 and the single record in step 3.
There are various ways around this, but none of them will happen by themselves. They all take technical leadership. Developers who are under pressure to add features and fix defects are unlikely to stop and put the required infrastructure in place. The person who is managing the construction of the code must be aware of the danger and build the road that avoids it.
This is an exemplar of many areas that take technical leadership. I well remember one presenter at a Boston Code Camp who said, “I love my job. I just love my job. What I do is put guard rails up that will keep the developers safe.” He was the right man for his position!