Más contenido relacionado
La actualidad más candente (20)
Similar a Laravel × レイヤードアーキテクチャを実践して得られた知見と反省 / Practice of Laravel with layered architecture (20)
Laravel × レイヤードアーキテクチャを実践して得られた知見と反省 / Practice of Laravel with layered architecture
- 9. プロジェクト A
• 2018 年 4 月~
• Laravel で HTML を render して返す
典型的な web アプリケーション
• PL + 実装者 2 名 +
プロジェクト B
• 2018 年 6 月~
• SPA(API を Laravel で実装)
• PM + フロント 3 名 + サーバサイド 4 名 +
9
2 つのプロジェクト
- 10. • いずれも実装者のほとんどが Laravel 未経験
• なぜ Laravel?
• 技術のキャッチアップのため
• チーム横断人材の育成のため
• の役割はアプリケーションアーキテクト
• 別チームで Laravel をメインで使っていたので
白羽の矢が立った
10
2 つのプロジェクト
- 11. ※ 2018 年 3 月ごろ
「チームはわざわざ『Laravel に切り替える』
というコストを払っている……」
11
自分が提供できる価値を考える
- 12. ※ 2018 年 3 月ごろ
「Laravel をただの MVC フレームワークとして
使うのでは得られるものが少ないのでは?」
12
自分が提供できる価値を考える
- 16. • ディレクトリ構成を自由に設定できる
• DI のための仕組みが充実
• Eloquent ORM などの豊富で強力な機能
16
Laravel の特徴
→レイヤードアーキテクチャと相性がいい
→どこまでその機能を活用するか悩ましい
- 17. • もとから Laravel に存在している
概念は該当する層の中に移動
• 依存性の逆転を発生させる際に
DI の仕組みを活用
17
自由なディレクトリ構成と DI の仕組み
- 18. • もとから Laravel に存在している
概念は該当する層の中に移動
• 依存性の逆転を発生させる際に
DI の仕組みを活用
18
自由なディレクトリ構成と DI の仕組み
Application
Infrastructure
Domain
処理の流れ 依存の方向
- 23. <?php
namespace App¥Domain¥Models¥News;
/**
* Class Title
*/
class Title
{
/**
* @var string
*/
private $value;
/**
* @param string $value
*/
public function __construct(string $value)
{
$this->value = $value;
}
/**
* @return string
*/
public function value(): string
{
return $this->value;
}
}
このようなクラスが
DB のカラムの数だけ
作成された
- 24. どうすればよかったか?
• Value Object に「どんなメリットがあるか」
をベースにしてメンバーの認識すり合わせる
• 振る舞いや制約がない値は Value Object にしない
• 自由入力形式のテキストや bool 値など
24
Value Object の形骸化
- 26. json API の実装において Entity や Value Object に
を実装
26
整形処理の実装箇所
class User implements ¥JsonSerializable
{
// 略
public function jsonSerialize(): array
{
return [
'id' => $this->id,
'mail_address' => $this->mailAddress,
'profile' => [
'last_name' => $this->lastName,
'first_name' => $this->firstName,
'user_name' => $this->userName,
'sex' => $this->sex,
],
];
}
}
{
"id": 1,
"mail_address": "john@example.org",
"profile": {
"last_name": "Doe",
"first_name": "John",
"user_name": "johndoe",
"sex": "male"
}
}
jsonSerialize()
- 27. Controller が薄く、はじめは良い実装に見えた
27
整形処理の実装箇所
class UserController extends Controller
{
public function detail(User $user)
{
return response(['user' => $user]);
}
public function create(CreateRequest $request, UserRepository $userRepository)
{
$user = $userRepository->create($request->validated());
return response(['user' => $user], 201);
}
public function update(User $user, UpdateRequest $request, UserRepository $userRepository)
{
$user = $userRepository->update($user->id(), $request->validated());
return response(['user' => $user], 200);
}
}
- 28. • 一方で「ユーザ一覧 API」では
次のようなレスポンス欲しくなった
• 対応するために Entity に という
プロパティをもたせて条件分岐させるようにした
➢ ドメインの関心ごと以外が混ざってしまった
28
整形処理の実装箇所
{
"users": [
{"id": 1, "user_name": "jonedoe"},
{"id": 2, "user_name": "janedoe"},
// ...
]
}
$requestType
- 29. どうすればよかったか? その 1
• そもそも整形処理(レスポンス形式)自体が
ドメインの関心ごとではない
➢ Application 層に整形を担う
Presenter のようなクラスを設置する
• 「Controller を薄くすること」を目的にしない
• あくまで 1 つの指標に過ぎない
29
整形処理の実装箇所
- 30. どうすればよかったか? その 2
• CQRS を適用する
• 副作用のある Command と
副作用のない Query で役割を分割する
➢ 「一覧取得」は Query で行い
Entity を経由せずに、連想配列の形で扱ってしまう
30
整形処理の実装箇所
- 32. プロジェクト A の場合
• 最初のリリースまでに 3 ヶ月程度
• リリース後に大きな追加開発はしない想定
• 一般に公開はしないクローズドなシステム
➢ システムの規模に対してクラスの種類が多く
機能実装のオーバーヘッドが大きくなっていたの
ではないか?
32
規模に見合ったアーキテクチャか?
- 33. 33
規模に見合ったアーキテクチャか?
MVC レイヤードアーキテクチャ
• routing
• Controller (Request)
• Model (ORM)
• View
• routing
• Controller (Request)
• Use Case
• Entity
• Value Object
• Domain Service
• Repository (Interface)
• Repository (Implementation)
• ORM
• View
MVC と比較して考慮するべき概念は増える
- 35. どうすればよかったか?
• 複雑でないシステムなら MVC でも充分
• レイヤードアーキテクチャに出てくる概念の
一部だけを適用するのも良い
• 一方で、この挑戦によって得られた知見が
たくさんあった事実も軽視できない
➢ これらを踏まえて、ステークホルダーの合意を
取ったうえで採用するのならば問題はない
(今回は合意を取っていた)
35
規模に見合ったアーキテクチャか?
- 37. • いずれも実装者のほとんどが Laravel 未経験
• なぜ Laravel?
• 技術のキャッチアップのため
• チーム横断人材の育成のため
• の役割はアプリケーションアーキテクト
• 別チームで Laravel をメインで使っていたので
白羽の矢が立った
37
再掲:2 つのプロジェクト
- 44. • メンバーに Laravel の知識や
レイヤードアーキテクチャの概念を伝搬する
• 試行錯誤の過程で生まれたドキュメント等を
組織の資産にする
• (失敗)事例は外に向けてアウトプットする
➢ 自分/組織/社会の成長の糧にする
44
やったからには余すこと無く価値に変える
- 45. • メンバーに Laravel の知識や
レイヤードアーキテクチャの概念を伝搬する
• 試行錯誤の過程で生まれたドキュメント等を
組織の資産にする
• (失敗)事例は外に向けてアウトプットする
➢ 自分/組織/社会の成長の糧にする
45
やったからには余すこと無く価値に変える
今日、この場でお話ししているのも
「取り組んだことそれ自体」を正解にするため