Nothing Premature Is Ever Good!
Most developers have heard the term “premature optimization.” What this means is that you shouldn’t focus on optimizing your code (for performance) until your project is winding down. The reason is simple: Spending hours optimizing a code to be optimally fast can instantly be wasted if that code needs to change, and if it does need to change, that change will be more difficult to make.
What’s less propagated is the idea of “premature refactoring.” It’s one of the best lessons I’ve learned as a developer over a long span of time and nixing early refactoring has been a tremendous boon to my enjoyment of coding.
A Case Study: Choo Choo!
Let’s consider a situation where you’re building a a Light Rail Monitoring System. (Nice gig if you can get it.) There’s obviously going to be a bunch of UI, but you’re going to start with the Landing screen. It has the following requirements:
- A list with the next 25 trains set to arrive at a station.
- A larger view that shows detailed information for any train you click on.
- Ability to mark a train as tracked so you can be alerted when it arrives.
- A train animation along the bottom for when a tracked train arrives safely.
- A working clock display.
In my younger days, I’d immediately start breaking this screen down into pieces. I’d separate the clock, train animation, detail view, and list into four components I’d assume would be reused. Now, there’s nothing disastrous about this approach, and if you are working it out this way then kudos to you for being a true software developer.
And what you might find strange is that I look at this list of requirements and my design will be to make one giant, monolithic screen with all of the logic included.
Why Not Componentize Now?
So, why is it that we don’t optimize early on in our code? It’s because we haven’t completely solved the problem yet, and optimizing early will likely be a waste of time. We also don’t know where our bottlenecks are and applying finite resources to problems that don’t exist yet would be wasteful.
But let’s not stop there. Let’s look at the Agile Methodology. In 2011, most developers are familiar with this approach, but may not be aware that it’s built on a fundamental philosophy similar to what we’ve discussed:
The longer you work on a project, the smarter you are about how to create it. Design upfront is less effective than design later in the project because you are wiser for having come that far.
With this in mind, you can better understand my seemingly odd approach to the Light Rail system.
I have a lot of questions regarding the individual components. Let’s start with the train list…are the rows displayed the same on other screens? Will the rows be homogenous within the table? What sorts of actions need to occur when they are selected and should those actions be reusable? Will the styling change on different screens (i.e., colors, fonts, etc.)? Is the data source going to be the same?
A lot of variability here. And since I’m an Agile developer, I prefer to wait as long as possible before committing to what the solution should be. Therefore, I choose to implement the list entirely in my Landing screen until I know more about the screen that needs it next.
What about the clock? Surely that’s simple, right? You’d be surprised. Should this clock sync to the local machine time, or sync to a server? (This is always a HUGE question.) Do the colors need to be configurable? (I’ve had apps where clock fonts change based on the color palette of the screen you’re on.) Should it display in military time, and is that an app setting that should be honored globally? What other scenarios will this clock be used in?
Think about it. A clock component is handy for more than the top-right of your screen. Perhaps it’s used in the train detail views to show schedules arrival times? It can be displayed in different fonts and colors. It could be a running clock or a static clock. Do we know yet?
You Can Make a Better Component — Later
So when do I start refactoring? Well, first, let me emphasize a few points about what my approach is to start with. I’m not advocating writing crap code. I’m not advocating writing code that will be harder to separate later, you must always be *anticipating* what will be refactored. For example, if I need a timer that updates the clock and updates the train schedule, even if they occur simultaneously, I create two separate timers. The fact that they update at the same time is a happenstance.
What I’m doing is delaying the refactor. Not avoiding it.
OK, so when do I begin this much-ballyhooed refactor? The short answer is, when it feels right.
Let’s say I work on the Scheduling screen next and it also has a clock and a list of trains. I note that the clock indeed has swapped color schemes, with the digits going from black to white and background white to black. I investigate further with the client and confirm these will be the only two color schemes. At this point, I refactor the clock out of the Landing screen and make it configurable with an enumeration so other screens can share the color schemes.
When I was a little boy and started coding, it was so much fun. I wrote terrible code, but I had fun doing it. By the time I became a professional, I wrote more organized code, and everything was still OK.
It wasn’t until years later when I started dabbling in Design Patterns. It was necessary education, but it screwed me up. Suddenly, every time I wrote a line of code I was concerned if it was optimally written. I tried to extract reuse from everything. That began a cycle of “tortured programming” for me. Suddenly, writing any code was an exercise in frustration.
The problem was that I was trying to anticipate how every blob of code could be reused without having the necessary information of how that code would be reused. Delaying the refactor allowed me to focus on the needs of the now and not the imagined needs of the future.