엔티티 대 DTO 사용법


15

기본 계층 형 웹 응용 프로그램에 대한 흐름을 생각해 내려고 상충되는 정보를 온라인에서 읽었습니다. 내가 알아 내려고하는 것은 일종의 매퍼를 사용하여 DAO에서 서비스 계층으로 DTO 객체를 계속 사용하는 이점이 있는지 여부입니다.

내가 예상하는 기본 흐름은 다음과 같습니다.

  1. UI 모델 / 양식-> 컨트롤러
  2. 컨트롤러가 모델을 도메인 개체 (엔터티)로 변환
  3. 도메인 객체-> 서비스 계층
  4. 도메인 객체-> DAO
  5. DAO-> 도메인 객체
  6. 서비스-> UI
  7. UI는 도메인을 UI 모델로 변환

DTO가 준수되면 DAO는 엔티티가 아닌 DTO를 다시 전달합니다. 약간의 독서를 한 후에 (적어도 Java에서는) 엔티티에 주석이 달린 POJO가되어 DTO가 약간 소진 된 것처럼 보입니다. 즉, 메모리 공간이 매우 작아졌습니다.

이 경우 DAO를 사용하여 DAO 계층 내에서 도메인 개체를 완전히 캡슐화해야하며,이 경우 서비스 계층이 DAO로 전달할 것은 무엇입니까?

무리 감사!

답변:


20

나에 따르면, 예를 들어 JPA가 관리하는 Bean과 같이 지속 가능한 POJO를 전달하는 것은 좋은 습관이 아닙니다.

왜?

세 가지 주요 이유가 있습니다.

  1. 게으른 컬렉션의 잠재적 인 문제. http://java.dzone.com/articles/avoid-lazy-jpa-collections
  2. 엔터티에는 비헤이비어 도메인 모델 과 달리 비헤이비어가 포함되어야합니다 . UI에 예기치 않은 비헤이비어가 호출되도록하지 않을 수 있습니다.
  3. 빈혈 도메인 모델의 경우 모델을 새로 변경할 때마다 UI가 손상 될 수 있으므로 모델 구조를 UI에 노출하지 않을 수 있습니다.

서비스 계층에서 엔티티를 양방향으로 해당 DTO로 변환하는 것을 선호합니다. DAO는 여전히 엔티티를 반환합니다 (변환을 보장하는 것은 아닙니다).


따라서 이것을 올바르게 이해하면 서비스는 본질적으로 DTO 객체 만 처리하고 UI와 DAO의 중개자 역할을합니다. 또한 포인트 3에서 여전히 DTO를 실행 가능한 UI 요소로 변환해야하므로 DTO도 업데이트가 필요하기 때문에 도메인 업데이트로 인해 UI가 여전히 중단되지 않습니다.
dardo

1
서버 측에서 일부 서비스를 호출하기 전에 @dardo UI 요소가 DTO이거나 최악의 경우 DTO로 변환되어야합니다. DTO는 자주 변경되지 않으며 UI 요구에 초점을 맞춘 엔터티의 적응 만 있습니다. 또한 서비스 계층은 DTO와 엔티티 모두에 관심을 가져야합니다.
Mik378

아 알았어, 내가 이해하지 못한 딸꾹질이있다. Anemic 도메인 모델은 내가 일하는 곳에서 매우 일반적이며 패러다임을 조금 이동하여 더 얇은 서비스 계층을 장려하려고합니다. 다시 감사합니다!
dardo

@dardo이 책을 읽을 수 있습니다. 훌륭한 회사 : amazon.com/Implementing-Domain-Driven-Design-Vaughn-Vern-Vernon/dp/…
Mik378

실제로 amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/ 에서이 기능을 사용했습니다. 지금까지 꽤 좋았습니다 = D
dardo

13

이 토론이 반복적으로 발생한다고 생각하는 이유 중 하나는 필요한 모든 데이터가 포함 된 객체를 가져 와서 동일하거나 거의 동일한 객체로 변환하는 것이 진지한 고통 인 것처럼 보이기 때문입니다. 당신은 전달하고 있습니다.

사실, 그것은 PITA입니다. 그러나 그렇게하는 데는 몇 가지 이유가 있습니다 (위에 열거 된 것 외에).

  • 도메인 개체는 매우 무거워 질 수 있으며 통화에 유용한 정보가 많이 포함되어 있습니다. 이 팽창은 전송, 마샬링 / 비 정렬 화 및 구문 분석 된 모든 데이터로 인해 UI 속도가 느려집니다. FE가 웹 서비스를 참조하고 AJAX 또는 다른 멀티 스레드 접근 방식으로 호출되는 수많은 링크가 있다고 생각하면 UI가 빠르게 느려집니다. 이 모든 것이 웹 서비스의 일반적인 확장 성을 얻습니다.
  • 너무 많은 데이터를 노출하면 보안이 쉽게 손상 될 수 있습니다. 최소한 DTO 결과에서 사용자를 제거하지 않으면 사용자의 이메일 주소와 전화 번호가 노출 될 수 있습니다.
  • 실제 고려 사항 : 하나의 오브젝트가 지속 도메인 오브젝트 및 DTO로 퍼레이드하려면 코드보다 더 많은 주석이 있어야합니다. 레이어를 통과 할 때 개체의 상태를 관리하는 데는 여러 가지 문제가 있습니다. 일반적으로 이것은 도메인 개체에서 DTO로 필드를 간단하게 복사하는 작업을 관리하는 데 훨씬 더 많은 PITA입니다.

그러나 변환 논리를 변환기 클래스 모음으로 캡슐화하면 상당히 효과적으로 관리 할 수 ​​있습니다.

'convert (domainObj, toDto)'를 수행 할 수있는 lambdaJ를 살펴보십시오. 컬렉션에 사용하기 위해 과부하가 있습니다. 다음은이를 사용하는 컨트롤러 방법의 예입니다. 보시다시피 그렇게 나쁘지 않습니다.

    @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);

    }

의견을 보내 주셔서 감사합니다. 제 생각은 같은 줄에 있습니다 =)
dardo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.