Claude-skill-registry acc-create-null-object

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

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/acc-create-null-object" ~/.claude/skills/majiayu000-claude-skill-registry-acc-create-null-object && rm -rf "$T"
manifest: skills/data/acc-create-null-object/SKILL.md
source content

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
Interface
src/Domain/{BoundedContext}/
Null Object
src/Domain/{BoundedContext}/
Real Implementation
src/Domain/{BoundedContext}/
Unit Tests
tests/Unit/Domain/{BoundedContext}/

Naming Conventions

ComponentPatternExample
Interface
{Name}Interface
CustomerInterface
Real Implementation
{Name}
Customer
Null Object
Null{Name}
NullCustomer
Test
{ClassName}Test
NullCustomerTest

Neutral Return Values

TypeNeutral Value
string
''
(empty string)
int
0
float
0.0
bool
false
array
[]
void
No 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