Much of refactoring is devoted to correctly composing methods. The refactoring techniques in this group streamline methods, remove code duplication, and pave the way for future improvements.
Extract Method
Create a new method and name it in a way that makes its purpose self-evident.
You place the result of an expression in a local variable for later use in your code.
calculateTotal(): number {
let basePrice = quantity * itemPrice;
if (basePrice > 1000) {
return basePrice * 0.95;
}
else {
return basePrice * 0.98;
}
}
calculateTotal(): number {
if (basePrice() > 1000) {
return basePrice() * 0.95;
}
else {
return basePrice() * 0.98;
}
}
basePrice(): number {
return quantity * itemPrice;
}
Substitute Algorithm
So you want to replace an existing algorithm with a new one? Gradual refactoring isn’t the only method for improving a program. Sometimes a method is so cluttered with issues that it’s easier to tear down the method and start fresh.
foundPerson(people: string[]): string{
for (let person of people) {
if (person.equals("Don")){
return "Don";
}
if (person.equals("John")){
return "John";
}
if (person.equals("Kent")){
return "Kent";
}
}
return "";
}
foundPerson(people: string[]): string{
let candidates = ["Don", "John", "Kent"];
for (let person of people) {
if (candidates.includes(person)) {
return person;
}
}
return "";
}
Split Temporary Variable
You have a local variable that’s used to store various intermediate values inside a method (except for cycle variables).
Each component of the program code should be responsible for one and one thing only, which makes it much easier to maintain the code.
If a parameter is passed via reference, then after the parameter value is changed inside the method, this value is passed to the argument that requested calling this method.
Multiple assignments of different values to a single parameter make it difficult for you to know what data should be contained in the parameter at any particular point in time.
discount(inputVal: number, quantity: number): number {
if (inputVal > 50) {
inputVal -= 2;
}
// ...
}
discount(inputVal: number, quantity: number): number {
let result = inputVal;
if (inputVal > 50) {
result -= 2;
}
// ...
}
Replace Method with Method Object
You have a long method in which the local variables are so intertwined that you can’t apply Extract Method. The first step is to isolate the entire method into a separate class and turn its local variables into fields of the class.
Isolating a long method in its own class allows stopping a method from ballooning in size. This also allows splitting it into submethods within the class, without polluting the original class with utility methods.
class Order {
// ...
price(): number {
let primaryBasePrice;
let secondaryBasePrice;
let tertiaryBasePrice;
// Perform long computation.
}
}
class Order {
// ...
price(): number {
return new PriceCalculator(this).compute();
}
}
class PriceCalculator {
private _primaryBasePrice: number;
private _secondaryBasePrice: number;
private _tertiaryBasePrice: number;
constructor(order: Order) {
// Copy relevant information from the
// order object.
}
compute(): number {
// Perform long computation.
}
}