Facade Pattern
debt(d7/e5/b5/t3)
Closest to 'only careful code review or runtime testing' (d7). The detection_hints indicate automated detection is 'no' and the only listed tool is phpstan, which cannot reliably identify that 5+ objects are being coordinated where a facade should exist — this is a structural/design judgment call that requires careful code review rather than automated tooling.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix describes creating a facade class that unifies a subsystem's interface. This means identifying all client call sites coordinating multiple subsystem objects, writing the facade class, and updating callers — spanning multiple files. It is more than a one-liner but falls short of a cross-cutting architectural rework.
Closest to 'persistent productivity tax' (b5). The facade applies broadly across web, cli, and queue-worker contexts. Common mistakes include facades growing into god classes or being misused (especially Laravel static proxies affecting testability), imposing a persistent tax on maintainers who must understand the facade boundary and keep it thin. It doesn't reshape the entire system but does affect multiple workstreams.
Closest to 'minor surprise (one edge case)' (t3). The canonical misconception is that the facade completely hides and prevents direct subsystem access, when in fact direct access remains available. This is a mild but real surprise — the facade is a convenience layer, not a hard encapsulation boundary. The Laravel static proxy confusion adds a secondary edge case around testing, keeping this at t3.
Also Known As
TL;DR
Explanation
The Facade pattern defines a higher-level interface that makes a subsystem easier to use. Rather than coordinating multiple subsystem classes directly, clients call the Facade which delegates internally. This reduces coupling between clients and the subsystem, simplifies APIs for common use cases, and provides a single seam for testing the subsystem in isolation. In PHP frameworks, facades are pervasive: Laravel's static facade classes (Cache::get(), Mail::send()) are thin proxies to the underlying container-managed services. The key trade-off: facades improve usability but can hide complexity and complicate static analysis.
Common Misconception
Why It Matters
Common Mistakes
- Facades that expose the entire subsystem API — they simplify nothing and add an unnecessary layer.
- Forgetting the facade is an entry point, not a god class — keep it thin and delegate to subsystem components.
- Using Laravel's static Facade proxies and not understanding they resolve from the service container — makes testing harder if not using facades correctly.
- Testing through the facade instead of testing subsystem components directly — leads to slow, brittle tests.
Code Examples
// Direct subsystem coordination in the client — what a facade should hide:
$encoder = new VideoEncoder();
$storage = new CloudStorage();
$notifier = new NotificationService();
$encoder->encode($file);
$url = $storage->upload($encoder->getOutput());
$notifier->notify($userId, $url); // Client manages all coordination
// Complex subsystem
class VideoEncoder { public function encode(string $file): string { ... } }
class ThumbnailGen { public function generate(string $file): string { ... } }
class StorageUploader { public function upload(string $file): string { ... } }
// Facade — one simple interface for a common use case
class VideoUploadFacade {
public function __construct(
private VideoEncoder $encoder,
private ThumbnailGen $thumbs,
private StorageUploader $storage,
) {}
public function upload(string $rawFile): UploadResult {
$encoded = $this->encoder->encode($rawFile);
$thumbnail = $this->thumbs->generate($encoded);
$url = $this->storage->upload($encoded);
return new UploadResult($url, $thumbnail);
}
}