You are on page 1of 8

SRE_W1_A1

SHAZAIB SARWAR F2018065021

What is refactoring?
Refactoring is the process of restructuring code, while not changing its original
functionality. The goal of refactoring is to improve internal code by making many small
changes without altering the code's external behaviour. Computer programmers and
software developers refactor code to improve the design, structure and implementation of
software. Refactoring improves code readability and reduces complexities. Refactoring can
also help software developers find bugs or vulnerabilities hidden in their software.

Refactoring Techniques

• Extract Method
• Changing Variables name
• Move Method
• Replace Temp with Query Method
• Inline Method
• Encapsulate Fields
• Self-Encapsulate Field
• Replace Conditional with Polymorphism
• Extract Class:

Extract Method
Refactoring is the process of restructuring code without changing its behaviour and the technique "Extract Method" is one of the
most important building blocks of refactoring.

Before Refactoring .

// Program to build a simple calculator


#include <iostream>
using namespace std;
int main () {
char value;
float value1, value2;
cout << "Enter a valuator (+, -, *, /): ";
cin >> value;
cout << "Enter two numbers: " << endl;
cin >> value1;
cin>> value2;
switch (value) {
case '+':
cout << value1 << " + " << value2 << " = " << value1 + value2;
break;
case '-':
cout << value1 << " - " << value2 << " = " << value1 - value2;
break;
case '*':
cout << value1 << " * " << value2 << " = " << value1 * value2;
break;
case '/':
cout << value1 << " / " << value2 << " = " << value1 / value2;
SRE_W1_A1

break;
default:
// valuator is don’t match any case constant (+, -, *, /)
cout << "Error! The valuator is not correct";
break;
}
return 0;
}

After Refactoring .

// Program to build a simple calculator

#include <iostream>
using namespace std;
public void calculate (char value, float value1, float value2) {
switch (value) {
case '+':
cout << value1 << " + " << value2 << " = " << value1 + value2;
break;
case '-':
cout << value1 << " - " << value2 << " = " << value1 - value2;
break;
case '*':
cout << value1 << " * " << value2 << " = " << value1 * value2;
break;
case '/':
cout << value1 << " / " << value2 << " = " << value1 / value2;
break;
default:
// valuator is don’t match any case constant (+, -, *, /)
cout << "Error! The valuator is not correct";
break;
}
}
int main () {
char value;
float value1, value2;
cout << "Enter a valuator (+, -, *, /): ";
cin >> value;
cout << "Enter two numbers: " << endl;
cin >> value1;
cin>> value2;
calculate (value, value1, value2);
return 0;
}

Changing Variables name Rrefactoring


Rename refactoring’s Use the Rename refactoring to change names of symbols, files, directories, packages, modules and all the
references to them throughout code. Because change the variable name with suitable name of the existing code so that
understandable for everyone and easily readable.
Before Refactoring .

// Before Refactoring .
// Program to build a simple calculator
#include <iostream>
using namespace std;
public void calculate (char value, float value1, float value2)
{
switch (value)
{
case '+':
cout << value1 << " + " << value2 << " = " << value1 + value2;
break;
case '-':
cout << value1 << " - " << value2 << " = " << value1 - value2;
break;
case '*':
cout << value1 << " * " << value2 << " = " << value1 * value2;
break;
case '/':
cout << value1 << " / " << value2 << " = " << value1 / value2;
break;
default:
// valuator is don’t match any case constant (+, -, *, /)
cout << "Error! The valuator is not correct";
break;
}
}
int main () {
char value;
float value1, value2;
cout << "Enter a valuator (+, -, *, /): ";
cin >> value;
cout << "Enter two numbers: " << endl;
cin >> value1;
cin>> value2;
calculate (value, value1, value2);
return 0;
}
SRE_W1_A1

After Refactoring .

// After Refactoring .
// Program to build a simple calculator
#include <iostream>
using namespace std;
public void calculate (char operator, float first_number, float second_number) {
switch (operator) {
case '+':
cout << first_number << " + " << second_number << " = " << first_number + second_number;
break;
case '-':
cout << first_number << " - " << second_number << " = " << first_number - second_number;
break;
case '*':
cout << first_number << " * " << second_number << " = " << first_number * second_number;
break;
case '/':
cout << first_number << " / " << second_number << " = " << first_number / second_number;
break;
default:
// valuator is don’t match any case constant (+, -, *, /)
cout << "Error! The valuator is not correct";
break;
}
}
int main () {
char operator;
float first_number, second_number;
cout << "Enter a valuator (+, -, *, /): ";
cin >> operator;
cout << "Enter two numbers: " << endl;
cin >> first_number;
cin>> second_number;
calculate (operator, first_number, second_number);
return 0;
}

Move Method
Refactoring is the maintenance process of restructuring software source code to improve its quality without changing its external
behavior. Move Method Refactoring (MMR) refers to moving a method from one class to the class in which the method is used the
most often.

Before Refactoring .

// Class 1
public class AccountType {
public static final String TYPE_CODE_PREMIUM = "Premium";
private String typeCode;

public AccountType(String typeCode) {


this.typeCode = typeCode;
}

public boolean isPremium() {


return TYPE_CODE_PREMIUM.equals(typeCode);
}

public double overdraftCharge(double daysOverdrawn) {


if (isPremium()) {
double result = 10;
if (daysOverdrawn > 7) {
result += (daysOverdrawn - 7) * 0.85;
return result;
}
}
return daysOverdrawn * 0.75;
}
}

// Class 2
public class Account {
private int daysOverdrawn;
private AccountType type;

public Account(int daysOverdrawn, AccountType type) {


this.daysOverdrawn = daysOverdrawn;
this.type = type;
}

AccountType getAccountType(){
return AccountType;
}

double bankCharge() {
double result = 4.5;
if (daysOverdrawn > 0) {
result += type.overdraftCharge(daysOverdrawn);
}
return result;
}
}
SRE_W1_A1

After Refactoring .

// Class 1
public class AccountType {
public static final String TYPE_CODE_PREMIUM = "Premium";
private String typeCode;
private int daysOverdrawn;

public AccountType(int daysOverdrawn, String typeCode) {


this.daysOverdrawn = daysOverdrawn;
this.typeCode = typeCode;
}

public boolean isPremium() {


return TYPE_CODE_PREMIUM.equals(typeCode);
}

public double overdraftCharge(double daysOverdrawn) {


if (isPremium()) {
double result = 10;
if (daysOverdrawn > 7) {
result += (daysOverdrawn - 7) * 0.85;
return result;
}
}
return daysOverdrawn * 0.75;
}

double bankCharge(int daysOverdrawn) {


double result = 4.5;
if (daysOverdrawn > 0) {
result += type.overdraftCharge(daysOverdrawn);
}
return result;
}
}

// Class 2
public class Account {

private AccountType type;

public Account(AccountType type) {


this.type = type;
}

AccountType getAccountType(){
return AccountType;
}

Replace Temp with Query refactoring


The Replace Temp with Query refactoring lets you extract the variable's initializer expression into a method, and replace all
references to the variable with the calls to the extracted method. The declaration of the variable will be removed and the query
method can be used in other methods.

Before Refactoring .

// Calculate total Price


public class Order {
private int quantity;
private double itemPrice;

double basePrice = quantity * itemPrice;


double discountFactor;

public Order (double itemPrice, int quantity) {


this.quantity = quantity;
this.itemPrice = itemPrice;
}

double calculateTotal () {
if (basePrice > 1000) {
discountFactor = 0.95;
return basePrice * discountFactor;
}
else {
discountFactor = 0.98;
return basePrice * discountFactor;
}
}
}
SRE_W1_A1

After Refactoring .

// Calculate total Price


public class Order {
private int quantity;
private double itemPrice;

public Order (double itemPrice, int quantity) {


this.quantity = quantity;
this.itemPrice = itemPrice;
}

double calculateTotal () {
return basePrice () * discountFactor ();
}

private double discountFactor () {


return basePrice () > 100 ? 0.95 : 0.98;
}

private double basePrice () {


return quantity * itemPrice;
}
}

Inline Method
Inline refactoring is a way to reduce the number of unnecessary methods while simplifying the code. By finding all calls to the method
and replacing them with the content of the method, the method can then be deleted.

Before Refactoring .

class PizzaDelivery {
private int numberOfLateDeliveries;
// Return Ratings
int getRating () {
return moreThanFiveLateDeliveries () ? 2 : 1;
}
boolean moreThanFiveLateDeliveries () {
return numberOfLateDeliveries > 5;
}
}

After Refactoring .

// Replace calls to the method with the method’s content and delete the method itself.

class PizzaDelivery {
private int numberOfLateDeliveries;

int getRating () {
return numberOfLateDeliveries > 5 ? 2 : 1;
}
}

Encapsulate Fields
The Encapsulate Fields refactoring lets you hide your data and create the necessary accessors. Hiding your data and accessing it
through an outward interface based on accessor methods is a good idea. Later you can change the data internals, preserving full
compatibility with the code relied on the class and its available methods.

Before Refactoring .
// Before
//File Class
public class Class {
public String aString;
}

//File AnotherClass
public class AnotherClass {
public Class aClass;
public void method() {
aClass.aString="string";
}
}
SRE_W1_A1

After Refactoring .

// After
//File Class.java
public class Class {
private String aString;
public void setaString(String aString) {
this.aString = aString;
}
public String getaString() {
return aString;
}
}

//File AnotherClass.java
public class AnotherClass {
public Class aClass;
public void method() {
aClass.setaString("string");
}
}

Self-Encapsulate Field
Self-encapsulation is distinct from ordinary Encapsulate Field: the refactoring technique given here is performed on a private field.
Problem: You use direct access to private fields inside a class. Solution: Create a getter and setter for the field, and use only them
for accessing the field.

Before Refactoring .

class Person{
public string _title;
public int _age;

public Person(String name, int age) {


_title = name;
_age = age;
}
}

After Refactoring .
class Person{
private string _title;
private int _age;

public Person(String name, int age) {


setTitle(name);
setAge(age);
}

// Name Setter
public setTitle(string t){
_title = t;
}

// Age Setter
public setAge(int p){
_age = p;
}
}

Replace Conditional with Polymorphism


Replace Conditional with Polymorphism: Problem: we have a conditional that performs various actions depending on object type
or properties. Solution: Create subclasses matching the branches of the conditional. In them, create a shared method and move
code from the corresponding branch of the conditional to it. Then replace the conditional with the relevant method call. The result
is that the proper implementation will be attained via polymorphism depending on the object class.

Before Refactoring .

class Employee {
private int _type;

static final int ENGINEER = 0;


static final int SALESMAN = 1;
static final int MANAGER = 2;

Employee (int type) {


_type = type;
}

int payAmount() {
switch (_type)
{
case ENGINEER:
return _monthlySalary;
case SALESMAN:
return _monthlySalary + _commission;
SRE_W1_A1

case MANAGER:
return _monthlySalary + _bonus;
default:
throw new RuntimeException("Incorrect Employee");
}
}
}

After Refactoring .

class Employee{
private int _type;
private double _monthlySalary;

void setType(int arg) {


_type = EmployeeType.newType(arg);
}

abstract int payAmount();


}

class Engineer extends Employee{


int payAmount() {
return _monthlySalary;
}
}

class SALESMAN extends Employee{


private double _commission;

int payAmount() {
return _monthlySalary + _commission;
}
}

class MANAGER extends Employee{


private double _bonus;

int payAmount() {
return _monthlySalary + _bonus;
}
}

Extract Class:
This refactoring allows you to move members of an existing class to a new class. It will be helpful when you need to replace a single
class that is responsible for multiple tasks with several classes each having a single responsibility.

Before Refactoring .

#include <iostream>
using namespace std;

class Person{
string Name;
string OfficeAreaCode, OfficePhoneNumber, OfficeFullNumber;

public:
Person(){}

void setName(string name){


Name = name;
}

string getName(){
return Name;
}

void setOfficeAreaCode(string officeareacode){


OfficeAreaCode = officeareacode;
}

string getOfficeAreaCode(){
return OfficeAreaCode;
}

void setOfficePhoneNumber(string officephonenumber){


OfficePhoneNumber = officephonenumber;
}

string getOfficePhoneNumber(){
return OfficePhoneNumber;
}

string getOfficeFullNumber(){
return OfficeAreaCode + " " + OfficePhoneNumber;
SRE_W1_A1

};

int main(){
Person person;
person.setName("Adnan");
person.setOfficeAreaCode("f2020");
person.setOfficePhoneNumber("042-120948474");

cout<<person.getOfficeFullNumber();

return 0;
}

After Refactoring .

// After Refactoring
#include <iostream>
using namespace std;

class TelephoneNumber{
string OfficeAreaCode, OfficePhoneNumber;

public:
TelephoneNumber(){}

void setOfficeAreaCode(string officeareacode){

OfficeAreaCode = officeareacode;
}
string getOfficeAreaCode(){
return OfficeAreaCode;
}
void setOfficePhoneNumber(string officephonenumber){

OfficePhoneNumber = officephonenumber;
}
string getOfficePhoneNumber(){
return OfficePhoneNumber;
}

string getOfficeFullNumber(){
return OfficeAreaCode + " " + OfficePhoneNumber;
}

};

class Person{
string Name;
TelephoneNumber telephone;

public:

Person(TelephoneNumber telephones){
telephone = telephones;
}
void setName(string name){
Name = name;
}
string getName(){
return Name;
}

string getOfficeFullNumber(){
return telephone.getOfficeFullNumber();
}

};

int main(){

TelephoneNumber telephoneObj;
telephoneObj.setOfficeAreaCode("f2020");
telephoneObj.setOfficePhoneNumber("042-120948474");

Person personObj(telephoneObj);
cout<<personObj.getOfficeFullNumber();

return 0;
}

You might also like