24
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CleanArchitectureでひとつ 『上』 のコードを目指す:概念編

Last updated at Posted at 2019-09-06

設計

コーディングを行うとき、事前に設計フェーズに時間を割いていますか?
プログラムをしている人でも

  • 作るものがぼんやりしてるから設計できない
  • 早く動くのもを見たい(見せないといけない)ので、コーディングから着手する
  • 先のことを考えるのが苦手だからコーディングしながらその都度考えよう

のような考えから、設計とかは深く考えずにコーディングから始めてしまう人が意外と多いのではないでしょうか?

しかし、実現したいことを最短でコーディングしてしまうと、往々にして後からの変更に弱い成果物になってしまいがちです。

歪な建築

どう作るか (how) のみを念頭にコーディングしてしまうと、設計の余地なくただ動くように作ってしまうのでお勧めしません。 何を作るか (what) を考えて設計フェーズで事前に方向性を決めておくことで、柔軟性と可読性を備えたコーディングを行うことが出来る、というのが私の考えです。

本記事では設計の指針として CleanArchitecture 1を取り入れてこの指針の下、具体的なアプリケーションのコーディングについて解説します。

設計が大事とは言われるが捉え切れてないない人、設計に対する他人の考え方を知りたい人、CleanArchitectureの具体的実装に悩んでいる人は是非参考にしてください。

Clean Architecture

CleanArchitectureの思想は以下の図に現れていると言われます。2

CleanArchitecture

この図で抑えるべきことは同心円状に層(レイヤ)をなしていることです。
似た(元になった?)考え方にヘキサゴナルアーキテクチャオニオンアーキテクチャがあったりします。3

この図で重要なことは以下の4点でしょうか。

  • 黄色など内側に入るほど、後で変更されない固定されたロジックである
  • 逆に青色など外側に出るほど、後から変更されやすい部分である
  • 依存の方向は 外側から内側 である
  • 赤色のアプリケーションのロジックと青色の具体的な実装(View/Web/DB/Devices)の中間に緑の層があること

各層について説明していきます。唐突ですが具体的なイメージのために身長と体重から BMI を求めるアプリ開発を想定します。4

Enterprise Business Rules

アプリの根幹となる(利用者に価値を提供する)部分です。業務ロジックとも呼ばれます。上図では Entities という名前がついていますが、これが混乱の元になることがあるようです。5

BMI計算アプリにおいては以下の計算式が該当します。この定義はよほどのことが無いと変わらないでしょう。

BMI = \frac{体重}{身長^2}

Application Business Rules

アプリを動かすためのロジックです。上図では Use Cases と言われています。
BMIのアプリでは身長と体重の入力をUIから受け取り、BMI計算式に当てはめて結果を表示。あるいは保存する処理になります。

UseCaseはアプリの実際の機能を指すと言えるでしょう。仮にログイン機能が必要なら新たにログインのUseCaseも追加する必要があります。

Interface Adapters

Use Caseがアプリの機能を実現するためには、そのための専用の部品が必要です。しかしUse Caseがそれらの部品を直接持つのでなく、この中間層を介して参照します。
一見無駄に思えるでしょうが、この中間層のお陰でUse Caseの実装を変更することなく、部品だけを取り換えてアプリの修正を行うことが可能になり、改修の際の影響範囲を絞ることが出来ます。

Frameworks & Drivers

アプリの各部品の具体的な実装を持つ層です。どんなUIにするか、データをファイルに保存するかクラウドに投げるか(さらにそのクラウドはAWSかGCPか)、などが挙げられます。開発エンジンやミドルウェアの選択肢もここに含まれる場合もありそうです。

CleanArchitectureを取り上げた本6では 詳細 という言葉がよく出てきますが、正にこの層に該当します。この層の決定(実装)を先延ばしにできるのがCleanArchitectureの利点でもあります。
また、原著では details という単語が使われているようですが、日本語訳には詳細に加えて 些細なこと というニュアンスもあるようです。

では概念を一通り説明したところで、もう少し実装へと掘り下げて解説します。

各層の捉え方

BMI計算アプリの実装を行う上で各層の捉え方について私の考えを述べます。

本アプリの典型的シーケンスは、
 1. UIから身長と体重の入力をうけつける
 2. 身長と体重からBMIを計算する
 3. 結果のBMIの値をUIに表示する
となります。

UseCase

アプリ実装の中心となるのはUseCaseです。
図の中心はEntitiesになっていますが、アプリの実装の中心はApplication Business Rulesという名前の通り、UseCaseだと捉えることにします。

数字の入力をPresenter経由で受け、BMI計算を呼び出し、結果をPresenterに返す実装をUseCaseで行います。
しかし、UseCaseにアプリのすべてを実装してはいけません。例えば、

  • float height = float(textInput.text) のようにUIの情報を直接参照してはいけません
  • float bmi = weight / (height*height) のように計算ロジックを書いてはいけません
やっちゃいがちな実装
float height = 0.0F;
float weight = 0.0F;

void Start() {
  // Viewのイベントを受信
  HeightInputView.OnValueChanged += x => { UpdateBMI(x, weight); };
  WeightInputView.OnValueChanged += x => { UpdateBMI(height, x); };
}

void UpdateBMI(float h, float w) {
  // cm を m に変換
  var hm = h / 100.0F;
  // BMI計算結果をViewに反映
  BMITextView.text = w / (hm * hm);
  // フィールドに保持
  height = h;
  weight = w;
}

UseCaseはアプリの振る舞いを記述するだけです。UseCaseにViewがどうとか、計算ロジックがどうとか難しいことをさせてはいけません。UseCaseは低学年くらいの小学生だと思ってください。

小学生

小学生に「数値は 画面のどこから 取得されるの?」とか聞いても

「わかんない」

と返答されます。(それでいいのです)
難しいことは大人達に任せます。

Presenter

大人その1です。Interface Adaptersに当たります。View(大人その2)から受け取った情報をUseCase(小学生)に渡します。そしてUseCase(小学生)から情報をもらった情報をView(大人その2)に返します。しかし、こいつにも難しいことはさせていけません。Presenterは言われたことだけを行うやる気のないダメ会社員だと思ってください。

だめ会社員

UseCase(小学生)に渡す情報が何に使われているのかも、View(大人その2)に渡した情報がどこに行きつくのかもこいつは関与しません。右から左、左から右に渡すだけの楽な仕事です。
こいつに質問してもほとんどの場合、

「いや、ちょっとわかんないすね。自分、これをUseCase(小学生)に渡せばいいって言われてるだけなんで...」

と返答されるでしょう。(それでいいのです)
難しいことは専門家達に任せます。

View

大人その2です。UIの詳細を担う専門家です。

専門家

Frameworks & Driversの層では特定のframeworkなどの処理をふんだんに使って目的の機能を実現してください。逆に言えば特定のframeworkに依存する処理は可能な限りこいつに閉じ込めてください。

こいつは専門家なので色々質問しても回答してくれます。
問:「文字入力は何のコンポーネントでうけとりますか?」
答:「はい。それは画面上のここのInputFieldからです。そして結果のBMIはこっちのTextに反映されます。」

といった具合です。

有能ですが、悲しいかなCleanArchitectureではこいつを交換可能な部品として扱います。アプリ全体の方針転換によっては別の専門家を雇って配置換えが行われます。新たな専門家も前からいるダメ会社員とコミュニケーションさえできればOKというわけです。(別のViewを実装することになっても既存のPresenterに接続できるように作ればUseCaseには影響しないということです)

Domain

業務ロジックのEnterprise Business Rulesです。
小学生でも使える道具のように簡単に実行できるメソッドを持ち、抽象化されているとなお良いでしょう。

道具

CleanArchitectureの説明で使った図にはDomainという言葉は出てきません。図に準拠するならEntitiesですが、単語の意味の通りやすさを考えてDomainとしてます。

実装

長くなりそうなので具体的な実装の説明は実装編として別記事に分けました。
小学生、ダメ会社員、専門家、道具をどう組み合わせて(抽象化して)アプリケーションを動かすのかという話はそちらで行います。

  1. クリーンアーキテクチャ(The Clean Architecture翻訳)

  2. The Clean Code Blog The Clean Architecture

  3. [DDD]ドメイン駆動設計で実装を始めるのに一番とっつきやすいアーキテクチャは何か

  4. BMIと肥満度を計算してみよう

  5. お前らがModelと呼ぶアレをなんと呼ぶべきか。近辺の用語(EntityとかVOとかDTOとか)について整理しつつ考える

  6. Clean Architecture 達人に学ぶソフトウェアの構造と設計

24
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?