🍔

ワタシ マク○ナル○ チョットデキル

2021/06/20に公開

つまりハンバーガーはclean architectureだったんだよ!

ΩΩΩ < ナ、ナンダッテー

この記事で説明したいこと

clean architectureを(実際の実装を含めて)マク○ナル○に例えて説明したいと思います!

なんでマク○ナル○?

早い・安い・美味い、エンジニアの気絶のお供と言えばマク○ナル○だからです!(関係ない)
キャッチーなタイトルだと書くモチベがあがりますよね!

ファーストフードでは誰がオーダーを受けようが誰が料理しようが基本的に同じ味で提供されますね。
例えばキッチンのスタッフが入れ替わっても、レジの人は気にせずキッチンへのオーダーを通す事ができますが、これはclean architectureの疎結合に似ています。
またclean architecture(に限らない話ですが)はdbの依存関係を極力少なくしているのでdbの移行などでも最小限の工数で済む。というメリットがあります。
今回inputのインターフェースを4つ。outputのインターフェースを計5つ盛りだくさんで実装しています。

この記事のターゲット

clean architectureについて解説してる有用な記事はたくさんありますが、clean architecture自体が難しい概念なので中々理解できない方が対象です。
かくゆう私も わからなくなることがたまによくあります!てへぺろ

ソースコードはこちら

https://github.com/yabeyuji/macOnalO-chot-dekiru

動作サンプル

demo

左側:スタッフが確認できるモニター
項目 概要 説明
reserve オーダー受付 オーダーリクエストを受け付けて予約番号が発行されるとこちらに表示
assemble 調理中 調理可能な数(サンプルは3)に空きがあればreserveのオーダーがこちらに移動
complete オーダー完成 調理が完成したオーダーはyummyフォルダにjsonファイルとしておかれこちらに移動
pass 引き渡し済み yummyフォルダにあるjsonファイルを削除するとこちらに移動
右側:オーダーを注文するAPIなど
種類 リクエスト方法 リクエスト受付 補足
mobile 1234port http:post:json echo
PC 2345port http:post:json gin
delivery 3456port grpc grpc ウー○ー的な提携業者を想定
register jsonファイル指定場所に配置 ファイル監視

ディレクトリ設計

全体の設計を Standard Go Project Layout

internal内のディレクトリ設計をclean Architecture

ディレクトリ設計詳細

全体

ディレクトリ 説明
build Dockerfile
cmd main.go
config .bashrc
internal 別テーブル参照
pkg 共通ライブラリ
script entrypoint.shとオーダー用スクリプト
storage ログ・エラーログ
web index.htmlとvueファイルなど
yummy オーダー完成場所(jsonファイル)

internal

ディレクトリ 説明
1_framework_driver Frameworks & Drivers レイヤー
1_framework_driver/db 食材の保管
1_framework_driver/db/freezer MySQL:冷凍庫 パティを保存
1_framework_driver/db/refrigerator PostgreSQL:冷蔵庫 野菜、チーズなどの保存
1_framework_driver/db/shelf MongoDB:棚 バンズを保存
1_framework_driver/external_interface オーダーモニター、商品の引き渡し
1_framework_driver/external_interface/monitor websocket&vue:オーダーモニター
1_framework_driver/external_interface/shipment jsonファイルを商品の引き渡しとする
1_framework_driver/web_ui オーダー受け付け
1_framework_driver/web_ui/mobile echo:モバイル注文
1_framework_driver/web_ui/pc gin:pc注文
1_framework_driver/web_ui/delivery grpc:ウー○ー的な提携業者からの注文
1_framework_driver/web_ui/register ファイル監視:レジ注文
2_interface_adapter Interface Adapters レイヤー
2_interface_adapter/controller web_uiからのオーダーをusecaseに渡す
2_interface_adapter/gateway usecaseからDBへのリクエストを渡す
2_interface_adapter/presenter usecaseからexternal_interfaceへリクエストを渡す
3_application_business_rule Application Business Rules レイヤー
3_application_business_rule/usecase ユースケース
4_enterprise_business_rule Enterprise Business Rules レイヤー
4_enterprise_business_rule/entity ビジネスロジック 調理(野菜を切る、パティを焼くなど)

オーダーフロー

orderflow

framework_driver/web_ui

オーダーを受けつけるパート

  • web_uiのデータ型をControllerに持ち込まないようにentityのデータ型に変換
  • オーダー番号発行
  • オーダー ※オーダー番号を即時返却する必要があるため、Controllerにてチャネルを使用
  • オーダー番号を返却

framework_driver/db

dbと接続するパート

  • dbの違いはこのパートで解消
  • 必要な食材を取得(デクリメント更新)

framework_driver/external_interface

db以外の外部と接続するパート

  • オーダー情報を随時更新するモニター(http://localhost:4567/)
  • 商品の出荷(backend/yummyディレクトリ)
  • 商品の出荷履歴(backend/storage/logディレクトリ)

interface_adapter/controller

web_uiからのオーダーを処理するパート

  • オーダー番号発行
  • オーダー処理

interface_adapter/presenter

usecaseからexternal_interfaceへ商品またはオーダー更新情報などを渡すパート

interface_adapter/gateway

usecaseからdbへ必要な食材の情報を渡すパート

application_business_rule/usecase

controllerからのオーダーを受け取り、目的に応じて以下に処理を渡すパート

  • オーダー内容の解析・調理(データの解析・変更)は enterprise_business_rule/entity
  • 食材の取り出し(DB更新)は interface_adapter/gateway
  • オーダー情報のモニタ表示・商品の出荷は interface_adapter/presenter

enterprise_business_rule/entity

ドメインロジックを扱うパート

  • 調理に必要な食材数をカウントする
  • 食材を調理する

動作確認

git clone git@github.com:yabeyuji/macOnalO-chot-dekiru.git

cd macOnalO-chot-dekiru
make build
make up

# オーダーは backend/script/order ディレクトリ内を参照

最後に

うーん。よく見るとハンバーガーのバンズ/レタス/パティ/トマト/バンズ もclean architectureが見えてきますね(タイトル回収)
疲れてるとclean architectureがゲシュタルト崩壊します。(初心者にありがち)

こんなときはハンバーガーを食べて寝るに限りますね。

ちなみに私はサブウェイ派なのでBLTを食べます!

メキシカンミートタコスおいしそう

参考URL

https://qiita.com/t2-kob/items/02a76572693130c9a66e
https://qiita.com/nrslib/items/a5f902c4defc83bd46b8
https://qiita.com/koutalou/items/07a4f9cf51a2d13e4cdc
https://www.m3tech.blog/entry/2020/02/07/110000
https://www.lifull.blog/entry/2020/10/13/110000

Discussion