Architecturally speaking, which is the preferable approach (and why)?
$validation_date = $users_repository->getUser($user_id)->validation_date;
- Seems to violate Law of Demeter by accessing member of object returned by method call
- Seems to violate Encapsulation by accessing object member directly
$validation_date = $users_repository->getUserValidationDate($user_id);
- Seems to violate Single Responsibility Principle as $users_repository no longer just returns User objects
15
The technically ‘correct’ way to deal with this problem is to pass the correct User object into the method (or class) which is going to require “validation_date”. Where possible, Dependency Injecting the exact object required should always be favoured over injecting Repositories, ServiceLocators and factories. The smallest required component should be passed in to the method that requires it. The code in the question doesn’t really have a dependency on the repository but on the user.
It’s not a Law of Demeter violation because, as the question suggests, the code needs access to the validation date. It’s a Law of Demeter violation because the repository is only used as a gateway to other objects.
See http://misko.hevery.com/code-reviewers-guide/flaw-digging-into-collaborators/ for a detailed explanation of the problem and the best way to fix it.
9
Sometimes, picking what’s the most intuitive is the best rule of thumb.
Many people actually don’t even agree with the laws/rules/principles you stated. I.e. the functional programming is clearly going away from OO and tries to separate data from processing, I think nobody cares about LoD for such trivial stuff, and the Single Responsibility stuff, although nice, is sometimes hard to achieve in the real world.
That being said, IMHO and this particular example, I find the first alternative the most direct and intuitive.