情報技術は飛躍的に発展し、新しいデバイス、プラットフォーム、オペレーティングシステムが登場すると同時に、開発者が解決しなければならないタスクの範囲が拡大しています。 しかし、すべてがそれほど悪いわけではありません。新しい開発ツール、ide'shki、新しいプログラミング言語、方法論などがプログラマを支援するために急いでいます。
プログラミングパラダイムの
リストだけでも印象的であり、最新のマルチ
パラダイムプログラミング言語 (C#など)を考えると、この質問は次のような疑問を提起します。 何を選ぶ?
少し理解してみましょう。
多くのパラダイムはどこから来たのですか?
実際、この投稿ではすでに答えが表明されています。適切なパラダイムを使用すると、さまざまなタイプのタスクを簡単かつ迅速に解決できます。 したがって、ITの開発に伴い、新しいタイプのタスクが出現し(または古いタスクが関連するようになった)、古いアプローチを使用してそれらを解決するのは不便であり、新しい手法の再考と出現が必要でした。
何を選択しますか?
それはすべて、何をする必要があるかに依存します。 すべての開発ツールが異なっており、一部は開発ツールをサポートし、他は開発ツールをサポートしていることに注意してください。 たとえば、モジュールの「標準」セットを持つPHPは、
アスペクト指向プログラミングをサポートしていません。 したがって、方法論の選択は開発プラットフォームと非常に密接に関連しています。 さまざまなアプローチを組み合わせることができることを忘れないでください。これにより、パラダイムのスタックを選択できます。
パラダイムを分類するには、ほとんどすべてのタスクに固有の4つのディメンションを使用します。
- データ
どのようなプログラムでも、何らかの方法でデータを処理します。データ、プロセス、分析、転送を保存します
- アクション
プログラムは何かを行う必要があります。通常、アクションはデータに関連しています。
- ロジック 。
ロジックまたはビジネスロジックは、データとアクションを管理するルールを定義します。 ロジックがなければ、プログラムは無意味です - インターフェース
プログラムが外界と相互作用する方法
この考えをさらに深く掘り下げることができます。これらの4つのメジャーの定性的特性を考え出し、厳格なルールと少しの数学を追加しますが、これはおそらく別の投稿のトピックです。 ほとんどのシステムアーキテクトは、知識と経験に基づいて特定のタスクのこれらの特性を決定すると思います。
これらの4つのディメンションでタスクを分析すると、特定のディメンションが他のディメンションよりも強く表現されていることがわかります。 そして、これにより、プログラミングパラダイムは通常1つの次元を対象としているため、プログラミングパラダイムを決定することが可能になります。
以下の例を検討してください。
- データ駆動型設計:データの相互関係ではなく、最初にデータを重視します。
適切なアプリケーションの種類:
- グラバー(さまざまなソースからデータを収集し、どこかに保存します)
- さまざまな管理領域、データベースインターフェイス、多くの単純なCRUD操作を備えたすべて
- データの処理がすでに定義されている場合、たとえば、プログラムの開発が必要であり、データベースが既に存在し、データスキームを変更できない場合。 この場合、データおよびデータアクセスレベルに対して追加のラッパーを作成するよりも、既に存在するものに集中する方が簡単な場合があります
- 多くの場合、ORMを使用するとデータの向きが表示されますが、これが良いか悪いかを事前に言うことはできません(詳細は以下を参照)
- アクションに焦点を当てる-開発への必須のアプローチ。 イベント駆動プログラミング 、アスペクト指向プログラミングなどのパラダイムは、ここに起因すると考えることができます。
- ロジック指向- ドメイン駆動設計 (DDD)およびそれに関連するすべて。 ここでは、問題の主題領域が重要であり、オブジェクトのモデリング、関係と依存関係の分析に注意を払っています。 主にビジネスアプリケーションで使用されます。
また、これには宣言的アプローチと部分的に機能的なプログラミング(数式でうまく説明されている問題を解決する)が含まれます。 - インターフェイスの方向。 プログラムが外界と相互作用する方法が主に重要である場合に使用されます。
インターフェイスのみに焦点を当てたアプリケーションの開発は、かなりまれな状況です。 私が出会ったいくつかの本では、このアプローチは真剣に考えられており、ユーザーインターフェイスに基づいていると述べましたが、ユーザーが直接見たものを取り上げ、これに基づいてデータ構造などを設計しました。
多くの場合、ビジネスアプリケーションのユーザーインターフェイスの方向は間接的に表れます。たとえば、ユーザーは取得が困難な特定のデータを確認する必要があります。そのため、アーキテクチャは追加の構造(たとえば、データの強制的な冗長化)に囲まれています。
正式には、これにはイベント駆動型プログラミングを含めることができます
実際には何ですか?
当社では、ビジネスアプリケーション(スタートアップ、Webサービス、Webサイト、アプリケーションプログラムなど)の開発に取り組んでいます。したがって、私たちの実践とこの分野で働く他のチームの両方で見られるプログラミングパラダイムについてさらに説明します。
私の経験に基づいて、この分野では2つのアプローチが普及していると言えます。データ駆動型とドメイン駆動型です。 実際、それらは競合する方法論ですが、実際には、よく知られているアンチパターンである共生生物に組み合わせることができます。
ドメインドリブンよりもデータドリブンの利点の1つは、その使いやすさと実装です。 そのため、ドメインドリブンを適用する必要がある場合は、データドリブンの使用を開始します(多くの場合、これは無意識に行われます)。 Data Drivenは、オブジェクト指向プログラミングの概念との互換性が低いという事実で問題が発生します(もちろん、OOPを使用する場合)。 小さなアプリケーションでは、これらの問題はほとんど目に見えません。 中規模のアプリケーションでは、これらの問題はすでに顕著であり、アンチパターンにつながり始めていますが、大規模なプロジェクトでは問題が深刻になり、適切な対策が必要になります。
ドメインドリブンは、大規模プロジェクトに有利であり、小規模プロジェクトではソリューションを複雑にし、より多くの開発リソースを必要とします。これは、ビジネス要件の観点からしばしば重要です(プロジェクトを小さな予算で「できるだけ」市場に持ち込むため)。
アプローチの違いを理解するために、より具体的な例を検討してください。 会計注文のシステムを開発する必要があるとします。 次のようなエンティティがあります。
- 製品
- お客様
- クォータ(クライアントにオファーとして送信)
- 注文(order)
- 請求書(支払い)
- サプライヤーへの注文
- 請求書(実際には、サプライヤーからの支払い)
コンテキスト領域が完全に表示されると判断したので、データベースの設計を開始します。 対応するテーブルを作成し、ORM-kuを実行し、必須クラスを生成します(まあ、または「スマート」orm-kiの場合は、たとえばxmlのどこかでスキームを個別に規定し、それから基本クラスと必須クラスを生成します)。 その結果、エンティティごとに個別の独立したクラスを取得します。 私たちは人生を楽しんでいます。オブジェクトの操作は簡単でシンプルです。
時間が経ち、プログラムに追加のロジックを追加する必要があります。たとえば、注文で最高価格の商品を見つけるためです。 あなたの組織が外部の関係をサポートしていない場合(つまり、本質的なクラスがデータコンテキストについて何も知らない場合)、ここですでに問題が発生する可能性があります。この場合、メソッドがあるサービスを作成する必要があります-目的の製品を順番に返します。 しかし、私たちのオームは優れており、外部接続を操作する方法を知っているので、注文クラスにメソッドを追加するだけです。 繰り返しますが、私たちは人生を楽しみ、目標が達成され、メソッドがクラスに追加され、ほぼ実際のOOPがあります。
時間が経ち、クォータ、請求書、および他の同様のエンティティに同じメソッドを追加する必要があります。 どうする このメソッドをすべてのクラスに登録するだけでかまいませんが、実際にはコードの重複であり、サポートとテストが行われます。 複雑にするのではなく、メソッドをすべてのクラスにコピーするだけです。 次に、同様のメソッドが表示され、重要なクラスが同じコードで膨らみ始めます。
時間が経つと、データベース内の外部接続では記述できないロジックが表示されるため、基本クラスに配置することはできません。 これらの機能を実行するサービスの作成を開始しています。 その結果、ビジネスロジックが重要なクラスとサービスに分散しているため、目的のメソッドを探す場所を理解することがますます難しくなっています。 リファクタリングして、たとえばサービス内でコードを繰り返すことを決定します-インターフェイスで一般的な機能を選択し(たとえば、インターフェイスをIProductable、つまり製品を含むものにする)、サービスはこれらのインターフェイスで動作します。抽象的に。 しかし、基本的にはこれで問題は解決しません。サービスでより多くのメソッドを取得し、必要なクラスからサービスにすべてのメソッドを転送するために画像の統一のために決定します。 これでメソッドを探す場所はわかりましたが、重要なクラスはすべてのロジックを失い、いわゆる「Anemic Model」を取得しました。
この段階で、OOPの概念から完全に脱却しました。オブジェクトはデータのみを格納し、すべてのロジックはカプセル化も継承もしない別々のクラスにあります。
これは見た目ほど悪くないことは注目に値します-単体テストの実装を妨げるものは何もありません。実際、テストによる開発、依存関係管理パターンの導入など、一般的には、あなたはそれで生きることができます。 アプリケーションが大きなものに発展するとき、頭の中にそれらを保持することが不可能なほど多くのエンティティがあり、相互作用について話す必要がないとき、問題が発生します。 この場合、そのようなアプリケーションのサポートと開発が問題になります。
ご想像のとおり、このシナリオではデータドリブンアプローチの使用とその問題について説明します。
ドメインドリブンの場合、次のようにします。 まず第一に、最初の段階ではデータベース設計に関する話はありません。 タスクのコンテキスト領域を慎重に分析し、シミュレートし、OOP言語に転送する必要があります。
たとえば、一連の基本的なプロパティを持つ抽象ドキュメントのモデルを作成できます。 彼からは製品を含むドキュメントを継承し、彼からは「支払い」ドキュメントを継承し、価格と請求先住所などを付けます。 このアプローチでは、最も高価な製品を受け取るメソッドを追加することは難しくありません。適切な基本クラスに追加するだけです。
その結果、タスクのコンテキスト領域は、OOPを使用して最大限に記述されます。
しかし、明らかな問題があります:データベースにデータを保存する方法は? 実際、このためには、モデルのデータをデータベースのフィールドにマッピングする機能を作成する必要があります。 このようなマッパーは非常に複雑になる可能性があり、モデルを変更する場合、マッパーを変更する必要があります。
さらに、複雑なリファクタリングにつながる可能性のあるモデリングエラーの影響を受けません。
データ駆動型とドメイン駆動型をまとめると:
データ駆動型 :
- 長所
- アプリケーションまたはプロトタイプを迅速に開発できます
- 設計に便利(スキームに応じたコード生成など)
- 小規模または中規模のプロジェクトでは、かなりの解決策になります。
- 短所
- アンチパターンにつながり、OOPを回避する可能性があります
- 大規模なプロジェクトでは、混乱、複雑なサポートなどにつながります。
ドメイン駆動:- 長所
- OOPの全機能を使用
- コンテキスト領域(ドメイン)の複雑さを制御できます
- ドメイン言語の作成やBDDの導入など、この記事には記載されていない多くの利点があります。
- 複雑で大規模なソリューションを開発するための強力なツールを提供します
- 短所
- 開発中に必要なリソースが大幅に増えるため、ソリューションのコストが増加します
- 特定の部分の保守がより難しくなります(データマッパーなど)
それで、私は何を選ぶべきですか?
残念ながら、明確な答えはありません。 問題、リソース、開発の見通し、目標、目的を分析します。 正しい選択は常に妥協です。