How to Eliminate 22 Common Code Smells with Refactoring Techniques
This article enumerates twenty‑two typical code smells—from duplicated code and long methods to speculative generality—and provides concrete refactoring tactics such as Extract Method, Pull Up Method, Introduce Parameter Object, and Move Method to improve design, readability, and maintainability of object‑oriented software.
1. Duplicated Code
When the same program structure appears in different places, unify them. Typical cases are two methods in the same class sharing an expression or sibling subclasses containing identical code. Apply Extract Method to create a shared method, then use Pull Up Method to move it to a superclass, or employ Form Template Method and Template Method patterns. If algorithms differ, consider Substitute Algorithm . For unrelated classes, use Extract Class to place the common code in a new class.
2. Long Method
A method should generally stay under 100 lines. When a method grows, repeatedly apply Extract Method to isolate cohesive blocks. Large numbers of parameters or temporary variables can be reduced with Replace Temp with Query , Introduce Parameter Object , or Preserve Whole Object . If parameters remain excessive, consider Replace Method with Method Object . Look for comments that signal extraction opportunities, and decompose complex conditionals with Decompose Conditional . Extract loops into separate methods as well.
3. Large Class
A class should not assume responsibilities beyond its core purpose (Single Responsibility Principle). When a class accumulates many instance variables, apply Extract Class to group related fields, possibly followed by Extract Subclass . Use Extract Interface to define distinct usage contracts. For GUI classes, move data and behavior to domain objects, and consider Duplicate Observed Data to keep synchronized copies.
4. Long Parameter List
Long parameter lists hinder understanding and maintenance. Replace multiple parameters with a single object using Replace Parameter with Methods , Preserve Whole Object , or Introduce Parameter Object . Avoid creating unnecessary dependencies between callers and large objects.
5. Divergent Change
If a class must be modified in many different ways, it suffers from divergent change. Split the class into separate classes so each handles a single reason for change, using Extract Class to relocate the varying responsibilities.
6. Shotgun Surgery
A simple change requiring modifications in many classes indicates shotgun surgery. Identify a responsible class (or create one via Extract Class ) and move related fields and methods into it, possibly using Move Field , Move Method , or Inline Class when appropriate.
7. Feature Envy
When a method is more interested in another class’s data than its own, move the method to the class it envies using Move Method . If only part of the method is envious, first Extract Method then Move Method . Choose the class that owns the most data used by the method.
8. Data Clumps
Repeated groups of three or four data items across classes or method signatures should be encapsulated in their own object. Use Extract Class and then apply Introduce Parameter Object or Preserve Whole Object to shorten parameter lists.
9. Primitive Obsession
Overreliance on primitive types instead of small objects leads to primitive obsession. Replace primitive values with domain objects via Replace Data Value with Object , Replace Type Code with Class , or Replace Type Code with Subclass/State‑Strategy . Introduce parameter objects or replace arrays with objects where appropriate.
10. Switch Statement
Switch statements often duplicate logic. Replace them with polymorphism: extract the switch into its own method ( Extract Method ), move it to the appropriate class ( Move Method ), then apply Replace Type Code with Subclass or Replace Type Code with State/Strategy , finally using Replace Conditional with Polymorphism . For simple selections, consider Replace Parameter with Explicit Methods or introduce a Null Object .
11. Parallel Inheritance Hierarchies
When adding a subclass to one hierarchy forces adding a matching subclass to another, collapse the duplication by having one hierarchy reference the other, and use Move Method and Move Field to eliminate the parallel structure.
12. Lazy Class
If a class does not justify its existence, collapse it ( Collapse Hierarchy ) or inline it ( Inline Class ).
13. Speculative Generality
Avoid creating classes, methods, or parameters that are never used. Collapse unnecessary hierarchies, inline trivial classes, remove unused parameters ( Remove Parameter ), and rename misleading methods ( Rename Method ). Delete test‑only scaffolding unless it serves a testing purpose.
14. Temporary Field
Fields that are only set for specific situations confuse readers. Extract such fields into a separate class ( Extract Class ) and consider a Null Object for invalid states.
15. Message Chains
Long chains of calls (e.g., a.getB().getC().do()) create tight coupling. Hide the delegation ( Hide Delegate ) or extract the chain into a method ( Extract Method ) and move it to a more appropriate class ( Move Method ).
16. Middle Man
When a class delegates most of its work to another, remove the middle man ( Remove Middle Man ) or inline its methods ( Inline Method ). If delegation is justified, replace it with inheritance ( Replace Delegation with Inheritance ).
17. Inappropriate Intimacy
Two classes that know too much about each other should have responsibilities separated using Move Method , Move Field , or by converting bidirectional associations to unidirectional ( Change Bidirectional Association to Unidirectional ). If inheritance causes intimacy, replace it with delegation ( Replace Inheritance with Delegation ).
18. Alternative Classes with Different Interfaces
When two functions perform the same task but have different signatures, rename them ( Rename Method ) and align their interfaces by moving behavior ( Move Method ) or extracting a common superclass ( Extract Superclass ).
19. Incomplete Library Class
Library classes that lack needed behavior can be extended without modifying the original code: use Introduce Foreign Method for small additions or Introduce Local Extension for larger enhancements.
20. Data Class
Classes that only hold data and expose getters/setters should be encapsulated ( Encapsulated Field , Encapsulated Collection ) and unnecessary setters removed ( Remove Setting Method ). Move client‑side behavior into the data class via Move Method or Extract Method , then hide the accessors ( Hide Method ).
21. Refused Bequest
When a subclass does not need all inherited members, create a sibling class and push down unused methods/fields ( Push Down Method , Push Down Field ). Keep superclasses abstract where appropriate, and consider replacing inheritance with delegation ( Replace Inheritance with Delegation ) if the bequest causes confusion.
22. Excessive Comments
Long comments often signal poor code. Eliminate the need for comments by applying refactorings such as Extract Method , Rename Method , or Introduce Assertion to make the code self‑explanatory.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
ITFLY8 Architecture Home
ITFLY8 Architecture Home - focused on architecture knowledge sharing and exchange, covering project management and product design. Includes large-scale distributed website architecture (high performance, high availability, caching, message queues...), design patterns, architecture patterns, big data, project management (SCRUM, PMP, Prince2), product design, and more.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
