2. Software Craftsmanship Manifesto
“Not only working software, but also well-
crafted software
Not only responding to change, but also steadily
adding value
Not only individuals and interactions, but also a
community of professionals
Not only customer collaboration, but also
productive partnerships”
3. Technical Debt
Software Finance
Skipping (or deferring) design Borrowing money
Refactoring (i.e. behavior-preserving
design improvements)
Repaying principal
Slower development due to code
smells
Paying interest
4. Code Smells
• Lost Intent
• Inefficient Name
• Duplicated Code
• Deodorant Comment
• Long Method
• Large Class
• Lazy Class
More…
5. Lost Intent
Just as a traffic sign may be obscured by shrubs, Code that doesn't easily communicate
it's author's intention is hazardous: hard to understand, extend and modify.
6. Lost Intent
Intention-Revealing Code Lost Intent
The purpose of the code is clear.
Low-level or complex logic obscures
the code's purpose.
You can easily find the code you seek.
The location of code makes little
sense.
Every step of an algorithm is clearly
defined.
The steps of the algorithm are
blended together.
9. Inefficient Name
tmp = finder.fetch("0182901");
Account theAccount = finder.fetch(transaction.getSource());
account = finder.fetch( new StateMatcher("VA") );
for(Account item : finder.fetchAll()) { … }
getDrctn()
getDir()
getDirection()
These are five lines chosen at random from a class.
Each is grabbing a fetch result and putting it in a variable of type Account.
10. Duplicated Code
If you see the same code structure in more than one place, you can be sure that your program
will be better if you find a way to unify them.
— Refactoring[page 76], Martin Fowler and Kent Beck
14. Comment Guidelines
• Whenever possible make your code express
the intent of the comment and remove the
comment.
• Comments are to provide intent that
is not expressible in code.
• Any comment that duplicates what the code
says should be deleted.
22. Oddball Solution
When a problem is solved one way throughout a system and the same problem is
solved another way in the same system, one of the solutions is the oddball or
inconsistent solution.
26. Switch Statement
Most times you see a switch statement you should consider polymorphism.
— Refactoring, Martin Fowler and Kent Beck (page 82).
27. Switch Statement
Move each leg of the conditional to an overriding method in a subclass. Make the original
method abstract.
28. Switch Statement
• Not every occurrence of a switch statement
(or if...else if...else if... statements) should be
replaced with a polymorphic solution.
29. Speculative Generality
You get this smell when people say "Oh, I think we will need the ability to do that someday"
and thus want all sorts of hooks and special cases to handle things that aren't required. —
Refactoring, Martin Fowler and Kent Beck (page 83).
31. Long Parameter List
Methods that take too many parameters produce client code that is awkward and
difficult to work with.
32. Long Parameter List
user = userManager.create(USER_NAME, group, USER_NAME, “test",
USER_NAME, LANGUAGE, false, false, new Date(), "blah", new Date());
33. Conditional Complexity
Conditional logic is innocent in its infancy, when it is simple to understand and contained
within a few lines of code. Unfortunately, it rarely ages well.
— Joshua Kerievsky, Refactoring to Patterns, page 41.
35. Combinatorial Explosion
When new combinations of data or behavior further bloat an already bloated design, you've got
a Combinatorial Explosion smell.
37. Alternative Classes With Different
Interfaces
This subtle smell results when differences in the interfaces of similar classes leads to
duplicated code.
39. Inappropriate Intimacy
Sometimes classes become far too intimate and spend too much time delving in each others'
private parts.
— Refactoring [page 85], Fowler and Beck
43. Refused Bequest
Subclasses get to inherit the methods and data of their parents. But what if they don't
want or need what they are given? — Refactoring[page 87], Martin Fowler and Kent Beck
47. Solution Sprawl
When code and/or data used to perform a responsibility becomes sprawled across numerous
classes, Solution Sprawl is in the air.
— Joshua Kerievsky, Refactoring to Patterns, page 43.
55. References
• Refactoring: Improving the Design of Existing
Code by Martin Fowler
• Refactoring to Patterns by Joshua Kerievsky.
• https://elearning.industriallogic.com/gh/subm
it?Action=AlbumContentsAction&album=reco
gnizingSmells&devLanguage=Java
Editor's Notes
Extract Method
An inefficient name is a name that isn't optimized for the way programmers work. An inefficient names wastes only a second (usually), but it wastes that second over and over again.
Refactor just select method or variable name and Alt+Shift+R
Don’t Repeat Yourself
Chain Constructors
Extract Composite
Extract Method
Extract Class
Form Template Method
Introduce Null Object
Introduce Polymorphic Creation with Factory Method
Pull Up Method
Pull Up Field
Replace One/Many Distinctions with Composite
Substitute Algorithm
Unify Interfaces with Adapter
This smell occurs when you use comments to explain code, rather than making your code self-documenting or intention-revealing.
If you write intention-revealing code, your code is so easy to understand that comments become unnecessary. If, on the other hand, your code isn't easy to understand, comments can help explain the code.
Rename Method
Extract Method
Introduce Assertion
Readable Code. Shorter methods are easier to read and comprehend.
Shared Code. Shorter methods provide greater opportunity for fine-grained code sharing.
Easier Testing. Shorter methods tend to be easier to microtest (A.K.A. unit test).
Extract Method
Compose Method
Introduce Parameter Object
Move Accumulation to Collecting Parameter
Move Accumulation to Visitor
Decompose Conditional
Preserve Whole Object
Replace Conditional Dispatcher with Command
Replace Conditional Logic with Strategy
Replace Method with Method Object
Replace Temp with Query
Large classes simply do too much work.
They contain too many methods and fields, all of which exist to provide too much diverse functionality for a single class.
Many large classes get that way by becoming a convenient dumping ground for newer pieces of functionality that don't have an obvious home.
Like large methods, large classes are harder to understand than smaller classes.
They don't tend to collaborate with other objects (i.e. little delegation: one object forwarding requests to another object) and their size usually inhibits good hierarchy design.
The diverse functionality within large classes tends to attract even more diverse functionality.
Large classes perpetuate poor design choices, since it is just so easy to add yet another method to a large class.
Extract Class
Extract Subclass
Extract Interface
Replace Data Value with Object
Replace Conditional Dispatcher with Command
Replace Implicit Language with Interpreter
Replace State-Altering Conditionals with State
Extract Class
Extract Subclass
Extract Interface
Replace Data Value with Object
Replace Conditional Dispatcher with Command
Replace Implicit Language with Interpreter
Replace State-Altering Conditionals with State
Such a class may result from moving methods from one class to another.
Whatever minor functionality it does provide can be offered by another class, thereby allowing you to delete the lazy class.
Collapse Hierarchy
Inline Class
Inline Singleton
Collapse Hierarchy
Inline Class
Inline Singleton
If a minority solution is better than a majority solution, it ought to become the standard, consistent solution.
Unify Interfaces with Adapter
Code that exhibits primitive obsession tends to rely on
primitives (like integers or strings)
low-level methods
classes that don't easily solve problems
Replace Data Value with Object
Encapsulate Composite with Builder
Introduce Parameter Object
Extract Class
Move Embellishment to Decorator
Replace Conditional Logic with Strategy
Replace Implicit Language with Interpreter
Replace Implicit Tree with Composite
Replace State-Altering Conditionals with State
Replace Type Code with Class
Replace Type Code with State/Strategy
Replace Type Code with Subclasses
Replace Array With Object
Move Accumulation to Visitor
Replace Conditional Dispatcher with Command
Replace Conditional with Polymorphism
Replace Type Code with Subclasses
Replace Type Code with State/Strategy
Replace Parameter with Explicit Methods
Introduce Null Object
Collapse Hierarchy
Rename Method
Remove Parameter
Inline Class
Introduce Null Object
Move Embellishment to Decorator
Replace Conditional Logic with Strategy
Replace State-Altering Conditionals with State
Introduce Null Object
Move Embellishment to Decorator
Replace Conditional Logic with Strategy
Replace State-Altering Conditionals with State
Replace Specialized Selection with Specification
Replace Implicit Language with Interpreter
If similar classes have differences in their interfaces, clients will differ in how they interact with each of the classes.
If the classes could share a common interface, clients could work with either class uniformly, thereby removing duplicated client code.
Unify Interfaces with Adapter
Rename Method
Move Method
Move Method
Move Field
Change Bidirectional Association to Unidirectional Association
Extract Class
Hide Delegate
Replace Inheritance with Delegation
We don't normally expose wires inside a wall or ceiling.So why do we expose classes that need not be public?
Encapsulate Classes with Factory
We don't normally expose wires inside a wall or ceiling.So why do we expose classes that need not be public?
Encapsulate Classes with Factory
The Refused Bequest smell occurs when a subclass doesn't support the interface of its superclass.
Push Down Field [F 329]
Push Down Method [F 322]
Replace Inheritance with Delegation [F 352]
The Refused Bequest smell occurs when a subclass doesn't support the interface of its superclass.
Push Down Field [F 329]
Push Down Method [F 322]
Replace Inheritance with Delegation [F 352]
Sometimes a subclass or method doesn't fit in so well with its family.
Sometimes a subclass or method doesn't fit in so well with its family.
This smell often results from quickly adding a feature to a system without spending enough time simplifying and consolidating the design to best accommodate the feature.
A typical sign of Solution Sprawl is when code for a feature is spread across three or more classes.
A classic smell is a method that seems more interestedin a class other than the one it actually is in.
Extract Method [F 110]
Move Method [F 142]
Move Field [F 146]
A classic smell is a method that seems more interestedin a class other than the one it actually is in.
Extract Method [F 110]
Move Method [F 142]
Move Field [F 146]
For example, if a method answers a query and also sets the value of a field (for later use by another method), the field may very well be a Temporary Field.
Extract Class [F 149]
Introduce Null Object [F 260, K 301]
Extract Class
Introduce Null Object
Methods ought to perform their primary purpose and avoid doing unrelated or secondary behavior. When a method diverges from its primary purpose, it is probably doing too much work.
Methods ought to perform their primary purpose and avoid doing unrelated or secondary behavior. When a method diverges from its primary purpose, it is probably doing too much work.