ビジネスオブジェクト-コンテナまたは機能的?


19

これは私がSOに戻ってしばらく尋ねた質問ですが、ここでよりよく議論されるかもしれません...

私が働いているところで、私たちは何度もこの主題について行き来しており、健全性チェックを探しています。ここに質問があります:ビジネスオブジェクトはデータコンテナ(DTOに似ています)であるか、またはそのオブジェクトでいくつかの機能を実行できるロジックも含まれている必要があります。

例-顧客オブジェクトを取得します。おそらく、いくつかの一般的なプロパティ(名前、IDなど)が含まれますが、その顧客オブジェクトには関数(保存、計算など)も含める必要がありますか?

1行の推論では、オブジェクトを機能(単一責任プリンシパル)から分離し、ビジネスロジックレイヤーまたはオブジェクトに機能を配置します。

もう一方の推論では、いいえ、顧客オブジェクトがある場合は、Customer.Saveを呼び出して終了します。オブジェクトを消費している場合、顧客を救うために別のクラスについて知る必要があるのはなぜですか?

私たちの最後の2つのプロジェクトでは、機能からオブジェクトが分離されていましたが、新しいプロジェクトで議論が再び行われました。

どちらがより理にかなっており、なぜですか?


1
プロジェクトについて詳しく教えてください。プロジェクトの性質によって、どちらのソリューションが優れているかが決まります。

回答:


5

顧客がドメインモデルの一部であると考える場合、そのオブジェクトのプロパティと操作の両方を持つことは理にかなっています(特にDDDのコンテキスト内で、それに限定されません)。

しかし、そうは言っても、あなたが使った例は貧弱なものであり、議論の原因だと思います。永続性について話している場合、通常、顧客は自分自身を「保存」しません。永続化に使用しているものは何でも。永続性のあらゆる種類が永続化レイヤー/パーティションに属する必要があることは理にかなっています。これは通常、リポジトリパターンの背後にある考え方です。** Customer.UpgradeWarranty()やCustomer.PromoteToPreferred()などのメソッドは、引数を明確にします。

これはまた、DTOを持つ可能性を排除しません。たとえば、顧客情報をリモートサービスに渡す場合を考えてみましょう。顧客がトランスポート用にそれ自体のDTOを作成することは理にかなっていない可能性がありますが、これはアーキテクチャ上の懸念事項ですが、永続性またはネットワークレイヤー/パーティション/コード/ what-have-youでケースを作成できます。その場合、そのようなオブジェクトには次のようなメソッドがあります

public static CustomerDTO GetDTO(Customer c) { /* ... */ }

public static Customer GetCustomer(CustomerDTO cdto) { /* ... */ }

したがって、要約すると、ドメイン内の論理操作と一致するドメインオブジェクトの操作を持つことは完全に理にかなっています。

問題に関する多くの良い議論のための「永続的な無知」のためのグーグル(このSO質問とその受け入れられた答えは開始するのに良い場所です)。

**これは、特定のOR / Mソフトウェアで少し混乱するため、「保存」メソッドを持つ永続ベースからの継承を強制されます。


3

実際、私は最近、オブジェクトをデータから分離するためにいくつかのコードを作り直しました。その理由は、データが別のサービスを介して取得されるため、オブジェクト全体をやり取りしてサーバーの検証エラーを処理する代わりに、サーバーとの間で生データを渡すだけの方がはるかに簡単だからです。

小規模なプロジェクトの場合、オブジェクトにビジネスロジックとデータを含めることはおそらく問題ありませんが、大規模なプロジェクト、または時間の経過とともに拡大する可能性のあるプロジェクトの場合、レイヤーを明確に分離します。


3

どちらの方法でもメリットがあると思いますが、オブジェクト指向またはドメイン駆動型の観点から見ていきます。異なるクラスとオブジェクトの責任は何ですか。

それで、あなたの具体的なケースで、私はこれを自問します:顧客はそれ自身を救う方法を知っているべきですか?

私にとって、答えは「いいえ」です。論理的には意味がありませんし、顧客は永続化フレームワークについて何も知る必要はありません(責任の分離)。

Customer.UpgradeWarranty()またはCustomer.PromoteToPreferred()を使用したSnOrfusの例に関しては、明らかにCustomer.Save()よりもビジネスロジック指向です。これにはさまざまなアプローチがありますが、顧客が保証をアップグレードできるかどうかを自問すると、答えは、見方によっては両方とも「はい」または「いいえ」になります。

  • はい:顧客はもちろん保証をアップグレードできます
  • いいえ:顧客はアップグレードを要求できますが、アップグレードは他の誰かによって行われます

元の質問に戻ります。どちらの方法がより理にかなっているかは、おそらくあなたが尋ねる人と彼らが好む方法に依存しますが、最も重要なことはおそらくそれを行う一つの方法に固執することです。

ただし、私の経験では、データと(ビジネス)ロジックを分離することでアーキテクチャは単純になりますが、それほどエキサイティングではありません。


2

ActiveRecordパターンとパターンの違いについて具体的に話していると思いますRepository。前者では、エンティティは自身を永続化する方法を知っており、後者では、リポジトリは永続性を知っています。後者の方が懸念事項をより適切に分離できると思います。

広い意味では、エンティティがデータ構造のように振る舞う場合、振る舞いはないはずですが、振る舞いがある場合、データ構造のように使用されるべきではありません。例:

データ構造:

class CustomerController
{
    public int MostRecentOrderLines(Customer customer)
    {
        var o = (from order in customer.Orders
                orderby order.OrderDate desc
                select order).First();
        return o.OrderLines.ToList().Count;
    }
}

非データ構造:

class Customer
{
    public int MostRecentOrderLines()
    {
        // ... same ...
    }
}

最初のケースでは、作業コード内のどこからでも問題なくモデルのデータ構造ツリーをナビゲートできますが、それはデータ構造のように扱っているため問題ありません。後者の場合、Customerは特定の顧客向けのサービスに近いため、結果に対してメソッドを呼び出さないでください。顧客について知りたいことはすべて、顧客オブジェクトのメソッドを呼び出すことで利用できるはずです。

エンティティをデータ構造またはサービスにしたいですか?一貫性を保つため、1つに固執することをお勧めします。前者の場合、「サービス」タイプのロジックをエンティティではなく別の場所に配置します。


1

私はあなたの質問に本当に答えることはできませんが、学校のプロジェクトの1つでこの議論を行っているのは面白いと思います。私は、ロジックをデータから分離したいと考えています。しかし、クラスメートの多くは、オブジェクトにはすべてのロジックとデータを保持する必要があると言っています。

私は彼らが持ち出す事実を要約しようとします:

  • ビジネスクラスオブジェクトはモノを表すため、すべてのデータとロジックを含める必要があります。(たとえば、ドアを開けたい場合は、自分でドアを開けます。他の人に尋ねないでください。悪い例です)

  • buオブジェクトのコードと機能を理解しやすくなります。

  • 設計の複雑さを軽減

私は彼らに怠け者だと言っています、そして私はこのようにします:

  • はい、ビジネスクラスは物事を表すため、データを保持します。しかし、自分自身を保存したり、コピーすることさえ間違っていると感じます。rlではできません。

  • オブジェクトをすべてに責任を持つようにすることは、将来の耐久性と保守性に適さないようにします。保存を担当する別のクラスがある場合、新しいオブジェクトをデザインに追加すると、その保存機能を簡単に実装できます。そのクラスですべてコーディングする代わりに。

  • 1つのオブジェクトがデータを保持できるようにすることで、そのオブジェクトはデータベース接続を保持でき、すべてのデータベーストラフィックはそのオブジェクトに導かれます。(基本的にはデータアクセスレイヤー)それ以外の場合、すべてのビジネスオブジェクトは接続を保持する必要があります。(これにより複雑さが増します)

どうにかして、私は先生に尋ねるつもりです。私がそれをしたとき、あなたが望むなら、私も彼の答えをここに掲示します。;)

編集:

このプロジェクトが書店に関するものであることを忘れていました。


クラスメートは正しいですが、ビジネスロジックを他の形式のロジック(この場合はアーキテクチャロジックまたは永続ロジック)と混同している点が異なります。
スティーブンエバーズ

1

答えは本当にあなたのアーキテクチャ/デザインが何であるかに依存します-ドメインモデルを備えたDDDアーキテクチャは、オブジェクトデザインに関してはCRUDデータ中心のモデルとは大きく異なります。

ただし、一般的には、オブジェクト指向設計では、状態をカプセル化し、動作を公開しようとしていることに留意してください。これは、通常、その動作に可能な限り近い動作に関連付けられた状態を取得しようとすることを意味します。これに失敗すると、何らかの形で状態を公開するように強制されます。

ドメインモデルでは、ビジネスモデルとインフラストラクチャの問題を区別する必要があるため、「。Save」などのメソッドは絶対に避けたいと考えています。私が実際に顧客を「救った」最後の時間を覚えていません!

CRUDアプリケーションでは、データが第一級市民であるため、「。Save」が完全に適切です。

大規模な実世界のアプリケーションには、これらのパラダイムが混在しています-急速に変化する、または複雑なビジネスルールがあるドメインモデル、境界を越えてデータを転送するためのDTO、CRUD(またはCRUDとアクティブレコードなどのドメインモデルの間の何か)すべてのルールに適合するワンサイズはありません。


0

私はしばらくの間、同じ質問を熟考してきました-データコンポーネントとロジックコンポーネントは分離しなければならないと思います。これは、ビジネスロジックを意味を提供するデータへのインターフェイスと見なすことで、適切な心構えに導かれるからです。

また、スコットホイットロックのポイントを上から修正します(新しいメンバーになるポイントがないことを除く)。データまたはビジネスロジッククラスは、オブジェクトが永続的に格納される方法を実際に心配する必要はありません。

そうは言っても、既存の製品を扱っている場合は、クリーンで契約上のインターフェースがあれば、それでも問題ありませんし、保守も可能です...

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