プログラミングパラダイム。 データ駆動型とドメイン駆動型

情報技術は飛躍的に発展し、新しいデバイス、プラットフォーム、オペレーティングシステムが登場すると同時に、開発者が解決しなければならないタスクの範囲が拡大しています。 しかし、すべてがそれほど悪いわけではありません。新しい開発ツール、ide'shki、新しいプログラミング言語、方法論などがプログラマを支援するために急いでいます。 プログラミングパラダイムリストだけでも印象的であり、最新のマルチパラダイムプログラミング言語 (C#など)を考えると、この質問は次のような疑問を提起します。 何を選ぶ?



少し理解してみましょう。



多くのパラダイムはどこから来たのですか?



実際、この投稿ではすでに答えが表明されています。適切なパラダイムを使用すると、さまざまなタイプのタスクを簡単かつ迅速に解決できます。 したがって、ITの開発に伴い、新しいタイプのタスクが出現し(または古いタスクが関連するようになった)、古いアプローチを使用してそれらを解決するのは不便であり、新しい手法の再考と出現が必要でした。



何を選択しますか?



それはすべて、何をする必要があるかに依存します。 すべての開発ツールが異なっており、一部は開発ツールをサポートし、他は開発ツールをサポートしていることに注意してください。 たとえば、モジュールの「標準」セットを持つPHPは、 アスペクト指向プログラミングをサポートしていません。 したがって、方法論の選択は開発プラットフォームと非常に密接に関連しています。 さまざまなアプローチを組み合わせることができることを忘れないでください。これにより、パラダイムのスタックを選択できます。



パラダイムを分類するには、ほとんどすべてのタスクに固有の4つのディメンションを使用します。





この考えをさらに深く掘り下げることができます。これらの4つのメジャーの定性的特性を考え出し、厳格なルールと少しの数学を追加しますが、これはおそらく別の投稿のトピックです。 ほとんどのシステムアーキテクトは、知識と経験に基づいて特定のタスクのこれらの特性を決定すると思います。



これらの4つのディメンションでタスクを分析すると、特定のディメンションが他のディメンションよりも強く表現されていることがわかります。 そして、これにより、プログラミングパラダイムは通常1つの次元を対象としているため、プログラミングパラダイムを決定することが可能になります。



以下の例を検討してください。





実際には何ですか?



当社では、ビジネスアプリケーション(スタートアップ、Webサービス、Webサイト、アプリケーションプログラムなど)の開発に取り組んでいます。したがって、私たちの実践とこの分野で働く他のチームの両方で見られるプログラミングパラダイムについてさらに説明します。



私の経験に基づいて、この分野では2つのアプローチが普及していると言えます。データ駆動型とドメイン駆動型です。 実際、それらは競合する方法論ですが、実際には、よく知られているアンチパターンである共生生物に組み合わせることができます。



ドメインドリブンよりもデータドリブンの利点の1つは、その使いやすさと実装です。 そのため、ドメインドリブンを適用する必要がある場合は、データドリブンの使用を開始します(多くの場合、これは無意識に行われます)。 Data Drivenは、オブジェクト指向プログラミングの概念との互換性が低いという事実で問題が発生します(もちろん、OOPを使用する場合)。 小さなアプリケーションでは、これらの問題はほとんど目に見えません。 中規模のアプリケーションでは、これらの問題はすでに顕著であり、アンチパターンにつながり始めていますが、大規模なプロジェクトでは問題が深刻になり、適切な対策が必要になります。



ドメインドリブンは、大規模プロジェクトに有利であり、小規模プロジェクトではソリューションを複雑にし、より多くの開発リソースを必要とします。これは、ビジネス要件の観点からしばしば重要です(プロジェクトを小さな予算で「できるだけ」市場に持ち込むため)。



アプローチの違いを理解するために、より具体的な例を検討してください。 会計注文のシステムを開発する必要があるとします。 次のようなエンティティがあります。





コンテキスト領域が完全に表示されると判断したので、データベースの設計を開始します。 対応するテーブルを作成し、ORM-kuを実行し、必須クラスを生成します(まあ、または「スマート」orm-kiの場合は、たとえばxmlのどこかでスキームを個別に規定し、それから基本クラスと必須クラスを生成します)。 その結果、エンティティごとに個別の独立したクラスを取得します。 私たちは人生を楽しんでいます。オブジェクトの操作は簡単でシンプルです。



時間が経ち、プログラムに追加のロジックを追加する必要があります。たとえば、注文で最高価格の商品を見つけるためです。 あなたの組織が外部の関係をサポートしていない場合(つまり、本質的なクラスがデータコンテキストについて何も知らない場合)、ここですでに問題が発生する可能性があります。この場合、メソッドがあるサービスを作成する必要があります-目的の製品を順番に返します。 しかし、私たちのオームは優れており、外部接続を操作する方法を知っているので、注文クラスにメソッドを追加するだけです。 繰り返しますが、私たちは人生を楽しみ、目標が達成され、メソッドがクラスに追加され、ほぼ実際のOOPがあります。



時間が経ち、クォータ、請求書、および他の同様のエンティティに同じメソッドを追加する必要があります。 どうする このメソッドをすべてのクラスに登録するだけでかまいませんが、実際にはコードの重複であり、サポートとテストが行​​われます。 複雑にするのではなく、メソッドをすべてのクラスにコピーするだけです。 次に、同様のメソッドが表示され、重要なクラスが同じコードで膨らみ始めます。



時間が経つと、データベース内の外部接続では記述できないロジックが表示されるため、基本クラスに配置することはできません。 これらの機能を実行するサービスの作成を開始しています。 その結果、ビジネスロジックが重要なクラスとサービスに分散しているため、目的のメソッドを探す場所を理解することがますます難しくなっています。 リファクタリングして、たとえばサービス内でコードを繰り返すことを決定します-インターフェイスで一般的な機能を選択し(たとえば、インターフェイスをIProductable、つまり製品を含むものにする)、サービスはこれらのインターフェイスで動作します。抽象的に。 しかし、基本的にはこれで問題は解決しません。サービスでより多くのメソッドを取得し、必要なクラスからサービスにすべてのメソッドを転送するために画像の統一のために決定します。 これでメソッドを探す場所はわかりましたが、重要なクラスはすべてのロジックを失い、いわゆる「Anemic Model」を取得しました。



この段階で、OOPの概念から完全に脱却しました。オブジェクトはデータのみを格納し、すべてのロジックはカプセル化も継承もしない別々のクラスにあります。



これは見た目ほど悪くないことは注目に値します-単体テストの実装を妨げるものは何もありません。実際、テストによる開発、依存関係管理パターンの導入など、一般的には、あなたはそれで生きることができます。 アプリケーションが大きなものに発展するとき、頭の中にそれらを保持することが不可能なほど多くのエンティティがあり、相互作用について話す必要がないとき、問題が発生します。 この場合、そのようなアプリケーションのサポートと開発が問題になります。



ご想像のとおり、このシナリオではデータドリブンアプローチの使用とその問題について説明します。

ドメインドリブンの場合、次のようにします。 まず第一に、最初の段階ではデータベース設計に関する話はありません。 タスクのコンテキスト領域を慎重に分析し、シミュレートし、OOP言語に転送する必要があります。



たとえば、一連の基本的なプロパティを持つ抽象ドキュメントのモデルを作成できます。 彼からは製品を含むドキュメントを継承し、彼からは「支払い」ドキュメントを継承し、価格と請求先住所などを付けます。 このアプローチでは、最も高価な製品を受け取るメソッドを追加することは難しくありません。適切な基本クラスに追加するだけです。



その結果、タスクのコンテキスト領域は、OOPを使用して最大限に記述されます。

しかし、明らかな問題があります:データベースにデータを保存する方法は? 実際、このためには、モデルのデータをデータベースのフィールドにマッピングする機能を作成する必要があります。 このようなマッパーは非常に複雑になる可能性があり、モデルを変更する場合、マッパーを変更する必要があります。



さらに、複雑なリファクタリングにつながる可能性のあるモデリングエラーの影響を受けません。



データ駆動型とドメイン駆動型をまとめると:

データ駆動型





ドメイン駆動:





それで、私は何を選ぶべきですか?



残念ながら、明確な答えはありません。 問題、リソース、開発の見通し、目標、目的を分析します。 正しい選択は常に妥協です。



All Articles