Tractor pulling and software engineering.

In tractor pulling the objective is to pull a contraption known as a "sled" the farthest.  The sled is designed to become progressively harder to pull the further it has been pulled.  Eventually the sled offers up too much resistance and the tractor will stop.  Occasionally blowing up.

Software projects are like tractor pulling sleds:  the further along they are the harder they get to pull.  And at some point not even the most brilliant team of programmers will be able to advance the project.

Usually, most of the weight on a software project comes from the mundane parts.  The parts that are not doing anything exciting, but for various reasons stop working or didn't really work in the first place.  Things that didn't really work in the first place have an annoying habit of manifesting themselves just when you start doing the exciting stuff.  The stuff you dream of doing and which you had envisioned would become glorious reality in endless hours of flow.

And then you end up doing none of the exciting stuff and spending all of your time fixing the boring stuff that should have worked by now.

The majority of software I have seen, or worked on, has, at some point where that happens.  I've seen it happen at every company I've worked at.  Sometimes it comes from an explosion in complexity.  Sometimes it comes from people just being sloppy.  Almost always it comes from arrogance.  From us thinking we know what we are doing or that thoroughness, discipline and attention to detail is something everyone else is supposed to have, but that we don't need to display since we're...well...special.

Write tests.

No really.  It is 2012 and I still see people who skimp out on testing.  I've seen recent projects catch fire and waste the time of lots of people because the developers didn't bother writing tests and eventually couldn't manage all the bugs.

Make sure that your code has high test coverage.  This doesn't mean being really anal about testing getters and setters, it means that you look at the (Java)doc comment on the code and then start by verifying that it does what it says on the tin.  If you haven't written any (Java)doc for the code they obviously you haven't given the code much thought.

Think about it this way:  if your code were to disappear tomorrow and only the (Java)doc and the tests were left, it should be possible to re-create the code and have it work precisely as before.


When designing things, design for the weakest programmer you can think of.  Nobody gives a shit about your code.  People want to solve problems.  They don't want to spend their entire day trying to figure out how to use your code.  Try to design things so that they are easy to understand.  Any moron can write code that does stuff -- that isn't hard or even incredibly useful.  What is useful is to make other programmers productive.  To become a multiplier.

Also, if your code is simple ... well, this leads us to the next item, which is

Avoid hard solutions.

The simplest solution is a solution for a problem you are not having: you don't have to do anything.

Try to look for the simplest possible solution to any problem.  The solution that most people will understand but which is still correct.  The more people understand your solution, the more likely it is that it will work, and if it doesn't, that someone can fix it.

There is a quote, uttered by the late Dennis Hopper in the movie "Speed" that applies here: "do not attempt to grow a brain".

Save your brainpower for where you need it.

Worry about design.

If you always just implement the first idea that comes to you and then settle with that, you will produce mediocre rubbish.  At best.  Obsess over design a bit and allow yourself to change your mind.  And if you do change your mind: it is okay to throw away or restructure code.

Of course, this is a tricky one in that it can lead to paralysis.  If you become too much of a perfectionist you won't be able to get anything done because nothing is good enough.  But in general, most programmers could do with a little less typing and a bit more pondering.

Memorizing algorithms and data structures isn't terribly useful.  But you should work hard at developing some intuition on complexity and design choices.  If you are a programmer and don't think about the big-O complexity of what you do 5-6 times a day you are not going to write good code.

Most performance problems and most friction points in systems are born the moment you decide how to solve a given problem.

Cargo Cult Programming.

Do things because you know they work, not because it happens to be the hip thing to do.

Every single day I see code where people obsess over the wrong thing.  They'll spend all their energy on making some crazy over-designed type hierarchy work or on fitting into some methodology or they throw themselves at the mercy of some framework they think will magically fix the fact that they have no idea what the code really does.

It really is simple:  if it doesn't influence the outcome in a positive manner:  throw it out.

This doesn't mean you should try things.  It means you should remind yourself to check if they work.  And possibly why they didn't work.


Cool products.

Products are cool when they work and they stand out.

When they work, but do not stand out they are boring.

When their main feature is that they stand out, but they do not work, that is just masturbation.