Developers Bad habits

You don’t want to do that

Copy & Paste

Yeah, your work would be hard without cut & paste, right? We do this all the time, to save time, and it actually has deeper roots: prototyping (creating from a canonical object) is a natural tendency to build concepts (B is a A but something).

  • similar to existing things that would look the same, but you don’t want to re-write the common part. However, if you follow the DRY principle, you should not duplicate things and (hopefully) that’s probably not what you want: you want to edit it afterwards. But nobody’s perfect, and you may forget to do it everywhere it should be, thus leading to a bug. Maybe you should wonder if that common part could be refactored as an object or a function, and the varying parts be arguments for such a function.
  • repetitive and you don’t want to rewrite it every time. However, this must fit one of two cases: either A) it is a long repetition, and you should probably benefit of automating it (through a tool or code) ; or B) it is not long and you should not duplicate things according to the DRY principle (see above).
  • complex and you don’t want to take the time to understand it. However if it is something you need to do, you’d better understand what you are doing. Pasting code or technical commands prevents you to memorize it or even understand what you’re doing. Even if you think you do when pasting it, you won’t memorize it as well as if you typed it.

Questioning the need

Hushing errors

One way to avoid problems is to hide or hush them. This is what too many developers do in too many situations:

try {
result = canFail()
}
catch (error) {
// Do nothing
}

Workaround instead of fix

A variant of this is the false fix. Suppose your program crashes because something is null. What it is the solution?

canFail(myVar)   // Crashes because myVar is null!
if (myVar != null)
result = canFail(myVar)
try {
result = canFail(myVar)
} catch (nullError) {
// It's ok, continue
}

Implementing more than one thing at a time

Committing multiple things

This one starts from good intentions: while implementing a feature or fixing a bug, you think about something else (refactoring, another fix or even another planned small feature) that should be done and for some reason (you’re in the right place in the code, it will be quick to do, etc.) you decide in include that secondary work in your current changes.

  • size: Your changes will get bigger ; so the time to review them ;
  • versatility: The topic of your changes will be diverse, so reviewing your code might require a broader knowledge. Also, depending on your pull request/committing policy (squashing or not), your whole set of change will become atomic, so that one cannot revert only the part of it that is relevant to a single topic.
  • refactoring: we all know that such tasks hardly find their place in a backlog where there is always something deemed as “more important” to do (which is wrong). So moderate refactoring should be allowed as an regular “hygienic” routine that prevents technical debt to grow way out of control.
  • testing: obviously there is nothing wrong in adding or improving tests when you add a feature or fix a bug. Tests should not be postponed or planned for a “later task”.

Bad design

There are other ways of developing multiple things at a time, when you:

  • write non-SRP code that melt multiple concerns.
  • implement some optionality mechanism, which is actually about implementing two contracts at a time (the one when the optional thing is provided, and the one when it is not).

Blaming others

A fraction of humans have a difficulty to acknowledge they did something wrong. There can be many reasons for that, from ego to stress. This can lead to blame the machine, the operating system which “must be bugged”, software tools that “did not do want you wanted” or did it incorrectly (like if they became sentient), or… the users themselves.

“Silly users”

Even if the user actually did something wrong with your software, you have to face the fact that you allowed it. It is your responsibility to prevent such misbehaviors: if you allowed users to do silly things with your software, that should be fixed too.

Loss of rationality

Say you encounter some behavior (a bug, a message, etc) that can’t understand. You really can’t. All explanations have been exhausted, and your brain is — quite rationally actually — starting to look for other variables: Did it work yesterday, even if I didn’t touch that code? Maybe it is working only even days? Could this be a bug of the OS or hardware bug? Could a solar wind event affected my computer?

Belief in non-idempotence

A specific case of this when you start to retry things that fails consistently. Idempotence (same causes produce same effects, in short) is more the rule than the exception in software: if you give the same inputs, it is more than likely that you’ll get the same outputs.

If you see something, say something.

Consider the feature as the only goal

Let’s say you asked a junior developer to develop some feature, and the feature is delivered (possibly on time), fully functional but with unmaintainable code. You complain about it but the developer assumes to invalidate all your remarks with a single argument:

  • Programming to mentor and show good practices ;
  • Check the developed code on a regular basis before it is finished.
  • Ask unit tests to be written, emphasising that such tests should allow to test one thing. That should drive the design toward a more granular design.

Uncertainty

Of course you can be sure of some things and uncertain about others ; but in the latter case, you should be able to say:

--

--

Software engineer for three decades, I would like to share my memory. https://javarome.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store