290 likes | 506 Views
“Blink-factoring”: Software engineering meets pop psychology. Presented by Jamie Hohman EECS 816: Object-Oriented Software Development April 22, 2008. Contents. Defining Refactoring Defining Blink Identifying types of “smelly” code Learning refactoring solutions for this code
E N D
“Blink-factoring”: Software engineering meets pop psychology Presented by Jamie Hohman EECS 816: Object-Oriented Software Development April 22, 2008
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
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
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
void funcA() { … x = sqr(y); … } void funcB() { … x = sqr(y); … } int sqr(int x) { return x * x; } Duplicate Code 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
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
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
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 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
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
When to refactor? • At any time, but only in short bursts as needed • 3 strikes, you refactor • Write it. Good job! • Second time, read and wince at duplication or poor structure • Third time, get fed up and refactor • When modifying any existing code by adding functionality, fixing bugs, or during code reviews
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
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
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
Large Class What smells in here? See Example Extract Class or Extract Subclass
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
How to test? • Critical since functionality must remain the same • Development time in descending order: • Debugging • Analysis & design • 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
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 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
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
How are tools useful? “Can we fix it? Yes, we can!” • 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
Demonstration • Refactoring in Visual Studio 2005 with Visual Assist X (http://www.wholetomato.com)
void funcA(acctObj acct) { int payment; payment = acct.getPayment(); // More stuff with // payment } Class acctObj { … int getPayment(); //new! … } Feature Envy 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) { animal.speak(); } Switch Statements 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
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
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
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
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
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
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.