Title: Gregor Gisler-Merz
1BrownBag Session Refactoring
2Content
- Refactoring The big picture
- Definition of refactoring
- A sample
- General rules of thumb
- Refactoring categories according to Fowler
- Where do I find a catalog for common
refactorings? - What indicators are there for a refactoring? Bad
smells (1-4) - When is the right time for a refactoring?
- Bigger refactorings
- Architectural Smells indicators for bigger
refactorings! - References
3Refactoring The big picture
- Everybody can write machine interpretable code
but only good programmers can write code
understandable by human beings! - Emergent Design - versus BigDesignUpfront.
- Refactoring is the main tool with an Emergent
Design approach. - Refactorings can be induced by technological
change (introduction of new technology) or due to
new requirements. - What is the difference between a refactoring and
a redesign? - Refactoring is ongoing over the livecycle
- Redesign and Reengineering tasks are big and
costly and indicate a lack of refactoring during
the product livecycle - Refactorings are necessary especially in agile
environments where the release cycles are short
and the involved parties know that the
requirements change within the cycles.
4Definition of Refactoring
Refactoring is a disciplined technique for
restructuring an existing body of code, altering
its internal structure without changing its
external behavior. Its heart is a series of small
behavior preserving transformations. Each
transformation (called a 'refactoring') does
little, but a sequence of transformations can
produce a significant restructuring. Since each
refactoring is small, it's less likely to go
wrong. The system is also kept fully working
after each small refactoring, reducing the
chances that a system can get seriously broken
during the restructuring.
5A sample
- Situation before refactoring
- No OO design
- Complete logic in Customer.statement()
- Not possible to reuse functionality if adding a
html report - A lot of case and if statements due to the lack
of inheritance and polymorphism - Situation after refactoring
- After a series of refactorings the classes and
its methods are small and good readable - Extensible code
- Things are done in the appropriate objects
Initial Class diagram movie sample
Class diagram movie sample after refactoring
6General rules of thumb
- If you have to add something to your program and
the structure does not allow a plain-vanilla
implementation refactor the code so the change
can be done easily afterwards. - Upfront refactoring ensure that a profound set
of test cases is available. - Refactor the code in small overseeable steps.
Possible bugs can then easily be found. - Kent Beck's metaphor of the two hats
- Add functionality -gt Don't change existing code
just add new features and tests - Refactoring -gt no new functionality, usually no
new tests - Don Roberts If you do a thing for the first
time then do it. If you do something similar the
second time you hesitate but do it once again. If
you do it for the third time refactor it!
7Refactoring categories according to Fowler
- Composing methods Extract Method, Inline Temp,
Replace Temp with Query - Moving Features Between Objects Move Method,
Extract Class, Remove Middle Man - Organizing Data Self Encapsulate Field, Replace
Type Code with Class, Replace Array with Object - Simplifying Conditional Expressions Introduce
Null Object, Decompose Conditional - Making Method Calls Simpler Rename Method, Add
Parameter, Replace Error Code with Exception - Dealing with Generalization Pull Up Field,
Extract Interface, Form Template Method
8Where do I find a catalog for common
refactorings?
- 72 Refactorings are described on Martin Fowler's
Page - Add Parameter
- Change Bidirectional Association to
Unidirectional - Change Reference to Value
- Change Unidirectional Association to
Bidirectional - Change Value to Reference
- Collapse Hierarchy
- Consolidate Conditional Expression
- Consolidate Duplicate Conditional Fragments
- Convert Dynamic to Static Construction by Gerard
M. Davison - Convert Static to Dynamic Construction by Gerard
M. Davison - Decompose Conditional
- Duplicate Observed Data
- Eliminate Inter-Entity Bean Communication (Link
Only) - Encapsulate Collection
- Encapsulate Downcast ..... see in the Internet
for the rest
9What indicators are there for a refactoring? Bad
smells (1)
Feature envy a method seems more interested in a
class other than the one it is actually in e.g.,
invoking lots of get methods -gt can use Move
Method and Extract Method Data clumps groups of
data appearing together in the fields of classes,
parameters to methods, etc. e.g., int x, int y,
int z -gt move these groups into their own class.
One can use Extract Class and Introduce
Parameter Example group (start Date, end Date)
into (aRange RangeDate) Primitive
obsession using the built-in types of the
language too much reluctance to use small objects
for small tasks e.g., zip code string -gt use
objects for individual data values. One can use
Replace Data Value with Object
10Bad smells continued (2)
Switch statements consider using polymorphism
instead e.g., conditionals on type codes defined
in other classes. One can use Extract Method (on
the switch), Move Method, Replace Type Code, and
Replace Conditional with Polymorphism Speculative
generality I think we might need this someday.
e.g., abstract classes without a real purpose
e.g., unused parameters. One can use Collapse
Hierarchy and Remove Parameter Message
chains long chains of navigation to get to an
object e.g., client object talks to server object
that delegates to another object that the client
object must also know about. One can use Hide
Delegate
11Bad smells continued (3)
Middle man a class that delegates many methods
to another class can use Remove Middle Man or
Replace Delegation with Inheritance. Attention
could also be a legitimate adapter Don t stand so
close two classes that depend too much on each
other, with lots of bidirectional communication.
Separate the two classes. One can use Move
Method, Move Field, and Extract Class (factor out
commonality) Alternative classes with different
interfaces methods that do the same thing but
have different signatures e.g., put() versus
add(). One can use Rename Method
12Bad smells continued (4)
Refused bequest when a subclass inherits
something that is not needed when a superclass
does not contain truly common state/behaviour.
One can use Push Down Method and Push Down Field
or one can use Replace Inheritance with
Delegation (e.g., Square versus
Rectangle) Comments often deodorant for bad
smelling code. Refactor code so that the comment
becomes extraneous
13When is the right time for a refactoring?
- Whenever you see something that isn't solved
adequately - Don Roberts "Rule of three" lt-gt "Once and only
once principle" - Before adding new functionality
- While fixing errors
- During and after Code Reviews
- If in doubt discuss it with your peers!
14Bigger refactorings
- Big refactorings denote larger refactoring tasks
like changing a large inheritance hierarchy - Reasons implying bigger refactorings
- Developer missed smaller refactorings
(cumulation) - Slow creep in of architectural smells
- New features technology changes (would be low
on good software) - Differentiation between
- Elementary Refactoring -gt Fowler 99
- Big Refactorings -gt Rule of thumb Effort more
than one day, affect the whole project team and
cannot be implemented by elementary safe
refactorings. There are additional unsafe
modifications needed
15Architectural Smells indicators for bigger
refactorings!
- Static relation usage (dynamic/runtime relation
usage) - Unused classes
- Tree like usage
- Static cycles
- Smells in the inheritance hierarchy
- InstanceOf calls and missing usage of
polymorphism - List like inheritance hierarchies Speculative
generality smell - Subclasses redefine no methods
- Parallel inheritance hierarchies
- Inheritance hierarchies that are too deep
- Smells in packages
- Unused packages, cycles, packages too small,
packages too big - No appropriate hierarchy (deep versus shallow)
16Architectural Smells (2)
- Smell in subsystems
- No subsystems, too little subsystems, too large
subsystems (more than 100 packages) - Too many subsystems
- By-pass subsystem API
- Cycles in subsystems
- Smells in layers
- No layering
- Upward references (cycles between the layers)
- Breach of layers
- Too many layers
- References between vertical separated layers
17References
Fowlers refactoring homepage http//www.refactori
ng.com/ Refactorings to patterns
http//industriallogic.com/xp/refactoring/ Bad
smells homepage http//c2.com/cgi/wiki?CodeSmell
Movie refactoring sample http//www.cs.umd.edu/cl
ass/fall2003/cmsc433/mwh/lectures/Refactoring-Exam
ple.pdf Refactoring M. Fowler et al.
Addison-Wesley, 1999