Refactoring MSO 08/09, WP. What is refactoring ? Refactoring is the act of transforming the...

24
Refactoring MSO 08/09, WP

Transcript of Refactoring MSO 08/09, WP. What is refactoring ? Refactoring is the act of transforming the...

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

Refactoring

MSO 08/09, WP

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

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

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

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.com

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

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 http://en.wikipedia.org/wiki/Anti-pattern

Buy the books “Refactoring” and “Antipatterns” as reference for you when you latter develop your software.

4

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

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

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

"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!=nullassert c!=null && s!=null less error prone

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

"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}

double total_weeklycost() { double c = 0 ; for (Subscription s : subscriptions) c += s.service.price() ; return c/52.0}

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

"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}

double total_weeklycost() { double c = 0 ; for (Subscription s : subscriptions) c += s.service.price() ; return c/52.0}

improve readability

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

"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()

VIPVIP

Solution 1

You have to rewrite print in VIP, probably with lots of code duplication.

Customer

print()total_weeklycost()

Customer

print()total_weeklycost()

VIPVIP

Solution 2

extract method

improve modularity & extensibility

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

"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

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

"Hide delegate"

11

class Customer {

double total_weeklycost() { double c = 0 ; for (Subscription s : subscriptions) c += s.service.price() ; return c/52.0 }

CustomerCustomer

SubscriptionSubscription

Serviceprice()Serviceprice()

0..*

CustomerCustomer

Subscriptionprice()Subscriptionprice()

Serviceprice()Serviceprice()

0..*

hide delegate

s.price()s.price()

reduce coupling

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

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

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

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

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

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

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

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()

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

Bad smell : primitive obsession You use a primitive type for representing a 'concept'.

Example:

16

Customer

name : Stringemail : String

Customer

name : Stringemail : String

Then at some point you need a method to validate an email. Where to put this method?

Customer

name : String

Customer

name : String

Email

validate()

Email

validate()

We'll do "replace data with object" refactoring:

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

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 ;}

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

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.

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

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

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

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

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

“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

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

Blob, example

22

Library

fineRate: floatborrowings: ...

doInventory()checkOut(Book, Client)checkIn(Book)add(Book)delete(Book)printCatalog()searchCatalog(String): Bookedit(Book)print(Book)add(Client)booksBorrowed(Client): Set...currentBorrower(Book): ClientprintCard(Client)calculateFine(Client): float

Bookauthor: Stringtitle: Stringid: String

Clientname: Stringaddressid: String

0..*

0..*

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

“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<Client,List<bool>>+ clients : Set<Client>+ books : Set<Book>

doInventory()checkOut(Book, Client)checkIn(Book)add(Book)delete(Book)printCatalog()searchCatalog(String): Bookedit(Book)print(Book)add(Client)booksBorrowed(Client): Set<Book>currentBorrower(Book): ClientprintCard(Client)calculateFine(Client): float

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

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