At work I was assigned a task to investigate on the severe slowness of an application I am not familiar with. Simple requests were taking several minutes to resolve.
Here's how it was before (simplifying):
There is a facade method to get a subset of information about orders, with the customers
There is a CustomerDAO, built around CRUD principles
There is a OrderDAO, built around CRUD principles
The facade method calls
OrderDAO.find(...), then for each order, calls
I'm oversimplifying here, I'll pass most of the details. This isn't even orders and customers I had to deal with, and there are other DAOs called in the process. You have to trust me when I say that the matter was much more complicated than this, the amount of redundant calls was absurd.
There was a case where a
findBy(...)method returned all the parents and each parent had a list of children, but for some reason within the DAO logic it would call
find(parentId)for the child, so the parent's model was present 1 + the number of children times in the returned model, totaling 1 + the number of children x 2 queries per parent. I don't know why the children have a copy of their parent, but it's done that way; enhancing that would be out of the scope of my activities.
More importantly, the facade only returns a subset of the retrieved information present in the model. Some data that had their own query within the DAO logic was discarded.
At first I tried to preserve the current architecture by adding a cache and optimizing some redundant calls, but the results were still mediocre.
I have solved the slowness issue by performing a database query joining the tables and building the subset models instead of building the complete models, reducing the processing time from several minutes down to a couple seconds. The facade signature remains unchanged.
However I feel like this solution is completely out of place in regards to the rest of the application. The logic happening within that new method is very specific. In addition, I am no longer returning Customers or Orders, so this new strategy does not seem to belong in either DAOs.
What would be a correct approach of dealing with a performance issue that happens to be easily solvable by bypassing CRUD oriented DAOs? Typically if I have multiple CRUD oriented DAOs but I need some kind of large data join, what am I supposed to do?