Al lavoro mi è stato assegnato un compito per indagare sulla grave lentezza di un'applicazione che non conosco. Richieste semplici richiedevano diversi minuti per risolverlo.
Ecco com'era prima (semplificando):
-
Esiste un metodo di facciata per ottenere un sottoinsieme di informazioni sugli ordini, con i clienti
-
Esiste un CustomerDAO, costruito attorno ai principi CRUD
-
Esiste un OrderDAO, costruito attorno ai principi CRUD
-
Il metodo della facciata chiama
OrderDAO.find(...)
, quindi per ogni ordine chiamaCustomerDAO.find(order.getCustomerId())
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 callfind(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.
Ancora più importante, la facciata restituisce solo un sottoinsieme delle informazioni recuperate presenti nel modello. Alcuni dati con una propria query all'interno della logica DAO sono stati scartati.
All'inizio ho cercato di preservare l'architettura corrente aggiungendo una cache e ottimizzando alcune chiamate ridondanti, ma i risultati erano ancora mediocri.
Ho risolto il problema della lentezza eseguendo una query di database che unisce le tabelle e creando i modelli di sottoinsieme invece di creare i modelli completi, riducendo il tempo di elaborazione da alcuni minuti a un paio di secondi. La firma della facciata rimane invariata.
Tuttavia, ritengo che questa soluzione sia completamente fuori luogo rispetto al resto dell'applicazione. La logica che si verifica all'interno di questo nuovo metodo è molto specifica. Inoltre, non restituisco più clienti o ordini, quindi questa nuova strategia non sembra appartenere ai DAO.
Quale sarebbe un approccio corretto per affrontare un problema di prestazioni che è facilmente risolvibile bypassando i DAO orientati a CRUD? In genere se ho più DAO orientati al CRUD ma ho bisogno di un qualche tipo di dati di grandi dimensioni, cosa dovrei fare?