This document discusses code smells and refactoring. It begins by defining technical debt as implied costs from easy short-term solutions versus better long-term approaches. It then lists common causes of technical debt like business pressure and lack of testing. Different types of technical debt like code debt and design debt are identified. Common code smells like long methods, duplicate code, and primitive obsession are explained along with refactoring treatments like extracting methods and replacing conditionals with polymorphism. The goal of refactoring is to improve code quality by treating code smells.
2. Technical Debt
Metaphor coined by Ward Cunningham in a 1992 report.
A concept in software development that reflects the implied
cost of additional rework caused by choosing an easy
solution now instead of using a better approach that would
take longer.
3. Stakeholders Goals
● Determine product/market fit
● Critical need to ship products early
● Meet customer needs
● Seize emerging opportunities
4. Causes of Technical Debt
● Business pressure
● Lack of understanding of the consequences of technical debt
● Failing to combat the strict coherence of components
● Lack of tests
● Lack of documentation
● Lack of interaction between team members
● Long-term simultaneous development in several branches
● Delayed refactoring
● Lack of compliance monitoring
● Incompetence
5. Types of Technical Debt
1. Code debt
2. Design & Architecture debt
3. Test debt
4. Documentation debt
7. Code Smells
A code smell is a surface indication that usually
corresponds to a deeper problem in the system.
—Martin Fowler
8. Common Code Smells
● Comments
● Uncommunicative Name
● Long method
● Long parameter list
● Data Clumps
● Large class
● Duplicate Code
● Primitive Obsession
● Divergent Code
● Shotgun Surgery
● Switch Statements
● Lazy Class
And many more…..
9. Comments
● Should only be used to clarify "why" not "what".
● Can quickly become verbose and reduce code clarity.
Please don’t do that.
10. Uncommunicative Name
● Choose names that communicate intent
● Pick the best name for the time, change it later if necessary
11. Long Method
Signs and Symptoms
A method contains too many lines of code.
Reason
Developers start coding without reading the existing implementation.
Treatment
● Extract Method
● Replace Method with Method Object
● Replace temp with query
15. Long Parameter List
Signs and Symptoms
More than three or four parameters for a method.
Reason
● Trying to do too many things in a method.
● Trying to minimize dependencies between objects.
Treatment
● Replace parameters with method call.
● Preserve whole object.
● Introduce parameter object.
19. Long Parameter List
Benefits
● Improving readability of code.
● Possibly reduces code duplication that was not noticed earlier.
Exceptions
Sometimes we might decide to go with a long parameters list.
● Passing a whole object would cause unwanted dependency between objects.
● In some cases the parameters can be unrelated. Grouping them in a parameter
object won’t make any sense.
20. Data Clumps
Signs and Symptoms
Sometimes different parts of the code contain identical groups of variables
Reasons for the Problem
● Copypasta programming
Treatment
● Extract Class
● Introduce Parameter Object
● Preserve whole object
22. Large Class
Signs and Symptoms
A class contains many fields/methods/lines of code.
Reason
Developers find it mentally less taxing to place a new feature in an existing class than
to create a new class for small feature.
Treatment
● Extract Class
● Extract Subclass
● Extract Interface
23. Duplicate Code
Signs and Symptoms
● Code fragments look almost identical.
● Same expression in two or more method in same class
Reasons for the Problem
● Multiple programmers doing same thing at the same time
● Novice programmers may not resist themselves to do Copy/Pasta
● Scary authors don’t allow to refactor their code
Treatment
● Extract Method
● Pull Up Field
● Form Template Method, Substitute Algorithm
26. Primitive Obsession
Signs and Symptoms
● Use of primitives instead of small objects for simple tasks
● Using arrays, map or dictionaries to represent specific object
Reasons for the Problem
● “Just a field for storing some data!” the programmer said
● Creating a primitive field is easier
Treatment
● Replace Data values with Object
● Replace array/map with object
29. Divergent Change
Signs and Symptoms
You find yourself having to change many unrelated methods when you make changes
to a class
Reasons for the Problem
● Often these divergent modifications are due to poor program structure or
"copypasta programming”.
Treatment
● Split up the behavior of the class via Extract Class.
32. Shotgun Surgery
Signs and Symptoms
A single change impact many other classes.
Reasons for the Problem
● Poor separation of concerns.
● Failure to understand responsibilities(SRP)
Treatment
● Move Method
● Move Field
● Inline Class.
35. Switch Statements
Signs and Symptoms
You have a complex switch operator or sequence of if statements.
Reasons for the Problem
● Switch Statements can be scattered in several places
● Need to find all SS for adding new case.
Treatment
● To isolate switch and put it in the right class, you may need Extract Method and then Move
Method.
● Think about Polymorphism
40. Switch Statements
Benefits
● If you need to add a new type code, you can just add a new subclass without
touching the existing code. This follows the Open/Closed Principle.
● Instead of asking an object for its state and performing actions based on that it is
easier to let the object decide what to do. This means following the Tell, Don't
Ask Principle.
● Removes duplicate code when you have several similar conditions.
Exceptions
In some cases replacing switch statements is not necessary:
● If the switch operator performs very simple actions, there is no reason to change
it.
● A factory method or an abstract factory might use switch statements to create
classes.
41. Lazy Class
Signs and Symptoms
If a class doesn’t do enough to earn your attention, it should be deleted.
Reasons for the Problem
● After refactoring the Class has become less important
● May be designed for future needs!
Treatment
● Inline Class
● Collapse Hierarchy.
42. “Any fool can write code that a computer can understand. Good
programmers write code that humans can understand.”
― Martin Fowler
Sometimes stakeholders set unrealistic deadline of a project.
We treat everything in the trash as another trash, no matters it is valuable or less valuable
Generally, any method longer than ten lines should make you start asking questions.
The majority of a programmer’s time is spent reading code rather than writing code
It is usually a sign that the method has too many responsibilities
Long methods make code hard to maintain and debug
If there are local variables or parameters that prevent extracting a method, replace temp with query, introduce a parameter object, or preserve whole object.
If there are conditional operators, you can try to decompose the conditional.
Extract method
In this example keep in mind that the local variable is preventing us from using extract method. The goal here is to present how to make it possible.
In this example keep in mind that the local variable is preventing us from using extract method. The goal here is to present how to make it possible.
It is not really clear what each parameter does. To find out you are forced to read the documentation.
If the parameters come from different objects, introduce a parameter object.
If the parameter can be obtained from another object, replace parameter with a method call. The object can be a field in the class or passed as a parameter.
If the parameters belong to a single object, preserve whole object.
In this example keep in mind that the local variable is preventing us from using extract method. The goal here is to present how to make it possible.
In this example keep in mind that the local variable is preventing us from using extract method. The goal here is to present how to make it possible.
For example: (such as parameters for connecting to a database)
If repeating data comprises the fields of a class, use Extract Class to move the fields to their own class.
If the same data clumps are passed in the parameters of methods, use Introduce Parameter Object to set them off as a class.
If some of the data is passed to other methods, think about passing the entire data object to the method instead of just individual fields. Preserve Whole Object will help with this.
Classes usually start small. But over time, they get bloated as the program grows.
Primitive obsessions are born in moments of weakness
Then another field was needed and added in the same way.
For example, when adding a new product type you have to change the methods for finding, displaying, and ordering products.
Payoff
Improves code organization.
Reduces code duplication.
Simplifies support.
Shotgun Surgery resembles Divergent Change but is actually the opposite smell. Divergent Change is when many changes are made to a single class. Shotgun Surgery refers to when a single change is made to multiple classes simultaneously
spreading around logic that should probably be in one place
if you add a value to one switch statement you’re likely to need to hunt down all the other ones and change them too.
Cyclometic complexity = Number of decisions in the source code