DDD集計のシリアル化のベストプラクティス


23

DDDによると、ドメインロジックは、シリアル化、オブジェクトリレーショナルマッピングなどの技術的な問題で汚染されるべきではありません。

それでは、ゲッターとセッターを介して公開することなく、集計の状態をどのようにシリアル化またはマッピングしますか?リポジトリの実装など、多くの例を見てきましたが、実際にはすべて、マッピングのエンティティと値オブジェクトのパブリックアクセサーに依存していました。

リフレクションを使用してパブリックアクセサーを回避することもできますが、これらのドメインオブジェクトはIMOで暗黙的にシリアル化の問題に依存します。たとえば、シリアル化/マッピングの設定を調整しないと、プライベートフィールドの名前を変更したり削除したりできませんでした。そのため、代わりにドメインロジックに焦点を当てる必要があるシリアル化を検討する必要があります。

ここで従うべき最良の妥協点は何ですか?パブリックアクセサーと一緒に住んでいますが、マッピングコード以外には使用しないでください。または、明らかな何かを見逃しただけですか?

私は、DDDドメインオブジェクト(エンティティと値オブジェクトで構成される集約)の状態をシリアル化することに明確に興味があります。これは、一般的なシリアル化や、ステートレスサービスが単純なデータコンテナオブジェクトで動作するトランザクションスクリプトシナリオではありません。

回答:


12

オブジェクトの種類

説明のために、オブジェクトを3つの異なる種類に分けましょう。

ビジネスドメインロジック

これらは作業を完了するオブジェクトです。彼らは、ある当座預金口座から別の当座預金口座に資金を移動し、注文を遂行し、ビジネスソフトウェアがとると予想される他のすべてのアクション実行します。

ドメインロジックオブジェクトは通常、アクセサー(ゲッターとセッター)を必要としません。むしろ、コンストラクターを介して依存関係を渡すことでオブジェクトを作成し、メソッドを介してオブジェクトを操作します(聞かないでください)。

データ転送オブジェクト

データ転送オブジェクトは純粋な状態です。ビジネスロジックは含まれていません。常にアクセサーがあります。不変の方法でそれらを書いているかどうかに応じて、セッターを持っている場合と持っていない場合があります。コンストラクタでフィールドを設定し、オブジェクトの有効期間中は値が変更されないか、アクセサが読み取り/書き込み可能になります。実際には、これらのオブジェクトは通常、ユーザーが編集できるように変更可能です。

モデルオブジェクトの表示

ビューモデルオブジェクトには、表示/編集可能なデータ表現が含まれています。通常、データ検証に限定されたビジネスロジックが含まれる場合があります。View Modelオブジェクトの例としては、Customerオブジェクト、Invoice Headerオブジェクト、およびInvoice Line Itemsを含むInvoiceViewModelがあります。View Modelオブジェクトには常にアクセサーが含まれます。

したがって、フィールドアクセサが含まれていないという意味で「純粋」になる唯一のオブジェクトは、ドメインロジックオブジェクトです。このようなオブジェクトをシリアル化すると、現在の「計算状態」が保存されるため、後で取得して処理を完了できます。ビューモデルとDTOは自由にシリアル化できますが、実際にはそれらのデータは通常データベースに保存されます。

シリアル化、依存関係、結合

シリアル化によって依存関係が作成されるのは事実ですが、互換性のあるオブジェクトにデシリアライズする必要があるという意味では、必ずしもシリアル化構成を変更する必要があるわけではありません。優れたシリアル化メカニズムは一般的な目的です。プロパティまたはメンバーの名前を変更しても、メンバーに値をマップできる限り、彼らは気にしません。実際には、これは、オブジェクトインスタンスを再シリアル化して、新しいオブジェクトと互換性のあるシリアル化表現(xml、jsonなど)を作成する必要があることを意味します。シリアライザーの構成を変更する必要はありません。

オブジェクトがシリアル化される方法を気にするべきではないのは事実です。このような懸念をドメインクラスから切り離すことができる1つの方法、つまりリフレクションについては既に説明しました。ただし、シリアライザーは、オブジェクトのシリアル化および逆シリアル化の方法を考慮する必要があります。結局のところ、それがその機能です。オブジェクトをシリアル化プロセスから切り離したままにする方法は、シリアル化を汎用機能にし、すべてのオブジェクトタイプで動作できるようにすることです。

人々が混乱することの1つは、デカップリングが両方向で発生しなければならないということです。ありません; それだけで動作するように持っている1つの方向。実際には、完全に分離することはできません。常に何らかのカップリングがあります。疎結合の目標は、すべての依存関係を削除するのではなく、コードの保守を容易にすることです。


デカップリングに関するあなたの見解に同意します。シリアライザーはドメインオブジェクトに依存するため、問題ありません。しかし、その逆ではありません。ただし、ドメインオブジェクトのパブリックアクセサーに対するあなたの見解には同意しません。実際には、彼らはしばしばそうです、はい。しかし、IMOきれいなオブジェクト指向設計にドメインロジックを実装するpreferrable次のようになります。質問しない、知らせます。ただし、マッピング目的(ORM、シリアル化、GUI ...)にはアクセサーが必要です。そして、可能であれば、それは避けたいものです。
イーグルビーク14

アクセサーがない場合、フィールドへのアクセスをどのように計画しますか?
ロバートハーベイ14

実際、私はあなたが説明する3種類のオブジェクトのどちらにも言及していませんが、DDDの用語とそのサブオブジェクト(エンティティ、値オブジェクト)の「集合体」に言及しています。私は今、私の質問がこれについて十分に明確ではなかったことに気付きました。ごめんなさい!上記の私の編集をご覧ください。
イーグルビーク14

1
これは基本的に未解決の問題です-カプセル化、デカップリング、シリアル化\エンコードを同時に行うことはできず、DTOを公開することは妥協を達成する1つの方法です。しかし、はるかに邪魔にならない方法があります:yegor256.com/2016/07/06/data-transfer-object.html
バシレフ

1
これによりカプセル化が解除され、だれでもオブジェクトの内部を読み取るためにフレンドクラスを実装または使用できます。
バシレフス

-1

シリアル化の基本的な目的は、1つのシステムで生成されたデータを1つ以上の互換性のあるシステムで消費できるようにすることです。

シリアル化の最も簡単で堅牢なアプローチは、データを単純な使いやすい形式で構造を維持する型に依存しない形式に変換することです。たとえば、最も一般的なシリアル化形式(JSON、XMLなど)は、明確に定義されたテキストベースの形式を使用します。テキストの作成、送信、および消費は簡単です。

これらの形式のいずれかを使用することが理想的でない場合がある2つの理由があります。

  1. 効率

    すべてのデータをテキストベースの同等物に変換するには、固有のコストがかかります。テキストがすべての異なる形式のデータを表現する最も効率的な方法である場合、データ型は存在しません。さらに、これらの形式の構造は、データのサブセットを非同期的にまたは部分的に取得するのには理想的ではありません。

    たとえば、XMLとJSONは、使用されるデータが最初から最後まで書き込まれ、読み取られることを想定しています。メモリが不足している非常に大きなデータセットを処理する場合、データを消費するシステムには、データを部分的に処理する機能が必要になる場合があります。その場合、データを処理するために特別な目的のシリアライゼーション/デシリアライゼーションの実装が必要になる場合があります。

  2. 精度

    目的の型からデータに依存しない型へのデータのシリアル化/逆シリアル化に必要なキャストにより、精度が失われます。

オブジェクトとデータのバイナリ表現を作成することが明らかに最も効率的かつ正確なソリューションであると主張することができます。主な欠点は、データを消費および生成するすべてのシステムの実装に互換性を維持する必要があることです。理論的には単純な制約ですが、実稼働システムは時間とともに変化/進化する傾向があるため、実際に維持するのは悪夢です。

とは言うものの。汎用形式はより堅牢で、さまざまなシステムでより適切にサポートされ、使用するメンテナンスオーバーヘッドがほとんどまたはまったく必要ないため、ドメイン固有の詳細からシリアル化/逆シリアル化を分離することは一般的なルールとして理にかなっています。


申し訳ありませんが、これは私の質問に答えません。これは、ドメインオブジェクトをシリアル化から分離することに関するものであり、シリアル化の理由やさまざまな形式の長所と短所に関するものではありません。プライベート状態を公開せずにドメインオブジェクトをシリアル化するにはどうすればよいですか?
イーグルビーク14

@EagleBeakああ、私はあなたの懸念がプライベートメンバーの取り扱いに特に関連していることを知りませんでした。あなたの場合、バイナリでシリアル化することができます(受信側システムは、ドメインオブジェクトが作成されたのと同じルール/構造に従うと仮定)、またはシリアル化の前にパブリックデータのみを抽出するロジックを記述できます。
エヴァンプライス14

「通常の」仮定は、汎用形式(xml、jsonなど)にシリアル化されるデータがパブリックになり、その特権がACLまたは他の同等物を介してAPIによって制御されることだと思います。汎用のシリアル化/逆シリアル化は、あるシステムから別のシステムに移動するビジネスロジックからデータを分離するという方向に沿っています。
エヴァンプライス14

通常、シリアル化されるオブジェクトに対してパブリックアクセサーが想定されることに同意します。しかし、これがDDDとどのように関係しているか、ドメインロジックのカプセル化に重点を置いていることについては、さらに知りたいと思います。すべてのDDDプラクティショナーは、シリアル化のためにパブリックアクセサーを介してドメインモデルの状態を公開するだけですか?疑わしい。誤解しないでください。ご意見ありがとうございます。ただ、私は別の側面に興味があるだけです。(これまでのところ、私の質問はあまりに曖昧ではないと思いますが、ロバート・ハーベイの答えとあなたの質問でそれについて考えさせられました。)
EagleBeak
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.