Warning: Illegal string offset 'filter' in /var/sites/t/theproactiveprogrammer.com/public_html/wp-includes/taxonomy.php on line 1409
Code smells offer us a convenient way to identify, classify and address bad code.
The phrase was first coined by Kent Beck, while helping Martin Fowler with his famous book, Refactoring. A code smell is an indication of bad code. It is something that is easy to spot quickly, and which probably tells us that the code could have been written in a more helpful way.
How can code be helpful, you might ask?
Helpful code will not be too difficult for future programmers (including your future self) to modify, debug, refactor or extend. It helps your future self and others. It is a sign of a considerate programmer, who not only prevents future headaches by allowing code which can be easily updated, but also creates code which can be quickly updated. This allows your system to include more new features and bug fixes per release, which means a competitive advantage for your product.
The most well-known list of smells comes from Fowler’s Refactoring book. If you don’t want to buy the book, two good starting points for learning about this topic are A Taxonomy of Code Smells and SourceMaking.
The 3 Worst-Smelling Smells
Long methods can be nightmarish for a number of reasons. They are difficult to unit test, difficult to read, and frightening to modify. The beauty of short methods, particularly if they are well named, is that they allow our brains to better process what the code is actually doing. If we can’t get past this essential first step in understanding someone else’s code, we are going to struggle.
The solution to the problem of a long method is to break it up into smaller methods. Resharper and Visual Studio offer ‘Extract Method’ tools which can help with this. To ensure we don’t break anything, it is preferable to thoroughly unit test the method before breaking it up, although this can be more difficult than it sounds, as explained by Michael Feathers in Working with Legacy Code.
Large classes often indicate a violation of the Single Responsibility Principle. If a class does a lot of things, it will have many potential reasons to change. Each change to the class risks breaking something in the same class, something which may be unrelated, leading to a system which lacks robustness.
Code duplication and large classes often co-exist. If you find a large class there is a good chance it will contain some duplicate code. If you need to change how that code works, you need to find multiple places in your codebase which need changing. Solutions which are littered with duplicate code are also harder to understand and are generally unnecessarily bloated.
Causes of Code Smells
I can think of three distinct reasons for the existence of code smells in our codebases: ignorance, laziness and denial.
Firstly, ignorance. This refers to programmers who don’t realise what they are doing. They have never been educated on best practices and code smells. Or they may know they are doing something wrong, but they don’t appreciate its consequences. For these programmers, the answer is education, and the topic of code smells is a good place to start.
The second common cause for code smells is laziness. These programmers know they are doing things badly. They appreciate that creating large classes and long methods is not the best way of doing things, but they do it anyway, because they can’t be bothered applying the extra mental effort to do things correctly. What we need to realise is that doing things the best way is just a habit we need to learn, and that it is well worth the effort in the long run, not only for the product you are working for, but for your own professional development.
Laziness can also be a cultural issue. If your teammates don’t make an effort to create high quality code, then you are obviously less likely to do so yourself. Conversely, if everyone else avoids code smells like the plague, then psychologically you are going to resist being the only person who writes bad code. This is one of many reasons to surround yourself with better, more experienced programmers where possible.
A third precursor for code smells is denial. This most commonly occurs when a programmer feels under pressure to hit a deadline, and so frequently opts for the quick and dirty solution, suppressing any underlying feelings that they are not doing things the right way. This most commonly is a cultural issue, where it is deemed more important to produce anything quickly, than to produce something of good quality which takes a slightly longer time.
In actual fact, the observation that doing things the right way takes longer is often a myth, at least in the long run. The answer here is to get into the habit of producing high quality code, so that you can do so quickly and without too much extra effort. Improving your estimating skills will also help avoid situations where you feel under pressure to deliver something quickly.
Martin Fowler makes an excellent point with regards to code smells. Just because a method is long, or a class is big, that doesn’t necessarily mean that there is a problem that needs to be addressed. It may be that fixing a code smell by refactoring would be too risky. Or it may be that a quick and dirty solution is in fact the best approach. Perhaps you are working on a throw-away project where meeting a deadline is genuinely more important than producing good quality code. Projects like this do exist, although they are few and far between.
I believe that the three code smells listed above: Long Method, Large Class and Duplicate Code, should be an essential part of any elementary programming course. Such courses tend to focus too much on syntax and not enough on language-agnostic principles. At the very least, programmers entering their first job must have an understanding of basic code smells such as these.
With experience and understanding of course, our ability to intuitively judge a situation will improve, and we will know when it is right to refactor and when it is not. Programming is a never-ending learning experience, which is one of the reasons it is such good fun.