DTO를 도메인 개체에 매핑하는 모범 사례
DTO 를 도메인 개체 에 매핑하는 것과 관련된 많은 질문을 보았지만 그들이 내 질문에 답하지 못했다고 생각했습니다. 이전에 많은 방법을 사용해 왔고 내 의견이 있지만 좀 더 구체적인 것을 찾고 있습니다.
그 상황:
우리는 많은 도메인 객체를 가지고 있습니다. CSLA 모델을 사용하고 있으므로 도메인 개체는 매우 복잡 할 수 있으며 자체 데이터 액세스를 포함합니다. 당신은 이것들을 와이어로 전달하고 싶지 않습니다. 다양한 형식 (.Net, JSON 등)으로 데이터를 반환하는 몇 가지 새로운 서비스를 작성할 예정입니다. 이를 위해 (그리고 다른 이유들) 우리는 또한 유선상에서 전달할 린 데이터 전송 객체를 생성하고 있습니다.
내 질문은 : DTO와 도메인 개체를 어떻게 연결해야합니까?
내 첫 번째 반응은 Fowler, DTO 패턴 유형 솔루션 을 사용하는 것 입니다. 나는 이것을 여러 번 보았고 나에게 옳다고 느낀다. 도메인 개체에 DTO에 대한 참조가 없습니다. 도메인 개체에서 DTO를 만들기 위해 외부 엔터티 ( "매퍼"또는 "어셈블러")가 호출됩니다. 일반적으로 도메인 개체 측에는 ORM 이 있습니다. 이것의 단점은 "매퍼"가 실제 상황에 대해 매우 복잡 해지는 경향이 있고 매우 취약 할 수 있다는 것입니다.
또 다른 아이디어는 DTO가 단순한 데이터 개체이기 때문에 도메인 개체가 DTO를 "포함"하는 것입니다. 도메인 개체 속성은 내부적으로 DTO 속성을 참조하고 요청시 DTO를 반환 할 수 있습니다. 나는 이것에 아무런 문제가 없다는 것을 알 수는 있지만 잘못된 것 같습니다. NHibernate 를 사용 하는 사람들 이이 방법을 사용 하는 것으로 보이는 기사를 보았습니다 .
다른 방법이 있습니까? 위의 방법 중 하나를 사용할 가치가 있습니까? 그렇다면 그 이유는 무엇입니까?
도메인과 DTO 사이에있는 매퍼의 이점은 단일 매핑 만 지원할 때처럼 나타나지 않지만 매핑 수가 증가함에 따라 해당 코드를 도메인에서 격리하면 도메인을 더 간단하고 간결하게 유지하는 데 도움이됩니다. 많은 추가 가중치로 도메인을 복잡하게 만들지 않습니다.
개인적으로, 저는 제 도메인 엔터티들로부터 매핑을 유지하려고 노력하고 제가 "관리자 / 서비스 계층"이라고 부르는 것에 책임을집니다. 이것은 애플리케이션과 리포지토리 (들) 사이에 위치하며 워크 플로우 조정과 같은 비즈니스 로직을 제공하는 계층입니다 (A를 수정하면 서비스 A가 서비스 B와 작동하도록 B도 수정해야 할 수 있음).
가능한 엔딩 형식이 많으면 방문자 패턴을 사용하여 엔터티를 변환 할 수있는 플러그 형 포맷터를 만드는 방법을 살펴볼 수 있지만이 복잡한 항목에 대한 필요성은 아직 찾지 못했습니다.
Jimmy Bogard 가 작성한 것과 같은 자동 매퍼를 사용할 수 있습니다.이 자동 매퍼 는 객체간에 연결이없고 준수되는 명명 규칙에 의존합니다.
T4 템플릿을 사용하여 매핑 클래스를 만듭니다.
Pro-런타임 매퍼보다 빠르게 컴파일 타임에 사람이 읽을 수있는 코드를 사용할 수 있습니다. 코드에 대한 100 % 제어 (부분 메서드 / 템플릿 패턴을 사용하여 임시로 기능을 확장 할 수 있음)
단점-특정 속성, 도메인 개체 컬렉션 등을 제외하고 T4 구문을 학습합니다.
또 다른 가능한 솔루션 : http://glue.codeplex.com .
풍모:
- 양방향 매핑
- 자동 매핑
- 다른 유형 간의 매핑
- 중첩 된 매핑 및 병합
- 목록과 배열
- 관계 확인
- 매핑 테스트
- 속성, 필드 및 방법
도메인 개체를 매개 변수로 사용하는 DTO 클래스 내부에서 생성자를 구현하는 방법은 무엇입니까?
말 ... 이런거
class DTO {
// attributes
public DTO (DomainObject domainObject) {
this.prop = domainObject.getProp();
}
// methods
}
Object-to-Object 매퍼 인 Otis를 사용해 볼 수도 있습니다. 개념은 NHibernate 매핑 (속성 또는 XML)과 유사합니다.
http://code.google.com/p/otis-lib/wiki/GettingStarted
내가 만든 도구를 제안 할 수 있으며 CodePlex : EntitiesToDTOs 에서 호스팅되는 오픈 소스 입니다.
DTO에서 엔티티로 또는 그 반대로 매핑은 확장 메서드에 의해 구현되며, 이들은 각 끝의 어셈블러 측을 구성합니다.
다음과 같은 코드로 끝납니다.
Foo entity = new Foo();
FooDTO dto = entity.ToDTO();
entity = dto.ToEntity();
List<Foo> entityList = new List<Foo>();
List<FooDTO> dtoList = entityList.ToDTOs();
entityList = dtoList.ToEntities();
왜 이렇게 할 수 없습니까?
class UserDTO {
}
class AdminDTO {
}
class DomainObject {
// attributes
public DomainObject(DTO dto) {
this.dto = dto;
}
// methods
public function isActive() {
return (this.dto.getStatus() == 'ACTIVE')
}
public function isModeratorAdmin() {
return (this.dto.getAdminRole() == 'moderator')
}
}
userdto = new UserDTO();
userdto.setStatus('ACTIVE');
obj = new DomainObject(userdto)
if(obj.isActive()) {
//print active
}
admindto = new AdminDTO();
admindto.setAdminRole('moderator');
obj = new DomainObject(admindto)
if(obj.isModeratorAdmin()) {
//print some thing
}
@FrederikPrijck (또는) 누군가 : 제안 해주세요. 위의 예에서 DomainObject는 DTO에 의존합니다. 이렇게하면 dto <-> 도메인 개체를 매핑하는 코드를 피할 수 있습니다.
또는 DomainObject 클래스가 DTO 클래스를 확장 할 수 있습니까?
또 다른 옵션은 ModelProjector 를 사용하는 것 입니다. 가능한 모든 시나리오를 지원하며 최소한의 풋 프린트로 사용하기 매우 쉽습니다.
We can use Factory, Memento, and Builder pattern for that. Factory hide the details on how to create instance of domain model from DTO. Memento will take care the serialization/deserialization of the domain model to/from DTO and can even access private members. The Builder will allows mapping from DTO to domain with fluent interface.
Keeping the mapping logic inside of your entity means that your Domain Object is now aware of an "implementation detail" that it doesn't need to know about. Generally, a DTO is your gateway to the outside world (either from an incoming request or via a read from an external service/database). Since the entity is part of your Business Logic, it's probably best to keep those details outside of the entity.
Keeping the mapping somewhere else would be the only alternative - but where should it go? I've tried introducing mapping objects/services but, after all was said and done, it seemed like overengineering (and probably was). I've had some success using Automapper and such for smaller projects but tools like Automapper come with their own pitfalls. I've had some pretty hard to find issues related to mappings because Automapper's mappings are implicit and completely decoupled from the rest of your code (not like "separation of concerns" but more like a "where does the godforsaken mapping live") so they can sometimes be hard to track down. Not to say that Automapper doesn't have its uses, because it does. I just think mapping should be something that is as obvious and transparent as possible to avoid issues.
Instead of creating a mapping service layer, I've had a lot of success keeping my mappings inside of my DTOs. Since DTOs alway sit at the boundary of the application, they are can be made aware of the Business Object and figure out how to map from/to them. Even when the number of mappings scale to a reasonable amount it works cleanly. All the mappings are in one place and you don't have to manage a bunch of mapping services inside of your Data Layer, Anticorruption Layer, or Presentation Layer. Instead, the mapping is just an implementation detail delegated to the DTO involved with the request/response. Since serializers generally only serialize properties and fields when you're sending it across the wire, you shouldn't run into any issues. Personally, I've found this the cleanest option and I can say, in my experience, it scales well on a large code base.
참고URL : https://stackoverflow.com/questions/678217/best-practices-for-mapping-dto-to-domain-object
'Program Club' 카테고리의 다른 글
| ASP.NET MVC 응용 프로그램의 여러 언어? (0) | 2020.11.05 |
|---|---|
| 목록을 (0) | 2020.11.05 |
| 콘텐츠 높이에 따라 iframe 높이 크기 조정 (0) | 2020.11.05 |
| setup.py에서 여러 작성자 / 이메일을 지정하는 방법 (0) | 2020.11.05 |
| 신경망 역 전파의 편향을 업데이트하는 방법은 무엇입니까? (0) | 2020.11.05 |