Software Craftsmanship
Code Smells
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”
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
Code Smells
• Lost Intent
• Inefficient Name
• Duplicated Code
• Deodorant Comment
• Long Method
• Large Class
• Lazy Class
More…
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.
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.
Lost Intent
Inefficient Name
Where The Streets Have No Name
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.
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
Duplicated Code
Deodorant Comment
Comments often are used as a deodorant.
— Refactoring [page 87], Martin Fowler and Kent Beck
Deodorant Comment
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.
Long Method
A long method is too much to digest
Long Method
Large Class
Take on too many responsibilities
Large Class
WebServicesProviderContoller
• performValidationCB()
• executeBusinessProcessCB()
Lazy Class
A lazy class isn't doing enough to justify its existence.
Lazy Class
Lazy Class
Employee constructor
.
Passing Jobs in
Employee
constructor.
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.
Oddball Solution
Primitive Obsession
Primitive Obsession exists when code solves a problem using a tool that's too simplistic.
Primitive Obsession
Switch Statement
Most times you see a switch statement you should consider polymorphism.
— Refactoring, Martin Fowler and Kent Beck (page 82).
Switch Statement
Move each leg of the conditional to an overriding method in a subclass. Make the original
method abstract.
Switch Statement
• Not every occurrence of a switch statement
(or if...else if...else if... statements) should be
replaced with a polymorphic solution.
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).
Speculative Generality
Long Parameter List
Methods that take too many parameters produce client code that is awkward and
difficult to work with.
Long Parameter List
user = userManager.create(USER_NAME, group, USER_NAME, “test",
USER_NAME, LANGUAGE, false, false, new Date(), "blah", new Date());
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.
Conditional Complexity
Combinatorial Explosion
When new combinations of data or behavior further bloat an already bloated design, you've got
a Combinatorial Explosion smell.
Combinatorial Explosion
Alternative Classes With Different
Interfaces
This subtle smell results when differences in the interfaces of similar classes leads to
duplicated code.
Alternative Classes With Different
Interfaces
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
Inappropriate Intimacy
Indecent Exposure
We don't normally expose wires inside a wall or ceiling.
Indecent Exposure
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
Refused Bequest
Black Sheep
Black Sheep
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.
Solution Sprawl
Feature Envy
Feature Envy
Temporary Field
An object's field (a.k.a. instance variable) should have meaning during the full lifetime
of the object.
Temporary Field
Side Effect
Side Effect
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

Code Smells

Editor's Notes

  • #8 Extract Method
  • #9 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.
  • #10 Refactor just select method or variable name and Alt+Shift+R
  • #12 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
  • #13 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.
  • #14 Rename Method Extract Method Introduce Assertion
  • #17 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
  • #18 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
  • #19 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
  • #20 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.
  • #21 Collapse Hierarchy Inline Class Inline Singleton
  • #22 Collapse Hierarchy Inline Class Inline Singleton
  • #24 If a minority solution is better than a majority solution,  it ought to become the standard, consistent solution. Unify Interfaces with Adapter
  • #25 Code that exhibits primitive obsession tends to rely on primitives (like integers or strings) low-level methods classes that don't easily solve problems
  • #26 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
  • #29 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
  • #31 Collapse Hierarchy Rename Method Remove Parameter Inline Class
  • #33 Primitive Obsession Replace Parameter with Method Introduce Parameter Object Preserve Whole Object
  • #34 Introduce Null Object Move Embellishment to Decorator Replace Conditional Logic with Strategy Replace State-Altering Conditionals with State
  • #35 Introduce Null Object Move Embellishment to Decorator Replace Conditional Logic with Strategy Replace State-Altering Conditionals with State
  • #37 Replace Specialized Selection with Specification Replace Implicit Language with Interpreter
  • #38 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.
  • #39 Unify Interfaces with Adapter Rename Method Move Method
  • #41 Move Method Move Field Change Bidirectional Association to Unidirectional Association Extract Class Hide Delegate Replace Inheritance with Delegation
  • #42 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
  • #43 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
  • #44 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]
  • #45 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]
  • #46 Sometimes a subclass or method doesn't fit in so well with its family.
  • #47 Sometimes a subclass or method doesn't fit in so well with its family.
  • #48 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.
  • #50 A classic smell is a method that seems more interested in a class other than the one it actually is in.  Extract Method [F 110] Move Method [F 142] Move Field [F 146]
  • #51 A classic smell is a method that seems more interested in a class other than the one it actually is in.  Extract Method [F 110] Move Method [F 142] Move Field [F 146]
  • #52 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]
  • #53 Extract Class Introduce Null Object
  • #54 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.
  • #55 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.