web-dev-qa-db-ja.com

ポートとアダプタ/六角形のアーキテクチャ-用語と実装の明確化

Alistair Cockburnのポートとアダプタアーキテクチャに関するさまざまなソースを読んだ後 オリジナル記事 「ポート」と「アダプタ」という用語の明確な意味については、特にこれらの概念のマッピングに関してはまだわかりません実装アーティファクトに。

いくつかのソース(例 this post )は、このアーキテクチャパターンのportsが非常に外側のアーティファクトであり、中間にadaptersが続くことを意味しますportsapplicationの間を変換するレイヤーが中心にあります。

ただし、Cockburnの元の記事では、ポートアダプタレイヤーの内側と同様に外側にも表示され、通信の方向によって異なります。

  • インバウンド通信: "イベントが外部からポートに到着すると、テクノロジー固有のアダプターがそれを使用可能なプロシージャコールまたはメッセージに変換し、アプリケーションに渡します。"
  • アウトバウンド通信: "アプリケーションが送信するものを持っている場合、アプリケーションはポートを介してアダプターに送信します。これにより、受信テクノロジー(人間または自動化)に必要な適切な信号が作成されます。"

実際、私にとっては、「すべて外側」のアプローチも、「内側と外側」のアプローチも意味がありません。portsは、通信の方向に関係なく、常にアプリケーションの隣に配置されるアーティファクトと見なされます。 Imoこれはportおよびadapterメタファーとも一致します。シリアルポートを備えたデバイスがあり、シリアルポートを備えていない別のデバイスをこれに接続するには、デバイスの観点からインバウンドとアウトバウンドの通信を調整するアダプターが必要です。

このアーキテクチャの実装に来ると、アプリケーションの一部としてではなく、portsの定義が表示されます。ここでは、異なるadaptersが「外部」であると表示されます。私のアプリケーションの。例:単一のportの実装は、facade(インバウンド通信用のアダプターによって呼び出される)とinterface(アウトバウンド通信用のアダプターによって実装される)で構成できます。 )。

portおよびadapterという用語の正しい意味は何ですか?これらの概念を実装アーティファクトにどのようにマッピングできますか?

更新:

見つかりました この記事 これは私の理解に似ています。ある種の共通の合意があるかどうかという問題は残っています。

29
lost

inf3rnoは元の質問を明確にする良い答えを出しましたが、ポートとアダプタの他の使用法を強調することは有用かもしれません。

私の理解によるとポートはインターフェースの表現です

ポート:

  • コアの機能の公開を定義します(「受信」ポート用)
  • コアの外界のビューを定義します(「発信」ポート用)

アダプター:

  • コンポーネントの外側に配置されている(六角形)
  • ポートとターゲット間のトランスポートがポートのインターフェースとの契約を満たす方法で行われることを保証するために使用されます
  • 六角形をテストするために(依存性注入を使用して)置き換えるものです

ポートはアダプターを受け入れ、アダプターがインターフェースを実装していることを確認する必要があります。次に、アダプタの適切なメソッド/関数を呼び出すだけです。

ポートは通信テストに含まれるべきです。その場合、「モックアウト」されるのは、2つの隣接する六角形(または六角形とサービス)のコアであり、ポート/アダプター/アダプター/ポートアセンブリをテストします。

詳細については、James Gardnerと私がロンドンのSkillsmatterマイクロサービス 2014年7月に会合 で行った六角形マイクロサービスに関する講演をご覧ください。

21
Vlad Mettler

かなりシンプルなコンセプトだと思います。あなたはそれ以外の何にも依存しないアプリケーションコアを持っています。たとえば、HTTPフレームワーク、データベースドライバー、メーリングフレームワークなどには依存しません...このコアは、問題のドメインに応じて非常に固有のインターフェイスを備えているため、問題のドメインが変更された場合にのみ、アプリケーションコアのコードを変更する必要があります。

たとえば、ブログの投稿があり、それらにカテゴリを追加したいとします。したがって、カテゴリはシステム全体を流れる必要があります。HTTP通信からデータベースへの書き込み、およびその逆の読み取りです。

たとえば、MySQLデータベースをMongoDBなどに置き換えたい場合はどうでしょうか。アプリケーションはまったく同じことを行うため、コアに影響を与えることはありません。ブログの投稿とofcを保存します。それらのカテゴリとオンデマンドでそれらを返します。したがって、必要なのは、この場合はMondogDBアダプターのみであり、MySQLアダプターの代わりに使用できます。

たとえば、REST APIだけでなく、単純なHTMLページではない場合はどうでしょうか?それでもアプリケーションコアには影響しないため、必要なのはRESTコミュニケーション。

したがって、私の意見では、アダプターにはアプリケーションコアで定義された特定のインターフェイスがあり、ポートはこれらのアダプターを使用してアプリケーションコアと通信する必要があります。したがって、私の意見では、ポートはクラスとして存在する必要はなく、アダプターとそのインターフェースのみとして存在します。この概念は理にかなっています。これは、アプリケーションコアが、使用するポートにではなく、定義するアダプターインターフェイスにのみ密接に結合されるためです。 (ちなみに、似たようなアーキテクチャは複数あります。クリーンなアーキテクチャ、オニオンアーキテクチャのように、同じ概念を異なる語彙で使用します。)

17
inf3rno

私の職場の誰かが、このアーキテクチャについて素晴らしい社内プレゼンテーションを行いました。最後に、質問時に別の同僚が尋ねました:

これは、単に異なる名前で描かれたレイヤードアーキテクチャだけではないのですか?

そして、正直に言うと、それはかなりの範囲で当てはまります。多くのアプリケーションでは、六角形のアーキテクチャは階層化されたアーキテクチャと同じように構造化され、いくつかの具体的な詳細があります。

  • Implからimplを呼び出すのではなく、各レイヤー(ポート)間のインターフェースを定義する際の規律が強化されています。
  • 「コア」(ビジネスロジック)が最も重要な層であることに焦点が当てられており、他のすべての層(アダプタ)はある程度従順であると見なされています。
  • コアの観点からインターフェースを定義することに焦点を当てているため、アダプターの言語がコアに漏れることはありません。たとえば、永続性(Hibernateなど)をアダプターに入れる場合は、コアに@Entityクラスを含めないでください。

これらすべてのことを実行しても、レイヤー間の境界が非常に厳格で中央レイヤーに焦点が置かれているだけの、階層化されたアーキテクチャーであることがわかります。

そのため、具体的に質問に答えるために、ポートはコアへのインターフェイスとコアからのインターフェイスであり、アダプタはコアではない実装層にすぎないことを認識することで、ポートとアダプタを理解できます。

8
Graham Lea

私の見解では、元の記事を読んで、Alistair Cockurn(「Alistair in Hexagone」)のいくつかの講演を見た後、正しいアプローチは、「すべての内部」と呼ばれるものであると考えます。ポートはアダプターの「内部」にあります。アダプターは、アプリと対話する外部アクターとポートの間にあります。ポートはアプリに属しています。

インバウンド通信の場合、アクター(ドライバーアクター)は、ドライバーアダプターを使用して通信をトリガーします。このアダプターは、アプリのドライバーポートを呼び出し、アプリに何かを要求します。

アウトバウンド通信の場合、アプリはドリブンポートを定義して呼び出すことにより、ドリブンアクターとの通信をトリガーします。このポートは、目的の観点からアプリが必要とするもののコントラクト(通常はインターフェース)です。このポートは、外部アクターと通信するアダプターによって実装されます。

依存関係は:

ドライバーアクター->ドライバーアダプター->六角形<-ドリブンアダプター<-ドリブンアクター

ポートは六角形に属します:

ドライバーポートは、Hexagonからドライバーアダプターに提供されるAPIです。

ドリブンポートは、SPIであり、ドリブンアダプターによって実装されます。

元の記事に出てきたこの文章についても、私は多くの苦労をしました。

「イベントが外部からポートに到着すると、テクノロジー固有のアダプターがそれを使用可能なプロシージャコールまたはメッセージに変換し、アプリケーションに渡します。」

これは、ドライバーポートが「外部」のドライバーアダプターであることを示しています。でも、記事全体を読んで会談を見ていると、そうではないと思います。この文が「ポート」と呼んでいるのは、単に外部のドライバーアクターとアダプターの間の相互作用です。 「ポート」は、アダプターとアプリの間の相互作用でなければなりません(「...をアプリケーションに渡します」)。

1
choquero70