Quale design scegliere per l'analisi di file diversi per popolare classi diverse?

7

Attualmente sto lavorando a un progetto che richiede l'analisi di diversi tipi di file. Il contenuto dei file popolerà le classi.

eg: file1 populate content of class1,  file2 populate content of class2, etc.

La mia domanda è dove dovrebbe andare la logica di analisi del file?

1st option : se inserisco la logica di analisi all'interno della classe, la classe diventa davvero enorme, perché attualmente la classe stessa è ~ 400 linee e crescerà in futuro. Il vantaggio di questo modo è che le cose sono davvero semplici, potrei usare operator > & gt ;, ecc.

2nd option : crea una nuova classe che prende std::istream e riferimento di classe, esegue la logica di analisi e popola la classe. Il vantaggio di questo modo di fare è che se la classe rimane la stessa ma la formattazione del file cambia,

eg: 'file1 populate content of class1 or file1-v2 populate content of class1'

Devo usare il polimorfismo per modificare la logica di analisi e mantenere il design semplice. Lo svantaggio di questa opzione è, è un po 'complesso ma posso conviverci.

Quale opzione pensi sia migliore o ci sono altre opzioni migliori?

    
posta vanta mula 17.10.2017 - 01:41
fonte

2 risposte

9

Le classi dovrebbero avere una singola responsabilità . Presumibilmente, la responsabilità di analizzare un file per popolare una classe e le responsabilità della classe stessa sono distinte e non dovrebbero essere combinate. Quindi la seconda opzione è il design migliore.

È piuttosto comune che i formati dei file cambino man mano che si sviluppa un sistema e, separando questa preoccupazione ora, ti troverai in una buona posizione se il formato del file o la classe che stai popolando cambiano. È anche un design che consente una maggiore flessibilità - ad es. se decidi di voler popolare la tua classe dalla rete, un diverso formato di file, ecc.

    
risposta data 17.10.2017 - 03:28
fonte
9

Se l'analisi è più complessa di alcune righe di codice, è probabilmente meglio metterla in classi separate, chiamiamole Class1Parser , Class2Parser e così via. Se quelle classi contengono parti simili, puoi

  • crea una classe base comune BaseParser per entrambi i luoghi in cui le parti riutilizzabili vivono

  • crea una classe di utilità separata ParserUtil per le funzioni riutilizzabili

  • trasforma il parser in una classe generica come Parser<T> dove T è o Class1 o Class2

  • usa una combinazione delle precedenti opzioni (ad esempio, rendendo solo ParserUtil o BaseParser generico)

Si noti che una gerarchia di ereditarietà dei parser ora può essere indipendente dalla gerarchia di ereditarietà delle classi analizzate, questo non sarebbe possibile mettendo la logica di analisi direttamente in Class1 / Class2 .

Nessuna di queste opzioni dovrebbe trattenerti dall'implementare un operator>> per Class1 o Class2 , se pensi di averne bisogno per facilità d'uso. Questo operatore può semplicemente delegare la sua funzionalità a un oggetto di tipo Class1Parser o Class2Parser .

Se questi approcci finiscono per diventare più complessi di mettere la logica del parser in Class1 o Class2 , allora c'è qualcosa di completamente sbagliato nel tuo codice. In sostanza, dovrebbe essere la stessa logica . Mettendo la logica di analisi in classi separate, rimane disaccoppiata da altri metodi in quelle classi, che dovrebbero ridurre la complessità complessiva, non aumentarla.

    
risposta data 17.10.2017 - 05:19
fonte

Leggi altre domande sui tag