2016-09-21 7 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) 
} 
//.......... 
//.......... 

ことの一つは、この問題は、ドメイン固有の問題はいないようだということです。私は私のdomain internals leakageをせずに、そして集計(ないマッピングツール)は、それがビジネスルールだinvalideできる値を受け入れていないことを確認していると、ユビキタスを持つこれらのif-else文を減らすことができますどのように

言語が適用されますか?

私はAoutoMapperを使ってこのトリックを行うことはできません。最後の部分は注意深くお読みください。

ありがとうございます。

答えて

2

DTO(実質的にはメッセージ)は、Commandに変換されます。ここでは、コマンドにはすべての引数がドメイン固有の値タイプとして表されています。

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

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

toCommandロジックは、コードの可読性を向上させるためにBuilderパターンのようなものを使用することはかなり一般的です。このようなケースでは

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

、戦略パターンを使用すると、ConnectionTypeFactoryがものであることを認識

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

、なぜあなたは、あなたがすることができますあなたの場合/他のシナリオの

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

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


} 

するのではなく、継承を使用することができます

class CompanyRegistration : Registration { 

} 

class PersonRegistraiton : Registration { 

} 

例えば、より継承

を使用していません例えばsetRouteメソッドや他の大きなif/elseの状況でsimmilarロジックを適用します。

また、私はあなたがそれを聞きたくない知っている、あなたは地図や検証が、それは例えば、このアイデアは

var mapper = new FluentMapper.ThatMaps<Aggregate>().From<DTO>() 
        .ThatSets(x => x.title).When(x => x != null).From(x => x.title) 
fluentmapperから来ているビジネスロジック

だということ(aggegate内)独自のマッパーを書くことができます

この種のルールを許可し、プロパティを検証する独自のマッパーを作成するのは難しくありません。そして、それは可読性を向上させると思います。

関連する問題