MVC サービス アーキテクチャは Symfony プロジェクトでは非常に一般的であるため、それが唯一の方法のように感じられます。シンプルで馴染みがあり、うまくいきます...うまくいかなくなるまでは。プロジェクトが成長するにつれて、亀裂が目立ち始めます。ビジネス ロジックがあちこちにあり、アプリの動作が不明確で、コードの保守が困難になります。これは最も一般的なアプローチですが、Symfony はこれに固執することを強制しません。
もっと良い方法があったとしたら?
プロジェクトが成長するにつれて、ビジネス ロジックはコード ベース全体に広がる傾向があります。プロジェクトのすべての層 (コントローラー、サービス、フォーム、エンティティ) には、最終的にドメイン モデルの断片が含まれることになります。そのため、特定の部分に焦点を当てることがますます困難になります。
アーキテクチャが技術レイヤーを中心に編成されている場合、プロジェクトが成長するにつれて、さまざまなコンテキスト間の明確な境界を特定することが難しくなります。この明確さの欠如により、密接に結合されたコードとメンテナンスの問題が発生する可能性があります。
デフォルトのアーキテクチャは技術層を強調しているため、プロジェクトの動作を理解するのは非常に困難になります。特定のエンティティが特定のサービスによって管理されていると推測したり、データベース スキーマを推測したりすることはできますが、最も重要な側面であるプロジェクトの実際の動作は不明瞭で暗黙的なままです。
ビジネス ロジックがプロジェクト全体に散在し、実装の詳細と混在している場合、それらを独立して進化させることが困難になります。時間の経過とともに、ビジネス ロジックのライフサイクルは、実装の詳細 (フレームワーク、サードパーティ API、データベースなど) のライフサイクルよりもはるかに長くなる傾向があります。この不一致により、依存関係に小さな変更が発生するたびに、コードの大部分を書き直す必要があります。
必要なときにビジネス ロジックに集中しやすくするために、最初のステップは、ビジネス ロジックをプロジェクトの残りの部分から分離することです。これを実現するには、Domain フォルダーを作成します。このフォルダーはプロジェクトの中核となり、実装の詳細に依存せず、純粋な PHP オブジェクトを使用してビジネス ロジックがモデル化されます。プロジェクトの残りの部分はこのフォルダーに依存しますが、ドメイン フォルダーは誰にも依存しません。
ドメイン フォルダー内では、ファイルは技術的な目的ではなくドメインの目的別にグループ化する必要があります。つまり、ここにはエンティティ、サービス、またはコントローラーのフォルダーはなく、機能またはドメインの概念に対応するフォルダー名のみが表示されます。
プロジェクトの最も重要な側面は、プロジェクトが何をするか、つまり処理できるアクションです。これらのアクションはプロジェクトの動作を表し、ビジネス ロジックにアクセスする唯一の方法として機能します。これを反映するには、プロジェクトのすべての動作を明示的に示す Application フォルダーを作成します。たとえば、プロジェクトの新しい開発者として、このフォルダーを見れば、プロジェクトで何ができるかを一目で理解できるはずです。
App フォルダーと Domain フォルダーを使用すると、ビジネス ロジックに集中しやすくなります。ただし、ある時点で、このビジネス ロジックは外部システムと対話する必要があります。これに対処するには、インフラストラクチャ という 3 番目のフォルダーを作成します。このフォルダーには、フレームワーク固有のコード、データベース接続、ライブラリなどの実装の詳細がすべて含まれています。
インフラストラクチャ フォルダー内のファイルは、アプリ ファイルとドメイン ファイルに依存します。たとえば、アプリケーション フォルダーからアプリケーション ハンドラーを呼び出したり、ドメイン フォルダーで定義されたインターフェイスを実装したりする場合があります。
具体的には、Symfony では、Controller フォルダーを変更し、どのサービスがどのインターフェースを実装するかを宣言する必要があります。
# config/routes.yaml controllers: resource: path: ../src/Catalog/Infrastructure/Controller/ namespace: App\Catalog\Infrastructure\Controller type: attribute
プロジェクトが進化するにつれて、ビジネス ロジックの一部がアーキテクチャ内で独自のスペースを必要とすることに気づくかもしれません。良い指標は、同じ用語が文脈に応じて異なる意味を持ち始める時期です。たとえば、「製品」という単語は、工場製品、倉庫製品、または電子商取引製品を指す場合があり、それぞれに独自のモデルが必要です。神のオブジェクトも良い指標になる可能性があります。 Symfony プロジェクトでは、User クラスでこの種の問題がよく発生します。
これが起こったら、それを抽出してビジネス ロジックを独自に進化させます。
一部のコンテキストはプロジェクトの中核を形成し、他のコンテキストはそれをサポートします。 Auth などの汎用コンテキストはドメインの中心ではないため、より単純なアーキテクチャを使用できます
この図では、Auth コンテキストが標準の Symfony 構造を使用し、Order コンテキストと Catalog コンテキストがドメイン中心のアーキテクチャを使用し、 Shipping コンテキストが機能中心のアーキテクチャを使用していることがわかります。
特定のコンテキストが独立して拡張する必要がある点まで成長する場合は、それを別のデプロイメント ユニットに分割することを検討してください。
ただし、このステップを急いで行わないでください。まずプロジェクトをモジュール化して、コンテキストを個別に拡張する必要があることに気付いた場合は、コンテキストを個別にデプロイします。
2 つのチームが同じコードベースで共同作業するのに苦労しているなど、組織上の課題が発生した場合にのみ、コードベースを分割します。
これらのソリューションを検討する中で、私たちはいくつかのクラフトマンシップの概念を適用しました。それぞれについて詳しく説明できるように、それらに名前を付けて簡単に説明しましょう。
この珍しい用語の背後には、非常に単純な概念があります。ユビキタス言語は、チームがドメイン モデルを説明するために使用する語彙です。この語彙は文書化され、製品に関する会話やコードベースなど、あらゆる場所で一貫して使用される必要があります。
具体的には、境界コンテキストのルートにマークダウン ファイルを作成し、製品担当者、ドメインの専門家、技術チームを集めてプロジェクトの各コンセプトを定義します。
境界付きコンテキストは、プロジェクト内の言語境界を定義し、ユビキタス言語が一致しなくなったシステムの部分を分離します。コンテキスト マップやイベント ストーミングなどのツールは、これらの境界を特定するのに役立ちます。
境界のあるコンテキストは抽象的な概念です。モジュール式モノリスの単純なフォルダーからマイクロサービス アーキテクチャのクラスターまで、さまざまな方法で実装できます。
これらのアーキテクチャはすべて、ビジネス ロジックを実装の詳細から分離することを目的としています。ポートとアダプター、ヘキサゴナル、またはクリーン アーキテクチャのいずれを使用する場合でも、中心となるアイデアは、ビジネス ロジック フレームワークに依存せず、テストを容易にすることです。
これを念頭に置けば、あらゆる実装があり、最適なものはコンテキストと好みによって異なります。このアーキテクチャの主な利点は、ビジネス ロジックを分離することで、より効率的なテストが可能になることです。
ビジネス ロジックを「叫ぶ」ためにフォルダーとファイルを整理するというアイデアは、スクリーミング アーキテクチャとして知られています。この概念は、コードの構造によってプロジェクトの目的が即座に明確になる必要があることを強調しています。目標は、新しい開発者がプロジェクトの内容を一目で理解できるようにすることです。
このテーマに関するボブおじさんの記事を読むことを強くお勧めします。彼の住宅計画との比較は特に洞察力に富んでいます。
垂直スライスにより、プロジェクトが機能ごとに整理され、各機能が独立して進化できるようになります。これにより、複雑さと成熟度に基づいて、さまざまなアーキテクチャをさまざまな機能に適用できます。
このアイデアは興味深いものですが、このようなアーキテクチャを効果的に実装し、維持するには高度なスキルを持ったエンジニアが必要です。
Symfony プロジェクトを構造化する方法は、そのスケーラビリティ、保守性、明瞭さに大きな影響を与えます。ビジネス ロジックを分離し、動作を明示することで、理解しやすく進化しやすいシステムを作成できます。
これらのアイデアに慣れていない場合でも、心配しないでください。ソフトウェアのクラフトマンシップは目的地ではなく旅です。最初は概念が難しそうに思えるかもしれませんが、それぞれの概念はビジネスにより多くの価値を提供するのに役立ちます。
ご質問がありますか、またはあなたの経験を共有したいですか?コメント欄に書き込んでください!次の記事もお楽しみに?
以上がSymfony プロジェクトを構成する別の方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。