Uma das razões pelas quais penso que essa discussão surge repetidamente é porque parece um grande problema pegar um objeto com todos os dados necessários e convertê-lo em um objeto que pareça idêntico ou quase idêntico àquele você está entregando.
É verdade, é uma PITA. Mas existem algumas razões (além das enumeradas acima) para fazer isso.
- Os objetos do domínio podem ficar muito pesados e conter muitas informações inúteis para a chamada. Esse inchaço diminui a velocidade da interface do usuário devido a todos os dados transmitidos, empacotados / não empacotados e analisados. Quando você considera que um EF terá vários links referentes aos seus serviços da Web e ser chamado com AJAX ou alguma outra abordagem multithread, você rapidamente tornará sua interface lenta. Tudo isso atinge a escalabilidade geral dos serviços da web
- A segurança pode ser facilmente comprometida expondo muitos dados. No mínimo, você pode expor endereços de e-mail e números de telefone de usuários se não os eliminar do resultado do DTO.
- Considerações práticas: Para um objeto desfilar como um objeto de domínio persistente E um DTO, ele teria que ter mais anotações que código. Você terá vários problemas ao gerenciar o estado do objeto à medida que ele passa pelas camadas. Em geral, é muito mais um PITA para gerenciar do que simplesmente executar o tédio de copiar campos de um objeto de domínio para um DTO.
Mas, você pode gerenciá-lo com bastante eficiência se encapsular a lógica de conversão em uma coleção de classes de conversor
Dê uma olhada no lambdaJ, onde você pode 'converter (domainObj, toDto)'; há uma sobrecarga disso para uso em coleções. Aqui está um exemplo de um método de controlador que faz uso dele. Como você pode ver, não parece tão ruim.
@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);
}