A readonly class that needed one mutable field, and what that meant

A readonly value object that wanted a lazily computed cache, which is exactly what readonly forbids and is usually a signal.

final readonly class Report
{
    // this cannot exist
    private ?array $computed;
}

// the three options:
//   1  drop readonly. loses the guarantee for one field.
//   2  a separate memoising wrapper. one more class.
//   3  compute in the constructor. eager, and here it
//      is 40ms that is always needed.

// we took (3).

The wrapper is the textbook answer and adds a class whose only purpose is to hold a cache, which is worth it when the computation is expensive and conditional. Ours was neither — every caller used the value — so the laziness was a habit rather than a requirement, and the constructor was the honest place.