Eliminazione delle dipendenze rispetto all'eliminazione della ridondanza

6

Durante il mio incarico a un progetto, ho scoperto che molte classi di messaggi sono state ricevute e quindi mantenute intatte e passate all'interno dell'applicazione ricevente. Quando questi messaggi sono stati modificati, è stato necessario modificare il codice nell'intera applicazione. Da questo problema, ho preso l'abitudine di convertire i messaggi in un nuovo formato alla ricezione.

Tuttavia, mi sembra di violare direttamente DRY (non ripeterti): ho queste classi interne quasi identiche che creo da messaggi esterni.

Dove si trova la linea tra l'eliminazione delle dipendenze e l'eliminazione della ridondanza? Ogni modulo dovrebbe avere i propri formati di dati?

    
posta user24449 08.11.2011 - 21:53
fonte

3 risposte

7

Suppongo che un "messaggio esterno" sia qualcosa che sta arrivando su un protocollo di rete, ad es. RPC, SOAP, buffer di protocollo, ecc.

In tal caso, è assolutamente una buona cosa mantenere due modelli separati. Uno per la messaggistica, uno per il dominio. Non è insolito avere ancora un altro modello per la presentazione e un altro modello per i dati.

Sembra terribilmente ripetitivo, ma ci sono molti strumenti di automapping che possono ridurre lo sforzo di quasi zero; in .NET abbiamo AutoMapper , in Java c'è Dozer , ecc.

Ancora più importante, l'alternativa è un odioso, gonfio modello canonico che costringe tutto ciò che lo tocca ad affrontare tutte le bizzarre idiosincrasie di tutto il resto che la tocca. Quando hai bisogno di mappare tra i modelli, di solito hai la possibilità di fare il controllo delle versioni (scegli impostazioni predefinite sane per i nuovi campi), ma quando hai un singolo modello condiviso ... dimentica di ricompilare solo una applicazione, devi ricostruire e ridistribuire la tua intera architettura . Questo succhia quando hai un sistema distribuito.

Solo perché due classi hanno strutture molto simili non significa che una di esse sia ridondante:

  • I modelli di dominio sono modelli "spessi", pensati per modellare accuratamente il mondo reale e contenere tutta o la maggior parte della logica aziendale per la tua applicazione. L'incapsulazione è re e gli oggetti del dominio enfatizzano il comportamento rispetto ai dati.

  • I modelli di messaggistica sono per definizione modelli "sottili" che contengono nient'altro che dati; in molti casi un messaggio è già stato convalidato (nel caso di un messaggio di evento) o dovrà comunque essere nuovamente convalidato (nel caso di un comando), quindi la convalida tende ad essere limitata al formato del messaggio. Inoltre, la struttura di uno di questi modelli di messaggi è quasi sempre ottimizzata per l'efficienza di trasmissione (nessun campo non necessario) e potrebbero esserci diversi attributi "metadati" (come le intestazioni di sicurezza) che non avrebbero alcun senso in nessun altro modello.

  • I modelli di dati sono (tradizionalmente) destinati a fornire un ponte a un DAL o ORM. Gli strumenti moderni hanno ottenuto un buon bello nell'allineamento di questi con i modelli di dominio, ma non in quasi tutti i casi. Generalmente ci sono molte fastidiose restrizioni su un modello di dati che non hanno senso in un modello di dominio, come le proprietà ID su ogni classe, riferimenti bidirezionali, setter su ogni proprietà e in alcuni casi ogni membro deve essere virtuale. Gli ultimi due sono particolarmente problematici; molto spesso vuoi che i tuoi modelli di dominio siano immutabili e sigillati (non ereditabili).

  • Infine, è probabile che il modello di presentazione sia molto più piatto del modello di dominio, abbia tutti i tipi di codice di formattazione e soprattutto le proprietà delle stringhe (che hanno tutti i tipi di convalida allegati). Quali campi sono di sola lettura dipenderà dalle funzionalità che l'interfaccia utente dovrebbe fornire.

È davvero, veramente difficile, al limite dell'impossibile, mantenere sincronizzati tutti questi requisiti in conflitto quando si tenta di mantenere un modello condiviso a livello di tutta l'architettura o persino a livello di applicazione.

Alla fine finirai con il lavoro less con modelli personalizzati con pochissime dipendenze, rispetto a un modello con un numero molto elevato di dipendenze.

    
risposta data 08.11.2011 - 22:42
fonte
1

Per evitare di violare il principio di DRY, è necessario capire le informazioni di un posto sui messaggi. Inoltre, non vuoi le dipendenze da altri moduli.

Che ne dici di inserire le informazioni nel messaggio stesso? Non solo i dati, ma come usare i dati. In questo modo tutto il codice che utilizza il messaggio può ancora usarlo, ma le modifiche al messaggio non devono propagarsi oltre.

A meno che, naturalmente, le modifiche non riguardino l'interfaccia esterna del messaggio. Ma in questo caso è difficile dire come limitare l'effetto a catena, soprattutto senza informazioni più specifiche. Ma la domanda indica che si tratta di un problema di formato, che dovrebbe essere curato rendendolo un oggetto "reale".

    
risposta data 08.11.2011 - 22:33
fonte
0

Direi che questa è una pausa tra informazioni e dati . Considera questo:

Il tuo cliente ha una scelta di file che possono inviarti. O un file CSV pieno di righe con nome utente, ID, indirizzo e così via, o un pdf con le stesse cose su un modulo. Quale vuoi leggere? Quale vuoi utilizzare un programma?

I dati sono i valori fondamentali di cui stai parlando, ID = 1 e USERNAME = SRR. Le informazioni sono dati e contesto . Metti qui il nome utente, rilascia l'id. Le tue classi di messaggi dovrebbero essere archivi di dati, contenenti tutte le informazioni richieste da chiunque e con metodi per raccogliere i dati grezzi.

Quindi, si passano i puntatori a questi oggetti intorno alle varie cose che hanno bisogno di accedere ai dati. Uno dei metodi sarà un semplice wrapper per le chiamate di metodo necessarie per produrre i dati necessari, quindi combinarli con il contesto corrente per ottenere le informazioni desiderate.

Tuttavia, i dati richiedono un metodo di raccolta, e ciò richiede un'interfaccia chiaramente definita. Allora sei nel design dell'interfaccia, con i requisiti in esso. Se i nuovi dati potrebbero dover essere aggiunti in seguito, l'interfaccia deve tenerne conto. Forse il tuo metodo get ha un parametro che elenca i vari oggetti desiderati, oppure viene aggiunto un metodo get per ogni variabile di dati. Qualunque cosa tu scelga, devi ridimensionare, o sei destinato ad entrare e ricostruire ogni volta i diversi pezzi.

    
risposta data 08.11.2011 - 22:17
fonte

Leggi altre domande sui tag