SOLID Struttura e design delle applicazioni

3

Un'unica struttura possibile per un'applicazione consiste nel suddividerla in moduli come Accesso ai dati, Core, Servizi, UI. Ora, a seconda del tipo di ORM che si sta utilizzando, il livello di accesso ai dati avrà un insieme di entità che rappresentano le tabelle nel database. Il livello principale avrà un insieme di entità che rappresentano la logica aziendale. Il livello di servizio avrà una serie di entità DTO che comunicherà con l'interfaccia utente. E infine l'interfaccia utente avrà una serie di modelli di vista che utilizzerà all'interno delle viste.

Ora, quando accediamo o archiviamo le informazioni nel database, dobbiamo trasformare gli oggetti da un tipo a un altro. Quando il servizio chiama il core di cui ha bisogno per trasformare gli oggetti da un tipo all'altro e infine l'interfaccia utente deve trasformare i DTO in View Models. In molti casi la trasformazione è un semplice atto di copiare le proprietà da un oggetto a un altro. È un'attività molto ripetitiva e dispendiosa in termini di tempo che genera grandi quantità di codice.

La mia domanda è che sto facendo qualcosa di sbagliato qui. Dovrei avere solo un tipo di entità? In caso affermativo, non pensate che avrebbe troppe informazioni in un oggetto per l'accesso ai dati, la logica aziendale, ecc ... Esiste un modo rapido per copiare le proprietà tra gli oggetti? La riflessione è un'opzione ma diventa complicata velocemente quando si ha a che fare con i grafici degli oggetti? So che non esiste un proiettile d'argento per risolvere questo problema, ma ci devono essere una serie di buoni approcci sulla copia delle proprietà a mano tra le entità?

    
posta Lukasz 12.08.2013 - 13:50
fonte

3 risposte

3

Odio l'idea delle gerarchie degli oggetti paralleli solo per motivi di purezza dei livelli.

Questo è un Pattern J2EE di base che a mio avviso è diventato un anti-pattern. Le persone erano solite creare DTO perché il modello di entità EJB 1.0 era troppo chiacchierone. Penso che i POJO / POCO siano più intelligenti e non debbano ricorrere a tali contorsioni.

Il livello di accesso ai dati potrebbe rappresentare tabelle o oggetti, a seconda del modo in cui si va.

Il livello di servizio viene mappato per utilizzare casi e unità di lavoro. Possiede transazioni e orchestra i processi per soddisfare i desideri dei clienti. Dovrebbe essere agevole dall'interfaccia utente.

Consiglierei di creare oggetti modello e usarli in modo appropriato. Assicurati solo di trovare un modo per evitare le dipendenze cicliche tra pacchetti / spazi dei nomi. Non accoppiarli tutti insieme. Il livello di accesso ai dati dovrebbe conoscere gli oggetti del modello ma nient'altro. Il livello di servizio dovrebbe conoscere il livello di accesso ai dati, gli oggetti del modello, altri servizi e nient'altro. Il livello di vista dovrebbe avere controller che invocano servizi e nient'altro.

    
risposta data 12.08.2013 - 14:01
fonte
3

Con la tua architettura, sì dovresti avere più oggetti.

Inizia sempre con l'entità del dominio poiché è la ragione principale per la creazione della tua applicazione.

Viene creato un livello di servizio per consentire al mondo esterno di parlare con l'applicazione. L'API in esso può o non può apparire esattamente come le entità del tuo dominio. La mia esperienza è che l'API si discosta dal modello sottostante mentre l'applicazione cresce. I DTO vengono utilizzati per trasferire le informazioni sui limiti del processo e quindi per separare l'API dal modello per cui è una facciata. Potresti anche voler appiattire l'entità, utilizzare le stringhe invece delle enumerazioni ecc.

Nel database potresti non essere in grado di memorizzare le informazioni nello stesso modo in cui viene modellata l'entità dominio. Potresti voler denormalizzare per ridurre il numero di join, o normalizzare per usare meno spazio. Tutto dipende dalla situazione e potrebbe anche variare da entità a entità.

Una vista potrebbe contenere informazioni da più entità. Ad esempio per un utente e un messaggio. Quindi il modello di vista è la combinazione di entrambe le entità. Il modello di vista può anche avere una logica usata per calcolare qualcosa che la vista richiede. Mettere quella logica all'interno della vista renderebbe molto più difficile testare quella logica.

Per quanto riguarda lo snellimento del processo, direi di no. Esistono strumenti come AutoMapper e simili che eseguono la copia per te. Ma il problema con questi è che non saprai mai se hai perso qualcosa nella configurazione (dato che di solito funzionano per convenzione e non per configurazione manuale). Pertanto, è possibile eseguire il refactoring di un campo nel DTO, ma non nell'entità risultante in tale campo che non viene copiato. È molto più robusto creare classi di convertitori a mano (poiché consentono anche di eseguire trasformazioni).

Personalmente ho usato strumenti del genere, ma a lungo andare mi ritrovo a chiedermi se non sarebbe andato più veloce se avessi creato da solo le classi convert. Ed è per questo che ho anche smesso di usare librerie del genere.

Quello che sto dicendo è che tutte le diverse rappresentazioni potrebbero sembrare le stesse a prima vista, ma hanno tutte piccole differenze da affrontare. Se usi la stessa rappresentazione per tutti i livelli devi fare dei compromessi per farlo funzionare su tutti i livelli. La qualità dell'entità diminuirà più a lungo manterrai l'applicazione.

Preferirei chiederti se hai bisogno di quel livello di servizio? La tua applicazione è abbastanza complessa da imporla? Hai bisogno di usare un RDBMS invece di un DB senza schemi?

    
risposta data 12.08.2013 - 14:15
fonte
2

Odio l'idea di mappare direttamente il tuo DB agli oggetti e di passarli come proprietà di theyre su una classe (che sappiamo essere an anti-pattern stesso )

Il modo migliore per modellare la tua applicazione è dividerlo in livelli, quindi pensare a ciò che ogni livello richiede e fornisce, indipendentemente dagli altri livelli. cioè, non iniziare a creare la tua interfaccia utente e pensare al database. Pensa a quali servizi la tua UI ha bisogno, questi saranno poi mappati a un livello applicativo che a sua volta richiederà dei servizi. Questi servizi verranno quindi modellati nel DB (preferibilmente come stored procedure in modo da ottenere una bella API DB), quindi questi sproc possono essere modellati su qualsiasi modello di dati che ti piace.

La ragione per farlo è che ti fa pensare in termini di requisiti dell'applicazione, non di implementazione. Una volta che inizi a pensare al passaggio degli oggetti, ti stai legando a un'implementazione fissa o peggio - come anche ai problemi di sicurezza (ad esempio quando diventa un po 'troppo conveniente per accedere al DB direttamente dall'interfaccia utente, le persone lo faranno) .

    
risposta data 12.08.2013 - 14:12
fonte

Leggi altre domande sui tag