The first time I coded something in my life was at around age 8 or 9, when an old MSX computer crept into my house. It came inside a box of random crap that my brother traded for a different box of random crap.
I’m pretty sure the MSX wasn’t inside that box by chance. My brother knew I had a thing for computers, because not only had I been snooping on his PC screen quite frequently when he was writing code, but I would also frequently sneak into his room when he was absent to subtract his programming books (but only the ones with chapters about computer games).
He then gave me the MSX along with a BASIC programming book and I proceeded to create my first ever computer program – one that would ask your name and then print it back to you.
Very useful stuff if you have some sort of extreme amnesia.
Some time later I eventually stumbled upon the concept of subroutines and found it amazing that I could reuse things I had made before. This immediately changed the way I think about programming. That moment was the first step on my journey to become a better programmer.
Since the good old MSX days I have written, deleted, and refactored countless lines of code, contributed to all sorts of small and large software projects and, from all this experience, gathered a list of good practices that could be useful for people who are just starting out.
1 – Deliver solutions, not problems
I know this sounds like cheap productivity advice but it is pretty much the reason why programmers are hired – be it in an abstract sense as in “let’s make our users lives easier” or in a more practical sense like “when I click the save button it actually kind of deletes my data instead”.
So the first advice is – be proactive.
For most software problems the computer will try to tell you what’s going on. Try to make sense of the problem before asking for help – read the screen, read the logs, try to spot something familiar on the stack trace, paste the error message on Google, use a debugger, pray.
Of course some particular problems will be too big for you to solve alone, perhaps because you don’t have the necessary technical skills yet. Or because it involves a decision that only your boss can make.
Make things easier for the next person by outlining possible solutions when you’re explaining the problem.
There’s still space for proactivity here: you can make things easier for the next person by trying to outline possible solutions when you’re explaining the problem.
2 – Test obsessively
This is an important one, perhaps the most important one of all.
It’s not only about automated testing. It is about every single effort you can make to guarantee that whatever you added to the codebase works without breaking something else.
My personal guideline here is that no change is too small to need testing. If a piece of code was changed, you should now look at it as if it was tainted. The only way to clean it is to test it all over again. Oh, and that includes dependencies.
Something that can help is to ask somebody else to test your code.
At Toggl we have code reviews as a step of our workflow, where we read and test each other’s code before it goes to production. It has been vital for our QA.
It’s also had an awesome side effect – it has made onboarding of new developers easier. It forces the more experienced developers to explain the codebase peculiarities, and to make suggestions about how code can be improved to better fit the company style.
Also, remember this – if you don’t test your software, your users will.
The time and energy you need to spend on testing should be directly proportional to how angry your users will be if something goes horribly wrong.
3 – Never trust your memory
Have you ever looked at a piece of code and thought “what sort of moron wrote this piece of shit?” only to then remember it was actually yourself?
If it hasn’t happened to you yet, just you wait.
If you don’t document your code properly for the sake of other people, at least do it for yourself. By “documenting” I don’t mean writing extensive, tedious documentation on Microsoft Word that will inevitably become outdated. I mean giving things good, descriptive and concise names so that in the end you have self-documenting code that explains itself.
On top of that, I find it useful to have documentation comments summarising each logical unit of a codebase. Concise is also the way to go here. If each comment is the size of a Wikipedia page nobody is going to read them and they’ll become outdated, just like the infamous MS Word docs.
Making your code readable for the computer is easy, what’s hard is to make code readable for humans.
But it pays off in many ways – it’s more pleasant to maintain the code, bugs are easier to spot, onboarding of new developers is smoother. It’ll save time for everybody. You don’t need to go all the way into literate programming, but keep in mind that it’s much easier for everybody to read natural language than code.
Oh, and if you ever need to make a hack (please don’t make a hack) you are obliged by law (or at least should be) to add a comment explaining the monstrosity you created.
4 – Don’t try to be Superman
When I started my career as a programmer I used to think it was cool to work over hours.
I’d skip weekends and pull all-nighters as if that was a normal thing to do. I admit that in the beginning it was fun because I was eager to learn and to build things.
The problems started when I began doing that because I thought it was my responsibility to save delayed projects, one after another. It took me a long time and several different jobs to break that cycle.
Some may think that it is a pretty good deal for a company having employees who work like that, but this can turn into a huge problem. If there are heroes in the house, projects will keep being underestimated. Also, when the inevitable rage quit (or premature death by too much pizza) comes, the company is definitely screwed.
One more problem about having a crazy work schedule is that it creates the perfect environment for you to be caught in the busy trap – you’ll think you’re super busy, but your productivity is actually really low.
It is obvious that sometimes there is a legitimate necessity to pull off some extra hours to meet a deadline, but that’s perfectly fine as long as you’re smart about it and don’t let it become the rule.
Somebody much smarter than me once said that “if you don’t prioritize your life, someone else will“.
5 – Know when to stop polishing
I read a story in a neurology book about a man who had a stroke in a particular part of the brain and lost, along with his emotions, the ability to know when it was time to stop working on a task.
Sometimes that decision is indeed beyond logic. When is it time to stop refactoring a module that is already working?
How close to the real world an abstraction needs to be?
There is no exact or formal way to answer those questions because it depends on the context.
My method for dealing with this is based both on the principle of the least effort and on what I call “guilt driven development”. If there’s a tight deadline I’ll pick the quickest solution that will not embarrass me too much when other people see it. If I do have time to do it properly, I’ll polish my code as much as I want until I’m proud of it, but will immediately stop if I start feeling guilty that I may have been sitting on that particular task for too long.
You’re not being paid to write code, but to solve problems for people
Something that can help you find the sweet spot is to always keep in mind that you’re not being paid to write code, but to solve real world problems for real people.
6 – Don’t reinvent the wheel
It is fun to write libraries and frameworks and that’s precisely the reason why you probably don’t need to create them yourself – somebody else already had the fun of writing them for you.
What makes code mature is how many times it was tested in production and refactored to fix the bugs. When you code something from scratch, its maturity level is going to be orders of magnitude away from a well-known library. So before you start coding something, spend some seconds on Google first and make sure it doesn’t exist already.
This doesn’t mean you shouldn’t know what’s going on inside the libraries you use, though.
It’s always a good idea to check who else is using it, what’s the software license, how often the authors update it. And definitely prefer open source stuff, because if something goes poorly at least you can peek under the hood, or even fix the problem yourself.
7 – Understand the tools you use
For each existing tool, there’s a problem that motivated some person to create it.
The hammer was invented because somebody wanted an easy way to perforate hard surfaces with sharp objects. You could also use that same hammer to cut down a tree, but then you’d be an idiot because it’s not the proper tool for that task. It’s the same with software.
Before adding a cool library to your project or choosing some hyped up tool, it’s important to make sure you and your team know exactly what it does, what was the motivation behind its existence, and what are its limitations.
Apart from reading the documentation, building a proof of concept around a library is a good way to force yourself to understand what it is and how to use it. One other trick is to search the web for best practices, corner cases, and also the general experience people had when using the tool.
Being extra careful can save you from finding yourself hammering down a tree (or your computer) in the pouring rain.
I’ve met many outstanding professionals in my life. All of them have one thing in common – a strong desire for self-improvement. These are people who never want to stop learning.
The good news is that it’s a contagious thing. This is why your should always try to surround yourself with people who are better than you.
What about you? Do you have your own set of advices? Disagree with something? Leave a comment below!