Anti-patterns and code smells
Anti-patterns and code smells are architectural bad practices or tips about possible bad design. Learning about best practices is as important as learning about bad ones, which is where we start. Moreover, there are multiple anti-patterns and code smells throughout the book to help you get started.
Unfortunately, we can't cover every detail of every topic, so I encourage you to dig deeper into those fields as well as into design patterns and architectural principles.
Anti-patterns
An anti-pattern is the opposite of a design pattern: it is a proven flawed technique that will most likely cause you some trouble and cost you time and money (and probably give you a headache or two along the way).
A priori, an anti-pattern is a pattern that seems to be a good idea, and that seems to be the solution that you were looking for, but in the end, it will most likely cause more harm than good. Some anti-patterns started out as legitimate design patterns and got labeled anti-patterns later. Sometimes, it is a matter of opinion, and sometimes the classification can be influenced by the programming language.
Anti-pattern – God class
A God class is a class that handles way too many things. It is usually a central class that many other classes inherit from or use; it is the class that knows and manages everything in the system; it is the class. On the other hand, it is also the class that nobody wants to update, and the class that breaks the application every time somebody touches it; it is an evil class!
The best way to fix this is to separate responsibilities and distribute them to multiple classes instead of only one. We see how to split responsibilities throughout the book, which helps create more robust software at the same time.
If you have a personal project with a God class at its core, start by reading the book, and then try to apply the principles and patterns that you learned to divide that class into multiple smaller classes that interact together. Try to organize those new classes into cohesive units, modules, or assemblies.
We are getting into architectural principles very soon, which opens the way to concepts such as responsibility segregation.
Code smells
A code smell is an indicator of a possible problem. It points to some areas of your design that could benefit from a redesign. We could translate code smell to the code that stinks.
It is important to note that code smells only indicate the possibility of a problem; it does not mean that there is one; they usually are good indicators though, so it is worth taking the time to analyze that part of the software.
An excellent example of this is when many comments are explaining the logic of a method. That often means that the code could be split into smaller methods with proper names leading to more readable code, and allowing you to get rid of those pesky comments.
Another thing about comments is that they don't evolve, so what often happens is that the code described by the comments has changed, but the comment remained the same. That leaves a false or obsolete description of a block of code that can lead a developer astray.
Code smell – Control freak
An excellent example of an anti-pattern is when you use the new
keyword. That is an indication of a hardcoded dependency where the creator controls the new object and its lifetime. That is also known as the Control freak anti-pattern. At this point, you may be wondering how it is possible not to use the new
keyword in object-oriented programming, but rest assured, we cover that and expand on the Control freak code smell in Chapter 7, Deep Dive into Dependency Injection.
Code smell – Long methods
A follow-up example that could be represented by our previous over-commented example would be long methods. When a method starts to extend to more than 10 to 15 lines of code, it is a good indicator that you should think about that method differently.
Here are a few examples of what could have happened:
- The method contains complex logic intertwined in multiple conditional statements.
- The method contains a big
switch
block. - The method does too many things.
- The method contains duplications of code.
To fix this, you could do the following:
- Extract one or more private methods.
- Extract some code to new classes.
- Reuse the code from external classes.
- If you have a lot of conditional statements or a huge switch block, you could leverage a design pattern such as the Chain of Responsibility, or CQRS, which you will learn in Chapter 10, Behavioral Patterns and Chapter 14, Mediator and CQRS design patterns.
Usually, each problem has one or more solutions, suffice to spot the problem then find, choose, and implement the solution. Let's be clear here; a method containing 16 lines does not necessarily need refactoring; it could be OK. Remember that a code smell is merely an indicator of a problem, and is not necessarily a problem; apply common sense.