不変オブジェクトとDDDは一緒になりますか?


18

DDDを使用するシステム(およびORMを使用するすべてのシステム)を検討してください。ほぼすべてのユースケースで、現実的にシステムのポイントは、これらのドメインオブジェクトを操作することです。それ以外の場合、実際の効果や目的はありません。

不変オブジェクトを変更すると、オブジェクトが永続化された後に新しいレコードが生成され、データソースに大量の膨張が発生します(変更後に以前のレコードを削除しない限り)。

不変オブジェクトを使用することの利点はわかりますが、この意味では、不変オブジェクトを使用する便利なケースはありません。これは間違っていますか?


回答:


16

(関数型プログラミングのように)不変オブジェクトを使用した計算は、生成されるすべてのオブジェクトを永続化することを必ずしも意味しません!


とにかく、そのシナリオで不変オブジェクトを使用するインスタンスは見ていません。したがって、それらは特定の目的のために存在することはありません。私が間違っている?
スティーブンエバーズ

1
不変オブジェクトは(並列スレッドでの)中間計算に役立つと考えていました
スティーブンA.ロウ

11

ドメインで不変とは、データベースで不変でなければならないということですか?たとえば、顧客が常に1つの住所を持っていると仮定して、次のことを検討してください。

customer.address = new Address('My Castle', 'Kings street');
customer_repo.save(customer);

顧客IDが1であることを考慮して、次のSQLが実行されます。

INSERT INTO addresses (customer_id, name, street)
VALUES (1, 'My Castle', 'Kings street');

現在、アドレスに対して次の変更が行われています。

customer.address = new Address('Pauper palace', 'Outlands');
customer_repo.save(customer);

そして永続化レイヤーは、非常に賢いので、次のSQLを実行します:

UPDATE addresses SET name='Pauper palance', street='Outlands'
WHERE customer_id = 1;

これにより、個別のDELETE AND INSERTステートメントのオーバーヘッドを回避できます。また、一部のRDBMSにはINSERT REPLACEなどがあると思います。MySqlにはREPLACEがあります。


+1一般原則については同意します。不変のドメインオブジェクトが不変のDB行を必ずしも意味する必要がある理由がわかりません。
アンドレスF.

?私たちが今まで私たちがそれを処理する方法を特定の顧客のためのアドレスクラスの都市属性を変更するために必要な場合は、上記の場合には、さらに顧客はそれように、複数のアドレスを持っている可能性が前提と顧客とアドレスの間に多くの関係船にAA 1
Sudarshan

1
@Sudarshanこれは単に「不変の値オブジェクト」を作成する方法であり、データベースで実際に不変ではありません。パフォーマンス上の理由から。もちろん、それぞれの状況を明確に処理する必要があります。私は今、私のドメインのイベントソーシングを好んでいますが、やみつきになっています。
アンドホ

@Sudarshanが具体的に質問に答えます。行を新しい値に更新する更新クエリを実行するだけです。1対多の場合、アドレスはカスタマー集合ルート内にある種の識別子を持ち、DB内で一意に識別するために使用されます。次に、この識別子とcustomer_idを使用して、「address」テーブルのその行を更新します。
アンドホ

@andho「これは単に「不変の値オブジェクト」を作成する方法であり、データベースで実際に不変ではありません。」これは本当に私の一日のおかげで作られた
Sudarshan

6

DDDでは、不変オブジェクトは値オブジェクトとほぼ同等です。これらのオブジェクトはエンティティではなく、アイデンティティを持ちません。したがって、私は常に値オブジェクトを、それらが含まれるエンティティの列として永続化します(N / Hibernateでは、そのためにコンポーネントを使用できます)。彼らは自分のテーブルを持っていません。


4

これは、データベース内で不変オブジェクトがどのようにマップされるかによって異なります。(Joda Timeライブラリからの)DateTimeのような単なるコンポーネントの場合、値を変更すると、挿入ではなく更新が行われます。ただし、不変オブジェクトがより複雑で、テーブルに行が必要な場合は、肥大化の問題が発生します。

弱い議論ですが、この方法で監査証跡を実装できると思います。immmutableに対するすべての変更は、挿入を通じて追跡できます。しかし、これを行うためのより良い方法がたくさんあります。

全体的に(単にコンポーネントではなく)不変のドメインオブジェクトを持っているのは、永続性とは少し不一致のようです。


どういたしまして。コンポーネントは、同じ基本データとは異なる方法でドメインオブジェクトを構成できるため、非常に便利です。問題は、不変性の強制に伴います。個人的には、ドメインオブジェクトを可変(プライマリキーフィールドを除く)として扱い、シンプルに保ちます。
ゲイリーロウ

「全体的に、(単にコンポーネントではなく)不変のドメインオブジェクトを持っているのは、永続性とは少し不一致のようです。」コンポーネントとしてモデル化すべきではない値オブジェクト(Hibernateの用語)はどこにある必要があるのでしょうか?---申し訳ありませんが、最後のコメントを誤って入力したため、削除しました。
スダルシャン

単一のエンティティが行で完全に表され、データが別のドメインオブジェクトで共有されていない場合は、コンポーネントを避けてください。
ゲイリーロウ

4

それはドメインに依存します。DDDは、プログラミングパラダイムがオブジェクト指向であることを指定していません。ただし、オブジェクト指向のパラダイムは、データベースに永続化する必要がある一般的なアプリケーションに適しています。

DDDは、ソフトウェアが解決しようとしている実際の問題を表すドメインモデルを中心にソフトウェアを構築する必要があると単に述べています。その問題が本質的に数学的なものである場合、関数型プログラミングと不変のデータ構造を使用してドメイン層を実装することは非常に理にかなっています。

一方、問題がより典型的なエンタープライズアプリケーションであり、すべてのドメインオブジェクトに不変オブジェクト構造を使用している場合は、DDDに従っていないと主張します。少なくとも2つの引数を考え出すことができます。

  • 実装は、問題のあるドメインのドメインモデルを表していません。この場合の問題ドメインは、変更する状態を持つエンティティで構成されます。そして、それはあなたがそれを実装した方法ではありません。

  • ユビキタス言語はありません。ドメインモデルの言語と概念は、ドメインの専門家が使用しているものに従いません。

注:DDDは、必要に応じて不変オブジェクトを使用します。これらは単に値オブジェクトと呼ばれます。

したがって、純粋に機能的なデータ構造を使用してデータベースアプリケーションを作成できないと言っているのではありません。アプリケーションの種類によっては、DDDと呼べるとは思わない


ピーター、素晴らしい答え。ここで私の質問を見てくださいstackoverflow.com/questions/13783666 / ...そして私の問題を理解するのを助けてください。不変の値オブジェクトは、企業に関係のないソフトウェアに最適だと思います。私の意見では、ほとんどのエンタープライズアプリケーションのオブジェクトは可変です。不変の深くネストされた値オブジェクトを持つことを想像してください... ContactInfo-> PhysicalLocation-> Addressで、zipcodeを更新したい...オブジェクトグラフ全体を作成することは、反パターンではなく反キリストのように思えます。どう思いますか?
ペピトフェルナンデス

3

Hibernate / NHibernateなどのORMを使用している場合は、カスケードオプションを設定して、孤立したオブジェクトを自動的に削除できます。個人が値オブジェクトAddressを持っている場合、住所を変更すると、新しいものが保存され、古いものは現在孤立しているため削除されます。


0

値オブジェクトはほとんど常にDDDで不変であり、フライウェイトパターンを使用して、.NETが文字列で行うようにメモリ内でその値オブジェクトの複製を保持できます。主なトレードオフは、メモリの片側と反対側の作成効率です。flyweightパターンでは、値ベースの比較を実行して、新しい値オブジェクトまたは再構成された値オブジェクトが既にflyweightキャッシュ内にあるかどうかを判断する必要がありますが、その時点以降のその他の比較は、単一のインスタンスが適用されるため、一般に参照によって安全に実行できます。flyweightが使用されるかどうかに関係なく、値オブジェクトは固有のIDのみを持ち、したがって値を変更するとIDが変更されるため、不変になります。


-1

不変オブジェクトを使用する別の方法があります...

値5.0、6.0、7.0、8.0を保存して毎回レコード全体をコピーする代わりに、次のようなものを保存できます:5.0、+ 1.0、+ 1.0、+ 1.0、そして依存関係を正しく構築してシーケンス5.0を再構築します、6.0、7.0、8.0。このように、小さな変更はわずかなメモリしか必要としません

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.