È causato dal paradigma di programmazione ingenuo: concentrati su un singolo oggetto, fai qualcosa con esso, e se devi lavorare con molti oggetti, fai un loop, iterate e attraversi, ripetendo l'operazione su ogni oggetto che incontrerai . Questo di solito è o.k. per raccolte piuttosto piccole in memoria.
È sbagliato in un ambiente in cui un approccio basato su set può essere gestito molto meglio, o ogni singola operazione ha costi di gestione costosi, quindi è meglio raggrupparli. Tipicamente, database e servizi che richiedono connessioni e round trip per ogni operazione e possono gestire le operazioni di set molto meglio.
Ad esempio, un livello di accesso ai dati codificato in modo nativo caricherà una raccolta di oggetti radice / padre aggregati, quindi eseguirà un ciclo sulla raccolta per recuperare oggetti figlio per ciascuno e quindi su ogni oggetto figlio per recuperare oggetti "nipotino" per singole query , invece di creare una query per le righe / gli oggetti di dati successivi di tutti i genitori e poi tutti. Poiché un numero di genitori N richiede 1 query per i genitori e poi N per i loro figli, questo problema è noto come SELECT N + 1, che spesso mette in ginocchio database e prestazioni delle applicazioni.
Bad:
var parents = dbaccess.SelectParentsFromDb(fromDateTime, toDateTime);
foreach(var parent in parents)
{
parent.Children = dbaccess.GetChildrenForParent(parent.Id);
}
Buono:
var parents = dbaccess.SelectParentsFromDb(fromDateTime, toDateTime);
var parentIds = parents.Select(p => p.Id).ToArray();
var allChildren = dbaccess.GetChildrenForParents(parentIds);
foreach(var parent in parents)
{
parent.Children = allChildren
.Where(c => c.ParentId == parent.Id)
.toList();
}
Nella codifica diretta del database, come con PL / SQL o T-SQL, questo anti-pattern sarebbe visibile come un cursore DB per scorrere su righe, piuttosto che usare comandi SQL o DML basati su set. Questo è il motivo principale per cui i cursori sono di solito considerati pessimi nella programmazione di database.
Utilizzando servizi web o altre fonti remote, si possono verificare svantaggi analoghi; enorme overhead e perdita di tempo attraverso un gran numero di query / operazioni su singoli oggetti.
A volte, gli sviluppatori insistono su questo approccio "gestisci un oggetto, ripeti per più", almeno finché non ne riconoscono le conseguenze; per questo motivo, ho iniziato a chiamare questa "malattia ad un oggetto" anti-pattern.
C'è un nome più "ufficiale" per questo?