Presentation is loading. Please wait.

Presentation is loading. Please wait.

Refactoring MSO 08/09, WP. What is refactoring ?  Refactoring is the act of transforming the internal structure of a program while preserving its observable.

Similar presentations


Presentation on theme: "Refactoring MSO 08/09, WP. What is refactoring ?  Refactoring is the act of transforming the internal structure of a program while preserving its observable."— Presentation transcript:

1 Refactoring MSO 08/09, WP

2 What is refactoring ?  Refactoring is the act of transforming the internal structure of a program while preserving its observable behavior.  The main motivation is to improve the 'quality' of your program:  improve its readability  make it less error prone  improve modularity and extensibility 2

3 Systematic refactoring 3  Idea: rely on a set of small-step changes that are easy to understand and evidently correct. Do refactoring as a series of such steps.  Fowler’s book (1999) contains a catalogue of refactoring steps.  See also www.refactoring.comwww.refactoring.com

4 Objective & plan  To make you aware of these concepts from software development: Refactoring, bad smell, antipattern  We’ll discuss some examples.  Consult your Web-resource for the full catallogues:  www.refactoring.com www.refactoring.com  http://en.wikipedia.org/wiki/Anti-pattern http://en.wikipedia.org/wiki/Anti-pattern  Buy the books “Refactoring” and “Antipatterns” as reference for you when you latter develop your software. 4

5 Systematic refactoring  Automated support by IDEs, e.g. in Eclipse. for a small subset of Fowler's refactoring.  No formal proof of the correctness (on-going research).  Current practice:  Relies on common sense.  Prepare a good set of tests; between the steps, do testing to check that you indeed don't change the program functionalities, nor introduce new bugs. 5

6 "introduce assertion" 6 class ApplicationLogic{... addSubscription(Customer c, Service s) { // c and s should not be null Subscription scr = new Subscription(c,s) ; c.subscriptions.add(scr) ; subscriptions.add(scr) ; } assert c!=null && s!=null less error prone

7 "extract method" 7 class Customer {... print() { println("name " + name) ; // calculate total weekly cost double c = 0 ; for (Subscription s : subscriptions) c += s.service.price() ; c = c/52.0 ; println("Weekly cost = " + (int) c ) } double total_weeklycost() { double c = 0 ; for (Subscription s : subscriptions) c += s.service.price() ; return c/52.0 }

8 "extract method" 8 class Customer {... print() { println("name " + name) double c = total_weeklycost() println("Weekly cost = " + (int) c ) } double total_weeklycost() { double c = 0 ; for (Subscription s : subscriptions) c += s.service.price() ; return c/52.0 } improve readability

9 "extract method"  Consider again the original Customer class.  We want a new feature: VIP customers. They get discounts  influence their price  you have to adapt "print" too. 9 Customer print() Customer print() VIP Solution 1 You have to rewrite print in VIP, probably with lots of code duplication. Customer print() total_weeklycost() Customer print() total_weeklycost() VIP Solution 2 extract method improve modularity & extensibility

10 "move method" 10 class Service { boolean isBigSpender(Customer c) { if (c.total_weeklycost() < 1000) return false for (Subscription scr : c.subscriptions) if (scr.service == this) return true return false } class Customer { boolean isBigSpender(Service s) { if (total_weeklycost() < 1000) return false for (Subscription scr : subscriptions) if (scr.service == s) return true return false } class Customer { boolean isBigSpender(Service s) { if (total_weeklycost() < 1000) return false for (Subscription scr : subscriptions) if (scr.service == s) return true return false } class Service { boolean isBigSpender(Customer c) { return c.isBigSpender(this) } class Service { boolean isBigSpender(Customer c) { return c.isBigSpender(this) } reduce coupling  less error prone

11 "Hide delegate" 11 class Customer { double total_weeklycost() { double c = 0 ; for (Subscription s : subscriptions) c += s.service.price() ; return c/52.0 } Customer Subscription Service price() Service price() 0..* Customer Subscription price() Subscription price() Service price() Service price() 0..* hide delegate s.price() reduce coupling

12 However...  Refactoring tends to add indirection  (small) run-time overhead  a "logic" that was centralized can become scattered  Refactoring may change a class "interface"  E.g. "move field", "remove parameter"  Problem if you have a client that is beyond your reach.  Don't publish your packages too early? 12

13 Bad smells  ‘If it stinks, change it’ (user manual for babies)  A 'bad smell' describes a set of characteristics indicating that refactoring may be wise.  Fowler has a list of smells in his book. See also the list in MSO website. 13

14 Bad smells  (Substantial) duplication of code  Overly long method  Overly large class  Too many attributes in a class  Method with lots of parameters ... etc. See the list in MSO website. We'll discuss some selected examples. 14

15 Bad smell : shotgun surgery  You need to change a feature but are forced to do this in many places. 15 Customer print() Customer print() Service print() Service print() E.g. you want to change how the Company logo is printed, but is forced to change the "print" method of both Customer and Service to do this. Let's try refactoring : 1."extract method" 2."extract superclass" 3."replace inheritance with delegation" CompanyLogo printlogo() CompanyLogo printlogo()

16 Bad smell : primitive obsession  You use a primitive type for representing a 'concept'. Example: 16 Customer name : String email : String Then at some point you need a method to validate an email. Where to put this method? Customer name : String Email validate() We'll do "replace data with object" refactoring:

17 Bad smell: switch statement  This is not to say that "switch" is bad; but consider this example: 17 switch (customer.code) { VIP : registrationfee = 2000 ; break ; PREMIUM : registrationfee = 1500 ; break ; default : registrationfee = 1000 ; }... switch (customer.code) { VIP : discount =.3 ; break ; PREMIUM : discount = 0.1 ; break ; default : discount = 0 ; }

18 Anti patterns 18  Help! Another caltalogue of “nasties” ??  Anti pattern:  pattern that initially appears beneficial, but ultimately produces more problems than benefits.  it has a (refactoring) solution.  Brown et al: “AntiPatterns: Refactoring Software, Architectures, and Projects in Crisis”, 1998.

19 Antipattern at different levels  “paralysis by analysis” (management level) Let’s allocate lots of effrot to do good design! But you over do it  blocking the implementation phase. Or ending up writing design documents with unproportional add-value.  Solution: turn the process to be more agile. 19 A single big cycle of design-implement-test Several smaller cycles of design-implement-test

20 Antipattern at different levels  “Softwarebloat” (design level) You want to reach out to a wide spectrum of users. To make them all happy you add LOTS of features.  Big software  expensive to maintain.  Use lots of resources, and slow.  Solution: make features to be plugable. 20

21 “Blob” antipattern (code level)  Lots of functionalities are coded into one class, e.g. because:  that’s the simplest way of coding them at the moment  the programmer lacks OO experience  Problem: long term modularity and extensibility  Solution: Fowler’s refactoring 21

22 Blob, example 22 Library fineRate: float borrowings:... doInventory() checkOut(Book, Client) checkIn(Book) add(Book) delete(Book) printCatalog() searchCatalog(String): Book edit(Book) print(Book) add(Client) booksBorrowed(Client): Set... currentBorrower(Book): Client printCard(Client) calculateFine(Client): float Book author: String title: String id: String Client name: String address id: String 0..*

23 “Object Orgy” antipattern (code level)  Free access to an object’s (of class C) internal state, e.g. because: Convenient for other classes that use C.  Problem: As your software grows, the logic becomes increasingly defragmented  hard to maintain.  Solution: refactor. 23 Library + fineRate: float + borrowings: Map > + clients : Set + books : Set doInventory() checkOut(Book, Client) checkIn(Book) add(Book) delete(Book) printCatalog() searchCatalog(String): Book edit(Book) print(Book) add(Client) booksBorrowed(Client): Set currentBorrower(Book): Client printCard(Client) calculateFine(Client): float

24 Final note on refactoring  Use smartly  don’t do it obsessively  blocking the actual work.  Plan ahead  pre-allocate resources for refactoring  When your software starts to smell really bad, you’re in urgent need to refactor.  Hey, I have pre-allocated resources, Yay!  When not to refactor  If the code is still unstable  Shortly before a hard deadline  If it is more efficient to just redo from scratch 24


Download ppt "Refactoring MSO 08/09, WP. What is refactoring ?  Refactoring is the act of transforming the internal structure of a program while preserving its observable."

Similar presentations


Ads by Google