“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 acceptedThe Tipping Point
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 structure 3. 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
14 What smells in here? Extract Class or Extract Subclass See Example Large Class
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. Debugging 2. Analysis & design 3. 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 (
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
28 Questions
29 Bibliography Demeyer, S., “Refactor conditionals into polymorphism: what’s the performance cost of introducing virtual calls?”, IEEE International Conference on Software Maintenance, Pgs , 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 , 2005, ACM.