문제

나는 대부분의 클래스에 약간의 동작과 멤버 객체의 특성을 계산하거나 노출시키는 속성을 가지고있는 풍부한 도메인 모델을 가지고 있습니다 (이 특성의 값은 결코 지속되지 않습니다).

내 클라이언트는 WCF를 통해서만 서버에 말합니다.

따라서 각 도메인 엔티티마다 데이터 만 포함하는 간단한 표현과 해당 DTO와 구현하는 맵퍼 클래스가 있습니다. DtoMapper<DTO,Entity> 엔터티를 정적 게이트웨이를 통해 DTO에 해당하거나 그 반대로 변환 할 수 있습니다.

var employee = Map<Employee>.from_dto<EmployeeDto>();

이 애플리케이션의 서버 측면은 대부분의 DTO가 WCF 서비스에서 나오는 지속성에 관한 것이고, 사화 된 다음, 임의의 ORM이 데이터베이스에 지속되거나 쿼리 요청이 WCF에서 들어오고 ORM이 해당 쿼리를 실행합니다. DB는 객체를 직렬화하고 WCF에 의해 돌려 보낼 객체를 반환합니다.

이 시나리오가 주어지면 내 지속성 저장소를 도메인 엔티티에 매핑하는 것이 합리적입니까, 아니면 DTOS에 직접 매핑해야합니까?

도메인 엔티티를 사용하면 흐름이

  1. 클라이언트는 객체를 요청합니다
  2. WCF는 서버로 요청을 전송합니다
  3. ORM은 데이터베이스를 쿼리하고 도메인 엔티티를 반환합니다
  4. 도메인 엔티티는 Mapper에 의해 DTO로 변환되었습니다
  5. WCF는 DTO를 연속화하고 클라이언트로 반환합니다
  6. 클라이언트는 DTO를 사로화합니다
  7. DTO는 Mapper에 의해 도메인 엔티티로 변환되었습니다
  8. 생성 된 뷰 모델, 등.

반환 여행에서 비슷합니다

DTO에 직접 매핑하면 요청 당 객체 당 하나의 매핑을 제거 할 수 있습니다. 이 작업을 수행하여 무엇을 잃어 버리나요?

떠오르는 유일한 것은 삽입/업데이트 전에 검증 할 수있는 또 다른 기회입니다. DTO가 유효성 검사를 받거나 전선을 가로 질러 발송되기 전에 도메인 엔티티로 존재한다는 보장이 없기 때문에, 나는 할 수있는 기회를 생각합니다. SELECT에서 유효성 검사 (다른 프로세스가 데이터베이스에 유효하지 않은 값을 넣을 수있는 경우). 다른 이유가 있습니까? 이러한 이유는 추가 매핑 단계를 보증하기에 충분합니까?

편집하다:

나는 위의 "임의의 orm"이라고 말했으며, 가능한 한 orm-and-peristence-agronstic이되기를 원하지만, 당신이 추가 할 특별한 것이 있다면, 그것을 nhibernate에만 해당하는 것이 있다면, 반드시 그렇게합니다.

도움이 되었습니까?

해결책

개인적으로 서버쪽에 매핑을 유지하는 것이 좋습니다. 당신은 아마도 지금까지 당신의 디자인을 구축하는 많은 일을했을 것입니다. 그것을 버리지 마십시오.

웹 서비스가 무엇인지 고려하십시오. 그것은 단지 당신의 ORM에 대한 추상화가 아닙니다. 이것은 계약. 내부 및 외부의 고객을위한 공개 API입니다.

공개 API는 변경해야 할 이유가 거의 없어야합니다. 새로운 유형과 방법을 추가하는 것 외에도 API에 대한 거의 모든 변경은 깨진 변화입니다. 그러나 도메인 모델은 그렇게 엄격하지 않을 것입니다. 원래 디자인에서 새로운 기능을 추가하거나 결함을 발견 할 때 때때로 변경해야합니다. 내부 모델의 변경이 서비스 계약을 통해 계단식 변경을 일으키지 않도록하려고합니다.

실제로는 일반적인 관행입니다 ( "모범 사례"라는 문구로 독자를 모욕하지 않습니다). Request 그리고 Response 비슷한 이유로 각 메시지에 대한 클래스; 변경 사항을 깨뜨리지 않고 기존 서비스 및 방법의 기능을 확장하는 것이 훨씬 간단 해집니다.

고객은 아마 그렇지 않을 것입니다 원하다 서비스에서 내부적으로 사용하는 것과 동일한 모델. 만약 당신이 당신의 유일한 클라이언트라면, 아마도 이것은 투명 해 보일 것 같지만, 외부 클라이언트가 있고 시스템의 해석이 얼마나 멀리 떨어져 있는지 보았을 때, 완벽한 모델이 누출되지 않는 가치를 이해할 것입니다. 서비스 API의 범위를 벗어납니다.


그리고 때로는조차도 아닙니다 가능한 API를 통해 모델을 다시 보냅니다. 이것이 발생할 수있는 이유는 여러 가지가 있습니다.

  • 객체 그래프의 순환. OOP에서 완벽하게 괜찮습니다. 직렬화에 비참한. 결국 그래프가 직렬화되어야하는 "방향"에 대해 고통스러운 영구 선택을해야합니다. 반면에 DTO를 사용하면 원하는 방향으로 직렬화 할 수 있습니다.

  • 비누/휴식을 통해 특정 유형의 상속 메커니즘을 사용하려고 시도하는 것은 기껏해야 Kludge가 될 수 있습니다. 구식 XML 시리얼 라이저는 최소한 지원됩니다 xs:choice; DataContract 그렇지 않고, 나는 이론적 근거를 촉발하지 않을 것이지만, 당신은 아마도 당신이 당신의 풍부한 도메인 모델에 다형성을 가지고 있다고 말하면 충분하며 웹 서비스를 통해 그것을 채널로 채널하는 것은 거의 불가능합니다.

  • 게으른/연기 로딩. 예를 들어 LINQ에서 SQL 엔티티를 사용하여 WCF는 게으른 로더를 트리거하지 않아도됩니다. null 수동으로로드하지 않는 한 해당 필드로 - 그러나 데이터가 다시 들어오는 경우 문제가 더욱 악화됩니다. List<T> 생성자에서 초기화 된 자동 프로퍼 (도메인 모델에서 충분히 공통)는 생성자를 호출하지 않기 때문에 WCF에서는 단순히 작동하지 않습니다. 대신 추가해야합니다 [OnDeserializing] 초기화 방법 및 당신 진짜 이 쓰레기로 도메인 모델을 혼란시키고 싶지 않습니다.

  • 나는 또한 당신이 nhibernate를 사용한다는 괄호 언급을 발견했습니다. 인터페이스를 고려하십시오 IList<T> 웹 서비스를 통해 전혀 직렬화 할 수 없습니다! 대부분의 사람들처럼 nhibernate와 함께 poco 클래스를 사용한다면, 이것은 단순히 작동하지 않습니다.


내부 도메인 모델이 단순히 클라이언트의 요구와 일치하지 않는 경우에도 많은 사례가있을 수 있으며 이러한 요구를 수용하기 위해 도메인 모델을 변경하는 것은 의미가 없습니다. 이 예를 들어, 송장만큼 간단한 것을 취합시다. 표시해야합니다.

  • 계정에 대한 정보 (계정 번호, 이름 등)
  • 인보이스 특정 데이터 (송장 번호, 날짜, 마감일 등)
  • A/R 레벨 정보 (이전 잔액, 늦은 요금, New Balance)
  • 송장의 모든 것에 대한 제품 또는 서비스 정보;
  • 등.

이것은 아마도 도메인 모델 내에서 잘 맞습니다. 그러나 고객 이이 송장의 1200 개를 보여주는 보고서를 실행하려면 어떻게해야합니까? 일종의 화해 보고서?

이것은 직렬화에 짜증납니다. 이제 1200 개의 송장을 보내고 있습니다 같은 반복해서 직렬화되는 데이터 - 동일한 계정, 동일한 제품, 동일한 A/R. 내부적으로 귀하의 응용 프로그램은 모든 링크를 추적하고 있습니다. 송장 #35를 알고 송장 #45는 동일한 고객을위한 것이므로 Customer 참조; 이 모든 정보는 직렬화시 손실되며 말도 안되는 양의 중복 데이터를 보냅니다.

당신이 정말로 원하는 것은 다음과 같은 사용자 정의 보고서를 보내는 것입니다.

  • 보고서에 포함 된 모든 계정 및 A/R;
  • 보고서에 포함 된 모든 제품;
  • 제품 및 계정 ID 만있는 모든 송장.

대규모 중복성을 피하려면 클라이언트에게 보내기 전에 나가는 데이터에 대한 추가 "정규화"를 수행해야합니다. 이것은 DTO 접근을 크게 선호합니다. 도메인 모델이므로 도메인 모델 에이 구조를 갖는 것은 의미가 없습니다. 이미 자체적으로 중복성을 처리합니다.

나는 그것들이 충분한 예와 충분한 근거가되기를 바랍니다. 당신이 당신의 매핑을 도메인 <--> 서비스 계약에서 그대로 유지하도록 설득하기를 바랍니다. 당신은 지금까지 절대적으로 옳은 일을했고, 당신은 훌륭한 디자인을 가지고 있으며, 나중에 주요 두통으로 이어질 수있는 무언가를 선호하는 모든 노력을 부정하는 것은 부끄러운 일입니다.

다른 팁

어쨌든 클라이언트 측에서 DTO를 매핑해야하므로 대칭을 위해 서버 측에서 역 매핑을 만드는 것이 좋습니다. 이렇게하면 전환을 잘 분리 된 추상화 레이어로 분리합니다.

추상화 레이어는 유효성 검사에 적합 할뿐만 아니라 아래/위/위의 변경 사항에서 코드를 단열하고 코드를보다 테스트 가능하고 반복적으로 덜 만듭니다.

또한 추가 변환에서 훌륭한 성능 병목 현상을 알지 못하면 다음을 기억하십시오. 조기 최적화는 모든 악의 근본입니다. :)

도메인 엔티티를 DTO와 분리하여 다른 우려 사항과 분리해야합니다. DTO는 일반적으로 도메인 엔티티로서 비즈니스 논리를 캡슐화하고 많은 행동을 첨부하는 자체 설명 모델입니다.

추가 매핑이 어디에 있는지 잘 모르겠다고 말 했습니까? ORM (일명 도메인 엔티티)을 사용하여 데이터를 검색하고 해당 객체를 DTO에 매핑하므로 1 개의 매핑 만 있습니까? BTW는 아직 같은 것을 사용하지 않는다면 automapper 당신을 위해 지루한지도를 수행합니다.

그런 다음이 동일한 DTO는 클라이언트에 사로화되며 여기에서 UIViewModels에 직접 매핑 할 수 있습니다. 큰 그림은 다음과 같습니다.

  • 클라이언트는 WCF 서비스의 ID에 의해 엔티티를 요청합니다
  • WCF Service는 리포지토리/orm에서 엔티티를 얻습니다
  • Automapper를 사용하여 엔티티에서 DTO로 매핑합니다
  • 클라이언트는 DTO를받습니다
  • Automapper를 사용하여 UI ViewModel에 매핑됩니다
  • uiviewmodel은 GUI에 묶여 있습니다

서버 사이드 앱이 지속성에 대해 "대부분"이라고 말하면 이것이 생각해야 할 중요한 일이라고 생각합니다. 실제로 WCF 서비스가 수신하거나 WCF 서비스가 도메인 모델과 데이터 저장소 사이의 게이트웨이 역할 역할을하는 데이터 주변에 약간의 지능이 필요한 서버 측 도메인 모델이 있습니까?

또한 DTO가 클라이언트 도메인을 위해 설계되었는지 여부를 고려하십시오.
서비스를 통해 해당 데이터 저장소에 액세스 해야하는 유일한 클라이언트 도메인입니까?
서버 측 DTO가 다른 애플리케이션 도메인을 제공 할만 큼 유연하거나 거친 입자입니까?
그렇지 않다면, 외부 인터페이스 구현을 추상화하려는 노력의 가치가있을 것입니다.

(db-> orm-> Employeeentity-> client1dtoassembler-> client1employeedto).

WCF 서비스가 주로 지속적인 데이터 저장소의 관문으로 작용하는 유사한 응용 프로그램이 있습니다.

우리의 경우, 우리의 클라이언트와 서버는 "DTOS"가 포함 된 어셈블리를 재사용하지 않습니다. 이를 통해 서비스 참조에 의해 생성 된 부분 클래스에 단순히 코드를 추가 할 수있는 기회를 제공하므로 클라이언트 측에서 DTO를 사용하여 도메인 객체로 취급 할 수 있습니다. 다른 시간에 우리는 WCF 서비스에서 얻은 지속적인 개체에 대한 외관 역할을하는 클라이언트 측 전용 도메인 객체를 가질 수 있습니다.

도메인 객체가 가지고있는 동작 및 계산 속성에 대해 생각할 때 실제로 클라이언트와 서버간에 얼마나 많은 오버랩이 있습니까? 우리의 경우, 우리는 클라이언트와 서버 사이의 책임 부서가 클라이언트와 서버 모두에 존재 해야하는 코드가 거의 없음을 의미했습니다.

귀하의 질문에 직접 답변하려면, 귀하의 목표가 완전히 지속되지 않은 상태로 유지되는 경우, 지속성 저장소를 도메인 객체에 매핑 한 다음 DTOS에 매핑 할 것입니다. 객체에 피를 흘리고 WCF DTO로 사용하여 복잡하게 할 수있는 지속성 구현이 너무 많습니다.

클라이언트 측에서는 DTO를 장식하거나 증강 할 수있는 경우 추가 매핑을 수행 할 필요가 없으며 매우 간단한 솔루션입니다.

당신의 건축은 꽤 잘 생각 된 것 같습니다. 내 직감은, 이미 WCF를 통해 객체를 DTO로 줄이기로 결정하고 현재 서버 측에서 추가 객체 기능이 필요하지 않다면 간단하고 매핑을 유지하지 않는 이유는 무엇입니까? 귀하의 지속성은 DTO에 직접 저장합니다.

당신은 무엇을 잃습니까? 나는 당신이 정말로 아무것도 잃지 않는다고 생각합니다. 당신은 건축이 깨끗하고 간단합니다. 미래에 서버 측에 더 풍부한 기능이 새로운 필요성이 있다고 결정한 경우, 해당 시점에서 항상 도메인 엔티티를 재현하기 위해 요약 할 수 있습니다.

나중에 필요에 따라 간단하고 요인을 유지하고, 이전 최적화를 피하려고 노력합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top