2008-10-23 2 views
4

표준 Customer 도메인 개체가 있다고 가정합니다. 고객이 표시되는 화면에는 외부 관리자, 내부 관리자 및 업데이트 계정의 세 가지 화면이 있습니다.여러 DTO에서 도메인 개체 구성

각 화면에는 Customer 개체에 포함 된 모든 데이터의 하위 집합 만 표시됩니다.

문제는 UI가 각 화면 (예 : DTO)에서 데이터를 다시 전달할 때 전체 고객 도메인 개체의 하위 집합 만 포함한다는 것입니다. 따라서 DTO를 Customer Factory로 보내면 Customer 객체를 다시 만들 때 고객의 일부만을 가질 수 있습니다.

그런 다음이 고객을 고객 저장소로 보내 저장하고 많은 데이터가 사라지게됩니다. 비극이 계속된다.

그래서 문제는이 문제를 어떻게 처리하겠습니까?

내 아이디어의 일부를 :

  • 당신이 고객을로드 할 때 고객이 업데이트하고 다른
  • 을 무시하는 의 일부를 나타내는 저장소에 대한 인수를 포함, 유지 정적 메모리 또는 세션에서 또는 어디서나 UI에서 DTO 중 하나를 수신하면 DTO와 관련된 부분 만 업데이트하십시오.

IMO, 둘 다 kludges입니다. 다른 좋은 아이디어가 있습니까?

@chadmyers : 여기에 문제가 있습니다.

엔티티 속성이 A, B, C 및 D.

DTO # 1

DTO # 2는 C 및 D.

속성을 포함을 가

UI 묻는 B 및 C에 대한 속성을 포함 DTO # 1의 경우 저장소에서 엔티티를로드하고 DTO # 1로 변환하고 B와 C 만 채우고 UI에 제공합니다.

이제 UI는 B를 업데이트하고 DTO를 되돌려 보냅니다. 엔티티를 다시 작성하면 B와 C 만 채워집니다. DTO에 포함 된 모든 것이기 때문입니다.

이제 B와 C 만 채워진 엔티티를 A와 D null/blank로 저장하려고합니다. 저장소는 A와 D를 영속성에서 공백으로 업데이트해야하는지 또는 무시해야하는지 여부를 알 수있는 방법이 없습니다.

답변

3

웹 앱입니까? repo에서 고객 오브젝트를로드하고, DTO에서 갱신하고 다시 저장하십시오. 그건 나 한테 멍청이 같지 않아. :)

업데이트 : 당신의 업데이트합니다 (A, B, C, D 예) 당으로

그래서 내가 무엇을 생각하면 엔티티를로드 할 때, 그것은 A, B, C 및 D를 가지고 있다는 것입니다 DTO # 1이 B & C 만 업데이트하면 괜찮습니다. A와 D는 영향을받지 않습니다 (원하는 상황 임).

B & C 업데이트로 저장소가 수행하는 작업은 전적으로 사용자가 결정합니다. 예를 들어, 당신이 Hibernate/Hibernate를 사용하고 있다면, 그것은 단지 그것을 알아 내고 업데이트를 발행 할 것이다.

단지 DTO # 1이 B & C 인 것만으로도 A &가 null이되어야 함을 의미하지는 않습니다. D를 그대로 두십시오.

+1

웹 응용 프로그램인지 여부는 중요하지 않습니다. 그리고 문제는 "the"DTO가 아니라 다른 것입니다. 그리고 그들 중 누구도 고객을 완전하게 묘사하지 못합니다. – moffdub

+0

상태가 좋다면 partial DTO와는 다른 접근법을 사용할 수도 있고 그것이 내가 탐구 할 것이기 때문에 중요합니다. DTO가 완벽하게 설명하는지 여부는 중요하지 않습니다. – chadmyers

+0

맞습니다. 한 가지 옵션은 DTO를 다시 디자인하는 것입니다. 나는 DTO의 디자인이 아마 내 손에 없다는 제약에 대해서는 언급하지 않았다. 별도의 DTO 클래스 대신 Customer 객체가 DTO 인터페이스를 구현할 것을 제안합니까? – moffdub

4

DTO를 받으면 저장소에서 완전한 고객 객체를로드하기 위해 factory를 사용할 것입니다. 그런 다음 DTO에 지정된 필드 만 업데이트 할 수 있습니다.

이렇게하면 마지막으로 업데이트 된 타임 스탬프를 확인하여 고객에게 낙관적 인 동시성을 적용 할 수도 있습니다.

+0

흥미로운 접근 방법. 하지만 리포지토리에 대한 라운드 트립이 두 번 있기 때문에 성능이 약간 향상됩니다. – moffdub

+1

DB 최적화 사고가 저장소 추상화를 통해 유출 될 수 있으므로 저장소 레벨 이상으로 최적화해야합니다. 나중에 성능이 문제가되는 경우 2 차 캐싱이나 다른 기술을 적용 할 수 있습니다. – chadmyers

+1

코드를 작동시키기 전에 코드 최적화에주의하십시오. 게다가 처리량의 모든 나노초가 필요한 경우 왜 객체를 사용하고 있습니까? – yfeldblum

1

처음에는이 질문의 요점을 놓쳤습니다. 디자인 관점에서 생각하지 않는 몇 가지 사항을 전제로하기 때문입니다.

  1. 저장소에서 엔티티를 수화하고 DTO로 변환하면 낭비됩니다. 귀하의 DAL이 DTO를 리포지토리에 전달한 다음이를 전체 개체 개체로 변환한다고 가정합니다. 그래서 그것을 다시 DTO로 변환하는 것은 낭비적인 것처럼 보입니다.

  2. 많은 양의 레코드를 표시하고 엔티티 데이터의 일부만 표시하는 검색 결과 페이지가있는 경우 여러 개의 DTO가있는 것이 좋습니다. 이 경우 해당 페이지를 필요한 데이터 만 전달하는 것이 효율적입니다. CRUD 페이지에 부분 데이터가 포함 된 DTO를 전달하는 것은 의미가 없습니다. 그냥 전체 DTO 또는 심지어 전체 엔티티 개체를 제공하십시오. 모든 데이터를 사용하지 않으면 아무런 해를 끼치 지 않습니다.

그래서 주요 문제는 부분 DTO를 사용하여 이러한 페이지에 데이터를 전달해야한다고 생각하지 않는다는 것입니다. 당신이 전체 DTO를 사용하는 경우, 내가 저장 작업이 수행 될 때마다 다음과 같은 3 개 단계를 할 것입니다 :

  1. 이 양식을 통해 변경 사항으로 저장소 또는 DB에서
  2. 업데이트 DTO를 전체 DTO를 당겨을
  3. 전체 DTO를 리포지토리 또는 db에 다시 저장하십시오.

이 방법을 사용하려면 추가 DB 히트가 필요하지만 실제로 CRUD 형식에서는 중요한 문제가 아닙니다.

1

리포지토리가 매우 풍부한 도메인 엔터티를 처리한다는 이해가 있다면 수많은 DTO가 간단히 매핑 할 수 있습니다.

즉 다시 엔터티 및 등등 DTO 정보를 얻을 수있는 역을 할 것

dtoUser.MapFrom<In,Out>(Entity) 
or 
dtoAdmin.MapFrom<In,Out>(Entity) 

. 그래서 저장소에만 저장이 풍부한 기업의 NOT 수많은 DTO의

entity.Foo = dtoUser.Foo 
or 
entity.Bar = dtoAdmin.Bar 

entityRepsotiry.Save(entity) <-- do not pass DTO. 
DTO의의 전체 포인트는 프리젠 테이션을 간단하게 또는 WCF의 dataTransfer에 대한 말을하는 것입니다

, 그 문제에 대한 저장소 또는 엔티티와는 아무 상관이 없습니다 .

또한 DTO에서 엔티티를 생성하면 안됩니다 ... 엔티티를 얻는 유일한 두 가지 방법은 각각 공장 (신규) 또는 리포지토리 (기존)를 통과하는 것입니다.

엔티티를 어딘가에 저장하는 것을 언급했는데, 왜이 작업을 수행할까요? 이것이 저장소의 임무입니다. 엔티티 (db, cache, e.t.c)를 가져올 위치를 결정할 것이고, 다른 곳에 저장할 필요가 없습니다.

도메인에서 책임을 할당하는 데 도움이되는 희망은 항상 도전적이며 회색 영역이 여기 저기에 있지만 일반적으로 이러한 것은 Repository의 일반적인 용도 인 DTO e.t.c입니다.