What are some bad developer habits?

Not writing tests, inconsistent code style, keeping commented code in commits or never branching. These are some of the cardinal sins of web development.

Andre Liem
Andre Liem

I recently had a question come up on Quora which asked “What are some bad developer habits?”. Being someone who contributes on occasion to Quora I decided to share a few bullet point thoughts that came to mind.

You can see my response here but this is what I posted

  • not writing tests
  • keeping commented out code in commits
  • never branching
  • not removing unused code
  • not refactoring big pieces of code
  • putting TODO on a piece of logic which is important. Eg – Todo – validate input. But if you are writing good tests you can’t get away with this
  • not indenting properly
  • not being consistent with syntax style…

I decided it would be worth while to unpack these points in more detail and explain. So without further ado, here they are:

Not writing tests

Forget TDD (Test Driven Development) and lets just focus on the bad habit of not writing automated tests. The thing with writing automated tests is that while it can seem like a waste of your time or a client’s budget, the time you invest in writing a test has massive returns.

Lets say you spend 30 minutes building a feature and it takes you 30 minutes to write the test when you could have manually tested it in 10 minutes with the browser or console. So you have spent 20 more minutes writing the test. In other words, you’ve invested 20 minutes to write a test.

Is that 20 minutes extra worth it?

If you bill $100/hour, you’ve costed the client $33.33 to write a test. Well, lets say over the span of 1 week you make 10 significant updates. Each time you make an update, you run the test suite. If you had to test the same feature 10 times that would be 10 minutes * 10 updates = 100 minutes spent on ad hoc testing. That’s $166 to manually test the same thing. Perhaps you get faster at manually testing, so you get it down to half that at 10 x 5, it’s still $83. In either scenario, over time the cost to manually test is enormous and tedious, which usually results in not testing the thing at all which is the worse case as now your software has a higher chance of being buggy. Over the long term, that $33.33 “investment” you make on adding a test will balloon to a return well over its cost.

Simplifying the cost / benefit of writing tests based on time saved may be overly simplistic, but if you explain this to a client they will probably get it. The main point is that you can’t use the excuse that there is “no time/money” to build tests.

Using the the excuse that it’s hard to write tests on the other hand is valid, as writing good tests is difficult at times. The nice thing is that if you get better at it, it actually improves your code because you need to write your code better to work with tests. If you need help writing tests than there are a plethora of courses and tutorials online that will teach you how to. You only need to invest a few hours per day and eventually it will become second nature. I also speak as someone who didn’t write tests during the early part of my career, so I understand the mentality and laziness associated with not doing it. But now that I’ve over to the other camp of tests are critical, I can say they really are because they not only benefit the code and value you deliver to the client, it is one of the quickest ways to improve your own coding abilities.

Keeping commented out code in commits

Adding comments to clarify complex code, a TODO or doc blocks is good, but committing commented out code is bad practice. It confuses other developers, and your future self who has to look at this in a few weeks, months or year. You’ll wonder, what is this for? Should I use it or keep it for later?

If you really think you may need that piece of code later at least commit the comment once, then take it out and commit again. This way you can look through the commit history to dig it up one day. Whenever I see commented out code, I just remove it. Better yet, use a linter or some script to cleanup your code for you.

Never branching

If you leave all your code on a master branch then it becomes hard to manage multiple features, releases and multiple contributors. If you only use a develop branch then it’s still hard, a bit better than just having a single master branch. Best thing to do is create a branch for every new task you’re working on, having the branch relate directly to an assigned task in your PM software is generally the easiest way to manage your work load.

I personally like a simple categorization of branching: feature, bug, and hotfix. A feature is for most regular updates, a bug is obviously for bugs which are breaking the site, and a hotfix is for something that needs to go live asap, often merged direct into master.

Not removing unused code

Sometimes you have a piece of code which is never touched anymore. Perhaps it’s really well coded and you want to keep it for the future. This happens to me often with “Event Listeners” which I end up not needing after a big refactor. I leave them there because they look good but they do nothing in terms of executed code. Just remove it! If you’re using code repository you’ll have a history of it, and leaving it there confuses developers on whether it’s needed.

If you need any inspiration, I remember reading about a top level engineer at Facebook, I believe director or higher up. When he looked at his total git contributions over the years, he had removed more code than he had contributed. The takeaway here is that more code is not always better, and if anything the less the better.

Not refactoring big pieces of code

Often we have good intentions of “cleaning” up a piece of code that should be refactored into many objects and we put a “TODO” note or create a “Technical Debt” task that we say we’ll do. Well we all know how often that happens. I still do this one to this day, I put faith in my “Technical Debt” column in Trello that I’ll fix all these things when I create time for “Technical Debt” week. Unfortunately, this hardly happens and what I should be doing is doing my best to refactor as you encounter code that should be refactored. So that doesn’t mean you always need to write the best code, but if you are in the habit of refactoring code as you come across it, over time you’ll be cleaning up your code base like a roomba picking up dust as it zig zags across your home.

Putting TODO on a piece of logic which is important.

I’ve been guilty of this when attempting to launch an application fast, I put a “TODO” on a piece of functionality that validates the data for an API request. If you are writing good tests you can’t get away with this one because you would have a test to ensure an API endpoint fails if it’s missing required data.

While a TODO can good for stubbing out methods to be built, or perhaps algorithmic improvements to a method, it’s a bad habit to TODO an important piece of code that should be built. Especially if the piece of code works at a surface level in “good scenarios” but comes crashing down after product usage.

Not indenting properly

Not indenting code consistently may be one of my major irks when it comes to code. I’ve seen code from the same developer using 1,2,4,8 spaces/indents all in the file. Why? Code should look clean and tidy and be well organized, when code isn’t indented consistently it makes you less concerned about keeping the rest of the code clean.

Not being consistent with syntax style

Another bad habit is changing your code styling without consistency. For example, going snake_case, camelCase, or hyphen-separated interchangeably. Sometimes you need to do a bit of both, for example PHP/Laravel is generally camelCase, but when you access model attributes they are by default snake_case because that’s the standard for DB tables. The key thing is to remain consistent and ideally follow a standard like this.

Summarizing

Developing good habits can be difficult, but it all starts with the small little wins. If you’re struggling to write tests, make really easy ones first and build up some momentum. For example, easy tests could be really basic unit tests that assert one thing against a method. Harder tests are ones which trigger a chain of actions that requires you to either prep a lot of data or “mock” a lot of things. Often times when a test is hard to write, it’s actually telling you the code itself is poorly built. Aside from testing, the other habits are mostly about making your code look as “beautiful” as possible. Pretend that your code is going to be open source, used by a massive audience. Now take away the pressure a bit 🙂 and focus on just polishing things up so it doesn’t look sloppy. These are the little things which go a long way.