This presentation is continuation to “Software Craftsmanship - Code Smells - Object Orientation Abusers”. Here we will cover the fifth and the final category of code smells – “Change Preventers”.
3. Change Preventers
Prevent = keep (something) from happening
Dread it. Run from it. Destiny still arrives.
ACCEPT THE CHANGE!
5
Parallel Inheritance Hierarchies
Divergent Change Shotgun Surgery
4. DIVERGENT CHANGE
A class gets changed in different ways for various unrelated reasons
Increased code complexity
Unorganized code
Code becomes inextensible
Difficult to support code base
Violation of Single Responsibility Principle
Class takes care of more than one distinct responsibility
We should be able to jump to a single clear point in the code to make a change
CAUSE
- Code Extensibility
5. Identify behaviors that do not belong to the class or behaviors that change for a
particular cause Put them into separate class
Extract Class
Single Responsibility Principle
6. SHOTGUN SURGERY
A small change in code requires changes in multiple classes
CODE
Changing code = Firing shotgun at the code
Single change affects large number of classes
Increased code complexity
Unorganized code
Code becomes inextensible
Difficult to support code base
Single responsibility has been split across multiple classesCAUSE
7. Identify code in different classes that gets affected at the same time
Group this into a single class
Move Field
Move Method
Certain class becomes empty after moving code?
Inline Class
CODE
8. PARALLEL INHERITANCE HIERARCHIES
Creating a subclass in one hierarchy forces you to create a subclass in another hierarchy
Special case of Shotgun Surgery
Increased code duplication
Unorganized code
Code becomes inextensible
Difficult to support code base
VEHICLE
- operator
+ getOperator ( )
OPERATOR
+ accelerate ( )
+ turn ( )
CAR PLANE
PILOT
+ barrelRoll ( )
DRIVER
+ handBrake ( )
For every new subclass of Vehicle,
a new subclass of Operator is required
9. VEHICLE
+ getOperator(): Operator
OPERATOR
+ accelerate ( )
+ turn ( )
PILOT
+ barrelRoll ( )
DRIVER
+ handBrake ( )
CAR
Driver driver
+getOperator( ): Driver
PLANE
Pilot pilot
+getOperator( ): Pilot
Merge one hierarchy into another Extend the new hierarchy
Move Field
Move Method
(class CarDriver implements VehicleOperator)
Do not collapse Extend both hierarchies
(class CarDriver implements Vehicle, Operator)
None of the solutions feel good? Use:
Intelligent Children Pattern
INTELLIGENT CHILDREN PATTERN
Trust your child
to do it for you!
This presentation is continuation to “Software Craftsmanship – Code Smells_4_Object Orientation Abusers”. Here we will cover the fifth and the final category of code smells – “Change Preventers”.
How do we know that code we have written is good or bad? Is it a subjective opinion or is there any metrics to determine whether it is readable/extensible/maintainable?
Luckily for us, there IS A METRIC!
When you go past a garbage can, you tend to block your nose, as the foul smell is almost unbearable. When there is something wrong with the code, we say there are certain elements in it which stink, making the whole code stink as well! These stinky elements are referred to as code smells. Now, when it comes to real life objects, the sense of foul smell is an innate human tendency. But when it comes to code, we need to teach ourselves to identify these code smells.
In other words, we need to develop a nose to identify foul smells in the code. And this ability can only be developed when you are relatively young (new to development). As soon as a hatchling starts flying, its mother teaches it to hunt, for it won’t survive in its adulthood without the ability. The same goes with the ability to smell stink inside the code. It becomes harder and harder to develop this ability as we grow further into software development without it. For it is easier to learn than to unlearn. Writing a code with wrong practices is more dangerous than not writing the code at all! IT IS VERY IMPORTANT FOR ANY YOUNG DEVELOPER TO DEVELOP A NOSE FOR THESE CODE SMELLS!
There are broadly 5 categories code smells are divided into. We are covering the fifth category here: Change Preventers
When certain elements in your code prevent it from being modified, the elements are said to fall under the category of code smells called - Change Preventers
These elements often make it difficult for the programmer to modify the code. Either a change breaks the code or it effects so many other elements in the code, that even for a small change, the programmer ends up spending huge amount of time on the code base. Program development becomes much more complicated and expensive as a result.
Lets look at these elements in detail!
Imagine a box outside your house that acts as a master control for electricity, water supply and gas supply. Now since this box handles so many supplies, there is a spaghetti of wires present inside it. Every time you have a problem with any of these three supplies, you end up looking inside the same box, trying to figure out which wire connects to which supply. There is a high probability of you touching a wrong wire and ending up loosing the water supply while fixing the electricity. Isn’t it?
What’s the primary problem here?
The box handles more than one supply.
In a similar fashion, if your class handles more than 1 responsibility, you end up coming back to it for lots of different reasons. You end up modifying the same class for various unrelated feature requests and there is high probability of breaking one of the other features during modification. Your code is said to exhibit Divergent Change smell.
Not only it is risky to modify the class, a class handling more than 1 responsibility brings with it all the drawbacks of a Large Class. (Both these code smells often co-exist)
Classes that have more than one distinct responsibility (more than one reason to change) violate the Single Responsibility design principle. This principle states that a “class should handle one and only one responsibility alone.” Modify your code to follow this design principle
Treatment
Split up the behavior of the class via Extract Class.
If different classes have the same behavior, you may want to combine the classes through inheritance (Extract Superclass and Extract Subclass)
Consider yourself having around 5 boxes outside your house controlling just a single water supply. Any problem with water supply results in you spending huge amount of time looking at each of the boxes and trying to figure out which one has a defect. And fixing one may force you to change some connections in others as well!
When a small change comes to your code, and forces you to make huge changes to your codebase by modifying many classes together at once, the change acts like a shot from a shotgun affecting huge amount of code in one shot!
This happens when a single feature (responsibility), instead of being assigned to a single class, is assigned to multiple classes in the code. So when a change request comes for that particular feature, you end up modifying code at various places.
Treatment
(read the slide)
When you create a new subclass for a class, and you find yourself needing to create a subclass for another class, you might have Parallel Inheritance Hierarchies in your code.
(Read the slide)