I’m posting this question as language and framework agnostic since I think it may be general to ORM Frameworks.
I’m wondering if anyone can tell me if there is a design pattern for the following use case:
The Use Case
The system is a Model-View-Controller web application running with an ORM Framework.
There are two entities in play Poll and Vote.
One Poll has a one-to-many relationship with Vote and votes are in a collection which is Lazy Loaded.
Each user in the system can only vote on a poll once.
For the sake of user experience it would be nice for the View to adapt by showing controls only for polls on which the current user has not yet voted therefore Poll has a method (in pseudocode):
public boolean hasVoteFor(user) {
for each vote
if vote.user == user
return true
return false
}
So that when the View is passed a Poll by the Controller it can render the correct controls by doing an if poll.hasVoteFor(user).
The Problem
The problem with the above method is that, since the collection is Lazy Loaded, iterating over it could become very memory & db intensive.
Using SQL/DQL/SQL you can obviously use the database to directly query the Poll entities on which a user has voted, however any such query should occur in a repository which I’m assuming that the View should not have access to.
Solutions?
So I’m wondering if there is a design pattern to solve this.
-
Should the
Controllerhave a method such ashasVoteFor(poll, user)? This is problematic if the view renders multiple polls. (A query with many criteria for each poll would be faster rather than doing many selects as theViewiteratesPolls that it is given.) -
Should the
Controlleruse a repository to query all thePolls that a user has voted on up front and pass it to theViewalong with thePoll(or array ofPoll). This kind of breaks the neat abstraction of aPollhaving ahasVoteFormethod – isn’t ORM supposed to let you only think about your objects? 😉 -
Some other solution commonly used in practice that I’m overlooking?
An ORM is just a tool to help you with your database. But the database is still the best tool you have to efficiently query for the data you want to display. And using an ORM without understanding and caring about the database and the queries that are generated is a recipe for disaster.
Your second solution is better than the first one, but it’s still not as logical and efficient as it could be.
Instead of querying for the poll or polls to display, and then querying for the polls that a user has voted on, and passing these two collections to the view, the controller could execute a query which returns a list of PollWithVoteFlag instances, containing each poll data, along with a flag indicating if the poll has been voted on by the user.