SlideShare a Scribd company logo
Refactoring
Source :
Refactoring
Improving the Design of Existing Code
by Martin Fowler
(with Kent Beck, John Brant, William Opdyke, and Don Roberts)
Prepared By-
Tausun Akhtary (Suptee)
Software Analyst
IPVision Canada Inc
Why Refactoring
● Improved Design
● Increased Readability.
● Less time consumption in adding/changing features.
When Refactoring is needed?
According to grandma,
If it stinks, change it.
—Grandma Beck, discussing child-rearing philosophy
We change code,
When code smells..
When Refactoring is needed?(Contd.)
● Duplicated Code
● Long Method
● Large Class
● Long Parameter List
● Divergent Change
● Parallel Inheritance Hierarchies
● Lazy Class
● Shotgun Surgery
● Feature Envy
● Data Clumps
● Primitive Obsession
● Switch Statements
When Refactoring is needed?(Contd.)
● Alternative Classes with
Different Interfaces
● Incomplete Library Class
● Data Class
● Refused Bequest
● Comments
● Speculative Generality
● Temporary Field
● Message Chains
● Middle Man
● Inappropriate Intimacy
How ?
● Composing Methods
● Moving Features Between Objects
● Simplifying Conditional Expressions
● Making Method Calls Simpler
● Organizing Data
● Dealing with Generalization
● Big Refactorings
Composing Methods
● Extract method :
○ Some lines of code that need a comment to explain what is
happening, should be extracted as a method.
Composing Methods
● Extract method :
void printOwing(double amount) {
printBanner();
//print details
System.out.println ("name:" + _name);
System.out.println ("amount" + amount);
}
void printOwing(double amount) {
printBanner();
printDetails(amount);
}
void printDetails (double amount) {
System.out.println ("name:" + _name);
System.out.println ("amount" + amount);
}
Composing Methods
● Inline method :
○ If statements in the method are self explaining, remove method
calls and keep the statements
○ Do not change polymorphic methods
Composing Methods
● Inline method :
int getRating() {
return (moreThanFiveLateDeliveries()) ? 2 : 1;
}
boolean moreThanFiveLateDeliveries() {
return _numberOfLateDeliveries > 5;
}
int getRating() {
return (_numberOfLateDeliveries > 5) ? 2 :
1;
}
Composing Methods
● Inline Temp :
○ Replace temp with expression, that can help to other
refactorings
double basePrice = anOrder.basePrice();
return (basePrice > 1000)
To
return (anOrder.basePrice() > 1000)
Composing Methods
● Replace Temp With Query:
double basePrice = _quantity * _itemPrice;
if (basePrice > 1000)
return basePrice * 0.95;
else
return basePrice * 0.98;
if (basePrice() > 1000)
return basePrice() * 0.95;
else
return basePrice() * 0.98;
...
double basePrice() {
return _quantity * _itemPrice;
}
Composing Methods
● Introduce Explaining Variable
double price() {
// price is base price - quantity discount + shipping
return _quantity * _itemPrice - Math.max(0, _quantity - 500) * _itemPrice * 0.05 + Math.min(_quantity * _itemPrice * 0.1, 100.0);
}
Composing Methods
● Introduce Explaining Variable
double price() {
final double basePrice = _quantity * _itemPrice;
final double quantityDiscount = Math.max(0, _quantity - 500) * _itemPrice * 0.05;
final double shipping = Math.min(basePrice * 0.1, 100.0);
return basePrice - quantityDiscount + shipping;
}
Composing Methods
● Split Temporary Variable
double temp = 2 * (_height + _width);
System.out.println (temp);
temp = _height * _width;
System.out.println (temp);
final double perimeter = 2 * (_height + _width);
System.out.println (perimeter);
final double area = _height * _width;
System.out.println (area);
Composing Methods
● Remove assignments to parameters
○ may be confusing for pass by reference
int discount (int inputVal, int quantity, int yearToDate) {
if (inputVal > 50) inputVal -= 2;
...
int discount (int inputVal, int quantity, int yearToDate) {
int result = inputVal;
if (inputVal > 50) result -= 2;
...
void aMethod(Object foo) {
foo.modifyInSomeWay(); // that's OK
foo = anotherObject; // trouble and despair will follow you
...
Composing Methods
● Replace Method with Method object
○ If a method has a long parameter list
//Class Account
int gamma (int inputVal, int quantity, int yearToDate) {
int importantValue1 = (inputVal * quantity) + delta();
int importantValue2 = (inputVal * yearToDate) + 100;
if ((yearToDate - importantValue1) > 100)
importantValue2 -= 20;
int importantValue3 = importantValue2 * 7;
// and so on...
return importantValue3 - 2 * importantValue1;
}
Composing Methods
● Replace Method with Method object
//class Gamma...
private final Account _account;
private int inputVal;
private int quantity;
private int yearToDate;
private int importantValue1;
private int importantValue2;
private int importantValue3;
Gamma (Account source, int inputValArg, int quantityArg,
int yearToDateArg) {
_account = source;
inputVal = inputValArg;
quantity = quantityArg;
yearToDate = yearToDateArg;
}
Composing Methods
● Substitute Algorithm
○ Use simpler algorithm for same task
String foundPerson(String[] people){
for (int i = 0; i < people.length; i++) {
if (people[i].equals ("Don")){
return "Don";
}
if (people[i].equals ("John")){
return "John";
}
if (people[i].equals ("Kent")){
return "Kent";
}
}
String foundPerson(String[] people){
List candidates = Arrays.asList(new String[] {"Don",
"John", "Kent"});
for (int i=0; i &lt; people.length; i++)
if (candidates.contains(people[i]))
return people[i];
return "";
}
Moving Features Between Objects
● Move Method
○ if a method looks more
relevant to another class(like
using that class’ data more
that habituating class or does
something that is part of the
other class’ task), move that
method to the other class
Moving Features Between Objects
● Move Field
○ A field is, or will be, used by
another class more than the
class on which it is defined,
move it to the another class.
Moving Features Between Objects
● Extract Class
○ If a class is doing work that should be done by
two classes
Moving Features Between Objects
● Inline Class
○ Opposite of Extract class
Moving Features Between Objects
● Hide Delegate
○ A client is calling a delegate class of an object.
○ Create methods on the server to hide the delegate.
Moving Features Between Objects
● Remove Middle Man
○ Opposite of hide delegate
○ If the client class has to add many features on the delegate class,
every time it will have to create a method on server class
Moving Features Between Objects
● Introduce Foreign Method
○ A server class you are using needs an additional method, but you
can't modify the class.
○ Create a method in the client class with an instance of the server
class as its first argument.
Moving Features Between Objects
● Introduce Foreign Method
Date newStart = new Date (previousEnd.getYear(),
previousEnd.getMonth(), previousEnd.getDate() + 1);
Add a foreign method for nextday that should be in Date class
Date newStart = nextDay(previousEnd);
private static Date nextDay(Date arg) {
// foreign method, should be on date
return new Date (arg.getYear(),arg.getMonth(), arg.getDate() + 1);
}
Moving Features Between Objects
● Introduce Local Extension
○ If we are having several foreign methods, then should make a
local extension of the server class.
Simplifying Conditional Expressions
● Decompose Conditional
if (date.before (SUMMER_START) || date.after
(SUMMER_END)) {
charge = quantity * _winterRate + _winterServiceCharge;
}
else
charge = quantity * _summerRate;
if (notSummer(date))
charge = winterCharge(quantity);
else charge = summerCharge (quantity);
private boolean notSummer(Date date) {
return date.before (SUMMER_START) || date.after
(SUMMER_END);
}
private double summerCharge(int quantity) {
return quantity * _summerRate;
}
private double winterCharge(int quantity) {
return quantity * _winterRate + _winterServiceCharge;
}
Simplifying Conditional Expressions
● Consolidate Conditional Expression
double disabilityAmount() {
if (_seniority < 2) return 0;
if (_monthsDisabled > 12) return 0;
if (_isPartTime) return 0;
// compute the disability amount
...
isNotEligableForDisability() {
return (_seniority < 2 || _monthsDisabled > 12 ||
_isPartTime);
}
double disabilityAmount() {
if (isNotEligableForDisability()) return 0;
// compute the disability amount
Simplifying Conditional Expressions
● Consolidate Duplicate Conditional Fragments
if (self.callLogs.count) {
self.editBarButton = [[[UIBarButtonItem alloc] initWithCustomView:editButton] autorelease];
self.navigationItem.rightBarButtonItem = self.editBarButton;
self.editBarButton.enabled = YES;
}
else {
self.editBarButton = [[[UIBarButtonItem alloc] initWithCustomView:editButton] autorelease];
self.navigationItem.rightBarButtonItem = self.editBarButton;
self.editBarButton.enabled = NO;
}
Simplifying Conditional Expressions
● Consolidate Duplicate Conditional Fragments
self.editBarButton = [[[UIBarButtonItem alloc] initWithCustomView:editButton] autorelease];
self.navigationItem.rightBarButtonItem = self.editBarButton;
if (self.callLogs.count) {
self.editBarButton.enabled = YES;
}
else {
self.editBarButton.enabled = NO;
}
Simplifying Conditional Expressions
● Remove Control Flag(simple)
void checkSecurity(String[] people) {
boolean found = false;
for (int i = 0; i < people.length; i++) {
if (! found) {
if (people[i].equals ("Don")){
found = true;
}
if (people[i].equals ("John")){
found = true;
}
}
}
}
void checkSecurity(String[] people) {
for (int i = 0; i < people.length; i++) {
if (people[i].equals ("Don")){
break;
}
if (people[i].equals ("John")){
break;
}
}
}
Simplifying Conditional Expressions
● Remove Control Flag(with return value)
String found = "";
for (int i = 0; i < people.length; i++) {
if (found.equals("")) {
if (people[i].equals ("Don")){
found = "Don";
}
if (people[i].equals ("John")){
found = "John";
}
}
}
return found;
String found = "";
for (int i = 0; i < people.length; i++) {
if (found.equals("")) {
if (people[i].equals ("Don")){
return "Don";
}
if (people[i].equals ("John")){
found = "John";
}
}
}
return found;
Simplifying Conditional Expressions
● Replace Conditional with polymorphism
Will be covered in organizing data
Simplifying Conditional Expressions
● Introduce Null Object
○ Don’t ask an object’s type to do something
class Customer...
public String getName() {...}
public BillingPlan getPlan() {...}
public PaymentHistory getHistory() {...}
Customer customer = site.getCustomer();
BillingPlan plan;
if (customer == null) plan = BillingPlan.basic();
else plan = customer.getPlan();
...
String customerName;
if (customer == null) customerName = "occupant";
else customerName = customer.getName();
Simplifying Conditional Expressions
● Introduce Null Object
class NullCustomer extends Customer {
public boolean isNull() {
return true;
}
public String getName(){
return "occupant";
}
}
class Customer...
public boolean isNull() {
return false;
}
Before
String customerName;
if (customer == null) customerName = "occupant";
else customerName = customer.getName();
Now
Customer customer = site.getCustomer();
String customerName = customer.getName();
Simplifying Conditional Expressions
● Introduce Null Object
@interface RIFeed : NSObject<NSCoding>
……
Call :
id obj = [self.profileNewsFeedArray objectAtIndex:indexPath.row - 1];
if (obj == [NSNull null]) {
return kRIFeedPlaceHolderHeight;
}
else {
RIFeed *feed = [self.profileNewsFeedArray objectAtIndex:indexPath.row - 1];
return feed.feedHeight;
}
Simplifying Conditional Expressions
● Introduce Null Object
@interface RINullFeed : RIFeed<NSCoding>
- (CGFloat) feedHeight
{
return kRIFeedPlaceHolderHeight;
}
……
Call :
RIFeed *feed = [self.profileNewsFeedArray objectAtIndex:indexPath.row - 1];
return feed.feedHeight;
Simplifying Conditional Expressions
● Introduce Assertion
○ Only for development, helps in debugging
double getExpenseLimit() {
// should have either expense limit or a primary project
return (_expenseLimit != NULL_EXPENSE) ?
_expenseLimit:
_primaryProject.getMemberExpenseLimit();
}
double getExpenseLimit() {
Assert.isTrue (_expenseLimit != NULL_EXPENSE ||
_primaryProject != null);
return (_expenseLimit != NULL_EXPENSE) ?
_expenseLimit:
_primaryProject.getMemberExpenseLimit();
}
Making Method Calls Simpler
● Rename Method
○ A method name should reveal its purpose.
○ getTelephoneNumber() is a better name that getTNum()
● Add Parameter
○ A method needs more info.
● Remove Parameter
○ A method does not use a parameter or became the member of the
object class that was used as a parameter.
○ Do not remove parameter in polymorphic methods
Making Method Calls Simpler
● Separate Query from Modifier
Making Method Calls Simpler
● Parameterize Method
class Employee {
void tenPercentRaise () {
salary *= 1.1;
}
void fivePercentRaise () {
salary *= 1.05;
}
Can be replaced as,
void raise (double factor) {
salary *= (1 + factor);
}
Making Method Calls Simpler
● Preserve Whole Object
int low = daysTempRange().getLow();
int high = daysTempRange().getHigh();
withinPlan = plan.withinRange(low, high);
Can be replaced as,
withinPlan = plan.withinRange(daysTempRange());
Making Method Calls Simpler
● Introduce parameter Object
○ If some parameters naturally go together
Making Method Calls Simpler
● Remove Setting Method
○ I don’t want to update a field’s value without constructor/factory
method.
● Hide Method
○ If a method is not used by any other class, make it private
● Replace Constructor with Factory Method
Employee (int type) {
_type = type;
if(type == 0)
{
//Do something
}
}
static Employee create(int type) {
return new Employee(type);
if(type == 0)
{
//Do something
}
}
Making Method Calls Simpler
● Encapsulate Downcast
Object lastReading() {
return readings.lastElement();
}
We need to cast Object as Reading by its caller, so..
Reading lastReading() {
return (Reading) readings.lastElement();
}
Making Method Calls Simpler
● Replace Error Code with Exception
int withdraw(int amount) {
if (amount > _balance)
return -1;
else {
_balance -= amount;
return 0;
}
}
void withdraw(int amount) throws BalanceException {
if (amount > _balance) throw new BalanceException();
_balance -= amount;
}
Organizing Data
● Self Encapsulate Field
○ Create setter and getter for each field and use those to access
● Replace data value with object
○ turn data item into object that needs extra data or behaviour.
Organizing Data
● Change Value to Reference
○ If there are limited return values for multiple other values, we
can change value to reference.
○ one customer can have many orders, and the number of
customer is limited.
Organizing Data
● Change Value to Reference
class Customer {
public Customer (String name) {
_name = name;
}
public String getName() {
return _name;
}
private final String _name;
}
class Order...
public Order (String customerName) {
_customer = new Customer(customerName);
}
public void setCustomer(String customerName) {
_customer = new Customer(customerName);
}
public String getCustomerName() {
return _customer.getName();
}
private Customer _customer;
Organizing Data
● Change Value to Reference
some client code:
private static int numberOfOrdersFor(Collection orders, String customer) {
int result = 0;
Iterator iter = orders.iterator();
while (iter.hasNext()) {
Order each = (Order) iter.next();
if (each.getCustomerName().equals(customer)) result++;
}
return result;
}
Organizing Data
● Change Value to Reference
some client code:
private static int numberOfOrdersFor(Collection orders, String customer) { // if many orders have the same customer
and the number of customers is limited
int result = 0;
Iterator iter = orders.iterator();
while (iter.hasNext()) {
Order each = (Order) iter.next();
if (each.getCustomerName().equals(customer)) result++;
}
return result;
Organizing Data
● Change Value to Reference
private static Dictionary _instances = new Hashtable();
class Customer...
static void loadCustomers() {
new Customer ("Lemon Car Hire").store();
new Customer ("Associated Coffee Machines").store();
new Customer ("Bilston Gasworks").store();
}
private void store() {
_instances.put(this.getName(), this);
}
public static Customer getNamed (String name) {
return (Customer) _instances.get(name);
}
Organizing Data
● Change Reference to Value
○ If the reference object doing nothing much and thus awkward to
manage.
Organizing Data
● Replace Array With Object
String[] row = new String[3];
row [0] = "Liverpool";
row [1] = "15";
Replace row array with object row.
Organizing Data
● Duplicate Observed Data
○ You have domain data available only in a GUI control, and
domain methods need access.
○ Copy the data to a domain object. Set up an observer to
synchronize the two pieces of data.
Organizing Data
● Change Unidirectional Association to Bidirectional
○ You have two classes that need to use each other's features,
but there is only a one-way link.
○ Add back pointers, and change modifiers to update both sets.
class Order... //controlling methods
void addCustomer (Customer arg) {
arg.friendOrders().add(this);
_customers.add(arg);
}
void removeCustomer (Customer arg) {
arg.friendOrders().remove(this);
_customers.remove(arg);
}
class Customer...
void addOrder(Order arg) {
arg.addCustomer(this);
}
void removeOrder(Order arg) {
arg.removeCustomer(this);
}
Organizing Data
● Change Bidirectional Association to Unidirectional
○ Opposite to Previous one
Organizing Data
● Replace Magic Number With Symbolic Constant
if (textField.tag == 5555)
{ ...}
else if (textField.tag == 6666) {
…...
should be
if (textField.tag == TAG_FOR_SOMETHING)
{
}
else if (textField.tag == TAG_FOR_OTHER) {
…...
Organizing Data
● Encapsulate Field
public String _name;
Should be,
private String _name;
public String getName() {return _name;}
public void setName(String arg) {_name = arg;}
Organizing Data
● Encapsulate Collection
class Person...
public Set getCourses() {
return _courses;
}
public void setCourses(Set arg) {
_courses = arg;
}
private Set _courses;
class Person...
public Set getCourses() {
return _courses;
}
public void setCourses(Set arg) {
_courses = arg;
}
private Set _courses;
public void addCourse (Course arg) {
_courses.add(arg);
}
public void removeCourse (Course arg) {
_courses.remove(arg);
}
Organizing Data
● Replace Record with Data Class
○ You need to interface with a record structure in a traditional
programming environment.
○ Make a dumb data object for the record.
Organizing Data
● Replace Type Code with Class
○ If we have a type code that does not affect behavior
○ If no conditional statements.
class Person {
public static final int O = 0;
public static final int A = 1;
public static final int B = 2;
public static final int AB = 3;
private int _bloodGroup;
public Person (int bloodGroup) {
_bloodGroup = bloodGroup;
}
public void setBloodGroup(int arg) {
_bloodGroup = arg;
}
public int getBloodGroup() {
return _bloodGroup;
}
}
Organizing Data
● Replace Type Code with Class
class BloodGroup…
public static final BloodGroup O = new BloodGroup(0);
public static final BloodGroup A = new BloodGroup(1);
public static final BloodGroup B = new BloodGroup(2);
public static final BloodGroup AB = new BloodGroup(3);
private static final BloodGroup[] _values = {O, A, B, AB};
private final int _code;
private BloodGroup (int code ) {
_code = code;
}
private int getCode() {
return _code;
}
private static BloodGroup code(int arg) {
return _values[arg];
}
class Person ...
public static final int O = BloodGroup.O.getCode();
public static final int A = BloodGroup.A.getCode();
public static final int B = BloodGroup.B.getCode();
public static final int AB = BloodGroup.AB.getCode();
public Person (int bloodGroup) {
_bloodGroup = BloodGroup.code(bloodGroup);
}
public int getBloodGroup() {
return _bloodGroup.getCode();
}
public void setBloodGroup(int arg) {
_bloodGroup = BloodGroup.code (arg);
}
Organizing Data
● Replace Type Code with SubClasses
○ if the type code affects behavior, the best thing to do is to use
polymorphism to handle the variant behavior.
○ If the type code doesn’t change.
Organizing Data
● Replace Type Code with SubClasses
class Employee...
private int _type;
static final int ENGINEER = 0;
static final int SALESMAN = 1;
static final int MANAGER = 2;
abstract int getType();
static Employee create(int type) {
if (type == ENGINEER) return new Engineer();
else return new Employee(type);
}
class Engineer extends Employee {
int getType() {
return Employee.ENGINEER;
}
}
Organizing Data
● Replace Type Code with State/Strategy
○ This is similar to Replace Type Code with Subclasses, but can
be used if the type code changes during the life of the object or
if another reason prevents subclassing
Organizing Data
● Replace Type Code with State/Strategy
abstract class EmployeeType {
abstract int getTypeCode();
static EmployeeType newType(int code) {
switch (code) {
case ENGINEER:
return new Engineer();
case SALESMAN:
return new Salesman();
case MANAGER:
return new Manager();
default:
throw new IllegalArgumentException
("Incorrect Employee Code");
}
}
static final int ENGINEER = 0;
static final int SALESMAN = 1;
static final int MANAGER = 2;
}
class Engineer extends EmployeeType {
int getTypeCode () {
return Employee.ENGINEER;
}
}
………...
class Employee...
private EmployeeType _type;
int getType() {
return _type.getTypeCode();
}
void setType(int arg) {
_type = EmployeeType.newType(arg);
}
Organizing Data
● Replace Subclasses with Fields
○ If we have subclasses that vary only in methods that return
constant data, Change the methods to superclass fields and
eliminate the subclasses.
Dealing With Generalization
● Pull Up Field
● Push Down Field
Dealing With Generalization
● Pull Up Method
● Push Down Method
Dealing With Generalization
● Pull Up Constructor Body
class Manager extends Employee...
public Manager (String name, String id, int grade) {
_name = name;
_id = id;
_grade = grade;
}
class Engineer extends Employee...
public Engineer (String name, String id) {
_name = name;
_id = id;
……
}
Dealing With Generalization
● Pull Up Constructor Body
class Employee...
public Employee (String name, String id) {
_name = name;
_id = id;
}
class Manager extends Employee...
public Manager (String name, String id, int grade) {
super(name, id)
_grade = grade;
}
class Engineer extends Employee...
public Engineer (String name, String id) {
super(name, id);
…..
}
Dealing With Generalization
● Extract Subclass
○ A class has features that are used only in some instances.
○ Create a subclass for that subset of features.
Dealing With Generalization
● Extract Superclass
○ You have two classes with similar features.
○ Create a superclass and move the common features to the
superclass.
Dealing With Generalization
● Extract Interface
○ Several clients use the
same subset of a class's
interface, or two classes
have part of their
interfaces in common.
○ Extract the subset into an
interface.
Dealing With Generalization
● Collapse hierarchy
○ A superclass and subclass are not very different.
○ Merge them together.
Dealing With Generalization
● Form Template Method
○ You have two methods in subclasses that perform similar steps in
the same order, yet the steps are different.
○ Get the steps into methods with the same signature, so that the
original methods become the same. Then you can pull them up.
Dealing With Generalization
● Form Template Method
○ Elimination of Duplication
Dealing With Generalization
● Replace Inheritance With Delegation
○ A subclass uses only part of a superclasses interface or does not
want to inherit data.
○ Create a field for the superclass, adjust methods to delegate to the
superclass, and remove the subclassing.
Dealing With Generalization
● Replace Delegation With Inheritance
○ You're using delegation and are often writing many simple
delegations for the entire interface.
○ Make the delegating class a subclass of the delegate.
Big Refactorings
● The Nature of The Game
○ Depends on intuition
○ Takes time
○ Can be done when adding features/fixing bugs
○ Requires a degree of agreement inside the team
Big Refactorings
● Four Big Refactorings
○ Tease Apart Inheritance
○ Convert Procedural Design to Objects
○ Separate Domain from Presentation
○ Extract Hierarchy
Four Big Refactorings
● Tease Apart Inheritance
○ You have an inheritance
hierarchy that is doing
two jobs at once.
○ Create two hierarchies
and use delegation to
invoke one from the
other.
Four Big Refactorings
● Convert Procedural
Design to Objects
○ You have code written
in a procedural style.
○ Turn the data records
into objects, break up
the behavior, and
move the behavior to
the objects.
Four Big Refactorings
● Separate Domain from Presentation
○ You have GUI classes that contain domain logic.
○ Separate the domain logic into separate domain classes
Four Big Refactorings
● Extract Hierarchy
○ You have a class that is
doing too much work, at
least in part through many
conditional statements.
○ Create a hierarchy of
classes in which each
subclass represents a
special case.
Thank You :)

More Related Content

What's hot (20)

KEY
Clean code and Code Smells
Mario Sangiorgio
 
PPTX
Code refactoring
Lalit Kale
 
ODP
Introduction to Version Control
Jeremy Coates
 
PPTX
Code smells and remedies
Md.Mojibul Hoque
 
PPTX
COCOMO (Software Engineering)
Biswadeep Mukhopadhyay
 
PDF
TypeScript Best Practices
felixbillon
 
PDF
Code Smells and Its type (With Example)
Anshul Vinayak
 
PPTX
Software development best practices & coding guidelines
Ankur Goyal
 
PDF
Understanding react hooks
Samundra khatri
 
PDF
Web Development with Python and Django
Michael Pirnat
 
PPTX
PHP FUNCTIONS
Zeeshan Ahmed
 
PDF
Intro to functional programming
Assaf Gannon
 
PPS
Coding Best Practices
mh_azad
 
PDF
Asynchronous JavaScript Programming with Callbacks & Promises
Hùng Nguyễn Huy
 
PPT
Design Patterns
Anuja Arosha
 
PDF
Asynchronous API in Java8, how to use CompletableFuture
José Paumard
 
PPT
C# Exceptions Handling
sharqiyem
 
PPTX
JAVA-PPT'S-complete-chrome.pptx
KunalYadav65140
 
PPTX
Coding standards
Mark Reynolds
 
PPTX
Javascript functions
Alaref Abushaala
 
Clean code and Code Smells
Mario Sangiorgio
 
Code refactoring
Lalit Kale
 
Introduction to Version Control
Jeremy Coates
 
Code smells and remedies
Md.Mojibul Hoque
 
COCOMO (Software Engineering)
Biswadeep Mukhopadhyay
 
TypeScript Best Practices
felixbillon
 
Code Smells and Its type (With Example)
Anshul Vinayak
 
Software development best practices & coding guidelines
Ankur Goyal
 
Understanding react hooks
Samundra khatri
 
Web Development with Python and Django
Michael Pirnat
 
PHP FUNCTIONS
Zeeshan Ahmed
 
Intro to functional programming
Assaf Gannon
 
Coding Best Practices
mh_azad
 
Asynchronous JavaScript Programming with Callbacks & Promises
Hùng Nguyễn Huy
 
Design Patterns
Anuja Arosha
 
Asynchronous API in Java8, how to use CompletableFuture
José Paumard
 
C# Exceptions Handling
sharqiyem
 
JAVA-PPT'S-complete-chrome.pptx
KunalYadav65140
 
Coding standards
Mark Reynolds
 
Javascript functions
Alaref Abushaala
 

Similar to Refactoring (20)

PPT
Refactoring - improving the smell of your code
vmandrychenko
 
PPTX
Software design principles SOLID
Foyzul Karim
 
PDF
Standardizing JavaScript Decorators in TC39 (Full Stack Fest 2019)
Igalia
 
PDF
Writing Node.js Bindings - General Principles - Gabriel Schulhof
WithTheBest
 
PPTX
C concepts and programming examples for beginners
SHAAMILIRAJAKUMAR1
 
PPTX
Programming Fundamentals lecture-10.pptx
singyali199
 
PDF
Pragmatic functional refactoring with java 8 (1)
RichardWarburton
 
PPTX
Object orinted programming lecture| Overlaoded Functions
cenaj3443
 
PDF
C# Advanced L02-Operator Overloading+Indexers+UD Conversion
Mohammad Shaker
 
PPTX
OOP.pptx
saifnasir3
 
PDF
Refactoring-ch7 moving feature btw objects
fungfung Chen
 
PPTX
Internal Anatomy of an Update
MongoDB
 
PDF
Performance measurement and tuning
AOE
 
PPTX
Chapter 2
application developer
 
PPTX
FAIZAN JAVED BUTT_845544_assignsubmission_file_ppt VP.pptx
bestmoviestrailerbes
 
PPTX
Cs1123 8 functions
TAlha MAlik
 
PDF
Core2 Document - Java SCORE Overview.pptx.pdf
ThchTrngGia
 
PPTX
Functions in C++ programming language.pptx
rebin5725
 
PDF
2.Types_Variables_Functions.pdf
TrnThBnhDng
 
Refactoring - improving the smell of your code
vmandrychenko
 
Software design principles SOLID
Foyzul Karim
 
Standardizing JavaScript Decorators in TC39 (Full Stack Fest 2019)
Igalia
 
Writing Node.js Bindings - General Principles - Gabriel Schulhof
WithTheBest
 
C concepts and programming examples for beginners
SHAAMILIRAJAKUMAR1
 
Programming Fundamentals lecture-10.pptx
singyali199
 
Pragmatic functional refactoring with java 8 (1)
RichardWarburton
 
Object orinted programming lecture| Overlaoded Functions
cenaj3443
 
C# Advanced L02-Operator Overloading+Indexers+UD Conversion
Mohammad Shaker
 
OOP.pptx
saifnasir3
 
Refactoring-ch7 moving feature btw objects
fungfung Chen
 
Internal Anatomy of an Update
MongoDB
 
Performance measurement and tuning
AOE
 
FAIZAN JAVED BUTT_845544_assignsubmission_file_ppt VP.pptx
bestmoviestrailerbes
 
Cs1123 8 functions
TAlha MAlik
 
Core2 Document - Java SCORE Overview.pptx.pdf
ThchTrngGia
 
Functions in C++ programming language.pptx
rebin5725
 
2.Types_Variables_Functions.pdf
TrnThBnhDng
 
Ad

Recently uploaded (20)

PDF
Download iTop VPN Free 6.1.0.5882 Crack Full Activated Pre Latest 2025
imang66g
 
PDF
Adobe Illustrator Crack Full Download (Latest Version 2025) Pre-Activated
imang66g
 
PDF
New Download FL Studio Crack Full Version [Latest 2025]
imang66g
 
PDF
Step-by-Step Guide to Install SAP HANA Studio | Complete Installation Tutoria...
SAP Vista, an A L T Z E N Company
 
PPTX
Web Testing.pptx528278vshbuqffqhhqiwnwuq
studylike474
 
PPTX
Presentation about variables and constant.pptx
kr2589474
 
PDF
Summary Of Odoo 18.1 to 18.4 : The Way For Odoo 19
CandidRoot Solutions Private Limited
 
PDF
AWS_Agentic_AI_in_Indian_BFSI_A_Strategic_Blueprint_for_Customer.pdf
siddharthnetsavvies
 
PDF
10 posting ideas for community engagement with AI prompts
Pankaj Taneja
 
PDF
What companies do with Pharo (ESUG 2025)
ESUG
 
PDF
System Center 2025 vs. 2022; What’s new, what’s next_PDF.pdf
Q-Advise
 
PDF
Enhancing Healthcare RPM Platforms with Contextual AI Integration
Cadabra Studio
 
PDF
Why Are More Businesses Choosing Partners Over Freelancers for Salesforce.pdf
Cymetrix Software
 
PDF
Applitools Platform Pulse: What's New and What's Coming - July 2025
Applitools
 
PDF
SAP GUI Installation Guide for Windows | Step-by-Step Setup for SAP Access
SAP Vista, an A L T Z E N Company
 
PDF
MiniTool Power Data Recovery Crack New Pre Activated Version Latest 2025
imang66g
 
PDF
Supabase Meetup: Build in a weekend, scale to millions
Carlo Gilmar Padilla Santana
 
PDF
How to Download and Install ADT (ABAP Development Tools) for Eclipse IDE | SA...
SAP Vista, an A L T Z E N Company
 
PPTX
Cutting Optimization Pro 5.18.2 Crack With Free Download
cracked shares
 
PDF
Balancing Resource Capacity and Workloads with OnePlan – Avoid Overloading Te...
OnePlan Solutions
 
Download iTop VPN Free 6.1.0.5882 Crack Full Activated Pre Latest 2025
imang66g
 
Adobe Illustrator Crack Full Download (Latest Version 2025) Pre-Activated
imang66g
 
New Download FL Studio Crack Full Version [Latest 2025]
imang66g
 
Step-by-Step Guide to Install SAP HANA Studio | Complete Installation Tutoria...
SAP Vista, an A L T Z E N Company
 
Web Testing.pptx528278vshbuqffqhhqiwnwuq
studylike474
 
Presentation about variables and constant.pptx
kr2589474
 
Summary Of Odoo 18.1 to 18.4 : The Way For Odoo 19
CandidRoot Solutions Private Limited
 
AWS_Agentic_AI_in_Indian_BFSI_A_Strategic_Blueprint_for_Customer.pdf
siddharthnetsavvies
 
10 posting ideas for community engagement with AI prompts
Pankaj Taneja
 
What companies do with Pharo (ESUG 2025)
ESUG
 
System Center 2025 vs. 2022; What’s new, what’s next_PDF.pdf
Q-Advise
 
Enhancing Healthcare RPM Platforms with Contextual AI Integration
Cadabra Studio
 
Why Are More Businesses Choosing Partners Over Freelancers for Salesforce.pdf
Cymetrix Software
 
Applitools Platform Pulse: What's New and What's Coming - July 2025
Applitools
 
SAP GUI Installation Guide for Windows | Step-by-Step Setup for SAP Access
SAP Vista, an A L T Z E N Company
 
MiniTool Power Data Recovery Crack New Pre Activated Version Latest 2025
imang66g
 
Supabase Meetup: Build in a weekend, scale to millions
Carlo Gilmar Padilla Santana
 
How to Download and Install ADT (ABAP Development Tools) for Eclipse IDE | SA...
SAP Vista, an A L T Z E N Company
 
Cutting Optimization Pro 5.18.2 Crack With Free Download
cracked shares
 
Balancing Resource Capacity and Workloads with OnePlan – Avoid Overloading Te...
OnePlan Solutions
 
Ad

Refactoring

  • 1. Refactoring Source : Refactoring Improving the Design of Existing Code by Martin Fowler (with Kent Beck, John Brant, William Opdyke, and Don Roberts) Prepared By- Tausun Akhtary (Suptee) Software Analyst IPVision Canada Inc
  • 2. Why Refactoring ● Improved Design ● Increased Readability. ● Less time consumption in adding/changing features.
  • 3. When Refactoring is needed? According to grandma, If it stinks, change it. —Grandma Beck, discussing child-rearing philosophy We change code, When code smells..
  • 4. When Refactoring is needed?(Contd.) ● Duplicated Code ● Long Method ● Large Class ● Long Parameter List ● Divergent Change ● Parallel Inheritance Hierarchies ● Lazy Class ● Shotgun Surgery ● Feature Envy ● Data Clumps ● Primitive Obsession ● Switch Statements
  • 5. When Refactoring is needed?(Contd.) ● Alternative Classes with Different Interfaces ● Incomplete Library Class ● Data Class ● Refused Bequest ● Comments ● Speculative Generality ● Temporary Field ● Message Chains ● Middle Man ● Inappropriate Intimacy
  • 6. How ? ● Composing Methods ● Moving Features Between Objects ● Simplifying Conditional Expressions ● Making Method Calls Simpler ● Organizing Data ● Dealing with Generalization ● Big Refactorings
  • 7. Composing Methods ● Extract method : ○ Some lines of code that need a comment to explain what is happening, should be extracted as a method.
  • 8. Composing Methods ● Extract method : void printOwing(double amount) { printBanner(); //print details System.out.println ("name:" + _name); System.out.println ("amount" + amount); } void printOwing(double amount) { printBanner(); printDetails(amount); } void printDetails (double amount) { System.out.println ("name:" + _name); System.out.println ("amount" + amount); }
  • 9. Composing Methods ● Inline method : ○ If statements in the method are self explaining, remove method calls and keep the statements ○ Do not change polymorphic methods
  • 10. Composing Methods ● Inline method : int getRating() { return (moreThanFiveLateDeliveries()) ? 2 : 1; } boolean moreThanFiveLateDeliveries() { return _numberOfLateDeliveries > 5; } int getRating() { return (_numberOfLateDeliveries > 5) ? 2 : 1; }
  • 11. Composing Methods ● Inline Temp : ○ Replace temp with expression, that can help to other refactorings double basePrice = anOrder.basePrice(); return (basePrice > 1000) To return (anOrder.basePrice() > 1000)
  • 12. Composing Methods ● Replace Temp With Query: double basePrice = _quantity * _itemPrice; if (basePrice > 1000) return basePrice * 0.95; else return basePrice * 0.98; if (basePrice() > 1000) return basePrice() * 0.95; else return basePrice() * 0.98; ... double basePrice() { return _quantity * _itemPrice; }
  • 13. Composing Methods ● Introduce Explaining Variable double price() { // price is base price - quantity discount + shipping return _quantity * _itemPrice - Math.max(0, _quantity - 500) * _itemPrice * 0.05 + Math.min(_quantity * _itemPrice * 0.1, 100.0); }
  • 14. Composing Methods ● Introduce Explaining Variable double price() { final double basePrice = _quantity * _itemPrice; final double quantityDiscount = Math.max(0, _quantity - 500) * _itemPrice * 0.05; final double shipping = Math.min(basePrice * 0.1, 100.0); return basePrice - quantityDiscount + shipping; }
  • 15. Composing Methods ● Split Temporary Variable double temp = 2 * (_height + _width); System.out.println (temp); temp = _height * _width; System.out.println (temp); final double perimeter = 2 * (_height + _width); System.out.println (perimeter); final double area = _height * _width; System.out.println (area);
  • 16. Composing Methods ● Remove assignments to parameters ○ may be confusing for pass by reference int discount (int inputVal, int quantity, int yearToDate) { if (inputVal > 50) inputVal -= 2; ... int discount (int inputVal, int quantity, int yearToDate) { int result = inputVal; if (inputVal > 50) result -= 2; ... void aMethod(Object foo) { foo.modifyInSomeWay(); // that's OK foo = anotherObject; // trouble and despair will follow you ...
  • 17. Composing Methods ● Replace Method with Method object ○ If a method has a long parameter list //Class Account int gamma (int inputVal, int quantity, int yearToDate) { int importantValue1 = (inputVal * quantity) + delta(); int importantValue2 = (inputVal * yearToDate) + 100; if ((yearToDate - importantValue1) > 100) importantValue2 -= 20; int importantValue3 = importantValue2 * 7; // and so on... return importantValue3 - 2 * importantValue1; }
  • 18. Composing Methods ● Replace Method with Method object //class Gamma... private final Account _account; private int inputVal; private int quantity; private int yearToDate; private int importantValue1; private int importantValue2; private int importantValue3; Gamma (Account source, int inputValArg, int quantityArg, int yearToDateArg) { _account = source; inputVal = inputValArg; quantity = quantityArg; yearToDate = yearToDateArg; }
  • 19. Composing Methods ● Substitute Algorithm ○ Use simpler algorithm for same task String foundPerson(String[] people){ for (int i = 0; i < people.length; i++) { if (people[i].equals ("Don")){ return "Don"; } if (people[i].equals ("John")){ return "John"; } if (people[i].equals ("Kent")){ return "Kent"; } } String foundPerson(String[] people){ List candidates = Arrays.asList(new String[] {"Don", "John", "Kent"}); for (int i=0; i &lt; people.length; i++) if (candidates.contains(people[i])) return people[i]; return ""; }
  • 20. Moving Features Between Objects ● Move Method ○ if a method looks more relevant to another class(like using that class’ data more that habituating class or does something that is part of the other class’ task), move that method to the other class
  • 21. Moving Features Between Objects ● Move Field ○ A field is, or will be, used by another class more than the class on which it is defined, move it to the another class.
  • 22. Moving Features Between Objects ● Extract Class ○ If a class is doing work that should be done by two classes
  • 23. Moving Features Between Objects ● Inline Class ○ Opposite of Extract class
  • 24. Moving Features Between Objects ● Hide Delegate ○ A client is calling a delegate class of an object. ○ Create methods on the server to hide the delegate.
  • 25. Moving Features Between Objects ● Remove Middle Man ○ Opposite of hide delegate ○ If the client class has to add many features on the delegate class, every time it will have to create a method on server class
  • 26. Moving Features Between Objects ● Introduce Foreign Method ○ A server class you are using needs an additional method, but you can't modify the class. ○ Create a method in the client class with an instance of the server class as its first argument.
  • 27. Moving Features Between Objects ● Introduce Foreign Method Date newStart = new Date (previousEnd.getYear(), previousEnd.getMonth(), previousEnd.getDate() + 1); Add a foreign method for nextday that should be in Date class Date newStart = nextDay(previousEnd); private static Date nextDay(Date arg) { // foreign method, should be on date return new Date (arg.getYear(),arg.getMonth(), arg.getDate() + 1); }
  • 28. Moving Features Between Objects ● Introduce Local Extension ○ If we are having several foreign methods, then should make a local extension of the server class.
  • 29. Simplifying Conditional Expressions ● Decompose Conditional if (date.before (SUMMER_START) || date.after (SUMMER_END)) { charge = quantity * _winterRate + _winterServiceCharge; } else charge = quantity * _summerRate; if (notSummer(date)) charge = winterCharge(quantity); else charge = summerCharge (quantity); private boolean notSummer(Date date) { return date.before (SUMMER_START) || date.after (SUMMER_END); } private double summerCharge(int quantity) { return quantity * _summerRate; } private double winterCharge(int quantity) { return quantity * _winterRate + _winterServiceCharge; }
  • 30. Simplifying Conditional Expressions ● Consolidate Conditional Expression double disabilityAmount() { if (_seniority < 2) return 0; if (_monthsDisabled > 12) return 0; if (_isPartTime) return 0; // compute the disability amount ... isNotEligableForDisability() { return (_seniority < 2 || _monthsDisabled > 12 || _isPartTime); } double disabilityAmount() { if (isNotEligableForDisability()) return 0; // compute the disability amount
  • 31. Simplifying Conditional Expressions ● Consolidate Duplicate Conditional Fragments if (self.callLogs.count) { self.editBarButton = [[[UIBarButtonItem alloc] initWithCustomView:editButton] autorelease]; self.navigationItem.rightBarButtonItem = self.editBarButton; self.editBarButton.enabled = YES; } else { self.editBarButton = [[[UIBarButtonItem alloc] initWithCustomView:editButton] autorelease]; self.navigationItem.rightBarButtonItem = self.editBarButton; self.editBarButton.enabled = NO; }
  • 32. Simplifying Conditional Expressions ● Consolidate Duplicate Conditional Fragments self.editBarButton = [[[UIBarButtonItem alloc] initWithCustomView:editButton] autorelease]; self.navigationItem.rightBarButtonItem = self.editBarButton; if (self.callLogs.count) { self.editBarButton.enabled = YES; } else { self.editBarButton.enabled = NO; }
  • 33. Simplifying Conditional Expressions ● Remove Control Flag(simple) void checkSecurity(String[] people) { boolean found = false; for (int i = 0; i < people.length; i++) { if (! found) { if (people[i].equals ("Don")){ found = true; } if (people[i].equals ("John")){ found = true; } } } } void checkSecurity(String[] people) { for (int i = 0; i < people.length; i++) { if (people[i].equals ("Don")){ break; } if (people[i].equals ("John")){ break; } } }
  • 34. Simplifying Conditional Expressions ● Remove Control Flag(with return value) String found = ""; for (int i = 0; i < people.length; i++) { if (found.equals("")) { if (people[i].equals ("Don")){ found = "Don"; } if (people[i].equals ("John")){ found = "John"; } } } return found; String found = ""; for (int i = 0; i < people.length; i++) { if (found.equals("")) { if (people[i].equals ("Don")){ return "Don"; } if (people[i].equals ("John")){ found = "John"; } } } return found;
  • 35. Simplifying Conditional Expressions ● Replace Conditional with polymorphism Will be covered in organizing data
  • 36. Simplifying Conditional Expressions ● Introduce Null Object ○ Don’t ask an object’s type to do something class Customer... public String getName() {...} public BillingPlan getPlan() {...} public PaymentHistory getHistory() {...} Customer customer = site.getCustomer(); BillingPlan plan; if (customer == null) plan = BillingPlan.basic(); else plan = customer.getPlan(); ... String customerName; if (customer == null) customerName = "occupant"; else customerName = customer.getName();
  • 37. Simplifying Conditional Expressions ● Introduce Null Object class NullCustomer extends Customer { public boolean isNull() { return true; } public String getName(){ return "occupant"; } } class Customer... public boolean isNull() { return false; } Before String customerName; if (customer == null) customerName = "occupant"; else customerName = customer.getName(); Now Customer customer = site.getCustomer(); String customerName = customer.getName();
  • 38. Simplifying Conditional Expressions ● Introduce Null Object @interface RIFeed : NSObject<NSCoding> …… Call : id obj = [self.profileNewsFeedArray objectAtIndex:indexPath.row - 1]; if (obj == [NSNull null]) { return kRIFeedPlaceHolderHeight; } else { RIFeed *feed = [self.profileNewsFeedArray objectAtIndex:indexPath.row - 1]; return feed.feedHeight; }
  • 39. Simplifying Conditional Expressions ● Introduce Null Object @interface RINullFeed : RIFeed<NSCoding> - (CGFloat) feedHeight { return kRIFeedPlaceHolderHeight; } …… Call : RIFeed *feed = [self.profileNewsFeedArray objectAtIndex:indexPath.row - 1]; return feed.feedHeight;
  • 40. Simplifying Conditional Expressions ● Introduce Assertion ○ Only for development, helps in debugging double getExpenseLimit() { // should have either expense limit or a primary project return (_expenseLimit != NULL_EXPENSE) ? _expenseLimit: _primaryProject.getMemberExpenseLimit(); } double getExpenseLimit() { Assert.isTrue (_expenseLimit != NULL_EXPENSE || _primaryProject != null); return (_expenseLimit != NULL_EXPENSE) ? _expenseLimit: _primaryProject.getMemberExpenseLimit(); }
  • 41. Making Method Calls Simpler ● Rename Method ○ A method name should reveal its purpose. ○ getTelephoneNumber() is a better name that getTNum() ● Add Parameter ○ A method needs more info. ● Remove Parameter ○ A method does not use a parameter or became the member of the object class that was used as a parameter. ○ Do not remove parameter in polymorphic methods
  • 42. Making Method Calls Simpler ● Separate Query from Modifier
  • 43. Making Method Calls Simpler ● Parameterize Method class Employee { void tenPercentRaise () { salary *= 1.1; } void fivePercentRaise () { salary *= 1.05; } Can be replaced as, void raise (double factor) { salary *= (1 + factor); }
  • 44. Making Method Calls Simpler ● Preserve Whole Object int low = daysTempRange().getLow(); int high = daysTempRange().getHigh(); withinPlan = plan.withinRange(low, high); Can be replaced as, withinPlan = plan.withinRange(daysTempRange());
  • 45. Making Method Calls Simpler ● Introduce parameter Object ○ If some parameters naturally go together
  • 46. Making Method Calls Simpler ● Remove Setting Method ○ I don’t want to update a field’s value without constructor/factory method. ● Hide Method ○ If a method is not used by any other class, make it private ● Replace Constructor with Factory Method Employee (int type) { _type = type; if(type == 0) { //Do something } } static Employee create(int type) { return new Employee(type); if(type == 0) { //Do something } }
  • 47. Making Method Calls Simpler ● Encapsulate Downcast Object lastReading() { return readings.lastElement(); } We need to cast Object as Reading by its caller, so.. Reading lastReading() { return (Reading) readings.lastElement(); }
  • 48. Making Method Calls Simpler ● Replace Error Code with Exception int withdraw(int amount) { if (amount > _balance) return -1; else { _balance -= amount; return 0; } } void withdraw(int amount) throws BalanceException { if (amount > _balance) throw new BalanceException(); _balance -= amount; }
  • 49. Organizing Data ● Self Encapsulate Field ○ Create setter and getter for each field and use those to access ● Replace data value with object ○ turn data item into object that needs extra data or behaviour.
  • 50. Organizing Data ● Change Value to Reference ○ If there are limited return values for multiple other values, we can change value to reference. ○ one customer can have many orders, and the number of customer is limited.
  • 51. Organizing Data ● Change Value to Reference class Customer { public Customer (String name) { _name = name; } public String getName() { return _name; } private final String _name; } class Order... public Order (String customerName) { _customer = new Customer(customerName); } public void setCustomer(String customerName) { _customer = new Customer(customerName); } public String getCustomerName() { return _customer.getName(); } private Customer _customer;
  • 52. Organizing Data ● Change Value to Reference some client code: private static int numberOfOrdersFor(Collection orders, String customer) { int result = 0; Iterator iter = orders.iterator(); while (iter.hasNext()) { Order each = (Order) iter.next(); if (each.getCustomerName().equals(customer)) result++; } return result; }
  • 53. Organizing Data ● Change Value to Reference some client code: private static int numberOfOrdersFor(Collection orders, String customer) { // if many orders have the same customer and the number of customers is limited int result = 0; Iterator iter = orders.iterator(); while (iter.hasNext()) { Order each = (Order) iter.next(); if (each.getCustomerName().equals(customer)) result++; } return result;
  • 54. Organizing Data ● Change Value to Reference private static Dictionary _instances = new Hashtable(); class Customer... static void loadCustomers() { new Customer ("Lemon Car Hire").store(); new Customer ("Associated Coffee Machines").store(); new Customer ("Bilston Gasworks").store(); } private void store() { _instances.put(this.getName(), this); } public static Customer getNamed (String name) { return (Customer) _instances.get(name); }
  • 55. Organizing Data ● Change Reference to Value ○ If the reference object doing nothing much and thus awkward to manage.
  • 56. Organizing Data ● Replace Array With Object String[] row = new String[3]; row [0] = "Liverpool"; row [1] = "15"; Replace row array with object row.
  • 57. Organizing Data ● Duplicate Observed Data ○ You have domain data available only in a GUI control, and domain methods need access. ○ Copy the data to a domain object. Set up an observer to synchronize the two pieces of data.
  • 58. Organizing Data ● Change Unidirectional Association to Bidirectional ○ You have two classes that need to use each other's features, but there is only a one-way link. ○ Add back pointers, and change modifiers to update both sets. class Order... //controlling methods void addCustomer (Customer arg) { arg.friendOrders().add(this); _customers.add(arg); } void removeCustomer (Customer arg) { arg.friendOrders().remove(this); _customers.remove(arg); } class Customer... void addOrder(Order arg) { arg.addCustomer(this); } void removeOrder(Order arg) { arg.removeCustomer(this); }
  • 59. Organizing Data ● Change Bidirectional Association to Unidirectional ○ Opposite to Previous one
  • 60. Organizing Data ● Replace Magic Number With Symbolic Constant if (textField.tag == 5555) { ...} else if (textField.tag == 6666) { …... should be if (textField.tag == TAG_FOR_SOMETHING) { } else if (textField.tag == TAG_FOR_OTHER) { …...
  • 61. Organizing Data ● Encapsulate Field public String _name; Should be, private String _name; public String getName() {return _name;} public void setName(String arg) {_name = arg;}
  • 62. Organizing Data ● Encapsulate Collection class Person... public Set getCourses() { return _courses; } public void setCourses(Set arg) { _courses = arg; } private Set _courses; class Person... public Set getCourses() { return _courses; } public void setCourses(Set arg) { _courses = arg; } private Set _courses; public void addCourse (Course arg) { _courses.add(arg); } public void removeCourse (Course arg) { _courses.remove(arg); }
  • 63. Organizing Data ● Replace Record with Data Class ○ You need to interface with a record structure in a traditional programming environment. ○ Make a dumb data object for the record.
  • 64. Organizing Data ● Replace Type Code with Class ○ If we have a type code that does not affect behavior ○ If no conditional statements. class Person { public static final int O = 0; public static final int A = 1; public static final int B = 2; public static final int AB = 3; private int _bloodGroup; public Person (int bloodGroup) { _bloodGroup = bloodGroup; } public void setBloodGroup(int arg) { _bloodGroup = arg; } public int getBloodGroup() { return _bloodGroup; } }
  • 65. Organizing Data ● Replace Type Code with Class class BloodGroup… public static final BloodGroup O = new BloodGroup(0); public static final BloodGroup A = new BloodGroup(1); public static final BloodGroup B = new BloodGroup(2); public static final BloodGroup AB = new BloodGroup(3); private static final BloodGroup[] _values = {O, A, B, AB}; private final int _code; private BloodGroup (int code ) { _code = code; } private int getCode() { return _code; } private static BloodGroup code(int arg) { return _values[arg]; } class Person ... public static final int O = BloodGroup.O.getCode(); public static final int A = BloodGroup.A.getCode(); public static final int B = BloodGroup.B.getCode(); public static final int AB = BloodGroup.AB.getCode(); public Person (int bloodGroup) { _bloodGroup = BloodGroup.code(bloodGroup); } public int getBloodGroup() { return _bloodGroup.getCode(); } public void setBloodGroup(int arg) { _bloodGroup = BloodGroup.code (arg); }
  • 66. Organizing Data ● Replace Type Code with SubClasses ○ if the type code affects behavior, the best thing to do is to use polymorphism to handle the variant behavior. ○ If the type code doesn’t change.
  • 67. Organizing Data ● Replace Type Code with SubClasses class Employee... private int _type; static final int ENGINEER = 0; static final int SALESMAN = 1; static final int MANAGER = 2; abstract int getType(); static Employee create(int type) { if (type == ENGINEER) return new Engineer(); else return new Employee(type); } class Engineer extends Employee { int getType() { return Employee.ENGINEER; } }
  • 68. Organizing Data ● Replace Type Code with State/Strategy ○ This is similar to Replace Type Code with Subclasses, but can be used if the type code changes during the life of the object or if another reason prevents subclassing
  • 69. Organizing Data ● Replace Type Code with State/Strategy abstract class EmployeeType { abstract int getTypeCode(); static EmployeeType newType(int code) { switch (code) { case ENGINEER: return new Engineer(); case SALESMAN: return new Salesman(); case MANAGER: return new Manager(); default: throw new IllegalArgumentException ("Incorrect Employee Code"); } } static final int ENGINEER = 0; static final int SALESMAN = 1; static final int MANAGER = 2; } class Engineer extends EmployeeType { int getTypeCode () { return Employee.ENGINEER; } } ………... class Employee... private EmployeeType _type; int getType() { return _type.getTypeCode(); } void setType(int arg) { _type = EmployeeType.newType(arg); }
  • 70. Organizing Data ● Replace Subclasses with Fields ○ If we have subclasses that vary only in methods that return constant data, Change the methods to superclass fields and eliminate the subclasses.
  • 71. Dealing With Generalization ● Pull Up Field ● Push Down Field
  • 72. Dealing With Generalization ● Pull Up Method ● Push Down Method
  • 73. Dealing With Generalization ● Pull Up Constructor Body class Manager extends Employee... public Manager (String name, String id, int grade) { _name = name; _id = id; _grade = grade; } class Engineer extends Employee... public Engineer (String name, String id) { _name = name; _id = id; …… }
  • 74. Dealing With Generalization ● Pull Up Constructor Body class Employee... public Employee (String name, String id) { _name = name; _id = id; } class Manager extends Employee... public Manager (String name, String id, int grade) { super(name, id) _grade = grade; } class Engineer extends Employee... public Engineer (String name, String id) { super(name, id); ….. }
  • 75. Dealing With Generalization ● Extract Subclass ○ A class has features that are used only in some instances. ○ Create a subclass for that subset of features.
  • 76. Dealing With Generalization ● Extract Superclass ○ You have two classes with similar features. ○ Create a superclass and move the common features to the superclass.
  • 77. Dealing With Generalization ● Extract Interface ○ Several clients use the same subset of a class's interface, or two classes have part of their interfaces in common. ○ Extract the subset into an interface.
  • 78. Dealing With Generalization ● Collapse hierarchy ○ A superclass and subclass are not very different. ○ Merge them together.
  • 79. Dealing With Generalization ● Form Template Method ○ You have two methods in subclasses that perform similar steps in the same order, yet the steps are different. ○ Get the steps into methods with the same signature, so that the original methods become the same. Then you can pull them up.
  • 80. Dealing With Generalization ● Form Template Method ○ Elimination of Duplication
  • 81. Dealing With Generalization ● Replace Inheritance With Delegation ○ A subclass uses only part of a superclasses interface or does not want to inherit data. ○ Create a field for the superclass, adjust methods to delegate to the superclass, and remove the subclassing.
  • 82. Dealing With Generalization ● Replace Delegation With Inheritance ○ You're using delegation and are often writing many simple delegations for the entire interface. ○ Make the delegating class a subclass of the delegate.
  • 83. Big Refactorings ● The Nature of The Game ○ Depends on intuition ○ Takes time ○ Can be done when adding features/fixing bugs ○ Requires a degree of agreement inside the team
  • 84. Big Refactorings ● Four Big Refactorings ○ Tease Apart Inheritance ○ Convert Procedural Design to Objects ○ Separate Domain from Presentation ○ Extract Hierarchy
  • 85. Four Big Refactorings ● Tease Apart Inheritance ○ You have an inheritance hierarchy that is doing two jobs at once. ○ Create two hierarchies and use delegation to invoke one from the other.
  • 86. Four Big Refactorings ● Convert Procedural Design to Objects ○ You have code written in a procedural style. ○ Turn the data records into objects, break up the behavior, and move the behavior to the objects.
  • 87. Four Big Refactorings ● Separate Domain from Presentation ○ You have GUI classes that contain domain logic. ○ Separate the domain logic into separate domain classes
  • 88. Four Big Refactorings ● Extract Hierarchy ○ You have a class that is doing too much work, at least in part through many conditional statements. ○ Create a hierarchy of classes in which each subclass represents a special case.