バックエンドエンジニアをしております。久住です。
「レアジョブ英会話 スマートメソッド®コース」ではLaravelとVue.jsを使ったSPAの開発をしておりバックエンドではDDDを意識した実装を行なってます。
その中の「レイヤードアーキテクチャ」について今回は書かせていただきます。
なぜレイヤードアーキテクチャを採用しようとしたのか
よくあるMVCの問題としては以下のようなものがあると思っております。
- Controllerにビジネスロジックを書くなど、FAT Controllerになる
- ModelにビジネスロジックとDBアクセスが混在して、メンテナンス性が悪くなる
- 共通のModel間で自由にコールし合い、互いの依存性が高くなる
- 共通のModelに、特定のControllerからしか使われないような汎用性の低いメソッドができる
- 共通のModelに、同じような役割のメソッドが複数できる
他のMVCを採用したプロダクトではこれらの問題がたびたびエンジニアのミーティングでも課題として挙げられる事がありました。
- 修正時に影響範囲がわかりにくい
- どこに何を実装すべきかチーム間で齟齬が出る 等
作成したアーキテクチャ
以下のような実装イメージをチームで統一しております。
- ソースをいくつかの層に分離し、実装すべき箇所を明確にする
- 各層の依存関係を限定的にする
- 各層の役割について
- Controller・・・Requestから入力値を取得し、Domain.Serviceに処理を移譲、結果をResponseに渡す
- Request・・・アクセス認証、入力値のvalidation、入力値のデータ型キャストを行う
- Response・・・APIレスポンスの構築、Viewファイル
- Domain・・・ビジネスロジックがここに集約される
- Service・・・Controllerからデータを受け取り、Entity、ValueObjectの生成、RepositoryへEntityの取得、作成、更新、削除を移譲する
- Entity・・・一意に識別できるIDを持ち、その属性が変化しても同じものだと判定する、もしくは同じ属性でも別のものだと判定する場合があるもの
例:ユーザー → 名前が変わっても同じ人である、同姓同名の人がいても別の人の場合がある - ValueObject・・・その属性やふるまいだけを表現し、それが「どの」人なのか、「どの」ものなのかは気にしないもの
どれかを識別するIDは持っていない。また、オブジェクト自体は不変であり、setterは絶対にない
- Infrastructure・・・DB、他サービスAPI、Platformなどの外部アクセスを行う(Platformとはデータ基盤の事です)
例えばDBから取得しているデータをAPIから取得するようにしたい。
となった場合infrastructureを修正すれば良いとすぐにわかります。
導入してわかったこと
- メリット
- どこかを修正した時に上位層を修正すれば良いので、影響範囲がわかりやすく、これが最大のメリットに感じています。
- おかげで開発者間での実装の相談のしやすさや見積もりの精度も上がりました。
- コードが増えてくるとどこに何をするものがあるのか不明確になる事が多いと思いますが、役割を明確にする事によって解決し変化に強いシステムが作れます。
- デメリット
- 開発メンバーの入れ替わり等があると共有認識を作るのが大変かもしれません。ドキュメントやサンプルコードを見る事でチーム間で共有しています。
- 初期段階の仕組み作りは少し大変かもしれません。(Laravelのディレクトリ構造も変えたような記憶があります)
今後もメリットを増やせるように仕組みをアップデートしていこうと思います。