Skip to content
acc-create-null-object logo

Null Object Pattern Generator

acc-create-null-object

Generates Null Object pattern for PHP 8.5. Creates safe default implementations eliminating null checks. Includes unit tests.

SKILL.md

Full skill instructions

Null Object Pattern Generator

Creates Null Object pattern infrastructure for eliminating null checks.

When to Use

ScenarioExample
Optional dependenciesLogger, Cache, Notifier
Missing entitiesCustomer, User, Product
Feature togglesDisabled feature returns null object
Default implementationsNo-op defaults

Component Characteristics

Interface

  • Defines expected behavior
  • Shared by real and null implementations
  • Enables polymorphic usage

Null Object

  • Implements interface with no-op behavior
  • Returns neutral values
  • Never throws on calls

Benefits

  • Eliminates null checks
  • Follows Liskov Substitution
  • Simplifies client code

Generation Process

Step 1: Generate Interface

Path: src/​Domain/​{BoundedContext}/

  1. {Name}Interface.php — Interface with isNull() method

Step 2: Generate Null Object

Path: src/​Domain/​{BoundedContext}/

  1. Null{Name}.php — Null implementation returning neutral values

Step 3: Generate Real Implementation

Path: src/​Domain/​{BoundedContext}/

  1. {Name}.php — Real implementation with business logic

Step 4: Generate Tests

  1. Null{Name}Test.php — Null object behavior tests

File Placement

ComponentPath
Interfacesrc/​Domain/​{BoundedContext}/
Null Objectsrc/​Domain/​{BoundedContext}/
Real Implementationsrc/​Domain/​{BoundedContext}/
Unit Teststests/​Unit/​Domain/​{BoundedContext}/

Naming Conventions

ComponentPatternExample
Interface{Name}InterfaceCustomerInterface
Real Implementation{Name}Customer
Null ObjectNull{Name}NullCustomer
Test{ClassName}TestNullCustomerTest

Neutral Return Values

TypeNeutral Value
string'' (empty string)
int0
float0.0
boolfalse
array[]
voidNo return
ObjectEmpty/​default instance
CollectionEmpty collection

Quick Template Reference

Interface

interface {Name}Interface
{
    public function {method1}(): {returnType1};
    public function {method2}({params}): {returnType2};
    public function isNull(): bool;
}

Null Object

final readonly class Null{Name} implements {Name}Interface
{
    public function {method1}(): {returnType1}
    {
        return {neutralValue1};
    }

    public function isNull(): bool
    {
        return true;
    }
}

Real Implementation

final readonly class {Name} implements {Name}Interface
{
    public function __construct({properties}) {}

    public function {method1}(): {returnType1}
    {
        return {realImplementation};
    }

    public function isNull(): bool
    {
        return false;
    }
}

Usage Example

Repository Returning Null Object

final readonly class DoctrineCustomerRepository implements CustomerRepositoryInterface
{
    public function findById(CustomerId $id): CustomerInterface
    {
        $row = $this->connection->fetchAssociative(
            'SELECT * FROM customers WHERE id = :id',
            ['id' => $id->toString()]
        );

        if ($row === false) {
            return new NullCustomer();
        }

        return $this->hydrate($row);
    }
}

Client Code Without Null Checks

final readonly class CreateOrderUseCase
{
    public function execute(CreateOrderCommand $command): Order
    {
        $customer = $this->customers->findById($command->customerId);

        // No null check needed - NullCustomer returns 0.0
        $discount = $customer->getDiscount();

        $order = Order::create(
            customerId: $customer->id(),
            items: $command->items,
            discount: $discount
        );

        return $order;
    }
}

Anti-patterns to Avoid

Anti-patternProblemSolution
Throwing in NullUnexpected exceptionsReturn neutral values
No isNull()Can't detect null objectAdd isNull method
Different InterfaceLSP violationSame interface as real
Side EffectsUnexpected behaviorPure no-op methods
Complex LogicNot a null objectKeep simple and neutral

References

For complete PHP templates and examples, see:

  • references/​templates.md — Interface, NullObject, Real Implementation, NullLogger, NullCache templates
  • references/​examples.md — NullCustomer, NullNotifier, Repository integration examples and tests