The static factory that should have been a constructor

A class with six static factory methods and a private constructor, where five of the factories did the same thing with different argument names.

// what it was
final class DateRange
{
    private function __construct(private DateTimeImmutable $from, ...) {}

    public static function between($a, $b): self { /* ... */ }
    public static function from($a, $b): self { /* ... */ }
    public static function of($a, $b): self { /* ... */ }
    public static function create($a, $b): self { /* ... */ }
    // and two that genuinely differ
    public static function month(int $y, int $m): self { /* ... */ }
    public static function today(): self { /* ... */ }
}

Named constructors earn their place when they encode a distinct way of building the thing — month() and today() do, and the four synonyms do not. The rule I settled on is that a factory must either take different arguments or apply a different rule; if it only renames new, it is an alias, and an alias in a public API is a thing every future reader has to check is not subtly different.