Weapons—an essential part of going into battle. Some prefer blades, some prefer swords, and others prefer spears. The choice of weapon depends on the opponent, the fighting style, the terrain… in short, it’s about choosing the most suitable one. This decision determines 70-80% of the chance of victory.
Coding is the same. Our weapons are the tools and design patterns recognized by the community for their value. But they aren’t always suitable for every project. My perspective is this: there are only suitable weapons, not a single best weapon for every fight. Sometimes, even with the right weapon, using it incorrectly is still a bad move. And if you choose the wrong one from the start, it’s even worse.
I work a lot with PHP—a language that seems worse the more I use it, yet it’s suitable for the job. I’m writing this article because a while ago, I was upgrading a system to improve its speed. When I wanted to apply caching, I hit a major roadblock: the Eloquent ORM was used in so many places that the upgrade became extremely difficult. Especially when I needed to fix one thing, I had to search through dozens of different files—a situation known as tight coupling. At that moment, I immediately thought of the Repository pattern, something I had read about before and deemed unnecessary, but now it seemed perfectly suited.
What’s so cumbersome about the Repository pattern? The answer is: a lot. Instead of writing a simple query like this:
// Writing directly with the ORM
$activeUsers = User::where('status', 'active')
->where('created_at', '>', '2024-01-01')
->orderBy('name')
->get();
You have to write a whole bunch of code like this:
// Create an interface
interface UserRepositoryInterface
{
public function getActiveUsers($fromDate = null);
}
// Implement the repository
class UserRepository implements UserRepositoryInterface
{
public function getActiveUsers($fromDate = null)
{
return User::where('status', 'active')
->when($fromDate, function($query, $fromDate) {
return $query->where('created_at', '>', $fromDate);
})
->orderBy('name')
->get();
}
}
// Inject it into the controller
class UserController
{
private $userRepository;
public function __construct(UserRepositoryInterface $userRepository)
{
$this->userRepository = $userRepository;
}
public function index()
{
$users = $this->userRepository->getActiveUsers('2024-01-01');
// ...
}
}
It looks redundant, but when the system grows and needs an upgrade, this “sledgehammer” starts to feel surprisingly light.
Taking my own case as an example, when I wanted to add caching to the system, I had to hunt down every single model call to modify it. If I had used a repository from the beginning, I would only have needed to change it in one single place. It’s like carrying a heavy sledgehammer—it’s a burden to carry, but when you need to break down a wall, nothing is more effective.
A repository creates an intermediary layer between your business logic and your data access logic. What if you want to switch from MySQL to MongoDB tomorrow? (I’m just using this as an example; personally, I’ve never actually swapped databases like this :D) You only need to change the implementation, and the business logic remains untouched. Want to cache data? Create a wrapper around the original repository. Want to test? Mocking an interface is far easier than mocking an entire ORM framework.
But the developer community often “flames” the repository pattern. The reason is understandable: ORM frameworks like Eloquent, Entity Framework, and Hibernate are already powerful enough, so why wrap them in another layer? Often, developers implement it incorrectly, creating “God Repositories” with hundreds of methods, making the code even more tangled. For small projects, a repository is indeed over-engineering.
My view remains: there is no single best weapon for every battle. The Repository pattern is like a sledgehammer—heavy and cumbersome, but incredibly effective when used at the right time. For small projects or prototypes, don’t use it. But if you want easier maintenance, or if you have a complex system that needs to be maintained for the long term, a repository will help you a great deal.
The most important thing is not to apply it blindly. Evaluate your project before you decide whether to “carry the sledgehammer” or not.
Bình luận