A logbook for curious waters
← Software Engineering Field Guide

Introduce Foreign Method

Before you begin: Functions, date values, and loops.

Introduce Foreign Method creates a helper for an operation that belongs with a type you cannot conveniently change. The helper accepts an instance of that type and clearly identifies the added operation. It does not modify the library itself. 1

Original version: scheduling repeats date arithmetic

A scheduler needs the next Monday-through-Friday date. This is a weekday rule, not a complete business calendar: it deliberately ignores public holidays.

public static class Scheduling
{
    public static DateOnly Next(DateOnly current)
    {
        DateOnly next = current.AddDays(1);
        while (next.DayOfWeek == DayOfWeek.Saturday ||
               next.DayOfWeek == DayOfWeek.Sunday)
        {
            next = next.AddDays(1);
        }
        return next;
    }
}

The platform’s DateOnly supplies day arithmetic, but not this application’s weekday rule. Copying the loop into another scheduler would duplicate that rule.

from datetime import date, timedelta


def next_date(current):
    next_day = current + timedelta(days=1)
    while next_day.weekday() >= 5:
        next_day += timedelta(days=1)
    return next_day

Python numbers Monday as 0 and Sunday as 6. The loop skips 5 and 6, but its location and generic name do not advertise a reusable weekday operation.

Refactored version: name the missing operation beside the library

public static class BusinessDates
{
    public static DateOnly NextWeekday(DateOnly current)
    {
        DateOnly next = current.AddDays(1);
        while (next.DayOfWeek == DayOfWeek.Saturday ||
               next.DayOfWeek == DayOfWeek.Sunday)
        {
            next = next.AddDays(1);
        }
        return next;
    }
}

A scheduler now calls BusinessDates.NextWeekday(current). The helper is ordinary application code operating on a library type; no inheritance or runtime modification is involved.

from datetime import date, timedelta


def next_weekday(current):
    next_day = current + timedelta(days=1)
    while next_day.weekday() >= 5:
        next_day += timedelta(days=1)
    return next_day

Place next_weekday in a date-helper module and import it where needed. Its name states the added rule; the built-in date type stays unchanged.

One helper, not a replacement standard library

Friday September 25, 2026 becomes Monday September 28 in both versions. The calculation is moved and named, not altered. Dates at the platform’s maximum representable value can still overflow; that limitation has not been removed.

For several related operations, a wrapper type may be useful; that is Introduce Local Extension. For one small rule, a helper is often enough. Prefer a platform-provided operation when it already has the semantics you need, and document domain assumptions such as weekends and holidays explicitly.

Sources

  1. Martin Fowler — Refactoring catalog, including the first-edition vocabulary.
  2. Microsoft — DateOnly.AddDays and Python — datetime, for the underlying date operations.