Refactoring 010 - Extract Method Object
Tags: webdev, javascript, beginners, programming
Published: 2022-11-07 13:16:12

*You have a big algorithmic method. Let's break it.*

> TL;DR: Long methods are bad. Move them and break them.

# Problems Addressed

- Lack of Testability

- Accidental Complexity

- [Testing Private Methods](https://dev.to/mcsee/code-smell-112-testing-private-methods-1gm8)

# Related Code Smells

{% post https://dev.to/mcsee/code-smell-10-too-many-arguments-4o67 %} 

{% post https://dev.to/mcsee/code-smell-21-anonymous-functions-abusers-47f5 %}

{% post https://dev.to/mcsee/code-smell-36-switch-case-elseif-else-if-statements-h6c %}

{% post https://dev.to/mcsee/code-smell-112-testing-private-methods-1gm8 %}

{% post https://dev.to/mcsee/code-smell-149-optional-chaining-jk %}

{% post https://dev.to/mcsee/code-smell-112-testing-private-methods-1gm8 %}

# Steps

1. Create an object to represent an invocation of the method

2. Move the big method to the new object

3. Convert the temporary variables of the method into private attributes.

4. Break the big method in the new object by using [Extract Method](https://dev.to/mcsee/refactoring-002-extract-method-1eee)

5. Remove parameters from method invocation by also converting them to private attributes 

# Sample Code

## Before

[Gist Url]: # (https://gist.github.com/mcsee/c8984513652806d25e26f5c184849af0)
```java
class BlockchainAccount {
  // ...
  public double balance() {
    string address;    
    // Very long untestable method
  }
}
```

## After

[Gist Url]: # (https://gist.github.com/mcsee/77d24738ede67a5a99d28e796ce1fade)
```java
class BlockchainAccount {
  // ...
  public double balance() {
    return new BalanceCalculator(this).netValue();
  }
}

// 1. Create an object to represent an invocation of the method
// 2. Move the big method to the new object
// 3. Convert the temporary variables of the method into private attributes.
// 4. Break the big method in the new object by using The Extract Method
// 5. Remove parameters from method invocation by also converting them to private attributes 


class BalanceCalculator {
  private string address;
  private BlockchainAccount account;
  
  public BalanceCalculator(BlockchainAccount account) {
    this.account = account;
  }
  
  public double netValue() {
    this.findStartingBlock();
    //...
    this computeTransactions();
  }
}
```

# Type

[X] Semi-Automatic

Some IDEs have tools to extract a function into a method object.

# Safety

This is a syntactic and structural refactoring. 

We can make the changes automatically in a safe way.

# Why code is better?

We extract the logic into a new component.

We can unit-test it, reuse it, exchange it, etc.

# Tags

- Bloaters 

# Related Refactorings

{% post https://dev.to/mcsee/refactoring-002-extract-method-1eee %}

# See also

[Wikipedia: Strategy Pattern](https://en.wikipedia.org/wiki/Strategy_pattern)

[Method Object Definition](https://learning.oreilly.com/library/view/smalltalk-best-practice/9780132852098/ch03.xhtml)

[Refactoring.guru](https://refactoring.guru/es/replace-method-with-method-object)

[C2 Wiki](https://wiki.c2.com/?MethodObject)

# Conclusion

The Method-Object is suitable when we are using several extract methods passing partial state among them as parts of an algorithm.

We store these partial computations in the method-object internal state.

A strong indicator of method object opportunity is when computations are not cohesively related to the host method.

We can also reify [anonymous functions](https://dev.to/mcsee/code-smell-21-anonymous-functions-abusers-47f5) with more atomic, cohesive, and testable method objects.

# Credits

Image by [Manuel de la Fuente](https://pixabay.com/users/mfuente-1590732/) on [Pixabay](https://pixabay.com/)

* * * 

This article is part of the Refactoring Series.

{% post https://dev.to/mcsee/how-to-improve-your-code-with-easy-refactorings-2ij6 %}