Make It Work, Make It Beautiful, Make it Fast: Overview

Tom Harrison
Tom Harrison’s Blog
4 min readApr 3, 2014

--

Welcome to my blog. I write about what I am thinking about at the moment, but am working on making the blog a more unified thing over time. I am a software engineer and have been since the mid-1980’s. I have been writing this blog since 2010.

I have worked at multiple companies, many startups, some larger companies, big projects, small projects, new, old, whatever. I have been leading engineering teams since 1990. I have been around the block.

In every case the following has applied:

  1. Make It Work,
  2. Make It Beautiful, then
  3. Make it Fast.

In that order.

I heard this rendering of the idea before I realized it was a misquotation of Kent Beck’s ideas which are the original, and the same, except for the my “Beautiful” should have been “Right” — same idea. I am by no means claiming that I arrived at this idea, only that I have been applying it to the software projects I have managed over a few decades.

Make it Work

Before you can work on improving anything you need to make it work. The cost of failure, the cost of maintenance, the cost of building something huge to find out that it’s not what’s needed are all reasons to get your project to stop failing.

New code

If it’s new code, this means focusing on some sort of end-to-end functionality and framework, including build, test, and deploy, into production. The key here is that building that first deployable deliverable is worth the effort to get right, without going overboard. This is your new liv

Old code

If it’s old code already in production, and you need to maintain or enhance, the first thing you need to do is get the part you’re going to work on up to some standard of stability, structure, or definition. It sounds a little crazy to fix the code before you are about to improve it. But in fixing, building tests where possible, instrumenting, measuring and otherwise reverse-engineering it, you’ll better understand what it is supposed to do.

Bad code

Some code is unfixable. The hard part here is to decide if you can create a scaffold around the old code that keeps it working, but allows you to replace parts at a time. The alternative is hiring a team to rewrite entirely while the old team nurses it along — a good opportunity for consultants.

Make It Beautiful

Having achieved some kind of balance and stability in at least a part of your code, it’s time to look it over and do a kind of refactoring that’s mainly about aesthetics. Give things proper names. Move modules or packages out. Try to document what is happening. See the whole and decompose into suitable parts.

If you don’t have good unit or functional test coverage, this is a good time to add it. Especially with old code, this can be hard — I recall thousand line “methods” that were completely untestable. In this case, extract units out slowly and build tests for the units. But through all of this beautification, avoid the temptation to completely rewrite. Now is not the time. Keep the code working, deploy small changes frequently and use the opportunity to understand the composition better.

When you have made code beautiful, it will be cleaner, more easily understood, better documented, more testable, and better tested.

You’ll know you’re done when it looks good. Code aesthetics are important.

It’s important to beautify code before optimizing because beautification is really about applying knowledge of the whole. Chances are, your beautification will result in some unexpected optimization on it’s own.

Make it Fast

Code that is in on your machine, or in dev or test environments usually tells you very little about performance in production.

I work with a lot of problems involving lots of data. I did spend some time focusing on optimizing user interface performance. Performance problems have a sneaky way of never being what you think.

It’s usually a fool’s errand to optimize for anticipated performance problems. Optimization tends to result in additional complexity.

For example, if your app has a simple mechanism of caching frequently used items, it’s very tempting to assume a given object or result or set or whatever you’re caching will be frequently accessed. But before you do that, determine two things:

  1. That the unoptimized version is actually a performance issue, and
  2. The the cost of optimizing this components does not squeeze out another optimization that is much more important.

I worked at one point with a guy named Matt who just loved to cache anything that came from the database, because (he said), “Databases are slow”. But everything is relative. So he cached simple results, huge results and all manner of thing. Then we noticed that one part of our system was becoming terribly slow simply because the many things being cached from Matt’s code resulted in the important things from other areas being evicted.

When we looked at actual measured time, the cache affinity, and all the rest, we found hundreds of lines of the same code caching results. We removed them all and tested performance and found no cases (not one) that actually improved performance. In fact, because our framework, OS, and database had built-in caching, there were several cases where removing the additional layer improve performance.

The point is simple: don’t optimize prematurely. Optimize last, after the simple code that works is in place, after the nicely beautified code is deployed, and then only when you identify optimizations for which trade-offs of complexity or difficulty of maintenance are outweighed by the performance benefit, then: make it fast.

New, Old, and Bad

This idea, “Make it work, make it beautiful, make it fast” has different characteristics depending on what you’re working on. I have found this notion works and helps focus people on what’s important at the moment. You get code out faster, you get better code sooner, and you optimize only what’s actually slow.

It varies by situation, so here are some other rambles about those.

--

--

30 Years of Developing Software, 20 Years of Being a Parent, 10 Years of Being Old. (Effective: 2020)