モデルにビジネスロジックを配置する理由 複数の種類のストレージがある場合はどうなりますか?


70

私は常に、ビジネスロジックはコントローラー内になければならず、コントローラーは「中間」部分であるため、静的のままであり、モデル/ビューはインターフェースを介してカプセル化する必要があると考えていました。そうすれば、他に何も影響を与えずにビジネスロジックを変更し、複数のモデル(データベース/ストレージのタイプごとに1つ)および多数のビュー(たとえば、異なるプラットフォーム用)をプログラムできます。

この質問で、ビジネスロジックを常にモデルに配置する必要があり、コントローラーがビューと深く関係していることを読みました

私にとって、それは本当に意味をなさないし、別のデータベース/ストレージのタイプをサポートする手段を持ちたいと思うたびに、ビジネスロジックを含むモデル全体を書き直さなければならないことを意味します。

また、別のビューが必要な場合は、ビューとコントローラーの両方を書き換える必要があります。

誰かがそれがなぜであるか、または私がどこかで間違った場合に説明してもらえますか?

回答:


69

ElYusubovの答えの大部分は、ドメインロジックがモデルに入り、アプリケーションロジックがコントローラーに入るべきだと答えています。

2つの説明:

  • ここではビジネスロジックという用語はあいまいなので、あまり役に立たない。ビジネスロジックは、ビジネスマンが気にするすべてのロジックの総称であり、データベースにデータを保存する方法や画面に表示する方法などの単なる技術とは区別します。ドメインロジック(「有効な電子メールアドレスは...」)とワークフロー/ビジネスプロセス(「ユーザーがサインアップするとき、電子メールアドレスを要求する」)は両方ともビジネスロジックと見なされ、前者は明らかにモデルと後者は、コントローラに組み込まれるアプリケーションロジックです。
  • MVCは、画面上にデータを配置し、ユーザーが操作できるようにするためのパターンであり、ストレージをまったく指定しません。ほとんどのMVCフレームワークは、単なるMVCを超えたフルスタックフレームワークであり、データの保存に役立ちます。また、保存するデータは通常モデル内にあるため、これらのフレームワークはモデルを保存する便利な方法を提供します。データベースのデータですが、MVCとは関係ありません。理想的には、モデルは永続性に依存せず、異なるタイプのストレージへの切り替えはモデルコードにまったく影響を与えません。本格的なアーキテクチャには、これを処理する永続化レイヤーがあります。

4
ほとんどのMVCフレームワークでは、モデルを簡単に保存できるように、多くの場合、すべてのストレージ/データベースをモデルにミックスします(多くの場合、フレームワークモデルクラスを拡張します)。これはおそらく混乱の原因です。技術的には、作成するモデルコードは実際のモデル(ドメイン層)である必要がありますが、フレームワークによって提供されるコードはストレージ(永続層)を処理する必要があります。たとえば、フレームワークがモデルの一部としてリポジトリパターンを実装したため、User.find(...)(Userはモデル)のようなものが機能します。
ワコ

3
View-Controller-Model-Storageは一般的な原則です(ただし、M、V、Cの関係は三角形として視覚化する必要があります)。フレームワークがストレージを「モデル」にミックスすると、View-Controller-(モデルはフレームワークからストレージを継承します)のように機能します。
ワコ

2
View-Controller-Model-Storageはフラットではないため、かなり粗雑です。たとえば、コントローラーがUser.find(...)のような操作を行ってモデルを取得する場合、ドメインレイヤーを経由するのではなく、ストレージレイヤーに直接問い合わせます。
ワコ

2
より慎重に階層化するアーキテクチャでは、UserRepository.find()のようなものになります。「モデル」とは、フレームワークが提供する「モデル」クラスを意味します。User.find()によって返されたユーザーオブジェクトには、誰かが、ユーザが...どのように振る舞うか、何であるか、モデル化という意味で、ユーザーのモデルである
Waquo

1
@flipdoubtビジネスロジックは、mvcからuwpアプリを移植するために移植する場合に同じままにする必要のあるロジックです。
アンディ

23

あなたとプログラミングの世界の大部分は、MVCパーツの役割を誤解しているようです。要するに、それらは:

モデル =ドメインロジック

ビュー =出力ロジック

コントローラー =入力ロジック

これは、モデルがビジネスロジック全体を担当することを意味します。画面上にウィジェットを描画する、プリンターを駆動する、HTMLとしてデータを出力する、HTTPリクエストを解析するなどに関連するものはモデルに属しません。

ただし、現代のいわゆる「MVC」フレームワークの多くは、実際にはMVCをまったく実行していないか、パーツに誤ったラベルを付けています。多くの場合、「モデル」と呼ばれるものはモデルの永続層であり、ビジネスロジックは「コントローラー」と呼ばれるものの中にあります。通常、実際のコントローラーは、ルーティングテーブルと、受信した入力を正しいビジネスプロセスにディスパッチするための個々の「コントローラー」のコードを備えた中央のエントリポイントです。これらのフレームワークが「ビュー」と呼ぶものは、実際にはすべてのビットです。プレゼンテーションロジック(ビュー)、入力の処理と検証(コントローラー)、およびビジネスロジック(モデル)です。実際のビューの大部分は、通常「テンプレート」と呼ばれます。

また、多層アーキテクチャについて読むこともできます。ここで、MVCは一方向(フローはController-> Model-> View)であり、Multi-Tierは双方向のもの(プレゼンテーション->ロジック->データ->ロジック->プレゼンテーション)であり、 MVCを実行するふりをするフレームワークは、実際には3層を実行し、プレゼンテーションを表示、ロジックをコントローラー、データをモデルに再ラベル付けします。


2
モデル(「モデル=ドメインロジック」)を誤って伝えていると思いますが、それはより多くのデータを持つ人口の容器であり、ビューを使用してMVCパターンの最も純粋な形でレンダリングされます。本当に単純な使用例では、「ドメインロジック」として扱うことができますが、既存の価値のあるほとんどのシステムは非常に早く成長することを保証します。「ドメインロジック」をサービスレイヤーなどの別のレイヤー/クラスに分割することをお勧めします。
A.マレー

@ A.Murray:もちろん、モデルは1つのモノリシックなコードの塊である必要はなく、通常、永続性、データ構造、およびドメインロジックに分離することは非常に理にかなっています。それでも、MVCはこれら3つの懸念をモデルにまとめています。いずれにせよ、コントローラーとビューにドメインロジックが含まれていると、実際のMVCではなくなります。
tdammers

@tdammers、私はあなたの答えの整頓と論理への焦点が好きです。あなたの見解では、永続性やトランザクション処理などのアプリケーションの懸念はどこに属しますか?MVCは、Sがサービス用であるMVCSのような4文字の頭字語であるようです。
flipdoubt

15

ビジネスロジックを完全に分離し、プレゼンテーションレイヤーインフラストラクチャから分離するには、アプリケーションサービスによってカプセル化する必要があります。MVCアーキテクチャは、プレゼンテーション層を実装する方法であり、すべてのビジネスロジックをこれらのアプリケーションサービスに委任し、そのスコープに留まる必要があります。ビューモデルは、ビューと表示または読み取りが必要なデータとの間のアダプターと考えてください。コントローラーは、ビジネスロジックをホストするビューモデル、ビュー、およびアプリケーションサービス間の相互作用を仲介します。

アプリケーションサービスは、ビジネスユースケースを実装し、MVCであろうとなかろうと、プレゼンテーション層から切り離されています。また、アプリケーションサービスは、トランザクションスクリプトまたはドメイン駆動設計をホストできます。

ストレージの場合、アプリケーションサービスは、リポジトリまたは永続化メカニズムの抽象化を参照できます。データアクセスをインターフェイスに抽象化することにより、さまざまな実装をサポートできます。通常、これらの抽象化は漏れやすく、実装間で部分的にのみ移植可能であり、完全な移植性を達成しようとする無駄な試みです。

更新

私の提案は、六角形のアーキテクチャに基づいています。六角形のアーキテクチャでは、ドメインモデル(ビジネスロジック)が中心になります。このコアは、ファサードとして機能するアプリケーションサービスによってカプセル化されます。アプリケーションサービスは、ドメインのユースケースに対応するメソッドを持つ単純なクラスです。アプリケーションサービスの詳細については、ドメイン駆動設計のサービスをご覧ください。コードサンプルにはPurchaseOrderService、購入ドメインのアプリケーションサービスであるが含まれています。(アプリケーションサービスは、ドメインドリブンデザインの使用を意味しないことに注意してください。)

六角形のアーキテクチャでは、MVCプレゼンテーションレイヤーは、ドメインモデル(ビジネスロジック)とGUIの間のアダプターです。ドメインモデルはプレゼンテーション層を認識しませんが、プレゼンテーション層はドメインモデルを認識します。

このソリューションには、ビジネスロジックをコントローラーに配置するソリューションよりも確かに可動部分があり、欠点と利点を比較検討する必要があります。複雑さを克服するために、ビジネスロジックをプレゼンテーションレイヤーから切り離したままにすることを好むため、提案する理由です。これは、アプリケーションが成長するにつれて重要になります。


コントローラーとビューモデルの両方を持つMVCとMVVMのろくでなしを説明しているように聞こえます。また、あなたが説明しているアーキテクチャは、OPのニーズに対して少し重いかもしれません。
ワコ

正直に言うと、私はWaquoの答えがもっと好きです。主に、「アプリケーションサービス」の意味がわからないからです。その用語を説明してもらえますか?私のGoogleFUは、ここでは機能していないようです。
ステフェンウィンクラー

1
@Waquo提案されたアーキテクチャは過剰である可能性があることに同意しますが、検討する必要があります。プレゼンテーションレイヤーを実装する別の方法であるMVVMについては言及していません。アプリケーションサービスは、MVCとMVVMのどちらを使用するかに関係なく適用されますが、この2つの組み合わせを示唆するものはありません。
eulerfx

1

ビジネスロジックの意味に依存します。モデルの内容に意味を与える「ロジック」は、モデル内にある必要があります。リンクされた質問では、最も投票数の多い回答が「ビジネスロジック」をデータに関連するものとして定義しているようです。これは、ビジネスのデータがビジネスであるという観点から理にかなっています!

私はかつてRailsの作成者(私が思うに)がモデルについて「ビジネスロジック」を入れずにまさにこれについて行っていた例を見ました。彼の例は、アプリの登録とログインのためのコントローラークラスとメソッドです。プレーンテキストで提供されたパスワードは、モデル(データベース)に挿入または照会される前に暗号化されました。

コントローラーロジックではなく、モデルに直接属するものの良い例は考えられません。

このモデルは、無数のデータストアへのインターフェイスとなり、移植性の問題を軽減できます。ここで、モデルインターフェースが実際に「コントローラー」であるかどうかについて、混乱を見つけることができます。

一般的に、コントローラーはモデルとビュー(アプリの要点)をリンクします。Cocoa開発では、コントローラーがXCode GUI(コントローラーオブジェクトとバインディング)を介して処理されるまで単純化できます。

MVCのGoFの「デザインパターン」セクション、大まかに引用:

クラスのMVCトライアドは、Smalltalk-80でユーザーインターフェイスを構築するために使用されます。モデルはアプリケーションオブジェクト、ビューは画面表示、コントローラーはUIがユーザー入力に反応する方法を定義します。MVCは、サブスクライブ/通知プロトコルを確立することにより、ビューとモデルを分離します。次の図は、モデルと3つのビューを示しています。簡単にするため、コントローラーは省略しました。

MVCはUIのすべてです。焦点はモデルとビュー-データの定義と表示にあります。「サブスクライブ/通知プロトコル」に注意してください-これがコントローラーの出番です。必要なビューをすべて作成できます。プロトコルに準拠している限り、モデルやコントローラーに触れる必要はありません。

特にWeb開発についてお話ししている場合、IMHOの多くの一般的なWebフレームワークは、MVCという用語とそのコンポーネント定義に関して高速で緩いものです。


私はC#/ Java(そこにある少数のプロジェクトのみ)開発者です。モデルが何をするのか誤解しているようです。「ビジネスロジック」をコントローラーに入れることは本当に後遺症に過ぎませんでした(私の思考の流れは「大丈夫、私はデータのモデルを持っています(データベース接続/ストレージを読んでください)、私のビジネスロジックはコントローラーに入れる必要があります」データベースにデータを保存する前に適用する必要があります。すべてをコントローラーから1レベル下に移動するだけです。実際、これは現在抱えていた問題を解決します(1つのプログラムでMySQLとMSSQLをサポート)
Steffen Winkler

0

サービス層を導入してみませんか?

そうすれば、コントローラーは無駄がなく読みやすくなり、コントローラーのすべての機能は純粋なアクションになります。

サービスレイヤー内で必要なだけビジネスロジックを分解できます。コードの再利用性が向上し、モデルやリポジトリへの影響はありません。

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