Design del codice: codice duplicato o buona implementazione

7

Sto lavorando sull'applicazione in C #, dove ho bisogno di serializzare e deserializzare alcune classi in / da XML. Queste operazioni saranno implementate nella libreria di classi. Ho scelto la classe XMLSerialization per serializzare / deserializzare queste classi in un file XML. Come sapete, questa implementazione usa la reflection, che ha la condizione che la classe serializzata / deserializzata abbia bisogno di avere un costruttore senza parametri. Tuttavia, la classe serializzata ha un parametro obbligatorio, che è un buon candidato come parametro per il costruttore, per essere sicuro che sia inizializzato correttamente. Ho creato una classe manager per la serializzazione con due metodi, uno per archiviare in file e uno per caricare da file. Ho pensato a più soluzioni:

  1. Per la classe serializzata creare due costruttori, uno senza parametri e l'altro con parametro obbligatorio. Questa classe può essere serializzata facilmente, ma può essere inizializzata male, il che può causare problemi (magari in altri luoghi, ad esempio se la classe viene utilizzata in qualsiasi servizio Web).
  2. Poiché questa implementazione è nella libreria di classi, è possibile creare una classe A (per serializzare), che sarà pubblica e avrà un costruttore con parametro obbligatorio. I metodi manager assumeranno come parametro questa classe A o restituiranno la classe A dopo il caricamento. Ma internamente creerei la classe B, che sarà 1: 1 come classe A, ma con il costruttore senza parametri per scopi di serializzazione o deserializzazione. Questa classe B sarà interna, il che significa che è visibile solo nell'assembly corrente, quindi non può accadere, che può essere inizializzata male quando la libreria di classi è collegata. Tuttavia, questo causa codice duplicato. Immagina, che ci possano essere più classi come questa e più complesse. Ciò significa un'altra spesa.
  3. L'ultima soluzione, che mi viene in mente è quella di implementare la serializzazione da solo utilizzando Linq in XML. Questa soluzione è sicura e senza codice duplicato, ma l'implementazione è difficile per le grandi classi. O, peggio ancora, quando vogliamo cambiare i nomi degli elementi o passare da elementi a attributi, dobbiamo passare questa implementazione ogni volta con attenzione e cambiarla (invece di cambiare gli attributi).

Mentre sto cercando di trovare una soluzione migliore (forse ce n'è un'altra, che non conosco) e ho buone maniere nelle applicazioni di programmazione. Cosa ne pensi, qual è la soluzione migliore (forse in uno scenario e in un altro scenario un'altra soluzione)? Per maintan codice duplicato o codice complesso (forse per esperienza reale)?

    
posta joettriscik 13.05.2016 - 22:40
fonte

4 risposte

3

Tratterei semplicemente le classi che verranno serializzate e deserializzate come DTO , e scegli quale utilità metodo che si desidera eseguire la serializzazione / deserializzazione. In questo modo hai solo bisogno di una singola classe per portare le informazioni.

Ogni metodo di utilità può contenere alcuni parametri di validazione, se sei preoccupato per un parametro non valido. Se si desidera mantenere i metodi nel DTO, creare un paio di metodi di fabbrica che accettano un'origine dati di serializzazione e restituiscono un DTO.

L'unica cosa che non fare è avere due classi di modelli solo perché vuoi automatizzarne una nuova, ma manualmente la nuova l'altra con un costruttore forzato. Ciò crea due posti diversi per i tuoi dati e viola il principio della Sorgente unica della verità.

Mantieni semplice, soldato.

    
risposta data 14.05.2016 - 00:26
fonte
2

Trovo abbastanza fastidioso che molte librerie di serializzazione richiedano costruttori senza parametri.

Con la possibilità di annotare i parametri, in teoria è possibile specificare le associazioni tra i parametri del costruttore e gli elementi di serializzazione, in modo che la libreria di serializzazione possa raccogliere tutti gli elementi necessari e passarli al costruttore dell'oggetto deserializzato. Ahimè, devo ancora imbattersi in una libreria di serializzazione che offre tale funzionalità.

Inoltre, la capacità di serializzare oggetti con costruttori parametrizzati è necessaria anche se non stiamo progettando di parametrizzarli con valori deserializzati; ad esempio, per implementare Iniezione di dipendenza senza ricorrere alla magia come Spring.NET.

Per quanto ne so, il modo in cui la maggior parte delle persone gestisce questo è di avere due gruppi separati di classi, uno per la logica dell'applicazione con cui lavorare e uno solo per la serializzazione.

Si scopre che questo non è male, perché il modello di dati con cui si desidera lavorare nella logica dell'applicazione di solito non è esattamente lo stesso del modello di dati che ha senso persistere.

Ad esempio, è possibile avere la libertà di modificare il modello di dati dell'applicazione mantenendo la compatibilità con i file di serializzazione creati da versioni precedenti del modello dati. Se una serie di classi è tutto ciò che hai, allora nel momento in cui apporti una modifica al tuo modello di dati, tutti i tuoi vecchi dati sono improvvisamente illeggibili. Se si mantiene il modello dei dati dell'applicazione separatamente dal modello dei dati di serializzazione, è possibile avere versioni diverse (contemporaneamente esistenti) del proprio modello di dati di serializzazione da utilizzare con versioni diverse dei file di serializzazione esistenti.

    
risposta data 14.05.2016 - 00:58
fonte
2

Mantenere questo pragmatico - la creazione di un gran numero di codice duplicato o standardizzato dovrebbe essere un no-go, oltre a reimplementare da solo un meccanismo di serializzazione maturo del framework. Quindi mordere il proiettile e fornire un costruttore senza parametri: questo, in realtà, non risulta essere così brutto come si potrebbe pensare.

È possibile rendere privato il costruttore e fornire un metodo statico all'interno della classe per la deserializzazione, che assicura che l'attributo "costruttore obbligatorio" sia passato nell'oggetto dopo la deserializzazione. Ciò rende almeno improbabile che qualcuno si dimentichi di impostare l'attributo aggiuntivo.

    
risposta data 14.05.2016 - 01:32
fonte
1

Che dire di due metodi statici nella classe per seralizzare e de serailize. Il parametro è un argomento di questa funzione e viene memorizzato come costante da qualche parte.

Se finisci per avere molti di questi oggetti, crea una classe che ha un elenco di questi. Questo dovrebbe avere la capacità di mettere in relazione i metodi dell'intero elenco. Richiederebbe anche un delegato del filtro e fornirà un nuovo elenco dopo il filtro (non eliminare i dati prima di salvare). Avrebbe anche i due metodi statici. La classe e l'altro parametro sono argomenti.

    
risposta data 14.05.2016 - 12:35
fonte

Leggi altre domande sui tag