It was a Sunday afternoon, when I had this “great” idea for a small but significant update to my self-made home automation system. It was a small change, so I thought that I would have it up and running in minutes. Excited, I launched the three years old solution to be greeted by a set of projects and files that I couldn’t recognize. The code that I once knew is now a total stranger to me.
After spending the entire afternoon navigating the code, deciphering the hard-coded workarounds (see: hacker), and trying to make sense of the mess, I gave up and decided to go the easy route by debugging the code and following the flow of the feature that I’m trying to modify. I ran the application and my computer started screaming with errors popping on my screen, the code is tightly coupled and dependent on all the different hardware components used in the system and couldn’t run unless they’re all connected correctly. That’s when I threw in the towel and decided that it’s cheaper and faster to rewrite the system than trying to fix the badly written codebase.
We learn best from our mistakes and believe me, I have made enough of them; ones when I didn’t know any better and ones when I was trying to cut corners and get results as fast as possible, but my advice is to look back, learn from your mistakes, and never repeat them again no matter how tempting it might get.
Clean code is a form of art and it feels way more satisfying when you write code that you’re proud of than when you just simply solve the problem quick and dirty. In this post, I wanna talk about the mistakes that I myself made in the past or saw a fellow developer make. So without further ado, let’s get started.
Tests Are Not The Enemy
“This app is so simple, it’s just a couple of functions, not more than 20 lines of code. Do I really need to write tests for that?”. One of the biggest lies I’ve ever told myself; a tiny project today can grow to become a big code base in a few months, we’ve all been there. Once that happens, it becomes even more cumbersome to add tests later (I’m yet to meet a developer who enjoys writing tests). Writing tests exposes problems in your code that you might not be aware of, such as tightly coupled code, functions or classes that do more than they should, etc. A well tested code base gives you peace of mind when making code changes, because you will get immediate feedback if something breaks.
There’s a lot of debate about the different types of tests, which one is better and how much is too much. In my opinion, each problem requires a different solution, what might work for one project might not work for another. The more tests you write the more you learn what’s useful and what’s just bloat.
Unlike my feeble attempt at making funny titles, source control is a “gud” and powerful tool that you have at your disposal and that you should use to its maximum potential.
There are several services that offer an unlimited number of free private repositories (Thanks GitHub), so you have no excuse to not use one of them to host your projects, big or small. I can’t tell you how many times I’ve lost old projects because I couldn’t remember where I had stored them. Source control offers you a convenient place to store all of your source code and a full (version) history of all the changes you’ve ever made to the code base. It also makes it a breeze to collaborate with a friend or a colleague on fixing that bug you’ve been struggling with for a week.
So go ahead, delete all these (Backup01.zip, Backup02.zip, etc.) and push your code to Source Control.
Make Analysis and Design Great Again
I get it, you’re excited, you can’t hold yourself back. I don’t blame you, you have a great idea after all and you can’t wait to code it over night. There’s nothing that beats seeing the results of your work, but take a step back, grab a pen and paper and start by drawing a rough design of your idea. It doesn’t have to be perfect, it just needs to allow you to see the bigger picture, and chances are, you’ll find some issues and opportunities that you didn’t think about.
Characters Are Free
Which one looks clearer to you, BatteryThreshold or BatThrhld? Always go for clarity over shorter names, whether it’s a name of a class, function, constant, or any variable. Clean and clear code doesn’t need comments, and a big part of that is good naming. I sometimes spend more time on finding a meaningful name for a variable than I do on writing the entire function, and I consider that a good investment of my time.
Conventions, Conventions, and Consistency
Just like in world languages, you can learn and speak multiple languages. However, you’re only considered fluent in a language when you use it the same way native speakers do. The same thing applies to programming languages, each language has a set of conventions that are different than other languages, try your best to adhere and follow them.
There are situations of course where you might need to stray away from the standard conventions, such as when working with a team and using the conventions that are used by that team instead. The rule of thumb here is consistency, whatever set of conventions you wanna follow, always stay consistent across the entire code base. There’s nothing worse than a project that contains camel casing in one file and pascal casing in another.
Quick and Dirty
Let’s imagine the following scenario: I have a big bug that needs fixing, I create an extensive presentation listing two solutions to the problem, I call them “the proper way” and “the quick and dirty way”. I list all the advantages of going with the proper way even though it takes more time and it’s more expensive, and then I list all the disadvantages of the quick and dirty fix for the future of the project. The manager asks me to go with the quick and dirty fix because it delivers value faster and costs less money.
I’ve encountered the above scenario more times than I can count. 70% of the time, the stakeholders will go with the easy fix. 100% of those times, the fix will come back biting at some point in the future. Unless the project is going to be replaced completely by something else in the near future, it’s never a good idea to go with the quick fix, because you’ll never have the time to come back to it and fix it properly, and that quick fix will grow as technical debt. If you value quality in what you do, don’t cut corners and don’t accept doing the quick and dirty fix no matter how tempting it might be .
The same goes for refactoring, don’t put it off until it’s too late! Get to it, you’ll feel way better when it’s done!
Complex Code = Bad Code
I once knew a developer who purposely writes very complex and hard-to-read code, because he thinks that it makes him very difficult to replace at his job. My answer to that is: if you’re a good developer, you should never have to worry about losing your job. Writing complicated and unreadable code doesn’t bring up your value as a developer, and the recent success of open source software is an evidence to that.
In my team, there was a developer that all other developers struggled to peer review his code, the code works, and it does what it should, but is it good code if no one else can modify it or add value to it? Complex code (with the exception of very few situations) shows that the developer is struggling with the problem and doesn’t have the abilities to solve it in a simpler manner. Don’t be afraid to ask questions, try breaking the problem into smaller pieces, and stay away from complicated code as much as you can, because the smartest solutions are the simplest, or as Albert Einstein put it “If you can’t explain it simply, you don’t understand it well enough”.
There have been some instances when I thought that writing build and deployment scripts takes more time than doing it manually. The system will rarely be updated, it will be redeployed maybe once or twice a year, so is it really that important to spend time on automating tasks that you do so rarely? The short answer is YES!
Believe it or not, those scripts are not only there to save you time in the long run, they’re there to protect you from yourself. Imagine you have a complete system shutdown, it’s almost midnight and you’re still working on bringing all the services back up. Automated tests and deployment scripts can make the difference between a few minutes and a few hours to redeploy everything. Not to mention the peace of mind that these scripts offer because they don’t get tired and make more errors when they’ve been working the whole day.
Always Keep Learning
If you chose the path of writing computer software, you must have realized by now that ongoing learning is an important component of your life. Every day, there are new technologies and new versions of existing ones. If you wanna stay competitive and up to date, don’t waste a day of your life without learning something new, no matter how small it might seem. Also, remember that no matter how experienced you are, there will always be room for improvement.
I try to stay up to date by reading new technology release news, following online courses every now and then, etc. I try to read at least one article that will teach me something new on a daily basis. Furthermore, never compare yourself to others around you, because if you believe that you know more than the average person, you might lose that desire to improve yourself. One of the professors that I had back when I was studying (Thank you Samir Stanbouli) gave me an advice that I remember all the time, he said “Always compare yourself to the you of yesterday, and if that person is still the same, then you’re doing something wrong”.
If you think that I missed anything or if you don’t agree with some (or all) of my points, I would love to hear your thoughts. Thank you for reading.