views:

48

answers:

1

Here's a method in my Spring/Hibernate website's code that exemplifies my codebase:

public class UserVoteServiceImpl implements UserVoteService {

   @Autowired UserRepository userRepository;

   public static int getUserScore(long userId) {
     return userRepository.findUserById(userId).getScore();
   }
 }

I believe that this method violates the Law of Demeter, since it is making calls on the object returned by findUserById(). How can I change this code to obey the Principle of Least Knowledge?

+1  A: 

I don't think it's a violation of the Law of Demeter. It would be a violation if you were passing in some object, getting userId off of it, and using only the userid.

Here's an example that would be a violation:

public class UserVoteServiceImpl implements UserVoteService {

   @Autowired UserRepository userRepository;

   public static int getUserScore(SomeWrapper someWrapper) {
     return userRepository.findUserById(someWrapper.getUserId()).getScore();
   }
 }

But there's nothing wrong with delegating work within the implementation of your method, and there's nothing wrong with making a call on the object returned from the repository.

(Personally I'm not crazy about using services to wrap single dao calls, but that's a different problem.)

Currently I'm working on a codebase perpetrated by people who apparently never heard of LoD, full of stuff like

public Thing getThing(Integer id) {
    return new Beta().getGamma().getDelta().getEpsilon().getOmega().getThing(id);
} 

and initially I thought your example didn't rise to the same level of pathology as that. But after reading this blog post, which is where I got the above example, of course, I think I'd recommend you changing your method to

public class UserVoteServiceImpl implements UserVoteService {

   @Autowired UserRepository userRepository;

   public User getUser(Long userId) {
     return userRepository.findUserById(userId);
   }
 }

and letting the caller pull the score off the User. This change also has the benefit of having the application's service interface deal in domain objects, not in primitives.

Nathan Hughes