Throw exceptions in repositories
Here's why you should consider throwing exceptions in your repositories.
99% of the time you're going to want to bail if you're expecting to find an entity by a specific key. Having code like the two private methods in the old code below in every single one of your handlers is crazy and not DRY.
I think the idea of "only throw exceptions when something exceptional happens" is too generic and doesn't take context into consideration.
A repository's only job is to find entities. If you give it a key and it can't find it, i think that's exceptional(in the context of the repository).
If it actually is expected in your client code it's not a big deal, catch the EntityNotFoundException
and carry on.
This also unifies the types of exceptions thrown. It is entirely possible some handlers could be throwing a EntityNotFoundException
while your partner developer is throwing a ValidationException
. Encapsulate that in the repository.
class AddPersonCommandHandler
{
private $categories;
private $people;
public function __construct(CategoryRepsoitory $categories, PersonRepository $people)
{
$this->categories = $categories;
$this->people = $people;
}
public function handle(AddPersonCommand $command)
{
$category = $this->findCategory($command->getCategoryId()));
$referrer = $this->findPerson($command->getReferrerId());
$person = new Person(
$command->getName(),
$category,
$referrer
);
$this->people->add($person);
}
private function findCategory($id)
{
if (null === $category = $this->categories->find($id)) {
throw new EntityNotFoundException("Cateogry not found.");
}
return $category;
}
private function findPerson($id)
{
if (null === $person = $this->people->find($id)) {
throw new EntityNotFoundException("Person not found.");
}
return $person;
}
}
Becomes:
class AddPersonCommandHandler
{
private $categories;
private $people;
public function __construct(CategoryRepsoitory $categories, PersonRepository $people)
{
$this->categories = $categories;
$this->people = $people;
}
public function handle(AddPersonCommand $command)
{
$category = $this->categories->find($command->getCategoryId());
$referrer = $this->people->find($command->getReferrerId());
$person = new Person(
$command->getName(),
$category,
$referrer
);
$this->people->add($person);
}
}
Categories: PHP