Slide 1

Slide 1 text

৽ଔ -BSBWFMॳ৺ऀ͕੒௕͍ͯ͘͠தͰ ײͨ͡ίϨδϟφΠײ @fuwasegu

Slide 2

Slide 2 text

自己紹介 $aboutMe = [ ‘📛’ => ‘竹下 拓秀(ふわせぐ)’, ‘🎂’ => CarbonImmutable::parse(‘1998-08-04 03:46:00’), ‘🏠’ => ‘長崎県出身・愛知県在住’, ‘🏢’ => ‘株式会社ゆめみ コーポレートエンジニア(フルサイクル)’, ‘👶’ => ‘2歳(男の子)’, ‘ ’ => ‘@fuwasegu’, ‘ ’ => ‘@lunain84’, ]; PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 2

Slide 3

Slide 3 text

3 PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション -BSBWFM ࢖͍౗ͯ͠·͔͢ʁ

Slide 4

Slide 4 text

正に職人用フレームワーク Laravel の代表的な機能の例 • サービスコンテナ • Eloquent ORM • Event / Job • Facade • MVC アーキテクチャのボイラープレート PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 4

Slide 5

Slide 5 text

5 丁寧なマニュアル PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 6

Slide 6 text

6 PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション Laravel に従いマニュアルに沿って開発すれば, なんとなく Web アプリが開発できる! \初心者にやさしい!/

Slide 7

Slide 7 text

7 PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション そう思っていた時期が僕にもありました

Slide 8

Slide 8 text

• 依存関係の混沌化 • 責務の肥大化 – 分割しようとしても責務が迷子に • 重くなるテスト 8 開発規模に比例して膨らむツラミ PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 9

Slide 9 text

9 Laravel 先生の言う通りにしたのに・・・ なんで? PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 10

Slide 10 text

犯人は Laravel 先生!? PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 10 • 依存関係の混沌化 → Facade のせいで何が何に依存しているか分かりにくくなる • 責務の肥大化 → Controller に処理を詰め込むと当然肥大化.安易に Model に処理を移そうとしても責務不明瞭で失敗しやすい • 重くなるテスト → Laravel の立ち上げ + DB 利用で実行に時間がかかる

Slide 11

Slide 11 text

11 Laravel 先生も万能じゃない・・・ PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 12

Slide 12 text

12 どうすればいいの? PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション • 依存関係の混沌化 → Facade の使用を極力控え,Constructor で依存注入する • 責務の肥大化 → レイヤー毎に求められる責務を意識してクラスを分割する • 重くなるテスト →ビジネスロジックを Laravel から切り離し UnitTest する

Slide 13

Slide 13 text

13 今日話すこと PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 'BDBEF ཭ΕΛ͠Α͏ .7$ ʹશͯΛ٧ΊΔͷ͸΍Ίʹ͠Α͏ 6OJU ςετΛॻ͜͏

Slide 14

Slide 14 text

👋Facade 離れをしよう PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 14

Slide 15

Slide 15 text

• こんなやつ – Auth,Cache,DB,Http,Log,Session,Validator etc … 15 Facade って PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 16

Slide 16 text

Facade に出会った僕 • Facade って便利だと思ってた – どこからでも簡単に呼べるじゃん! – どんどん使っていく べきでは? • Facade は static メソッドの集まりだと思ってた – Laravel は static メソッドを作るのが主流? PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 16

Slide 17

Slide 17 text

17 政治問題 PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 18

Slide 18 text

思想がインスコされた僕 • Facade はできるだけ使わない方がいい – 乱用すると秩序が乱れる – どこからでも呼べるのがむしろダメ – 部分的に使う分にはOK • Route,DB::transaction() とか • 全然 static メソッドじゃなかった PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 18

Slide 19

Slide 19 text

19 Facade の仕組み PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション • ただの Static メソッドに見えるけど実は全然違う – Static メソッドとしては存在していない Sample::method() Facade.php __callStatic() Facade.php getFacadeRoot() Facade.php resolveFacadeInstance() $instance = app()-> make(Sample::class) $instance->method() ※ 若干簡略化しています サービスコンテナの機能 = Laravel の立ち上げが必要 実体は static じゃなかった!

Slide 20

Slide 20 text

20 Facade を使ったとき PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション コンテナ OK! OK! また? まとめて言えよ FacadeA FacadeB __construct() methodA() methodB() FacadeC FacadeD Aを用意して! Bを用意して! Cを用意して! Dを用意して! FacadeA FacadeB Aを用意して! Bを用意して!

Slide 21

Slide 21 text

• サービスコンテナを介しているので無駄 に処理が複雑になる • コードを追わないと依存してるものが分 かりづらい 21 PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション Facade を使ったとき

Slide 22

Slide 22 text

依存関係を確認したくても PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 22 • 呼び出し側から実装にジャ ンプできない • Laravel 標準 Facade は @see アノテーションがあるのでまだ マシ • 自作 Facade は明示的に @see を書く or サービスプロ バイダを見に行く必要がある • Facadeの実体 から 別の Facade を呼んだりするといよ いよ依存関係の確認が大変

Slide 23

Slide 23 text

じゃぁどうする? PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 23 Constructor DI をしよう!

Slide 24

Slide 24 text

24 コンストラクタDIを使ったとき PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション __construct(A,B,C,D) methodA() methodB() ご注文の A・B・C・D です 準備完了! ClassD 準備完了! ClassC 準備完了! ClassB 準備完了! ClassA 準備完了! ClassB 準備完了! ClassA

Slide 25

Slide 25 text

• サービスコンテナを使わないので,依存 注入の処理がシンプルになった • コンストラクタを見ただけで依存関係が 分かるようになった 25 PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション コンストラクタDIを使ったとき

Slide 26

Slide 26 text

26 既存 Facade どうするの? PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 実体をそのまま DI をしよう!

Slide 27

Slide 27 text

27 Facade の基底クラス一覧 PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 28

Slide 28 text

28 PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション Facade は 「使用上の注意」をよく読み, 用法用量を守って正しくお使いください. 体に異常がみられた方はすぐにご使用を中断し, 医師にご相談ください.

Slide 29

Slide 29 text

🎓.7$ ʹશͯΛ٧ΊΔͷ͸ ΍Ίʹ͠Α͏ PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 29

Slide 30

Slide 30 text

はじまりの街 PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 30 app Models Console Http Controllers • Laravel プロジェクトを新 規作成すると現れるボイ ラープレート • すでになんか出来上がっ てる?

Slide 31

Slide 31 text

Laravel のボイラープレート • MVC2 アーキテクチャで出来てる – Controller: HTTP リクエストの受け取り – (Eloquent)Model: DB アクセス PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 31 Web Browser Controller (Eloquent)Model View HTTP リクエスト DB 操作の依頼 Database DB 操作 結果の返却 表示に必要なデータの 受け渡し 親の顔より見たアーキテクチャ図 ビジネスロジックをどこに置く? • Controller • Model レンダリング結果 レスポンス (HTML・JSON)

Slide 32

Slide 32 text

Controller に置くつらみ • HTTP を扱う場所と,DB を扱う場所が同じところにな り,責務が不明瞭になる • HTTPリクエスト起点の大きな機能テストしか書けない – 一つのテストで考えることが多すぎる • リクエストバリデーション • ドメインバリデーション • ビジネスロジック • レスポンスの整形 PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 32

Slide 33

Slide 33 text

Model に置くつらみ • すべてのビジネスロジックが Model と1対1で対応す るとは限らない • Model から 外部 API を叩く違和感 • ビジネスロジックに関する例外を置く場所に困る – app/Models/Exceptions は違う – app/Exceptions はなんか遠い... • Eloquent Model が多くのメソッドを持つので,たまにメ ソッド名が衝突して命名に悩む – delete, update など PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 33

Slide 34

Slide 34 text

• Model にも Controller にも似たようなロジック が現れたり • Utility 系クラスとして切り出された謎のロジッ クが別のところに現れたり 34 ルールを定めないと... PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 35

Slide 35 text

責務分散を助ける Laravel の機能 • Policy – 認可処理の切り出し • FormRequest – フォームバリデーションの切り出し • Resource – レスポンス整形処理の切り出し PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 35

Slide 36

Slide 36 text

• 検索条件が細かいとき – if ($request->has(‘email’)) みたいなのが沢山ある • 外部 API が絡むとき – メッセージを生成して Slack へ通知を送る – 弊チームは Slack アプリ開発が多く,このツラミをよく感じ ています 36 それでも太るもんは太る PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 37

Slide 37 text

PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 37 最高のアーキテクチャに出会った

Slide 38

Slide 38 text

どんなアーキテクチャ? • ビジネスロジックの置き場として UseCase を導 入 👍 • UseCase が Eloquent Model や Eloquent Builder に 依存することを認めて使いやすく 👍 PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 38

Slide 39

Slide 39 text

• HTTP の知識を剥がした純粋なビジネスロジックを置 く場所が(Models/ 以外で)でき,明確な責務の分割 ができた • Eloquent Model への依存は妥協することで厳格な クリーンアーキテクチャより導入コストが低い 39 ”なんちゃって” のここが良い! PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 40

Slide 40 text

40 設計に悩んだらとりあえず “なんちゃって”を使ってみよう! PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 41

Slide 41 text

💯Unit テストを書こう PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 41

Slide 42

Slide 42 text

テスト書いてますか? • バグを発見できる • 実装のリファクタリングが安全にできる ようになる • テストを意識した実装をするようになり ,自然とコードが綺麗になる • 仕様把握にも使える PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 42

Slide 43

Slide 43 text

Laravel におけるテストの種類 • Feature テスト – Httpリクエスト単位のテスト – リクエストを受けててレスポンスを返すまでの一連の流れ を検証する – 大きな単位のテストなので,時間がかかる • Unit テスト – メソッド単位のテスト – 各々のロジックが正しく動作するかを検証する – 小さな単位のテストなので,あまり時間がかからない PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 43

Slide 44

Slide 44 text

テストに必要な環境 • Feature テスト – bootstrap() を使って Laravel アプリケーションの立ち 上げが必要 – DB アクセスを伴うこともある – Illuminate¥Foundation¥Testing¥TestCase を継承する • Unit テスト – PHP が動けば良い – PHPUnit¥Framework¥TestCase を継承で済む PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 44

Slide 45

Slide 45 text

つまり PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 45 Feature テストは Laravel に依存するテスト Unit テストは Laravel に依存しないテスト

Slide 46

Slide 46 text

• ライブラリに切り出しにくい – PHP ライブラリとして切り出すなら大幅なリファクタリングが必要 • 別のフレームワークで使い回せない – フレームワーク固有の機能を使ったコードはコピペでは動 かない – この先ずっとそのフレームワークを使いづつける? – もし同じ言語でリプレースするなら,サービスのコアな部分(ビ ジネスロジック)はできるだけそのまま使いまわしたい 46 PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション (おまけ)「FW に依存する」ということ

Slide 47

Slide 47 text

Laravel は基本 Feature テスト • Facade を使用している – サービスコンテナを使うためアプリケーション の起動が必須 • Eloquent Model / Builder を使用している – DB アクセスを伴うためアプリケーションの起動が 必須 PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 47

Slide 48

Slide 48 text

”なんちゃって” も Feature テスト PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 48 mpyw. “5年間 Laravel を使って辿り着いた,全然頑張らない「なんちゃってクリーンアーキテクチャ」という落としどころ”. Zenn, https://zenn.dev/mpyw/articles/ce7d09eb6d8117#テストどうするの? より抜粋

Slide 49

Slide 49 text

UseCase は Unit テストがしたい • もちろん Feature テストは必須 • しかし網羅性の担保を Feature テストに委ねるのは重す ぎる – 細かい分岐それぞれの検証でわざわざ一連のテストをする? • Unit テストは機能結合前のテストなので細かい分岐な どを網羅するのに向いている • UseCase などビジネスロジックを置くところでは,Unit テ ストを補助的に使えるように実装すべき PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 49

Slide 50

Slide 50 text

PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 50 どうやって? • Facade を使うのはもうやめた • あとは UseCase から Eloquent を剥がすのみ Laravel からロジックを切り離そう!

Slide 51

Slide 51 text

• Entity を導入 – Eloquent Model の詰め替え先を作る • Repository を導入 – Eloquent Model,Eloquent Builder に依存する DB アクセスの処理を切り離す 51 UseCase,脱 Eloquent 計画 PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 52

Slide 52 text

Entity • Constructor で属性を受 け取る • Getter で属性を返す 52 実装例 PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 53

Slide 53 text

Model • toEntity を実装するこ とで,メソッドチェ ーンで Entity へ変換が 可能に 53 実装例 PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 54

Slide 54 text

Repository • Eloquent を使って DB から値を取得し,Entity に変換して返す 54 実装例 PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 55

Slide 55 text

UseCase • 依存するクラスはすべ て Constructor で注入 • User データの取得を Repository 経由にする 55 実装例 PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 56

Slide 56 text

• UseCase のロジックから Laravel に依存するも のがなくなった • データの取得部分をモックして,簡単に Unit テストが書けるようになった 56 Entity & Repository 導入で得られたもの PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 57

Slide 57 text

🔖今回のまとめ PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション 57

Slide 58

Slide 58 text

• Laravel は便利な機能が豊富だけど,Laravel標準の書 き方で推し進めるとつらみが出てくるよ • Facade は依存関係を分かりづらくするよ • Model・Controller だけでは責務の分散がしづらいよ • Unit テストを適宜導入することで開発体験が向上する よ • なんちゃってクリーンアーキテクチャ はオススメだよ 58 今回のまとめ PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 59

Slide 59 text

59 最後に PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション Laravel は使っても使われるな!

Slide 60

Slide 60 text

60 ྑ͍ -BSBWFM ϥΠϑΛʂ PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 61

Slide 61 text

61 次回予告 PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 62

Slide 62 text

62 もっと大規模な Laravel プロジェクトを ガチモジュラモノリスでやってみた? PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション

Slide 63

Slide 63 text

63 PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション from Yumemi

Slide 64

Slide 64 text

64 モジュール境界を意識した 「なんちゃってクリーンアーキテクチャ」からの進化系(仮) from @mpyw COMING SOON !! PHPerkaigi 2022 04/10 12:45 〜 Track B スポンサーセッション