← Home ← Codex ← DEBT ← Engine
Browse by Category
+ added · updated 7d
← Back to glossary

Null Object Pattern

Code Quality PHP 5.0+ Intermediate
debt(d5/e3/b3/t5)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The detection_hints list phpstan and psalm as tools, both static analysis specialists. The code_pattern identifies repeated null checks as a candidate — this is not caught by a compiler or default linter but requires a configured SAST/type-checker to surface the pattern.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix describes creating a NullLogger or GuestUser implementing the same interface — a small, focused refactor within one component. It is more than a single-line patch (you must create a new class and wire it in) but does not span multiple files cross-cuttingly in the typical case.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). The pattern applies to web, cli, and queue contexts broadly, but its structural burden is localised — once the NullObject class exists and is injected at one seam, the rest of the codebase is largely unaffected. It does not impose a persistent productivity tax on many work streams.

t5 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'notable trap' (t5). The misconception field states that developers think it is just a way to avoid null checks, missing that it eliminates entire conditional branches structurally. The common_mistakes reinforce additional traps: partial interface implementation, returning null from null-object methods, and silently swallowing meaningful nulls — all documented gotchas that competent developers eventually learn.

About DEBT scoring →

Also Known As

null object pattern NullObject do-nothing object

TL;DR

Replace null with an object that implements the expected interface but performs no operation, eliminating null checks throughout the codebase.

Explanation

The Null Object pattern (Bobby Woolf) provides a do-nothing implementation of an interface that can be used wherever a null check would otherwise be required. For example, a NullLogger that implements LoggerInterface but discards all messages replaces if ($logger !== null) $logger->log(...) checks everywhere. The Null Object makes the absence of something explicit and type-safe, simplifies calling code, and follows Tell Don't Ask. PHP 8+ Null Object are often combined with union types and nullsafe operators as complementary approaches.

Common Misconception

Null object pattern is just a fancy way to avoid null checks. It eliminates entire branches of conditional logic by providing a safe default behaviour — code that calls methods on a NullObject works without branching, making it structurally simpler.

Why It Matters

A null object implements the same interface as a real object but does nothing — it eliminates null checks at call sites and makes the absence of a thing an explicit, safe concept.

Common Mistakes

  • Not implementing the full interface — callers that use methods not on the null object still get null errors.
  • Null objects that return null from methods — they should return safe defaults (empty string, 0, empty array).
  • Using null objects where an Optional/Maybe type better communicates the possible absence.
  • Applying null objects everywhere — sometimes null carries meaning that should be handled, not silently swallowed.

Code Examples

✗ Vulnerable
// Null checks spread throughout call sites
$discount = $user->getDiscount();
$price = $discount !== null ? $price * (1 - $discount->rate()) : $price;
✓ Fixed
interface Discount {
    public function apply(float $price): float;
}

class PercentDiscount implements Discount {
    public function __construct(private float $rate) {}
    public function apply(float $price): float { return $price * (1 - $this->rate); }
}

class NullDiscount implements Discount {
    public function apply(float $price): float { return $price; } // no-op
}

// Now: no null check needed at call sites
$price = $user->getDiscount()->apply($price);

Added 15 Mar 2026
Edited 22 Mar 2026
Views 60
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 1 ping T 0 pings F 3 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S
No pings yet today
No pings yesterday
Ahrefs 6 Google 6 SEMrush 6 Scrapy 4 PetalBot 4 ChatGPT 3 Perplexity 2 Claude 2 Bing 2 Applebot 2 Meta AI 1 Majestic 1 Twitter/X 1
crawler 32 crawler_json 8
DEV INTEL Tools & Severity
🟢 Low ⚙ Fix effort: Low
⚡ Quick Fix
Create a NullLogger or GuestUser that implements the same interface as the real object but does nothing — callers never need to check for null
📦 Applies To
PHP 5.0+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
Repeated null checks: if ($logger !== null) $logger->log() — candidate for Null Object pattern
Auto-detectable: ✓ Yes phpstan psalm
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: Medium Context: Class Tests: Update


✓ schema.org compliant