LIFULL Creators Blog

「株式会社LIFULL(ライフル)」の社員によるブログです。

クリーンアーキテクチャの各概念を定食屋で表現する

プロダクトエンジニアリング部のカマトです。

普段はマーケティング・エンジニアとして、LIFULL HOME'SでLINEやメールを活用したサービスの開発に従事しています。
今回は業務でシステムの刷新を行う中で、アーキテクトにクリーンアーキテクチャを採用し初めて経験しましたのでこちらについてお話しをさせていただきます。

新しいアーキテクトに触れるときは、このレイヤーは何を担当しどのような概念でどのような機能を持たせればいいのか?と理解するをするまでいつも苦戦するのですが、クリーンアーキテクチャは特に登場人物が多く今まで以上に大変でした。
このクリーンアーキテクチャの処理の流れを日常のものに置き換えれば、別な視点で理解が深まるのではと考え、各レイヤーの概念を定食屋のフローに落とし込んで表現をし振り返りをしてみようと思います。

参考にしたイメージ図に沿ってのレイヤーと概念ですので、これにそってなければクリーンアーキテクチャではないということはないです。
クリーンアーキテクチャはこうすればいい!や、このような思想でやってください!というものではないので暖かい目で見ていただけれたら嬉しいです。


さてクリーンアーキテクチャというと、この図がよく出てくると思います。

f:id:LIFULL-kamatoa:20200930173126j:plain
出典:The Clean Code Blog https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html


これともう一つ。

f:id:LIFULL-kamatoa:20200930173617p:plain
出典:図解クリーンアーキテクチャ https://qiita.com/kz_12/items/bc79102247b86626fc72


こちらもよく見ますね。
この図の構成を定食屋さんのフローに置き換えて表現したものがこちらになります。

f:id:LIFULL-kamatoa:20200930182914p:plain

かなり強引なものですが各概念をレイヤー毎に説明をさせていただきます。

Enterprise Business Rules

Entities

f:id:LIFULL-kamatoa:20200930183749p:plain

まず、どの定食屋さんでもお客さんに提供するために必要なものは料理のメニューですね。
唐揚げ定食であれば

  • 唐揚げが5個
  • サラダ
  • ご飯
  • 味噌汁

といった内容です。

Application Business Rules

調理開始 Use Case Interactor 

f:id:LIFULL-kamatoa:20200930183725p:plain

コックさんが厨房に立ちフロアスタッフが伝票置き場(Input Boundary)へ置いてくれた伝票に書かれた注文情報を見て、メニュー内容(Entities)を思い出し料理をします。
料理に必要な食材の指示を出し(Data Access Interface)、材料が集まり料理(Output Data)が完成したら受け取り口に料理を並べ、横に伝票(Output Boundary)を置いておきます。

注文情報 Input Data

f:id:LIFULL-kamatoa:20200930183738p:plain

お客さんの注文仕方は様々です。
厨房のコックさんが作業しやすいように注文内容を整理した言葉に変換してます。

からてい 一つ

唐揚げ定食 1人前

伝票置き場 Input Boundary

フロアスタッフの人は厨房に入りませんので、整理した言葉(Input Data)で作った伝票をコックさんがメニューを出してくれるところに置いておきます。

必要材料の指示 Data Access Interface

f:id:LIFULL-kamatoa:20200930183727p:plain

コックさんが倉庫・冷蔵庫(Data Access)から用意して欲しい食材を指示します。

受け取り口 Output Data

f:id:LIFULL-kamatoa:20200930183905p:plain

コックさんの元に材料を届けると材料が揃ったので料理を開始します。
ここで完成した料理を受け取り口に料理を並べます。

伝票置き場 Output Boundary

ここでフロアスタッフがどの注文に対しての料理なのかをわかるように、料理の横に伝票を置いておきます。

Interface Adapters

テーブル(注文をうける) Controller

f:id:LIFULL-kamatoa:20200930183738p:plain

次にどこのお店でもお客さんがする行動である注文です。
フロアスタッフがお客さんから注文を受け取ります。
ここでうけた注文は伝票を使い(Input Data)、作ってもらいたいメニューを調理場へ伝えます。(Input Boundary)

提供準備 Presenter

f:id:LIFULL-kamatoa:20200930183935p:plain

厨房から出された料理を受け取り口で受け取り(Output Data)、提供するテーブルを伝票で確認したら(Output Boundary)お客さんが気持ちよく食べられるよう、お盆に食器、箸やスプーン、フォーク味噌汁なども揃えてテーブルへ運びます。

テーブルViewModel

f:id:LIFULL-kamatoa:20200930183724p:plain

お客さん(View)がいるテーブルへ料理を提供します。

倉庫係 Data Access

f:id:LIFULL-kamatoa:20200930183958p:plain

コックさんからの依頼通り(Data Access Interface)に、様々な業者に発注していた食材がある(倉庫・冷蔵庫)から調理に必要な食材を取り出して送ります。

倉庫・冷蔵庫 Data Base

倉庫や冷蔵庫には様々な業者に発注した食材や調味料が並んでいます。
倉庫係さん(Data Access)が必要なものを発注をしたり、取り出したりします。

お客さん View

注文された料理が来たらお客さんは食事を開始します。

依存関係について

クリーンアーキテクチャで重要になると思われる依存関係(上位のモジュールは下位のモジュールに依存してはならない。)ですが、以下のように表現しています。
メニュー内容(Entities)が唐揚げ5個から3個になったらコックさんの振る舞いも変わり、倉庫係の方が倉庫や冷蔵庫から用意する材料も変わります。
コックさんが別な人に変わったら、レシピも変わるので、倉庫や冷蔵庫から出す材料は変わるかもしれません。ですが毎日出しているメニュー内容に変わりはありません。
そして倉庫や冷蔵庫が変わったとしても必要になる材料は変わらないので、コックさんの指示に影響は出ないはずです。

依存関係逆転の原則

もう一つクリーンアーキテクチャで大事な依存関係逆転の原則ですが、こちらは振る舞いを下位モジュールへの作業の依頼(伝票や用意してもらう食材の指示)という形で表現してみました。
これによりフロアスタッフの方や、倉庫係の人に依存せずコックさんは作業を続ける事ができます。

f:id:LIFULL-kamatoa:20200930192335p:plain

f:id:LIFULL-kamatoa:20200930192318p:plain

f:id:LIFULL-kamatoa:20200930183727p:plain

(一応ここでの表現の中での話ですが、上位モジュールが立場が上というわけではありません。)

まとめ

どうでしょうか?かなり強引でしたので、間違っている表現もあると思いますが、思ったよりいい感じなのではと・・・。
ちなみに自分は学生の頃にファミレスでアルバイトをした経験があるくらいしか料理の経験はありません。
難しい言葉で半分くらい理解して進めるといざという時にどうだったかな?と手が止まってしまいますが、こういった自分が普段使っている言葉に変えて整理してみるとすんなり入ってきませんか?
クリーンアーキテクチャに限らず普段の業務などで、ここはこういう表現の方がいい、こうした方がわかりやすいというものを考える機会にしていただけたら嬉しいです。