A logbook for curious waters
← Software Engineering Field Guide

Move Method

Before you begin: Objects, methods, fields, and parameters.

Move Method relocates behavior to another class or module, then updates callers to use its new home. It is useful when a method works mainly with another object’s data and naturally describes something that object does. 1

Original version: a fare calculator borrows everything

A trip stores its distance and price per distance unit. A separate calculator reads both values to multiply them. Use small nonnegative integers here; currency rounding is not part of this example.

public sealed class Trip
{
    public int Distance { get; }
    public int PricePerUnit { get; }
    public Trip(int distance, int pricePerUnit)
    {
        Distance = distance;
        PricePerUnit = pricePerUnit;
    }
}

public sealed class FareCalculator
{
    public int For(Trip trip)
    {
        return trip.Distance * trip.PricePerUnit;
    }
}

FareCalculator has no data of its own. Its method reads two properties of Trip and performs a trip-specific calculation.

class Trip:
    def __init__(self, distance, price_per_unit):
        self.distance = distance
        self.price_per_unit = price_per_unit


class FareCalculator:
    def for_trip(self, trip):
        return trip.distance * trip.price_per_unit

The calculator uses only the trip’s distance and rate. The calculation has a plausible home on the trip itself.

Refactored version: ask the trip for its fare

public sealed class Trip
{
    public int Distance { get; }
    public int PricePerUnit { get; }
    public Trip(int distance, int pricePerUnit)
    {
        Distance = distance;
        PricePerUnit = pricePerUnit;
    }

    public int Fare()
    {
        return Distance * PricePerUnit;
    }
}

The caller changes from new FareCalculator().For(trip) to trip.Fare(). The calculation and result remain the same.

class Trip:
    def __init__(self, distance, price_per_unit):
        self.distance = distance
        self.price_per_unit = price_per_unit

    def fare(self):
        return self.distance * self.price_per_unit

The caller changes from FareCalculator().for_trip(trip) to trip.fare(). For distance 8 and rate 3, either version returns 24.

Move responsibility, not merely text

Create the method at its destination, redirect the old method temporarily if callers need a gradual migration, then remove the forwarding method when it is safe. Check access to private fields, overridden methods, side effects, and external API users before deleting anything.

A separate calculator can be appropriate when pricing is an independent policy used with many trip types, or when the model intentionally uses plain data and functions. Do not move a function into a class merely because it reads that class. Move it when the new home makes ownership and likely changes easier to understand.

Sources

  1. Martin Fowler — Move Function, also known as Move Method.