Yesterday I retweeted @donnfelker, who said
Ugly code that ships and solves a problem is a 100 times better than beautiful code that doesn’t ship
One of my friends later told me that if he didn’t already know me well he would have added my name to his list of people to never hire. Although I’m not really worried about being on a do-not-hire list I think it’s helpful to clarify why I feel this way and what I think the limitations are.
First of all, it’s just a fact
Code that works, regardless of it’s quality, is better than no code. Beautiful code that doesn’t ship is NOT code that works. So, in reality, ugly code that works is actually INFINITELY better, in a divide-by-zero kind of way, than nothing (i.e. beautiful code that doesn’t ship).
Beautiful code that ships and solves a problem is way better than ugly code that does the same thing
Who wouldn’t rather have great code? Who wouldn’t choose a car that is safe, fast, efficient, and beautiful over one that is just safe and fast if they both cost the same?
The truth of the matter is that an experienced, disciplined programmer with a comprehensive understanding of the problem space can write beautiful code just as efficiently as a programmer who lacks experience, discipline, or understanding can write ugly code. Even experienced, disciplined programmers will make mistakes as they learn the ins and outs of a problem space. Just look at the evolution of attachments in Ruby on Rails – from attachment_fu to paperclip to carrierwave, you can see the evolution of understanding how to deal with files in a web application.
Making ugly code beautiful is how we become experienced, disciplined, understanding programmers
I re-entered programming after a long hiatus as an “enterprise architect” and project manager. With the help of google, indy.rb, and my friends, I taught myself ruby and rails. I’ve written a lot of bad code. Some of it is still out there, open to the world, on my github repository. You could look through some of the silly projects I’ve done and conclude that I suck. That’s totally fine with me – if you are not smart enough to put publicly shared code in an appropriate context I don’t want to work with you anyway.
Does all code have to be beautiful the day it’s released?
I don’t think so, but I also don’t see code as a one-and-done thing. Code is not like building a desk to me, where at some point it is exactly the way you want it and you are done. It’s more like an extrapolated portion of my brain that has been encoded – I don’t see it as “done” any more than I see my own learning as “done”. Code that is beautiful to me today will be ugly to me four months from now when I have learned something else.
For example, a few years ago I got on a “skinny controller” kick and cleaned up a whole lot of ugly code in TroopTrack. I was pretty happy with the result – nice simple controllers and big fat models. Over time, I started to experience the problems this causes for you, and I started looking for ways to make it better. I experimented with concerns and service objects, and now when I touch code I consider whether it should be re-factored into one of those two things, then I include that refactoring in the work I do.
There are a number of situations where spending as little effort as possible is the right thing to do. Here are some that I have seen in the past:
- You are performing an experiment to understand how something works
- You are performing a short-term market experiment on a feature and the results of that experiment are likely to result in the feature being killed
- You have a meaningful deadline and you are going to miss it if you spend more time on the code
- Your production environment is down and you are losing money every minute until it comes back
- You don’t know any better and releasing it will expose you to an educational experience. I have written code that I thought was good, shown it to someone else and learned a ruby idiom that eliminated huge chunks of code.
- You are building an OSS product and you want to gauge the potential for a community of contributors to develop
- When it’s just a simple utility for automating something you find cumbersome on your own personal computer that you never intend to use in a production “Application”
In these cases, do the best you can, but understand that releasing the code into the wild is the true value of your efforts and that you should minimize the energy required to do that.
If you work at a place where continuously improving code quality is not allowed… You made your choices – please don’t blame the programmers.
Some of my friends have spent years working with code bases where, because of the ineptitude of the organization where they have chosen to work, continuously improving code quality is discouraged or prohibited and crappy code is actually encouraged in the name of deadlines that are contrived or meaningless. These are unhappy places. I’m sorry that you work there, and that you aren’t allowed to put forth your best effort. I sincerely hope you will find a way to make it better or leave. The crappy code you have to deal with is not the fault of people like me who live in a world where they can make the code better every time they touch it.
A little git fu can help you hide your “learning experiences”, and it’s good discipline
Want to work on something you aren’t sure about without exposing all the mistakes you made along the way to the world? Create a feature branch, work there until you are happy, and then don’t fast forward when you merge. Then, people will only see the final beautiful result and not the horrible creatures you spawned along the way.
I am not advocating you write crappy code
Write the best code you can under whatever circumstances you find yourself, and ship it. If people call you names, ask them to give you advice. If they don’t, write them off. If they do, you will become a better programmer and you might also make a friend.