Post on 21-Dec-2015
“Blink-factoring”:
Software engineering meets pop psychology
Presented by Jamie Hohman
EECS 816: Object-Oriented Software Development
April 22, 2008
2
Contents Defining Refactoring Defining Blink
Identifying types of “smelly” code Learning refactoring solutions for this code
Deciding when and when not to refactor Understanding the role of testing Learning about tools available for
refactoring Breaking down examples throughout
3
What is Refactoring? Is either a noun (the actual code changes) or
a verb (the act of applying the changes) Represents a structured and tested
method of reversing software decay Makes no observable changes in functionality Helps future developers find bugs and add
new functionality faster Ensures code says things once and only once
4
Why are developers wary? Don’t know how or when
Automated tools can detect “fishy” areas No short term benefits
Refactoring results in bugs found in common code, fixed once, and results in smaller code
Constitutes overhead Pays for itself in more maintainable code
Risk of newly introduced errors Good practices help eliminate these Automated tools help reduce the manual, error-prone
tasks Needs to reach The Tipping Point in an
organization to be fully accepted
5
What smells in here?void funcA()
{
int x, y = 2;
x = y * y;
printf(“%d”, x);
}
void funcB()
{
int x, y = 4;
x = y * y;
funcC(x);
}
Extract Method
void funcA()
{
…
x = sqr(y);
…
}
void funcB()
{
…
x = sqr(y);
…
}
int sqr(int x)
{
return x * x;
}
Duplicate Code
6
Contents Defining Refactoring Defining Blink
Identifying types of “smelly” code Learning refactoring solutions for this code
Deciding when and when not to refactor Understanding the role of testing Learning about tools available for
refactoring Breaking down examples throughout
7
What is Blink? Pop psychology book by Malcolm Gladwell, a
staff writer for The New Yorker Subtitle is “The Power of Thinking Without
Thinking” Subconscious is better at realizing
something quickly than conscious is at realizing it slowly
This explains how we identify “smelly code” Amateurs have a hard time explaining it;
experts do not
8
What smells in here?void funcA(){int temp1, temp2, temp3;
// Do stuff with temp1……
// Do stuff with temp2// and temp 3……
//Do lots more stuff}
Extract Method
void DoStuff1()
{
int temp;
// Do stuff here
}
void DoStuff2and3()
{
int temp, temp2;
// Do more stuff
}
int DoLotsMore(int x)
{
// Encapsuplate more // changes here
}
Long Method
9
Contents Defining Refactoring Defining Blink
Identifying types of “smelly” code Learning refactoring solutions for this code
Deciding when and when not to refactor Understanding the role of testing Learning about tools available for
refactoring Breaking down examples throughout
10
When to refactor? At any time, but only in short bursts as
needed 3 strikes, you refactor
1. Write it. Good job!2. Second time, read and wince at
duplication or poor structure3. Third time, get fed up and refactor
When modifying any existing code by adding functionality, fixing bugs, or during code reviews
11
When not to refactor? Database support often means being
tied to a schema Either abstract this away or don’t refactor
Public interfaces should not change, published interfaces cannot change Make the old function call the new one
Trying to fix inherently flawed design When code is beyond help When approaching a deadline
12
Design and Performance Refactoring complements upfront design
Software is malleable so do it simply first and then refactor in flexibility as needed
Find a reasonable solution, not the solution Most of the time, the more complicated, flexible solution
is overkill Performance suffers from refactoring, right?
Not necessarily; according to Demeyer, modern compiler optimizations make virtual functions equal to branching
Doesn’t matter most of the time Can concentrate on optimization in small, well-defined
areas Binary refactoring (Tilevich, Smaragadakis) – WHAT?!?! –
is exclusively for performance
13
Binary refactoring: a study in contradictions “Premature optimization is the root of all
evil.” – C.A.R. Hoare Money, Microsoft and MU are finally off the
hook Not to increase performance, but to not
force source code changes to increase performance
Example 1: Objects that make sense to be stored in a database as a whole but only parts need to be transmitted
Example 2: Replace virtual function call with static or inline function call
15
Contents Defining Refactoring Defining Blink
Identifying types of “smelly” code Learning refactoring solutions for this code
Deciding when and when not to refactor Understanding the role of testing Learning about tools available for
refactoring Breaking down examples throughout
16
How to test? Critical since functionality must remain the
same Development time in descending order:
1. Debugging2. Analysis & design3. Writing code
JUnit helps organize testing code in classes and run suites of tests
Only for unit testing Don’t try to get all the bugs; build tests that
are easy to run and are designed to get most of the bugs
17
What smells in here?void funcA(
int param1,int param2,char* param3,float param4,float param5,void* param6)
{int temp1, temp2,
temp3;
// Do stuff with all// this data}
Introduce Parameter Object
class newObj
{
public:
int getParam1();
int getParam2();
char* getParam3();
float getParam4();
float getParam5();
void* getParam6();
}
void funcA(newObj obj)
{
int temp1, temp2, temp3;
// Do stuff with all
// this data
}
Long Parameter List
18
Contents Defining Refactoring Defining Blink
Identifying types of “smelly” code Learning refactoring solutions for this code
Deciding when and when not to refactor Understanding the role of testing Learning about tools available for
refactoring Breaking down examples throughout
19
How are tools useful?
Refactoring Browser was originally designed for Smalltalk
Requires a program database and parse tree
Must also be accurate, speedy, undo-able, and integrated with other tools
“Can we fix it? Yes, we can!”
20
Demonstration
Refactoring in Visual Studio 2005 with Visual Assist X (http://www.wholetomato.com)
21
What smells in here?void funcA(acctObj acct){int payment;
payment = acct.getBalance();
payment /= acct.getTerm();
payment *= acct.getRate();
// More stuff with// payment}
Extract Method -> Move Method
void funcA(acctObj acct)
{
int payment;
payment = acct.getPayment();
// More stuff with
// payment
}
Class acctObj
{
…
int getPayment(); //new!
…
}
Feature Envy
22
What smells in here?void funcA(acctObj acct)
{
switch (getAnimalType()){
case DOG:
bark();
break;
case COW:
moo();
break;
// etc.
}
}
Extract Method -> Move Method -> Replace Type Code with Subclass -> Replace Conditional with Polymorphism
void funcA(acctObj acct)
{
animal.speak();
}
Switch Statements
23
More “smelly” code Divergent Change – any change to handle
a variation should change a single class and everything within that class Extract Class
Shotgun Surgery – opposite of above; to accommodate a change, must make lots of small changes to different classes Move Method, Move Field, Inline Class
24
Some more “smelly” code Data Clumps – data (like children) enjoy
hanging around in groups; move these to a new class Extract Class, Introduce Parameter Object
Primitive Obsession – group related primitives in a function into a new class Replace Data Value with Object, Replace
Type Code with Class Parallel Inheritance Hierarchies – special
case of shotgun surgery where subclass of one class requires subclass of another class every time
25
Even more “smelly” code Lazy Class – classes (like teenagers)
enjoy doing nothing if given the chance; must pull its own weight Collapse Hierarchy, Inline Class
Speculative Generality – somebody over-engineered or over-designed -> too complicated Collapse Hierarchy, Inline Class, Remove
Parameter Temporary Field – a member variable is
used in some cases but not others Extract Class, Introduce Null Object
26
The last of the “smelly” code
Message Chains – object asks another object, which asks another object, …
Hide Delegate, Extract Method, Move Method Middle Man – half of an object’s methods call
other objects Remove Middle Man, Inline Method, Replace
Delegation with Inheritance Inappropriate Intimacy – spend too much time
delving into private parts Move Method, Move Field, Change Bidirectional
Association to Unidirectional, Extract Class, Replace Inheritance with Delegation
Alternative Classes with Different Interfaces, Incomplete Library Class, Data Class, Refused Bequest
27
Watch out for comments (huh?!?)
Comments are often used as deodorant on this smelly code
Refactoring eliminates the smelly code so that the comments are superfluous
Replace each commented block of code with a new method using Extract Method and Introduce Assertion
29
Bibliography Demeyer, S., “Refactor conditionals into
polymorphism: what’s the performance cost of introducing virtual calls?”, IEEE International Conference on Software Maintenance, Pgs. 627-630, 2005.
Fowler, M., Refactoring: Improving the Design of Existing Code, Addison-Wesley, 1999, First Edition.
Gladwell, M., Blink: The Power of Thinking Without Thinking, Back Bay Books, 2005, First Edition.
Tilevich, E., Smaragdakis, Y., “Binary refactoring: improving code behind the scenes”, International Conference on Software Engineering, Pgs. 264-273, 2005, ACM.