こんにちは。バックエンドエンジニアの河内です。
LaravelのEloquent ORMにクエリスコープという機能があります。 その中に、ローカルスコープという機能があって、それを使うと頻繁に利用するクエリ条件を1箇所にアクセスしやすい形でまとめることができます。
このローカルスコープを使うと、コードが非常に読み下しやすくなるんですね。それはなぜなんだろう、というお話です。
ローカルスコープ使い方
公式からの抜粋ですが、たとえば「人気のあるアクティブユーザー」だけをDBから取得したい場合、以下のように「人気のある」スコープ(=scopePopular)と「アクティブ」スコープ(=scopeActive)を用意します。
ここで想定されている仕様については、「人気のある」とは「票数が100より大きい」であり、「アクティブ」とは「アクティブフラグが立っている」…と読み取れます。
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * Scope a query to only include popular users. * * @param \Illuminate\Database\Eloquent\Builder $query * @return \Illuminate\Database\Eloquent\Builder */ public function scopePopular($query) { return $query->where('votes', '>', 100); } /** * Scope a query to only include active users. * * @param \Illuminate\Database\Eloquent\Builder $query * @return \Illuminate\Database\Eloquent\Builder */ public function scopeActive($query) { return $query->where('active', 1); } }
これらのスコープを利用するには、以下のように書きます(チェーンできます)。利用時に、scopeプレフィックスは不要で、scopeを取り去ったあとの単語を小文字で呼び出します。
- scopePopular → popular
- scopeActive → active
ですね。
<?php : $users = User::popular()->active();
逆に、スコープを利用しないと以下のような同じような条件を何度も書くことになります。
<?php : $users = User::where('votes', '>', 100)->where('active', 1);
たとえば、「人気」の基準が、「票数が200より大きい」という仕様に変更になった場合、個別に書いて回ったソースコードを書き換える旅が始まってしまいます。
処理をまとめるのはプログラムの基本ですが、スコープで条件が書かれていると、読み下しやすいのもポイントです。
要求と意図
なぜ読み下しやすいのでしょうか。それは、たとえばscopePopularについていえば、「票数が100より大きい」ユーザーを取得するという論理的な「要求」が、「人気のある」という「意図」である、という位置付けに変換されたから…だと考えます。
ここでの「要求」と「意図」という単語は、スケールする要求を支える仕様の「意図」と「直交性」という記事の文脈から援用しました。
この「要求」と「意図」、わりと順不同でどちらが発端にもなるのかな、と思っています。
意図発
たとえば、「人気のある」ユーザーだけをトップページに表示したい、という「意図」発で依頼がやってくることも往々にしてあるかと思います。
この場合、「人気のある」とはどういうことなのか…ということを依頼者(DDD*1の文脈ではドメインエキスパート)と協議して「要求」を煮詰めることになります。
要求発
逆に、「要求」発の場合、まさに「意図」を見出だす必要があります。これは依頼者が「意図」を意識的に持っていることもあれば持っていないこともあり、持っていなかった場合、プログラマ側が抽出する必要があります。
「サイトのトップページに『票数が100より大きい』ユーザーの降順に表示したいんだよね」という要求があったときに、「つまり、『人気のある』ユーザーですよね」という意図を見出だし名付ける…ローカルスコープのメソッド名はまさに、その意図についての名付けの好例なのだと思います。
まとめ
Laravelのローカルスコープは、「要求」を「意図」に変換しその「意図」に名付けをおこなっている行為でした。
このローカルスコープの例に限らず、およそプログラミング自体がそういうものなのだ、ということは、DDDなどの設計思想に触れるにつれ痛感します。
また、「意図」の名前は、客観的な「要求」と違い、主観的なより生き生きとしたものになってくるかと思います*2。
そういう「意図」で編まれたプログラムは見通しのよいものになるのだと思っています。
最後に
Wizではエンジニアを募集しております。 興味のある方、ぜひご覧下さい。