web-dev-qa-db-ja.com

Clean Architectureをリッチデスクトップアプリケーションに適応させる方法

私はクリーンなアーキテクチャについて学んでいるだけで、すぐに構築したいアプリケーションの概念実証を設計しようとしています。

クリーンアーキテクチャでは、プレゼンテーション層とドメインモデル層がアプリケーション層によって分離されています。これが、WebベースのMVCアプリケーションや、ほとんどの操作がCRUDである「レコードベースの」デスクトップアプリケーションなどのステートレスアプリケーションにとってどのように意味があるかを理解しています。また、私の理解では、プレゼンテーション層はドメインオブジェクトを直接使用するのではなく、アプリケーション層のモデルとの間でマップされる独自のViewModelを持つ必要があります。この仮定は正しいですか?

私が開発する予定のアプリケーションは、ユーザーが一度に1つの動きでチェスのゲームを入力できるようにします。チェスのルールはドメインモデルレイヤーにあるように思えます。この場合、プレゼンテーション層は各ユーザー入力をどのように検証しますか(各ムーブの合法性を検証するため)?毎回アプリケーション層を通過する必要がありますか、それともプレゼンテーション層にドメインオブジェクトを直接操作させて、ユーザー入力に従ってモデルを構築し、保存するときにアプリケーション層に送信する方が理にかなっていますか。データベースに?

これについて説明するリソースをオンラインで見つけようとしましたが、すべての例/コース/チュートリアルで、Webアプリケーションまたは少なくともデータを保存する前にビジネスルールが適用されるCRUDタイプのステートレスアプリケーションについて話していることがわかりました。それらをロードした後。私のアプリケーションでは、ユーザーがViewModelを編集して即座にフィードバックを与えるたびに、チェスのルールを適用する必要があります。

(私が書いたように、ラバーダック効果が発生し、私はおそらくアプリケーション層を常に通過する必要があると思います。もっと経験豊富な人々がどう思うかを知りたいです)

3
Mathieu Pagé

約1年前から、リッチデスクトップアプリケーションにClean Architectureを使用していますが、GUIを多用したイベントベースのアプリケーションに適しています。ジャンプアンドランのような「リアルタイム」ゲームには適していませんが、チェスゲームは問題なく動作します。

あなたの質問を解体する代わりに、私はレイヤーの要約を通り、そして置物を動かすプロセスに従うことで終わります。

エンティティレイヤー

"企業全体のビジネスルール"。あなたの場合、それはゲームのルールをカプセル化することを意味します。実際のビジネスの代わりに古くからあるチェスのゲームをここに置くと、利点が得られます。このレイヤーを作成した後、ここでバグを発見した場合にのみ、変更が必要になります。

ユースケースレイヤー

ユースケースは、アプリケーションのユーザーアクションと考えてください。この層では、これらのユーザーアクション、ユーザーが行う入力、ユーザーが返す出力、およびユーザーが目標を達成するために使用するインターフェイスを定義します。このようなユースケースでは、実際にはそれ自体は何も行いません。何が起こるかを段階的に説明するようなものです。

インターフェイスアダプターレイヤー

「面倒な作業」を行うコードをここに記述します。

フレームワークとドライバー層/詳細層

このレイヤーは、純粋に外部の要素からコード(=内側の3つのレイヤー)へのアダプターです。ほぼ完全にラッパーで構成されています。この部分は、他の3つのレイヤーについて知るために、必要にならないように非常に薄く/単純である必要があります。それはあなたのモデルを知りません、それは文字列、int、イベントなどでのみ機能します。

これの例外は、すべてを接続するセットアップコードである可能性があります。これは、意味的というよりも実際的な理由でこのレイヤーにもあります。

(これを「プレゼンテーションレイヤー」と呼んでいましたが、少し誤解を招くかもしれません。一方で、DB、一部のハードウェアデバイス、インターネットアクセスなども、このレイヤーでラッパーを取得するすべての外部のものであるためです。他方、すべての「ロジックの表示」-モデルをGUIの文字列に変換するような-は前のレイヤーで発生します。)

チェスの駒を動かす

詳細レイヤー

  • GUIで、ユーザーはチェスの駒を別の正方形にドラッグします
  • その出来事を聞いているクラスは、詳細レイヤーのBoardViewです
  • BoardViewは、単純な情報_('A', 1, 'B', 3)_でBoardViewPresenterを呼び出します

インターフェースアダプター層

  • BoardViewPresenterは、エンティティレイヤーから適切なモデルに変換します。
  • A1のChessPieceBoardPosition B3を見つけます。
  • それらをユースケースレイヤーからMoveChessPieceRequestに入れます。
  • それはMoveChessPieceUseCaseに送信します(明らかにユースケースレイヤーからも)。

ユースケースレイヤー

  • MoveChessPieceUseCaseは、エンティティレイヤーのルールに従ってリクエストを検証します。
  • 「対象のマスは自由」「チェスの駒の種類はそのように動く」「解決するチェックはありません」というステップを踏みます。
  • 検証ステップのいずれかが失敗した場合、ユースケースはブール値MoveChessPieceResultをfalseに設定してSucceededを早期に返します。
  • ただし、この例ではリクエストが有効であるため、メモリ内のエンティティが変更され、肯定的な結果が返されます。

インターフェイスアダプターレイヤー

  • BoardViewPresenterMoveChessPieceResultが追加され、肯定的な結果に反応します。
  • ChessPieceViewを取得し、Move('B', 3)に通知します。

詳細レイヤー

  • ChessPieceViewは、画面上の実際の位置を変更します。
  • 「移動」音も再生します
3
R. Schmitz

enter image description here

ViewModelアーキテクチャ および

enter image description hereクリーンアーキテクチャ は同じではありません。

いくつかの点で互換性がありません。不用意に混ぜないでください。

それらを分ける一番のことは cycles です。 ViewModelアーキテクチャは、設計にサイクルを作成するのに適しています。クリーン(またはタマネギ、または16進数)アーキテクチャはそうではありません。 ViewModelはバインダーを使用して、これが引き起こす問題を解決します。 Cleanは、 依存関係の逆転の原則 に従い、外部レイヤーをスワップ可能なプラグインにし、自分でバインドすることを期待しています。

続けますが、これについては話しました before 。ここからは、ViewModelが私たちが無視できる迷ったアイデアであると仮定します。

クリーンアーキテクチャでは、プレゼンテーション層とドメインモデル層がアプリケーション層によって分離されています。これが、WebベースのMVCアプリケーションや、ほとんどの操作がCRUDである「レコードベースの」デスクトップアプリケーションなどのステートレスアプリケーションにとってどのように意味があるかを理解しています。また、私の理解では、プレゼンテーション層はドメインオブジェクトを直接使用するのではなく、アプリケーション層のモデルとの間でマップされる独自のViewModelを持つ必要があります。この仮定は正しいですか?

これらの他の用語の多くは、クリーンアーキテクチャに由来するものでもありません。それらは Onion Architecture からのものです。

enter image description here

ボブおじさんがClean Architectureを明確にその概念と構造の多くをOnion Architectureから持ち上げたので( Hex/Ports and Adapters から同じことをするので)、ここで私はずっと混乱を気にしません。ブログや本にあなたを駆り立てる、さまざまな話題の言葉を使っても、ほとんど同じ考えです。

あなたが言っていたように:

プレゼンテーション層とドメインモデル層は、アプリケーション層によって分離されています。

はい、「ドメイン」とはClean Architectureのエンティティを意味し、「アプリケーション層」とはCleanのアプリケーションビジネスルール(ユースケース)を意味します OSIsアプリケーション層 ではなく

OnionsドメインをCleans EntitiesとUse Caseの両方にマッピングする人がいることに注意してください。それは、分離ロジックがまだ良い考えではないという意味ではありません。ここでは文字通りセマンティクスを議論しています。

だから私はあなたの仮定が正しいと思います。私があなたの意味を正しく解読しているなら。

私が開発する予定のアプリケーションは、ユーザーが一度に1つの動きでチェスのゲームを入力できるようにします。チェスのルールはドメインモデルレイヤーにあるように思えます。

私はそれに同意することができます。

...プレゼンテーション層はどのようにして各ユーザー入力を検証しますか(各ムーブの合法性を検証するため)?毎回アプリケーション層を通過する必要がありますか、それともプレゼンテーション層にドメインオブジェクトを直接操作させて、ユーザー入力に従ってモデルを構築し、保存するときにアプリケーション層に送信する方が理にかなっていますか。データベースに?

多くの場合、検証は1か所で行われるように見えますが、これがうまく機能することはめったにありません。その理由は、あるオブジェクトに有効なものは別のオブジェクトには無効なためです。各オブジェクトは、それ自体の専門家になることを目的としています。アプリケーション全体を考慮しなければならない1つの場所で発生するように強制することもできますが、これを考慮してください。ボードはそれがどれほど大きいかを認識しています。それをチェスに使用していることはわかりません。ボードがチェスが安全を保つと想定する場合、またはボードが大声で「私は8 x 8のボードです。このクレイジーな9,9ムーブをどこに置くかわからない」と言うべきですか。そのようにボードを設計すれば、そのコードを使用してチェッカーや三目並べをプレイしたり、ボードにそれらのゲームについて何も教えることなく行ったりできます。

ボードにボードの問題を検証させ、ゲームにゲームの問題を検証させることをお勧めします。そして、「ドメイン」のこれらの部分の両方を検討します。

これについて説明するリソースをオンラインで見つけようとしましたが、すべての例/コース/チュートリアルで、Webアプリケーションまたは少なくともデータを保存する前にビジネスルールが適用されるCRUDタイプのステートレスアプリケーションについて話していることがわかりました。それらをロードした後。私のアプリケーションでは、ユーザーがViewModelを編集して即座にフィードバックを与えるたびに、チェスのルールを適用する必要があります。

IOが遅い。スピードチェスはそれほど得意ではないかもしれませんが、IOに直接動きを送るという考えはまだ好きではありません。移動は最初にメモリに移動する必要があります。しかし、それらが検証された後にのみ。

ここで理解しておくべきことの1つは、例外を設けて検証を強制する必要がないことです。すべての移動は、状態を変更する試みです。すべての移動が状態の変化をもたらす必要はありません。移動するたびに、ユーザーはフィードバックを受け取る必要があります。検証オブジェクトが何らかの方法でフィードバックを提供できる限り、状態を変更する試みをシャットダウンしても問題ありません。

これで出力ポートが表示されます。 Clean Architectureプラグインの気の利いた点の1つは、ソースコードの変更がコードベースを介して伝播されないようにするすべてが循環的であるにもかかわらず、制御フローをどこにでも送信できることです。

enter image description here

Thatこの小さなトリック のために機能します:

enter image description here

Presenterとユースケース出力ポートの間の開いた矢印は、ある種の多態性を求めています。情報を必要な場所に流すことができ、アーキテクチャが循環しないことを保証できる限り、.

(私が書いたように、ラバーダック効果が発生したので、おそらくアプリケーション層を常に通過する必要があると思います。経験豊富な人々の考えを知りたいです)

確かに、それがバリデーターが住んでいる唯一の場所である限り。それは私がそれらを置く場所です。

Clean ArchitectureとChessについて詳しくお話ししますが、それについてもお話ししました before

実際、私はこれについて話しました たくさん

5
candied_orange

それは素晴らしい質問だと私は考えてきました。私が取っているアプローチは次のとおりです。

  • まず、ドメインオブジェクトをアドレス指定します。チェスの世界では、おそらくBoardPieceオブジェクトのセットがあります。 Pieceオブジェクトには、一般的な部分から継承する具体的なクラス(例:RookQueenPawnなど)があります(たとえば、すべての部分がボードですが、ピースに固有です)。単体テストを作成して、ドメインロジックを検証します。
  • 次に、アプリケーション層を構築します。アプリケーションはボードの状態を操作し、ドメインに移動が正当かどうかを尋ねます。繰り返しになりますが、チェスアプリケーションの周りのロジックを検証するための単体テストを作成します
  • 最後に、アプリレイヤーの上にUIを構築します。 UIは「E5からE7にピースを移動する」だけをアプリに送信する必要があります。その後、アプリは「正常に移動」または「無効に移動」などのメッセージを表示します
2
Bryan

クリーンアーキテクチャは、アプリケーションを構築するための他の多くのアーキテクチャパターンと同様に、どのロジックがどこに行くかを体系化する手段にすぎないことを覚えておいてください。彼ら一人一人が彼らが対処しようとしている特定の目標と課題を持っています。

クリーンアーキテクチャに関する記述では、onlyを自分のすぐ下のレイヤーで操作する必要があります。作業中のレイヤーよりも下位のレイヤーを操作できます。それはどういう意味ですか?

  • UIから直接アプリケーションレイヤーを操作できます(ゴム製のアヒルセッションで推測したように)。
  • 特定のアプリの各レイヤーにすべてのものを必要とするわけではありませんが、必要な場合はどこに配置するかを知っています。

仕立て屋がファッションデザイナーに成長する方法と同様に、これらのパターンを書いたとおりに完全に使用する必要はありません。あなたはあなたがあなたのビジョンのためによりよく働く何かを思いつくためにあなたがあなたがあなたがあなたがあなたがあなたのビジョンのためにより良いものを思いつくために2、3の異なるパターンの間で少しミックスしてマッチすることができるのを見つけるでしょう。これらのパターンは常にインスピレーションを得て、そこから作業の基本的な構造を提供するために存在します。

0
Berin Loritsch