Sto lavorando su un programma di elaborazione dati Scala. In sostanza, iniziamo con una raccolta di molti piccoli oggetti di dati, ad esempio (eventId: String, basicInfo: Basic)
e filtriamo gradualmente alcuni oggetti e aggiungiamo ulteriori informazioni unendoci alle raccolte originali con altre origini dati (in genere sul campo eventId
) o calcolando nuove campi come funzioni dei campi esistenti.
Ora, sto avendo un certo problema a progettarlo correttamente. È piuttosto ad hoc ora: l'elemento di dati originale è modellato come case class FirstStage(eventId: String, basicInfo: Basic)
e le fasi successive sono modellate in modo compositivo: case class SecondStage(first: FirstStage, someOtherId: Long)
e così via. Ne risultano catene di accessori piuttosto brutte (ad esempio third.second.first.basicInfo
) e rende il codice molto difficile da modificare. Ad esempio, potremmo voler cambiare qualche funzione persist:ThirdStage =>
per operare invece o in aggiunta su SecondStage
, ma la mancanza di polimorfismo nel design lo rende piuttosto difficile.
Un'idea potrebbe essere quella di iniziare con lo stadio terminale, inizialmente impostare tutti i suoi campi su null, e gradualmente riempirli, ma sembra come se sarebbe difficile tenere traccia di ciò che accade quando. Oppure, potremmo abbandonare le classi case per avere SecondStage
estendere FirstStage
e così via, ma penso che sia probabile che il programma perderà la sua linearità nei prossimi mesi, il che renderà l'approccio di ereditarietà piuttosto grossolano.