Help us understand the problem. What is going on with this article?

【改訂版】クライアント、サーバー それぞれから視点で見た Clean Architecture

TL; DR

以前、同じ様な題材の記事 を書いたのですが、 The Clean Architecture翻訳(いわゆるボブおじさん) を改めて読み直したり、アプリを何個か実装していく上で認識を改めましたので、改訂版として現在の考え方をまとめました。

今回、サーバーサイドの方がシンプルだったので、そちらを中心に説明していき、クライアントサイドは差分を中心に説明していきます。

サーバーサイドから見た Clean Architecture

大まかな流れとして、以下のようなAPIが実施されたとします。

  1. ユーザーからリクエストを受信
  2. DBからデータを取得し、それを利用して外部サービスからデータを取得
  3. 外部サービスから取得したデータをJSONにして返す

これを ボブおじさんの同心円 で出てくる登場人物にあわせた図にすると以下のようになります。(F/W & Drivers に登場しているのは Go のライブラリとしています)
尚、 EntityUse CaseBusiness Rules として纏めています。

アーキテクチャ構成図.png

ボブおじさんとの違い

ボブおじさんでは、依存関係は必ず円の内側を向くとなっています。しかし、次の理由により、 Interface Adapter を中心に内と外の両方に依存方向を向くように考えました。

  • F/W & Drivers はライブラリ依存のコードが基本となるため変更が効かない
  • GIN や SpringWeb などの一般的な Web F/W を見ても、リクエストに対してのハンドラーを紐付けることで、そこにコールバックを返す形になる
    • この事から I/F を定義しているのは F/W & Drivers であり、 Interface Adapter がその実装を満たす形になっている
  • DBHTTPクライアント からデータを取得する場合も、 Interface AdapterF/W & Drivers を利用する形となっている
  • Business RulesF/W & Drivers は、相互にお互いを知らないという関係は保たれているので、 関心の分離 は出来ていると捉える
    • Business Rules はフレームワークやデバイス、プラットフォームに依存しないので、(開発言語がマルチプラットフォーム対応可能ならば)複数プラットフォームに流用ができる
  • F/W & Drivers が、 Interface AdapterBusiness Rules どちらにも依存しないので、モジュールとしての独立性が高く、単体で細かいテストが可能

Interface Adapter の役割

上の図の F/W & DriversBusiness Rules を並べてみました。

説明用1.png

この図の凹凸(凸しかないですが)を各層への I/F(言語的な Interface ではなく、ただの出入口として読んでください) とした際に、凹凸の位置や大きさが異なることからこのままではF/W & DriversBusiness Rules は連携できないことがわかります。
これ自体は 関心の分離 を行っているのであれば当然のように起こり得ることです。
そこで登場するのが Interface Adapter となります。

上記の通り、 Interface AdapterF/W & DriversBusiness Rules 両方に依存しているので、両者の I/F を知っている形になります。
そこで、 Interface Adapter は両者の I/F の満たすような実装をしつつ、お互いをバイパスしてあげるようにします。
まさに名前の通り F/W & DriversBusiness RulesI/F に対する Adapter となります。

Wiki より抜粋

Adapter パターンを用いると、既存のクラスに対して修正を加えることなく、インタフェースを変更することができる。Adapter パターンを実現するための手法として継承を利用した手法と委譲を利用した手法が存在する。

クライアントサイドから見た Clean Architecture

続いてクライアントサイドの図です。
サーバーサイドの図と違っている点としては下記の事柄くらいで、 Interface Adapter を中心に F/W & DriversBusiness Rules関心の分離 を行っている点は一緒です。
良く View のテストを書くのが大変という話が出ますが、 View の I/F を満たした Stub を作ることで Business Rules と切り離した表示のみを確認するためのテストが書きやすくなっています。

UIアプリアーキテクチャ構成図理想(iOS).png

サーバーサイドとの図の違い

  • UIスレッドバッググラウンドスレッド が出てくるので、 オブザーバーパターン(Rx的に書いてます)で状態の変化を監視する形を取っておりその辺を赤線で表現しています
  • View 契機の処理以外にも、スケジューラーなどによって View を介さない場合も書いてます

実際の所

今回はあくまで理想的な形を説明していますが、どういう単位で実装して、どこをテストするのかなど、現場のコンセンサスに応じて依存性を反転させて I/F を書かく手間を省いたりしています。
理想を追いすぎても費用対効果が悪かったり現場が疲弊するだけだったりするので、あえて理想から崩す勇気も必要だと考えます。

まとめ

以前の記事から2、3ヶ月しか経ってないのに、ほぼ考えをガラ変させてしまいました。
また、よく見られる Clean Architecture を取り上げた記事とも考え方が異なると思っています。

何が言いたいかというと、 常により良い形を求めて進化しよう って事で、
ここに書いてあることがゴールだとは思っていないのでまた考えを改めるかもしれないですが、生暖かく見ていただければと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away