Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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
share|improve this question
3  
I would rather ask myself if a validation_date really is a part of a user? to me, that's a violation of SRP. validation_date, password, activation code etc belongs rather to an Account used to login an User. Else the User entity got two reasons to change: Changed account details and changed user details –  jgauffin Dec 12 '12 at 7:42
    
@jgauffin: I guess coderabbi uses "user" as a synonym for "account", in the sense that it stores the data about the "user account" ;) –  arnaud Dec 12 '12 at 10:51
    
What would be the point of returning objects if you weren't going to access their members?! –  AakashM Dec 12 '12 at 11:08
    
I dont mean to sound like a dick.. but this has to be the first time I've seen a PHP developer actually concerned about these principles.. I salute you though :) –  Simon Whitehead Dec 12 '12 at 11:10
1  
How about $validation_date = $users_repository->getUser($user_id)->getUserValidationDate(); –  onlineapplab.com Dec 12 '12 at 11:49

2 Answers 2

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.

share|improve this answer

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.

share|improve this answer
    
I find it interesting that this answer was down-voted. I take dependency injection as pretty much a given (though admittedly in this partially contrived exampleI was assuming injection of the user repository rather than the user object itself). That approach may not be possible here, as the code in question exists at the 'outermost' level, the controller - my IoC container can inject the repository but not a specific object. The basis of the question then is how to get at the property once the injected repository is used to retrieve the user object. My upvote brings you to zero - thanks! –  coderabbi Dec 12 '12 at 14:39
    
I have no idea why it was downvoted either, perhaps because it wasn't detailed enough. Anyway, I believe the issue, then, is a workaround for a limitation of your IoC container rather than a purely OO conceptual one. From a pure OOP perspective it's always best to inject the smallest, simplest level needed. In this instance, you're getting $user_id from somewhere. Use a User object instead of a scalar $user_id and this is a non-issue. It may present practical problems due to higher level architectural decisions but from a OO purist perspective this is the ideal methodology. –  Tom B Dec 12 '12 at 14:53
    
@TomB I didn't downvote this answer, but on the surface it sounds odd because it seems to be saying that developers have to choose between Dependency Injection and Repositories as if they are mutually exclusive. Which is clearly not the case, and probably not what you are saying. –  Eric King Dec 12 '12 at 14:59
    
@Tom B - And if the $user_id comes from $_GET['user_id']? :) –  coderabbi Dec 12 '12 at 15:00
1  
I believe this highlights a SoC issue that is prevalant in most PHP frameworks that don't correctly implement MVC. In MVC proper, controllers don't contain domain logic. Ideally the program flow would be: Controller gets $id, pulls the user from the repo then passes it into a model method for validation. This way the controller never has an knowledge of domain logic and the model is agnostic about where its domain entity comes from -it shouldn't have to come from the repository see blog.astrumfutura.com/2008/12/… for more info –  Tom B Dec 12 '12 at 15:18

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.