2016-09-21 2 views
0

내 도메인 개체에 유비쿼터스 언어를 적용하려고합니다.DTO를 도메인 개체로 변환하는 방법

클라이언트의 Data Transfer Object을 도메인 개체로 변환하려고합니다. Aggregate's Constructor은 필수 입력란 만 허용하며 Aggregate을 만들 때 (예 : CreateAggregatecommand)에도 나머지 매개 변수는 aggregate'sAPI을 사용하여 전달해야합니다.

그러나 DTOAggregate 매핑 코드는 지저분한 조금이된다 : 내가 언급해야

if(DTO.RegistrantType == 0){ 
    registrantType = RegistrantType.Person() 
} 
elseif(DTO.RegistrantType == 1){ 
    registrantType = RegistrantType.Company() 
} 
//..... 
//..... 
var aggregate = new Aggregate(
     title, 
     weight, 
     registrantType, 
     route, 
     callNumber, 
    ) 

//look at this one: 

if(DTO.connectionType == 0){ 
    aggregate.Route(ConnectionType.InCity(cityId)) 
} 
elseif(DTO.connectionType == 1){ 
    aggregate.Route(ConnectionType.Intercity(DTO.originCityId,DTO.DestinationCityId) 
} 
//.......... 
//.......... 

한 것은이 문제가 도메인 특정 문제가 보이지 않는다는 것입니다.

어떻게하고, 유비쿼터스을 갖는, 그리고집계 (안 매핑 도구)는 비즈니스 규칙의이 Invalide 수있는 값을 허용하지 않는지 확인되는 내 domain internals leakage을 말도없이 이러한 IF-else 문을 줄일 수 있습니다 언어가 적용 되었습니까?

트릭을 수행하려면 AoutoMapper을 사용하십시오. 마지막 부분을주의 깊게 읽으십시오. '

감사합니다.

답변

2

일반적인 대답은 DTO (사실상 메시지 임)을 Command으로 변환하는 것입니다. 여기서 명령에는 도메인 특정 값 유형으로 표시된 모든 인수가 있습니다. Builder 패턴처럼 toCommand 논리 사용 뭔가 코드의 가독성을 향상시키기 위해

void doX(DTO dto) { 
    Command command = toCommand(dto) 
    doX(command) 
} 

void doX(Command command) { 
    // ... 
    aggregate.Route(command.connectionType) 
} 

그것은 매우 일반적입니다. 당신이 ConnectionTypeFactory이 일 것을 인식이되면 이와 같은 경우

if(DTO.connectionType == 0){ 
    aggregate.Route(ConnectionType.InCity(cityId)) 
} 
elseif(DTO.connectionType == 1){ 
    aggregate.Route(ConnectionType.Intercity(DTO.originCityId,DTO.DestinationCityId) 
} 

, 전략 패턴이

ConnectionTypeFactory f = getConnectionFactory(DTO.connectionType) 
ConnectionType connectionType = f.create(DTO) 

을 도울 수, 당신은 바로 하나를 선택 룩업 테이블을 구축에 대해 생각할 수 있습니다.

Map<ConnectionType, ConnectionTypeFactory> lookup = /* ... */ 

ConnectionTypeFactory f = lookup(DTO.connectionType); 
if (null == f) { 
    f = defaultConnectionFactory; 
} 
+0

당신의 대답은 완벽 합니다만,'RegistrantType.Person()'은 enum 값을 0으로 돌려주고,'RegistrantType.Company()'는 enum 값을 1로 반환합니다. 번호를 집계에 전달하지 않은 이유는 도메인의 내부가 누출되지 않기 위해서였습니다. 그리고이 특별한 경우에 팩토리를 만들면 팩토리는 열거 형 플래그로 숫자를 반환해야합니다. 그리고 그것은 암묵적이고 빈혈적인 모델처럼 들립니다. 어떤 제안입니까? – Mohsen

1

그래서 왜

class CompanyRegistration : Registration { 

} 

class PersonRegistraiton : Registration { 

} 

은 당신이 대신 상속을 사용할 수 있습니다

예를 들어 더 상속

를 사용하지 않는 사용자/다른 시나리오의

public class Aggregate { 
    public Aggregate (CompanyRegistration) { 
    registantType = RegistrantType.Company();  
    } 

    public Aggregate (PersonRegistration p) { 
    registrantType = RegistrantType.Person(); 
    } 


} 

할 수 있다면 setRoute 메소드 또는 다른 큰 if/else 상황에 대해 simmilar 논리를 적용하십시오.또한

, 난 당신이합니다 (aggegate 내부) 자신의 매퍼를 작성하는 것이지도를하고이 아이디어는 fluentmapper

var mapper = new FluentMapper.ThatMaps<Aggregate>().From<DTO>() 
        .ThatSets(x => x.title).When(x => x != null).From(x => x.title) 
에서 온다 예를 들어 비즈니스 로직

의 유효성을 검사 할 수 있습니다, 당신이 그것을 듣고 싶지 않아 알고

이러한 종류의 규칙을 허용하고 속성의 유효성을 검사하는 자체 매퍼를 작성하는 것은 그리 어렵지 않습니다. 그리고 그것은 가독성을 향상시킬 것이라고 생각합니다.

관련 문제