Refactoring II Dealing with Polymorphism. Switch in Rental Switches on Movie! class Rental … public double getCharge() { double result = 0; switch (getMovie().getPriceCode()){

Slides:



Advertisements
Similar presentations
12-Dec-14 Refactoring IV. Previously discussed bad smells Duplicated code — and other forms of redundancy Long method — use short methods that delegate.
Advertisements

About Me – Frank Xu Education ▫ North Dakota State University  Ph.D. in Software Engineering ▫ Towson University  MS in Computer Science ▫ Southeast.
© 2010 Shawn A. Bohner Software Construction and Evolution - CSSE 375 Even more Bad Smells in Code Shawn & Steve Q1 Shawn & Steve Hint 
Software Testing and Maintenance 1 Today’s Agenda  Course Evaluation  HW 4 Return  HW 5 Correction  Quiz 4 Next Class  Software Refactoring.
Refactoring: Improving the Design of Existing Code © Martin Fowler, Martin Fowler.
Software Construction and Evolution - CSSE 375 Bad Smells in Code Shawn Bohner & Steve Chenoweth.
1 Software Maintenance and Evolution CSSE 575: Session 1, Part 4 Even more Bad Smells in Code Steve Chenoweth Office Phone: (812) Cell: (937)
Refactoring Software Engineering Refactoring Software Engineering 2011 Department of Computer Science Ben-Gurion university Based on slides of: Mira Balaban.
Introduction to Refactoring Excerpted from ‘What is Refactoring?’ by William C. Wake and Refactoring: Improving the Design of Existing Code by Martin Fowler.
George Blank University Lecturer. REFACTORING Improving the Design of Existing Code Supplement to Ian Sommerville, Software Engineering, Chapter 20 Prepared.
CPSC150 Abstract Classes and Interfaces Chapter 10.
25-Jun-15 Refactoring III. General philosophy A refactoring is just a way of rearranging code Refactorings are used to solve problems If there’s no problem,
REFACTORING Improving the Design of Existing Code Atakan Şimşek e
CPSC150 Interfaces Chapter CPSC150 Inheritance Review No different than any other class. Has no access to or information about subclasses class.
Refactoring, continue. Announcements Due today Resubmit HW5 (feedback on HW5 in SVN) HW7 HW8 will be up tonight Due Saturday at 5:59! Quiz 9 Spring 15.
Abstract Classes and Interfaces
Test. A software house decides to develop a DVD renting program. The product manager identifies the following requirements: Every DVD will have a title,
Maintenance Refactoring and Code Smells. Where are we? Over the semester we have talked about Software Engineering. The overall goal of software engineering.
Refactoring: Improving the Design of Existing Code © Martin Fowler, Martin Fowler.
1 Software Maintenance and Evolution CSSE 575: Session 1, Part 3 Bad Smells in Code - 1 Steve Chenoweth Office Phone: (812) Cell: (937)
Refactoring - A disciplined approach to rework for better design.
Refactoring (continued) Source: "Refactoring: Improving the Design of Existing Code", Martin Fowler.
Refactoring1 Improving the structure of existing code.
Refactoring Software Engineering Refactoring Software Engineering 2012 Department of Computer Science Ben-Gurion university Based on slides of: Mira Balaban.
Refactoring Deciding what to make a superclass or interface is difficult. Some of these refactorings are helpful. Some research items include Inheritance.
Agile Software Development Lab Spring 2008 R O O T S 1 Sina Thomas ) XP: Extreme.
Introduction to Refactoring Jim Cooper Falafel Software.
Informatics 122 Software Design II
Refactoring: Improving the Design of Existing Code © Martin Fowler, Martin Fowler.
Incremental Design Why incremental design? Goal of incremental design Tools for incremental design  UML diagrams  Design principles  Design patterns.
Software Engineering CS3003 Lecture 4 Code bad smells and refactoring.
Refactoring and such ● (Side note) Specialization ● Key terms ● Abstraction, state, persistence and association and their relationship to software development.
Refactoring: Code Smells. Admin Notes REGISTER FOR BLACKBOARD Watch blackboard site for updates on class as hurricane season approaches.
Refactoring 2. Admin Blackboard Quiz Acknowledgements Material in this presentation was drawn from Martin Fowler, Refactoring: Improving the Design of.
Module 3. Smells Between Classes Course: Refactoring.
1 Software Maintenance and Evolution CSSE 575: Session 2, Part 1 Refactoring Principles Steve Chenoweth Office Phone: (812) Cell: (937)
Design Patterns.
1 Software Maintenance and Evolution CSSE 575: Session 3, Part 3 Dealing with Generalization Steve Chenoweth Office Phone: (812) Cell: (937)
Refactoring. Announcements HW7 due today, HW8 coming up tomorrow (I’m taking a late day on posting HW8) Grades and feedback for HW0-5 in Homework Server.
Session 6 Comments on Lab 3 & Implications of Inheritance.
CSSE 375 Organizing Data – Part 2 Shawn and Steve Continue the same quiz!
Refactoring1 Improving the structure of existing code.
Pertemuan 12 Refactoring Mata kuliah: T0144 – Advanced Topics in Software Engineering Tahun: 2010.
Quick Review of OOP Constructs Classes:  Data types for structured data and behavior  fields and methods Objects:  Variables whose data type is a class.
CSSE 375 Organizing Data – Part 1 Shawn and Steve Q1.
Software Construction and Evolution - CSSE 375 Dealing with Generalization Steve and Shawn Left – In the 1990 movie “The Freshman,” Matthew Broderick,
Refactoring Improving code after it has been written.
Module 9. Dealing with Generalization Course: Refactoring.
Software Construction Lab 05 Abstraction, Inheritance, and Polymorphism in Java.
Refactoring (1). Software Evolution Cope with change Feature bloat Design decay Code duplications “Pattern time is refactoring time” Make future changes.
A (Very) Simple Example Consolidate duplicate conditional fragments if (isSpecialDeal()) { total = price * 0.95; send (); } else { total = price * 0.98;
Principles and examples
Catalog of Refactoring
Steve Chenoweth Office Phone: (812) Cell: (937)
Inheritance and Polymorphism
Outline A. What is Refactoring? B. Why do we Refactor?
Steve Chenoweth Office Phone: (812) Cell: (937)
Refactoring and Code Smells
Software Construction and Evolution - CSSE 375 Composing Methods
بازآرایی برنامه Code Refactoring
State Design Pattern 1.
Refactoring III 27-Nov-18.
Refactoring.
Reusability 11/29/2018© 2006 ITT Educational Services Inc.
Code Smells 1.
Improving the structure of existing code
Refactoring III 25-Dec-18.
Refactoring.
Refactoring.
Presentation transcript:

Refactoring II Dealing with Polymorphism

Switch in Rental Switches on Movie! class Rental … public double getCharge() { double result = 0; switch (getMovie().getPriceCode()){ case Movie.REGULAR: result += 2; if (getDaysRented()>2) result += (getDaysRented()-2)*1.5; break; case Movie.NEWRELEASE: result += getDaysRented()*3; break; case Movie.CHILDRENS: result += 1.5; if (getDaysRented()-3)*1.5; break; } return result; }

So Put It In Movie class Movie … public double getCharge(int daysRented) { double result = 0; switch (getPriceCode(){ case Movie.REGULAR: result += 2; if (getDaysRented()>2) result += (getDaysRented()-2)*1.5; break; case Movie.NEWRELEASE: result += getDaysRented()*3; break; case Movie.CHILDRENS: result += 1.5; if (getDaysRented()-3)*1.5; break; } return result; }

Remarks This needs data from Rental This needs data from Rental So make it an int parameter daysRented instead of a call getDaysRented() So make it an int parameter daysRented instead of a call getDaysRented() Leave the type of Movie alone for now Leave the type of Movie alone for now  A good candidate for polymorphism  This type of information is more volatile, i.e. subject to change

Change getCharge on Rental class Rental … public double getCharge(){ return _movie.getCharge(_daysRented): }

Similar for getFrequentRenterPoints() Move it from Rental to Movie Move it from Rental to Movie Details not shown (exercise) Details not shown (exercise) class Rental … int getFrequentRenterPoints(){ if((getMovie().getPriceCode()== Movie.NEW_RELEASE) && getDaysRented() > 1) return 2 else return 1;

Problem Movie data used in switch statement Movie data used in switch statement Fix it with inheritance and polymorphism Fix it with inheritance and polymorphism Not possible since child type can change over the movie class’s lifetime Not possible since child type can change over the movie class’s lifetime So, use state/strategy pattern So, use state/strategy pattern

The State Pattern ContextState ConcreteStateAConcreteStateB state.handle() handle() request

State Pattern Behavior is encapsulated in the concrete state objects Behavior is encapsulated in the concrete state objects Context delegates to one of the states Context delegates to one of the states It appears that the state class is changing It appears that the state class is changing  But in reality it is just changing its behavior Change behavior by composing with a different object Change behavior by composing with a different object

State Pattern Context: The class with the internal states Context: The class with the internal states State: The common interface for all concrete states State: The common interface for all concrete states ConcreteStates: deal with requests from the context. Each provides own implementation for the request ConcreteStates: deal with requests from the context. Each provides own implementation for the request When Context changes state so will the concrete state’s behavior When Context changes state so will the concrete state’s behavior

We change

To Replace Type Code with State/Strategy

Step 1: ensure fields accessed by get and set Work on constructor in movie Work on constructor in movie Use Self Encapsulate Field Use Self Encapsulate Field class Movie{ … public Movie (String name, int priceCode){ _title = name; setPriceCode(priceCode);} } Self Encapsulate Field

Why encapsulate data access? If a datum is accessed in a base class, but you want to compute a different value from this in a child. If a datum is accessed in a base class, but you want to compute a different value from this in a child. If this is encapsulated, you can override the accessors to change the value. If this is encapsulated, you can override the accessors to change the value. See Self Encapsulate Field See Self Encapsulate Field

Step 2: Add new classes abstract class Price{ abstract int getPriceCode(); } class ChildrensPrice extends Price{ public int getPriceCode(){return Movie.CHILDRENS;} } class NewReleasePrice extends Price{ public int getPriceCode(){return Movie.NEW_RELEASE;} } Class RegularPrice extends Price{ public int getPriceCode(){return Movie.REGULAR ;} }

Step 3: Change get and set in Movie class Change the accessors Change the accessors class Movie{… private Price _price; public int getPriceCode(){return _price.getPriceCode;} public void setPriceCode(int arg){ switch(arg){ case REGULAR: _price = new RegularPrice(); break; case CHILDRENS: _price = new ChildrensPrice();break; case NEW_RELEASE: _price = new NewReleasePrice(); break; } … }

Step 4 Move getCharge to Price class Price{… public double getCharge(int daysRented){ double result = 0.0; switch (getPriceCode()){ case Movie.REGULAR: result += 2; if (daysRented > 2) result += (daysRented–2)*1.5; break; case Movie.NEW_RELEASE: result += daysRented*3; break; case Movie.CHILDRENS: result += 1.5; if (daysRented>3) result += (daysRented-3)*1.5; break; } return result; } Move Method

Don’t forget you need it in Movie class Movie{… double getCharge(int daysRented){ return _price.getCharge(daysRented); } … }

Get rid of the switch

Do a getCharge() in class RegularPrice class RegularPrice{… double getCharge(int daysRented){ double result = 2.0; if (daysRented>2) result += (daysRented-2)*1.5; return result; } … }

Don’t forget to compile and test Replace Conditional With Polymorphism

Now same for ChildrensPrice class ChildrensPrice{… double getCharge(int daysRented){ double result = 1.5; if (daysRented > 3) result += (daysRented-3)*1.5; return result; } … }

And finally NewReleasePrice class NewReleasePrice{… double getCharge(int daysRented){ return daysRented*3; } … }

Finally get rid of the old getCharge class Price{… abstract double getCharge(int daysRented); … }

Do the same to getFrequentRenterPoints class Movie{… int getFrequentRenterPoints(int daysRented){ return _price.getFrequentRenterPoints(daysRented); … } Class Price{… int getFrequentRenterPoints(int daysRented){ if ((getPriceCode()==Movie.NEW_RELEASE)&& daysRented >1) return 2; else return 1; }

Now Override to NewReleasePrice class NewReleasePrice{… int getFrequentRenterPoints(int daysRented){ return (daysRented>1)?2:1; } And keep a defined method on superclass Price Class Price{… int getFrequentRenterPoints(int daysRented){ return 1; } … }

When do I refactor? “If it stinks change it”

Hence the Name: Code Smelling

Code Smells Duplicated Code Duplicated Code Long Method Long Method Large Class Large Class Long Parameter List Long Parameter List Divergent Change Divergent Change Shotgun Surgery Shotgun Surgery

More Code Smells Feature Envy Feature Envy Data Clumps Data Clumps Primitive Obsession Primitive Obsession Switch Statement Switch Statement Parallel Inheritance Hierarchy Parallel Inheritance Hierarchy Lazy Class Lazy Class

And Even More Speculative Generality Speculative Generality Temporary Field Temporary Field Message Chains Message Chains Middle Man Middle Man Inappropriate Intimacy Inappropriate Intimacy Incomplete Library Class Incomplete Library Class

And Finally Data Class Data Class Comments Comments Refused Bequest Refused Bequest And Many More And Many More