web-dev-qa-db-ja.com

(別のサービスクラスの)エンティティの外部にビジネスロジックを保持することはどの程度許容できますか?

オブジェクトはデータと動作を備えた自己完結型のものであり、したがって、それらは属性に作用するメソッドを持つ必要があると教えられました。ただし、エンティティとその動作の間のこの結合が観察されない状況がいくつかあります。

  • エンティティフレームワーク(POCOを使用した.NETおよびPOJOエンティティを使用したEnterprise Javaなど)では、CRUD /永続性/検索操作は、エンティティ自体ではなく外部エンティティマネージャー(およびリポジトリ)で実行する必要があると規定しています。コードentityManager.save(entity)ではなくentity.save();
  • ビジネスルールエンジンは、ビジネスロジックをエンティティから分離する最もわかりやすい例です。ビジネスルールは、エンティティとは完全に異なるコード(異なる言語であっても)を形成します。例えば。 JBoss Drools、IBM ILOG、またはその他のルールエンジン。ビジネスルールパラダイムは、OOプログラミングの外挿に使用できます。OOでは、データとメソッドを考慮しますが、セマンティックWebでは、オントロジーと、作用している論理/ビジネスルールを考慮できます。オントロジーのABoxまたはTBox-2つの完全に異なる言語と推論システム。
  • 分散コンピューティングでは、オブジェクトのシリアル化と非シリアル化の使用、およびネットワークを介したそれらのオブジェクトの通信が規定されています。これには、XML、ネイティブバイナリ形式、またはJSONが使用されます。通常、ネットワークを介して通信されるのはデータのみで、ビジネスロジックは1つのレイヤーに保持され、ネットワークやプラットフォーム間でビジネスロジックを移動するためのテクノロジーはありません。 JavaエンティティがJSONオブジェクトに変換され、REST AP​​Iを介してAngular 2フロントエンドに公開される場合、ビジネスロジックの自動変換および通信はありません。通常、ビジネスロジックは片側に保持されます(Javaなど)。
  • OOドメインモデルは現実世界を反映/モデル化する必要があると言われています。また、現実のオブジェクトには、内部にビジネスロジックがない場合があります。例えば。計算機に関する概念があります。税計算機、給与計算機などです。したがって、_invoice.recalcTaxes_ではなくcalculator.recalcTaxes(invoice)と記述します。前者のアプローチでは、異なるケースに異なる計算機を適用できます。法律全体。異なるビジネスメソッドがあるからといって、複雑な継承階層を構築する必要はありません。同じデータに異なるビジネスサービス/計算機を適用するだけです。

データ/エンティティからビジネスロジックを分離するこれらの引数を考慮してくださいビジネスソフトウェアのプロジェクトの設計の一般的なルールとしてこの分離を行うことはどの程度許容できますか?ビジネスロジックをデータから分離することに反対する引数は何ですか?

6
TomR

あなたが言及している問題は、考慮されている問題に対して確立された単一クラスの特性とクラス分解のレベルに関連していると思います。あなたの例のそれぞれは、クラスの特性を考慮すると妥当に聞こえます。一方、データがロジックにバインドされるシナリオはたくさんあります。このような場合、ビジネスロジックではなくクラスの動作と呼ばれます。

これらはそれぞれ、少なくとも以下を考慮して個別に検討する必要があります。

  • ビジネスロジックは外部ロジックまたは内部クラスの動作を表しますか?
  • クラスはモデルを表しますか?
  • ロジックの複雑さのレベルとは何ですか?
  • ビジネスロジックが変化する確率とは
  • オブジェクトに適用される新しいビジネスロジックルールがある確率とは
  • クラスは外部環境に公開されていますか?
  • クラスロジックはn層アプローチで層に分散していますか?

ncle Bob[〜#〜] solid [〜#〜] と呼ばれるオブジェクト指向設計の原則を導入しました。原則の1つである単一責任原則(SRP)は、あなたが参照している内容を正確に説明します。

クラスは単一の責任しか持たない必要があります(つまり、ソフトウェアの仕様の1つの潜在的な変更のみがクラスの仕様に影響を与えることができます)

それが原則です。重要なこと(これもMartinが推奨)、原則を使用する必要がありますクラスis変更チェーンで考慮されるシナリオでのみ/ 変更する理由があります。他の場合では、原則を使用するとコードが複雑になる可能性があります...

短い例:2つのクラス(ListContainerとListManager)ではなく、モデル(Items)と動作(Add、Edit、Delete)を含むListという1つのクラスを作成(または使用)します。これは、「内部」クラスの動作である問題に導入された不要な複雑さのためです。さらに、リストがオブジェクトを管理する方法は変更されません。

5
tom3k

文字どおりビジネスロジックについて話している場合、それはビジネス向けであり、一般にドメインロジックではありません。ほとんどのエンティティには、外部のインフルエンサーによって、またはコンテキストのためにロジックが課されていることがわかります(次の場合は割引します...) 。物事が恣意的であるように見える可能性があるため、ビジネスプログラミングが非常にイライラするのはそのためです。エンティティは常に現実の世界と一致するとは限りませんが、ビジネスが異なる状況下で認識している世界。 「Acme、Inc.」という顧客は1人だけです。しかし、システムでは1人の営業担当者しか割り当てられないため、2つのエントリが必要です。また、yadda-yadda-yadda誰かのいとこのため、2つのエントリが必要です。心配する必要はありません。これを常に行う必要はないので(重要であるかのように)、合計購入額を計算するときに、これを1つの例外とするようにコンピュータをプログラムできます。

米国では、請負業者を雇った場合、400ドルを超える請求があった場合、1099の納税申告書を提出するとします。このルールは請負業者や特定の請求書には含まれていませんが、特定の税年度の請求書の合計を調べる外部政府の税ルールです。このルールは1年ごとに変動する可能性さえあります。非営利団体への対応には、もう1つの懸念があります。これには本当にある種のtax.calculatorが必要です。

ロジックを適切に分離しないと、ビジネスロジックがエンティティに密接に関連付けられているため、ユーザーは計画していない方法でエンティティを使用し始める可能性があります。クライアントの住所データの入力は単純明快なはずですが、これまでに見たことがあるでしょう:アプリはビジネス宅配と私邸を区別しないので、AddressLine3 = "c/o John Smith"ですか。宛名ラベルを印刷するための個別のロジックがないため、ユーザーはアドレス印刷ロジックからの個別のアドレス情報がないことを回避するためにあらゆる種類のことを行います。

ビジネスルールは要因の組み合わせである傾向があり、特定のエンティティに対してカットアンドドライされることはほとんどありません。ビジネスエンティティにロジックを配置することはできますが、実際にどのように処理が行われるか、または行われるかを誰もが最終的に確認すると、これをリファクタリングすることに気付くでしょう。

4
JeffO

この分離をビジネスソフトウェアのプロジェクトの設計の一般的なルールとして作成することは、どの程度許容できますか?

フォローするパラダイムによって異なります。あなたは基本的に、手続き型プログラミング(データに作用する一連の命令)とオブジェクト指向プログラミング(オブジェクトが動作の単位を実行することを要求することでオブジェクトが動作の単位を実行する)について説明しています。

Alan Kayが指摘したいように、実際の真のオブジェクト指向言語/システムはほとんどありません。したがって、リストにあるように、手続き型プログラミングのパラダイムが "OO"言語に潜入するのは当然のことです。手続き型のパラダイムが必要であるという意味ではありませんが、コードを記述しているときは、手続き型の考え方(Dave Westが呼ぶ)の方が簡単です。実はオブジェクト指向ではない、いわゆる「オブジェクト指向」コードが非常にたくさんあります。

個人的に私は、手続き型パラダイムに従う場合は、手続き型言語(または手続き型とOOの両方をサポートする言語の手続き型機能)を使用するべきだという考えの購読者です。手続き型のコードを、できるだけオブジェクト指向にしようとするコードに変換しようとすると、少し混乱を招く可能性があります。

1
Cormac Mulhall