Ecco uno scenario in cui ho riscontrato variazioni in molte occasioni.
Immagina un feed XML che visualizza i dati relativi a tre diversi tipi di eventi: concerti, giochi e film. Ognuno ha un diverso set di parametri. Vogliamo racchiudere queste informazioni e memorizzarle per i nostri scopi. Quindi creiamo un database che contiene dati applicativi e tre tabelle per questi dati che chiameremo event_concert, event_play ed event_movie. Attacchiamo un ORM in cima.
Ogni ora eseguiamo il polling del feed, alla ricerca di nuovi dati e al salvataggio nel nostro database. Poiché il nostro ORM crea oggetti tipizzati, ci sono essenzialmente due modi in cui possiamo farlo.
Per prima cosa, scrivi tre funzioni separate, una per ciascun tipo di oggetto, che creano e popolano l'oggetto necessario e lo inseriscono nel database. Questo è pulito e facilmente comprensibile. Ma è più codice da scrivere e non è necessariamente il migliore per la manutenzione, dal momento che si aggiungono nuove funzioni per gestire nuovi tipi di oggetto e c'è il rischio di duplicare il codice.
In secondo luogo, scrivi un singolo loop che usa le varie funzioni di reflection del contesto ORM per iterare sui tipi di oggetto (usando un prefisso fisso come event_ per riconoscerli), quindi scorre le proprietà per popolarle prima di salvare nel Db . Questo è complicato e difficile da capire, ma fatto bene dovrebbe essere un'opzione "fire-and-forget" che raccoglierà semi-automaticamente e gestirà nuovi tipi di oggetti con un minimo di confusione.
In questo esempio è facile andare con la prima opzione poiché ci sono solo tre oggetti da salvare. Ma cosa succede se ce ne sono cinque? O cinquanta? O più? Gestire all'improvviso tutti quegli oggetti diversi con le loro funzioni personalizzate non sembra più così attraente.
Esiste un altro approccio o modello di progettazione che raggiunge un risultato simile ed è sia pulito che in grado di gestire molti tipi di oggetto?
Ecco un esempio di cosa intendo in pseudocodice.
Se consideriamo gli oggetti come tipi diversi:
GetAndInsertConcerts();
GetAndInsertMovies():
GetAndInsertPlays();
// if we need a fourth object type, we'll need to add a new function
public void GetAndInsertConcerts()
{
var xmlConcerts = GetObjectsFromXML("Concerts");
foreach(var xmlConcert in xmlConcerts)
{
Event_Concert c = new Event_Concert(xmlConcert);
repository.InsertAndSave(c);
}
}
// the functions for plays and movies will repeat this structure
E il secondo approccio:
string[] eventTypes = repository.GetTablesStartingWithEvent();
foreach(string eventType in eventTypes)
{
string xml = GetXmlForEventType(eventType);
// BuildObjectFromXml function is reflection based, likely hard to code & to follow
var obj = BuildObjectFromXml(xml);
repository.InsertAndSave(obj);
}
Vale la pena ripeterlo - il boilerplate nel primo approccio va bene se hai a che fare con una manciata di tipi di oggetti che non ti aspetti di cambiare. Ma scrivere funzioni ripetute "ottieni e salva" per un sacco di tipi di oggetti diversi sta diventando noioso.