> For the complete documentation index, see [llms.txt](https://xiaoyang-liu.gitbook.io/programming-notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://xiaoyang-liu.gitbook.io/programming-notes/software-engineering/refactoring/refactoring-techniques/composing-methods.md).

# Composing Methods

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.

```typescript
printOwing(): void {
  printBanner();

  // Print details.
  console.log("name: " + name);
  console.log("amount: " + getOutstanding());
}
```

```typescript
printOwing(): void {
  printBanner();
  printDetails(getOutstanding());
}

printDetails(outstanding: number): void {
  console.log("name: " + name);
  console.log("amount: " + outstanding);
}
```

## Inline Method

When a method body is more obvious than the method itself, use this technique.

Make sure that the method isn’t redefined in subclasses. If the method is redefined, refrain from this technique.

```typescript
class PizzaDelivery {
  // ...
  getRating(): number {
    return moreThanFiveLateDeliveries() ? 2 : 1;
  }
  moreThanFiveLateDeliveries(): boolean {
    return numberOfLateDeliveries > 5;
  }
}
```

```typescript
class PizzaDelivery {
  // ...
  getRating(): number {
    return numberOfLateDeliveries > 5 ? 2 : 1;
  }
}
```

## Extract Variable

You have an expression that’s hard to understand.

* Condition of the if() operator or a part of the ?: operator in C-based languages
* A long arithmetic expression without intermediate results
* Long multipart lines

```typescript
renderBanner(): void {
  if ((platform.toUpperCase().indexOf("MAC") > -1) &&
       (browser.toUpperCase().indexOf("IE") > -1) &&
        wasInitialized() && resize > 0 )
  {
    // do something
  }
}
```

```typescript
renderBanner(): void {
  const isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
  const isIE = browser.toUpperCase().indexOf("IE") > -1;
  const wasResized = resize > 0;

  if (isMacOs && isIE && wasInitialized() && wasResized) {
    // do something
  }
}
```

## Inline Temp

You have a temporary variable that’s assigned the result of a simple expression and nothing more.

```typescript
hasDiscount(order: Order): boolean {
  let basePrice: number = order.basePrice();
  return basePrice > 1000;
}
```

```typescript
hasDiscount(order: Order): boolean {
  return order.basePrice() > 1000;
}
```

## Replace Temp with Query

You place the result of an expression in a local variable for later use in your code.

```typescript
calculateTotal(): number {
  let basePrice = quantity * itemPrice;
  if (basePrice > 1000) {
    return basePrice * 0.95;
  }
  else {
    return basePrice * 0.98;
  }
}
```

```typescript
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.

```typescript
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 "";
}
```

```typescript
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.

```typescript
let temp = 2 * (height + width);
console.log(temp);
temp = height * width;
console.log(temp);
```

```typescript
const perimeter = 2 * (height + width);
console.log(perimeter);
const area = height * width;
console.log(area);
```

## Remove Assignments to Parameters

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

```typescript
discount(inputVal: number, quantity: number): number {
  if (inputVal > 50) {
    inputVal -= 2;
  }
  // ...
}
```

```typescript
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.

```typescript
class Order {
  // ...
  price(): number {
    let primaryBasePrice;
    let secondaryBasePrice;
    let tertiaryBasePrice;
    // Perform long computation.
  }
}
```

```typescript
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.
  }
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://xiaoyang-liu.gitbook.io/programming-notes/software-engineering/refactoring/refactoring-techniques/composing-methods.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
