綺麗なコードとはなんですか?と聞かれるとは思いますが、これは人によって答えが違いますね。しかし、答えは最終的に人が簡単に読めるかどうかになりますね。
綺麗な字は読みやすい字ですよね?綺麗な絵は見やすい絵ですよね?
そう考えて綺麗なコードを書くことを求めます。
マシンのためじゃなくて、人のためのコード
PHPとLaravelで考えていますけど、どんな言語でも同じです。
個人的に綺麗なコードはマシンが発動できることを考えながら書かれたコードではなく、人間が読めることを考えながら書かれたコードです。
下記のコードを見てください。
// 日本語で読むとこうなります
// もし $post の user_id がログインしているユーザーの id と同じだったら
@if ($post->user_id == Auth::user()->id)
読みやすくて、誰でも理解できると考えているなら… ちょっと待って!これで本当に確認したいことは、idが同じかどうかじゃないんですね!明らかに確認したいのはユーザーがポストの作成者かどうかですね。
下記のコードと比べてみてください
// もしログインしているユーザーがポストの作成者だったら
@if (Auth::user()->owns($post))
今の方がいいですね!User
クラスの中にコードが増えるのが別に問題ありません。
owns()
の中でどうやって比べているかは全く構いません。Viewの責任じゃありません。
// ownsは一応こうなっています。 :)
class User
{
public function owns(Post $post)
{
return $this->id === $post->user_id;
}
}
一つの比較でコードは確かに複雑になりませんけど、コードは大きくなっていくと複雑になっていく一方ですから、簡単でいられるようにするのが目的です!
たとえ数カ月後に、ビジネス・ルールが他にも追加されて… ポストが出版されているかどうかをチェックしなきゃいけなくなるとか?そしてシステム管理者の場合、ポストの作成者じゃなくても編集できるとか?
// 重ねて行くと地獄になっていきますね
@if (($post->user_id == Auth::user()->id || Auth::user()->admin === true) && $post->published_at !== '0000-00-00 00:00:00' && $post->published_at < Carbon::now())
// ↓ 上記より、読むコードが
// ↓ 下記のようだったら、読むときは簡単ですね
@if ((Auth::user()->owns($post) || Auth::user()->isAdmin()) && $post->isPublished())
// ↓ 最終的に本当に確認したいのは編集できるかどうかですね?
// ↓ それなら、下記の方が簡単です
@if (Auth::user()->canEdit($post) && $post->isPublished())
そしてUser
とPost
クラスの中のメソッドも綺麗に読めます。
class User
{
public function canEdit($post)
{
return $this->owns($post) || $this->isAdmin();
}
public function owns($post)
{
return $this->id === $post->user_id;
}
public function isAdmin()
{
return $this->admin === true;
}
}
class Post
{
public function isPublished()
{
return $post->published_at !== '0000-00-00 00:00:00'
&& $post->published_at < Carbon::now()
}
}
文章を書いてるように考えること
マシンに近い低いレベルのコードで考えるより、人間に近い高いレベルのコードで書くほうが綺麗なコードになります。
たとえユーザー登録のとき、メールを送る方法はSMTPか他なのか、メールのタイトルや、誰から飛ばされるのか、コンテンツはどうなのか、コントローラーは構いません。登録に関して細かいことと、メールに関して細かいことはそれぞれのメソッドに書き込めばいいですね。
AuthController extends Controller
{
public function postRegister(Request $request)
{
// 文章 Extract from the request only the name, email and password.
extract($request->only('name', 'email', 'password'));
// 文章 Register a new user with the name, email and password.
// Then send a welcome email.
(new RegisterUser($name, $email, $password))
->sendWelcomeEmail();
}
}
結論
細かいコードを理解しやすいメソッド名で隠せばいいです。
プログラミング言語は他の言語と同じ
日本語で「ポストは出版されていますか」って聞くと、「はい」か「いいえ」の答えを期待しますよね?
「ポストの出版のタイムスタンプが現在のタイムスタンプより低いですが、ゼロですからね」って答えたら、ふざけてると思われるんですよね?w