In an MVC framework like Rails, the overall consensus is to put business logic in the model. However, when it comes to logic like "get all problems that a user solved", I am not sure which model class I should put the logic, as the it needs to first look up all solutions submitted by the user, and collect the problem id from each solution, then the problem ids to get all the problems needed.
It feels more elegant to put it in the User model, so we can call something like user.getAllProblemsSolved()
. However, all we need from the user instance is the user id. In places where no user instance is readily available, we have to create one just to call its getAllProblemsSolved
method.
What is more, as the logic mainly deal with Problem and Solution models, it smells Feature Envy to put it in the User model. To avoid Feature Envy, it feels equally fine to put in Problem or Solution. Intuitively, I would put it in Problem to be like Problem.getAllProblemsSolvedBy(userId)
, but I don't have good justification for that.
So where should I put that logic?
I can see that the relation between Problem
and User
is an m2m relation, so if you want to follow the rules and put the business logic in the model class, you can put getAllProblemsSolvedBy
in the model class that is representing the m2m relationship, but using that logic the getAllProblemsSolvedBy
will return problems ids, and then you'll have to get the problems from the Problem
model class.
I would put it in the Problem
model class as the method will return instances of Problem
class.
Update Apr 23 2014, 07:00 UTC
Note also that the m2m class, Solution
in your case, depends on the existence of those two models User
and Problem
, so you can query both models from within this model, and therefore if I had an m2m model in my code I'd let it usually be responsible for querying both ends of the m2m relationship.
So for example in your case the getAllProblemsSolvedBy
can be implemented in the Solution
model class and it can return a list of Problem
instances and can be passed an instance of User
.