Skip to main content

Depend on Abstractions

The Dependency Inversion Principle says: high-level code — your business logic — should not depend on low-level details like a specific database or file format. Both should depend on an abstraction: in PHP, an interface.

The "inversion" is the direction of the arrow. Instead of the service pointing at one concrete storage, the service points at an interface — and every storage points at that same interface from the other side.


Hard-Wired to the Details

This user service creates and uses a concrete DiskStore directly. It works — but the service is welded to one storage. A different store, a faster store, a fake store for tests: every one of them means editing the service itself.

The service welded to its storage

UserService builds its own DiskStore inside. High-level registration logic now depends on a low-level detail — the file on disk.

Prompt
Write a PHP script showing a Dependency Inversion violation: a UserService whose register method uses a concrete DiskStore created inside the service, printing that the user was written to a file on disk. Register one user.
Output: PHP script

Invert the Dependency

The fix: the service asks for a Storage interface in its constructor and never learns which one it got. The disk store and the memory store both implement the interface.

Now the arrow points from both sides to the abstraction — and swapping the storage is a one-line change at the place where the service is created, not inside it.

The service accepts an interface

Same registration logic, two different storages. new UserService(new DiskStore()) or new UserService(new MemoryStore()) — the service code itself never changes.

Prompt
Invert the dependency in PHP: define a Storage interface with a save method, a DiskStore and a MemoryStore that implement it, and a UserService whose constructor accepts any Storage. Register one user through the disk store and one through the memory store to show the swap without changing the service.
Output: PHP script
The service accepts an interface

The payoff: testing without a disk

Because the service depends on the abstraction, a test can hand it a memory store and check the result instantly — no files, no cleanup. Dependency inversion is what makes code easy to unit-test.

Prompt
Show the testing payoff of Dependency Inversion in PHP: give MemoryStore a record of saved users, hand it to the UserService, register two users, and verify the memory store holds both, printing the check result like a small test.
Output: PHP script