Prendere una decisione progettuale sulla lettura dei dati del modello da un file di input

2

Sto scrivendo un software ad elementi finiti in C ++ e Qt. Voglio caricare i dati di input sul modello. Ho una classe Model che contiene i dati e fa il lavoro. Ho creato un semplice lexer e parser per leggere il file di input (cose che assomigliano ai record del database). Non ho l'esperienza per prendere una decisione informata su come collegare la classe del lettore di file e la classe del modello. Ho due opzioni:

1) Nel modello di classe, creare un metodo per caricare il file, ad es. in pseudocode:

 class Model
 {
   // private fields

   public:
     loadFile( filename )
  }

2) Questo:

class Lexer(input filename)
{
    ...
    loadToModel(Model&)  // red the input filename into the Model.
}

Quale è meglio o ha più senso? Quali sono i pro e i contro di ciascuno?

    
posta Ring Zero. 15.11.2018 - 09:17
fonte

1 risposta

5

Sebbene il codice nella tua domanda non sia molto chiaro, la mia comprensione è che stai proponendo di creare un oggetto da alcuni dati di input. Descrivi due opzioni:

  1. Rendi il caricamento dei dati un metodo pubblico. Ci sono alcuni aspetti positivi a questo aspetto. È una chiara violazione del principio di responsabilità unica e associa la rappresentazione in memoria del modello alla sua rappresentazione su disco. Questo di solito non è una cosa molto buona. Inoltre, potenzialmente lascia il tuo modello in uno stato non valido dopo la creazione, che è anche molto soggetto a errori. È molto meglio avere classi che non sono mai in stati non validi quando possibile. Un leggero miglioramento sarebbe quello di rendere questa una funzione membro statica , piuttosto che un metodo di istanza.

  2. Passa un'istanza esistente a un caricatore separato. Questo è un approccio un po 'migliore se, ancora, il tuo oggetto modello non ha stati non validi. E se il tuo modello non ha stati non validi, allora dovrebbe essere banale inizializzare uno predefinito costruito all'interno della funzione, piuttosto che prendere un riferimento come parametro.

La soluzione migliore, quindi, è la regolazione che ho menzionato in (2). Progetta il tuo modello in modo che un'istanza costruita in modo predefinito sia valida , quindi scrivi un metodo in Lexer (forse rinominato in "ModelLoader" o "Parser" poiché sta facendo più di lexing ) per caricare un file dal disco e compilare una nuova istanza Model , quindi restituirla. Nel moderno C ++, l'ottimizzazione del valore di ritorno garantito (RVO) dovrebbe alleviare eventuali dubbi che potresti avere nel restituire un oggetto di grandi dimensioni.

Idealmente, il tuo loader / deserializzatore prenderà anche un flusso di input di qualche tipo, piuttosto che un nome file direttamente. Il QDataStream di Qt, ad esempio, può essere astratto su diversi supporti (unità, rete, buffer in memoria, ecc.)

Se hai bisogno (o vuoi) che il tuo Model sia immutabile, puoi utilizzare il Modello di generatore per mettere in scena gli aggiornamenti a Model prima di costruirlo effettivamente.

    
risposta data 15.11.2018 - 09:36
fonte

Leggi altre domande sui tag