Correct, Beautiful, Fast (In That Order)
One of the books I am occasionally grazing on is Beautiful Code. The title of this post is the title of Chapter 6. I’ll be honest, I only skimmed the chapter as one can only digest so much Java, but the title is spot on.
Step 1: Correct (With Tests)
I have been thinking exactly this as of late, though I will admit in no way as succinctly. First, you get it working. It does not matter if it is dirty. Rather, what matters is that it functions and is well tested.
If it works and it is not tested, you can never make it beautiful with confidence, so testing is very important to this step.
Step 2: Beautiful
Once your program is working and testing, make it beautiful. Leave the tests alone and head back into the code. Branch out and try new idioms that you have not tried before. Ensure that someone with no prior knowledge could jump in and know what is going on (without ridiculous comments all over).
Note that this step is not optional. Once your code is functional and well tested, you still have an obligation to make it beautiful. I think a lot of people skip this step. They think once it works and is tested, that is the end. Wrong.
Not only is this step the most fun, it also forces you to think through the code more. I often find edge cases during this step that I would never find if I stopped and correct and tested.
Step 3: Fast (optional)
If you pass these first two steps and you run into slowness at an unacceptable level, make it fast. The author puts it best in the summary at the end of the chapter, so I will quote them:
If there’s a moral to this story, it is this: do not let performance considerations stop you from doing what is right. You can always make the code faster with a little cleverness. You can rarely recover so easily from a bad design.
So true. I have never focused on speed in MongoMapper. No benchmarks to wow the noobs. No dramatic statements about performance. I have focused on cleaning up the code and making it easier for myself to maintain and others to contribute.
Not long ago, one of those contributors sent me a tiny patch (~30 lines) that improved overall performance by at least two, maybe three times what it was in 0.6.10. I do not think that it would have been that simple to to find and fix the performance issues if the code had been a mess.
- Correct: make it work and test it.
- Beautiful: refactor original code in a manner that others (and yourself down the road) can easily understand.
- Fast: often the first two steps leave code fast enough, but if they do not, make it faster.