Entity to DTO Usage

15

Ho provato a creare un flusso per un'applicazione web multilivello di base e ho letto online informazioni contrastanti. Quello che sto cercando di capire è se c'è un vantaggio nell'utilizzare ancora oggetti DTO dal tuo DAO al livello di servizio attraverso l'uso di una sorta di mapper.

Il flusso di base che prevedo è il seguente:

  1. Modello / Modulo UI - > Controllore
  2. Controller converte il modello in oggetto dominio (entità)
  3. Oggetto dominio - > Livello di servizio
  4. Oggetto dominio - > DAO
  5. DAO - > Oggetto / i del dominio
  6. Servizio - > UI
  7. L'interfaccia utente converte il dominio in modelli UI

Se DTO è stato seguito DAO passerebbe indietro a un DTO non all'entità. Dopo aver fatto alcune letture, sembra che DTO sia diventato leggermente defunto da quando le entità (almeno in Java) sono diventate POJO annotate, il che significa che il loro impatto sulla memoria è diventato molto piccolo.

È questo il caso, o dovrebbero essere utilizzati DTO per incapsulare completamente gli oggetti del dominio all'interno del livello DAO e, in tal caso, cosa passerebbe al livello di servizio il DAO?

Grazie mille!

    
posta dardo 17.05.2013 - 17:40
fonte

2 risposte

20

Secondo me, passare un POJO persistente, come ad esempio un bean gestito da JPA, non è LA buona pratica.

Perché?

Vedo tre motivi principali:

  1. Potenziale problema con le raccolte pigre. link
  2. L'entità deve contenere un comportamento (al contrario di un modello di dominio anemico ) Potresti non voler consentire alla tua interfaccia utente di chiamare un comportamento inaspettato.
  3. In caso di modello di dominio anemico, potresti non voler esporre la struttura del tuo modello all'interfaccia utente, poiché ogni nuova modifica al modello potrebbe interrompere l'interfaccia utente.

Preferisco lasciare che il mio livello di servizio converta le entità in DTO corrispondente in entrambe le direzioni. DAO che ancora restituisce un'entità (non è compito suo garantire la conversione).

    
risposta data 17.05.2013 - 17:56
fonte
12

Uno dei motivi per cui penso che questa discussione si presenti ripetutamente è perché sembra un serio rompicapo prendere un oggetto con tutti i dati necessari e convertirlo in un oggetto che sembra identico o quasi identico a quello che stai consegnando.

È vero, è un PITA. Ma ci sono alcune ragioni (oltre a quelle elencate sopra) per farlo.

  • Gli oggetti di dominio possono diventare molto pesanti e contenere molte informazioni inutili per la chiamata. Questo ingigantimento rallenta l'interfaccia utente a causa di tutti i dati trasmessi, sottoposti a marshalling / unmarshalled e analizzati. Quando consideri che un FE avrà numerosi link che si riferiscono ai tuoi servizi web e che sono stati chiamati con AJAX o qualche altro approccio multi-thread, la tua interfaccia diventerà presto pigra. Tutto questo arriva alla generale scalabilità dei servizi web
  • La sicurezza può essere facilmente compromessa esponendo troppi dati. Come minimo, potresti esporre indirizzi e-mail e numeri di telefono degli utenti se non li elimini dal risultato DTO.
  • Considerazioni pratiche: per 1 oggetto da sfoggiare come oggetto di dominio persistente E un DTO dovrebbe avere più annotazioni del codice. Avrai un numero qualsiasi di problemi con la gestione dello stato dell'oggetto mentre passa attraverso i livelli. In generale, questo è molto più di un PITA per gestire quindi semplicemente il tedio di copiare i campi da un oggetto dominio a un DTO.

Tuttavia, puoi gestirlo in modo abbastanza efficace se incapsuli la logica di traduzione in una raccolta di classi di convertitori

Dai un'occhiata a lambdaJ dove puoi fare 'convert (domainObj, toDto)' c'è un sovraccarico di questo da usare con le collezioni. Ecco un esempio di un metodo controller che ne fa uso. Come puoi vedere, non sembra così male.

    @GET
    @Path("/{id}/surveys")
    public RestaurantSurveys getSurveys(@PathParam("id") Restaurant restaurant, @QueryParam("from") DateTime from, @QueryParam("to") DateTime to) {

        checkDateRange(from, to);

        MultiValueMap<Survey, SurveySchedule> surveysToSchedules = getSurveyScheduling(restaurant, from, to);
        Collection<RestaurantSurveyDto> surveyDtos = convert(surveysToSchedules.entrySet(), SurveyToRestaurantSurveyDto.getInstance());
        return new RestaurantSurveys(restaurant.getId(), from, to, surveyDtos);

    }
    
risposta data 17.05.2013 - 18:52
fonte

Leggi altre domande sui tag