Laravel+クリーンアーキテクチャの実装サンプル

Laravel,PHP,クリーンアーキテクチャ,勉強,設計

概要

今月の目標に「Clean Architectureのサンプルリポジトリを完成させる」と立ててしまったのでリポジトリを載せておく。

https://github.com/shoki-kitajima/laravel-clean-sample

今月も明日までとなるが、まだ完成はしていない。アプリケーション自体は動作するが、内部構造に十分な納得がいっていない状況。完成次第READMEを充実させ、解説記事を書く予定。

手をつけられなかった残りの部分は以下。

  • OutputBoundaryの実装
  • README及び解説記事の執筆
  • UseCase層~Infrastructure層のテスト
  • ディレクトリ及び名前空間の整理
  • エンティティやVOの要/不要判断(taskIdは必要か?など)
  • 登録前taskのIDどうしようかな問題(現状int|nullと気持ち悪い形にしている。VOを分けるか微妙なところ)
  • バリデーションを行う層の定義(Entityに全て責務を持たせても良かったかもしれない)
  • 実務的なエラー処理(今回のコンセプトとは外れるので、これは無視してもよい)

なぜこんな目標を立てたか

クリーンアーキテクチャを学んでいく上で、具体的な作り方が想像つかないと感じた。実践することで学びが深まり、間違いに気が付くことや具体的な実装について想像できるようになる機会が得られるのではないかと考えた。

また、レビューをしていただく際や他のエンジニアの方と議論をする際に、何かごく簡単なリポジトリがあれば便利かと思い公開することにした。

作りながら変化した状況

今月受けたコーディングテストで、RailsのアプリケーションをLaravelに書き直す機会があった。

関連記事

その際思い切ってクリーンアーキテクチャを採用してコーディングをした。そちらの方は割と綺麗に書け、Laravelの設定等理解が深まる部分もあったので、作りかけであったこのリポジトリも一回消して全て書き直してしまおうかと考えていた。

しかし理解が浅いまま書いたコードも、残しておけば後で振り返りに使える。自分のダメなコードを見て襟を正したり、成長実感をしたりなど勉強になることもあるのでこのままでいこうと思い直した。人生は旅行、千里の道も一歩から、旅の恥はかき捨て、と思うこととする。

特に気をつけたこと

詳しくは後に解説記事を書くつもりではあるが、ざっと気をつけたことをメモしておく。

  • 他のFWを使っている方でも見やすく、自身でも見返しやすいよう書いたコードはなるべく1ディレクトリにまとめる
  • 上に付随してLaravelの設定も少しいじる(viewやテストの読み込みディレクトリを変更するなど)
  • viewの見え方部分は本題ではないが、一応bulmaを使って汚くない程度にした
  • アーキテクチャの勉強として始めているので、冗長なクラス名(~Interface等)をあえてつける
  • 詳細なエラー処理(Exception拡張するなりなんなり)は一旦後回しとする
  • 実務ではあまりORMは使わないが、今回はEloquentをラップしたInfrastructure層のクラスを用いる

いつもLaravelの設定箇所を地味に忘れる。TimeZoneの設定やDBコネクションの設定に加え、今回は普段いじらないviewの読み込みディレクトリも変更している。app/config/view.phpのpathsを変更することで対応した。

    'paths' => [
        // resource_path('views'),
        __DIR__ . '/../packages/Views'
    ],

ちなみにView::addLocation()等でも対応できるらしい。その辺りはhttps://stackoverflow.com/questions/27458439/how-to-set-view-file-path-in-laravelで確認。こんな使い方に需要があるんだな、と驚いた。

所感

今月は先述したコーディングテストの件と本件にて、クリーンアーキテクチャの簡単な実装例を二つ用意できたのが嬉しい。どちらもまだ完璧とは言えないが、それなりにクリーンアーキテクチャの勘所のような部分がわかってきた。依存の方向性を制御すること、I/Oの型を明確に定義し接続することによりテスタブルかつアダプタブルな構成が作れる、という強みも理解でき、実務で実践する準備段階には至ったと感じる。

例えばLoggerを追加したい場合に、FW独立とするためにはLogger用interfaceを作ってそれに依存させるようにしようだとか、依存の向きはクリーンアーキテクチャの例の図で言うと一方向でならなければならないから置ける場所は限られるな、というような具体的なことが想像できるようになった。

あとはInput,UseCase(interface),Interactorあたりを一発で作れるコマンドラインツールなどを作れば楽に開発できるし布教もしやすいなあ、という思い。