Software Refactoring and
Code Smells
Malik Nabeel Ahmed Awan, PhD
Why do good developers write bad software?
Requirements change over time, making it hard to update your code
(leading to less optimal designs)
Time and money cause you to take shortcuts
You learn a better way to do something (the second time you paint a
room, it’s always better than the first because you learned during the
first time!)
Two questions:
1.How do we fix our software?
2.How do we know our software is “bad”… when it works fine!
Coming up: Refactoring
Refactoring
Definition: Refactoring modifies software to improve its readability,
maintainability, and extensibility without changing what it does.
External behavior does NOT change
Internal structure is improved
This is sometimes called
“improving the design after it has been written”
Coming up: Refactoring
Refactoring
The goal of refactoring is NOT to add new functionality
The goal is refactoring is to make code easier to maintain in the
future
The main purpose of refactoring is to fight technical debt.
It transforms a mess into clean code and simple design.
Clean Code
Obvious for other programmers.
Does not contain duplication.
Have minimal classes and moving objects.
Passes all tests.
Easier and cheaper to maintain.
But Refactoring is Dangerous!
Although refactoring helps to reduce bugs, it can also introduce new
bugs into the code
Manager’s point of view
Ifmy programmers spend time “cleaning up the code” then that’s less time
implementing required functionality (and my schedule is slipping as it is!)
To address these concerns
Refactoring needs to be systematic, incremental, and safe
6
Refactoring is Useful Too
The idea behind refactoring is to acknowledge that it will be difficult
to get a design right the first time and, as a program’s requirements
change, the design may need to change
refactoring
provides techniques for evolving the design in small
incremental steps
Benefits
Oftencode size is reduced after refactoring
Confusing structures are transformed into simpler structures
◼ which are easier to maintain and understand
7
Principles in Refactoring
Fowler’s definition
Refactoring (noun)
◼ a changemade to the internal structure of software to make it easier to
understand and cheaper to modify without changing its observable behavior
Refactoring (verb)
◼ torestructure software by applying a series of refactorings without changing its
observable behavior
8
Principles, continued
The purpose of refactoring is
tomake software easier to understand and modify
no functionality is added, but the code is cleaned up, made easier to
understand and modify, and sometimes is reduced in size
Contrast this with performance optimization
functionality
is not changed, only internal structure;
however, performance optimizations often involve making code harder to
understand (but faster!)
9
Principles, continued
How do you make refactoring safe?
First, use refactoring “patterns”
◼ Fowler’s book (and Website) assigns “names” to refactorings in the same way that
the GoF’s book assigned names to patterns
Second, test constantly!
◼ This ties into the agile design paradigm
◼ you write tests before you write the code
◼ after you refactor, you run the tests and check that they all pass
◼ if a test fails, the refactoring broke something, but you know about it right away and
can fix the problem before you move on
10
Why Should you Refactor?
Refactoring improves the design of software
without refactoring, a design will “decay” as people make changes to a software
system
Refactoring makes software easier to understand
because structure is improved, duplicated code is eliminated, etc.
Refactoring helps you find bugs
Refactoring promotes a deep understanding of the code at hand, and this
understanding aids the programmer in finding bugs and anticipating potential
bugs
Refactoring helps you program faster
because a good design enables progress
11
When Should you Refactor?
The Rule of Three
Three “strikes” and you refactor
◼ refers to duplication of code
Refactor when you add functionality
do it before you add the new function to make it easier to add the function
or do it after to clean up the code after the function is added
Refactor when you need to fix a bug
Refactor as you do a code review
12
Problems with Refactoring
Databases
Business applications are often tightly coupled to underlying databases
◼ code is easy to change; databases are not
Changing interfaces (!!)
Some refactorings require that interfaces be changed
◼ if you own all the calling code, no problem
◼ if not, the interface is “published” and can’t change
13
How do I identify code to refactor?
Martin Fowler uses “code smells” to identify when to refactor.
Code smells are bad things done in code, somewhat like bad patterns
in code
Many people have tied code smells to the specific refactorings to fix
the smell
Coming up: Code Smells
Code Smells
• Bloaters are code, methods and classes that have increased to such gargantuan
Bloaters proportions that they are hard to work with.
Object-orientation • No implementing object-oriented programming principles as they should be.
abusers
Change Preventors • Same code over multiple places make code hard to fix.
• A pointless and unneeded code whose absence would make the code cleaner,
Dispensable more efficient and easier to understand.
• All the smells in this group contribute to excessive coupling between classes or
Couplers show what happens if coupling is replaced by excessive delegation.
Bloaters
Long Methods
A method longer than ten lines should make you start asking questions.
Large Classes
A class contains many fields/methods/lines of code.
Primitive Obsession
Use of primitives instead of small objects for simple tasks (such as
currency, ranges, special strings for phone numbers, etc.)
Use of constants for coding information (such as a constant
ADMIN_ROLE=1for referring to users with administrator rights.)
Use of string constants as field names for use in data arrays.
Bloaters
Long Parameters Lists
More than three or four parameters for a method.
Data Clumps
Sometimes different parts of the code contain identical groups of variables
(such as parameters for connecting to a database). These clumps should be
turned into their own classes.
Object-Oriented Abusers
Switch Statement
Complex switch or multiple if statements.
Temporary Fields
Temporary fields get their values only under certain circumstances. Outside of
these circumstances, they’re empty.
Refused Bequests
If a subclass uses only some of the methods and properties inherited from its
parents, the hierarchy is off-kilter. The unneeded methods may simply go unused
or be redefined and give off exceptions.
Alternative Classes with Different Interfaces
Two classes perform identical functions but have different method names.
Change Preventers
Divergent Changes
You find yourself having to change many unrelated methods when you make
changes to a class. For example, when adding a new product type, you must
change the methods for finding, displaying, and ordering products.
Shotgun Surgery
Making any modifications requires that you make many small changes to many
different classes.
Parallel Inheritance Hierarchies
Whenever you create a subclass for a class, you find yourself needing to create a
subclass for another class.
Dispensable
Comments
A method is filled with explanatory comments.
Duplicate Code
Two code fragments look almost identical.
Lazy Class
If a class doesn’t do enough to earn your attention, it should be deleted.
Data Class
A data class refers to a class that contains only fields and crude methods for accessing
them (getters and setters).
Dead Code
A variable, parameter, field, method or class is no longer used (usually because it’s
obsolete).
Speculative Generality
There’s an unused class, method, field or parameter.
Couplers
Feature Envy
A method accesses the data of another object more than its own data.
Inappropriate Intimacy
One class uses the internal fields and methods of another class.
Message Chain
In code you see a series of calls resembling
Middleman
If
a class performs only one action, delegating work to another class, why
does it exist at all?
THANK YOU