はじめに
今回が初投稿となります。
今回は、入社してから約1ヶ月間の研修で頂いたコードレビューから
アプリケーションを作る上で大切だと学んだことについてまとめたいと思います。
* 言語/フレームワークはLaravel(PHP)
とVue(JavaScript)
です。
1. コメント
誰が見てもわかりやすく書く
今回作成したSNSアプリケーションの中で、ログインユーザがフォローしているユーザリストを表示する画面を作成するために、以下のような手順を取りました。
1. フォロー関係を表すfollower
テーブルを作成
public function up()
{
Schema::create('follower', function (Blueprint $table) {
$table->unsignedBigInteger('following_id')->nullable(false)->comment('フォローしているユーザID');
$table->unsignedBigInteger('followed_id')->nullable(false)->comment('フォローされているユーザID');
});
}
2. ログインユーザ自身がフォロー中のユーザを取得
public function getFollowings(int $userId)
{
return Follower::select('followed_id')
->where('following_id', $userId)
->get();
}
3. 2で取得した値をコレクションメソッドpluck
を使ってfollowed_id(フォローされているユーザid)
のみを取り出す
$followings = $accountService->getFollowings(Auth::id());
$followingIds = collect($followings)->pluck("followed_id");
この時、取得した値をログインユーザの目線でフォローしているアカウントという意味でfollowingIds
という変数に格納しました。
しかし取得したデータベースのカラム名はフォローされたを意味するfollowed_id
です。
このような内容は、読み手は書き手と同じ認識レベルであるとは限らない為わかりにくい状態です。
誰が見てもわかりやすいようにコメントを記載する必要があります。
// データベースのカラム名はfollowed(フォローされた)ですが、主語が変わるので変数名はfollowing(フォローしている)になっている
PHPdoc(ドキュメントコメント)を書く
PHPdocとは
Docブロックはコードに詳細な情報を記述することができる、特別な種類のコメント文です。
このコメントは機能についての理解を促進させる情報を提供するために利用されます。 DocコメントをもとにIDEが自動補完の手がかりとしたり、phpDocumentorがAPIドキュメントを生成します。
引用:phpDocumentor
PHPdocを書くことで、自分だけではなく他の開発メンバーもコードを理解するのにとても役立ちます。
コメントは全ての開発する人にとって、ソースの意図を理解する助けになり、プログラムを読みやすくするため、とても重要である。
2. 安全なアプリケーション
CSRF対策
CSRF(クロスサイトリクエストフォージェリ)とは
クロスサイトリクエストフォージェリは、認証済みユーザーに代わって不正なコマンドを実行する、悪意のある攻撃の一種です。
引用:CSRF保護 9.x Laravel
CSRF対策のためには、処理が実行される前に認証済みユーザからのリクエストであるかを確認する必要があります。
Laravelは、アプリケーションによって管理されているアクティブなユーザーセッションごとにCSRF「トークン」を自動的に生成します。このトークンは、認証済みユーザーが実際にアプリケーションへリクエストを行っているユーザーであることを確認するために使用されます。このトークンはユーザーのセッションに保存され、セッションが再生成されるたびに変更されるため、悪意のあるアプリケーションはこのトークンへアクセスできません。
引用:CSRF保護 9.x Laravel
このセッションに保存されたトークンを使って、認証済みユーザからのリクエストであるかを確認します。
<form method="POST" action="{{ route('login') }}">
@csrf
</form>
Bladeディレクティブの@csrf
を使って、以下の内容となる非表示のinputフィールドを生成します。
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
<!-- csrf_token() : 現在のセッションのCSRFトークンを取得 -->
formに@csrf
を記載することで、リクエストにトークンが含まれ、その値とセッションに保存されたトークンが一致することにより認証済みユーザからのリクエストだと確認でき、CSRF対策ができます。
(一致したかどうかはApp\Http\Middleware\VerificationCsrfToken
ミドルウェアが自動的に検証)
CSRFのみならず、安全なWEBアプリケーションの開発のために対策が必要である。
3. 無駄のない、綺麗で可読性の高いソースコード
値の利用頻度を考える
下記のようなソースコードがある場合
$isLogged = Auth::check();
if ($isLogged) {
$postNum = $postService->countUserPost(Auth::id());
$favoriteNum = $postService->countUserFavorite(Auth::id());
}
if文の条件として一度しか使わないAuth::check()
は変数$isLogged
に格納され、
Serviceのメソッドの引数としてAuth::id()
が複数回呼び出されています。
このような場合は複数回呼び出されるものを変数として定義し、一度しか利用されないものは直接呼び出します。
$id = Auth::id();
if(Auth::check()) {
$postNum = $postService->countUserPost($id);
$favoriteNum = $postService->countUserFavorite($id);
}
利用頻度は低くてもあえて変数に定義することにより可読性が上がることもあるので、その状況に合わせることが必要。
ソースコードを簡略化する
ControllerからViewに下記のような複数の値を渡す場合
return view('home.index',[
'title' => $title,
'posts' => $posts,
'followee' => $followee,
'follower' => $follower,
'favorite' => $favorite,
]);
Viewで使う変数名と値となるphpの変数名が同じ場合はcompact関数
を使うと簡略化できます。
return view('home.index', compact('title', 'posts', 'followee', 'follower', 'favorite'));
アクセサを利用する
テーブルから取得したcreated_at
をY年m月d日
のフォーマットで表示するために下記のように実装していました。
<div class="date">{{ $tweet->created_at->format('Y年m月d日') }}</div>
このような場合、データベースからデータを取得した際に実行されるアクセサ
を使うと、画面側の実装がより簡潔化できます。
アクセサとは
アクセサは、Eloquentの属性値にアクセスが合った時に、その値を変換するものです。
引用:Eloquent:ミューテタ/キャスト Laravel 9.x
モデルにcreated_at
をY年m月d日
の形にフォーマットするアクセサを定義します。
protected function formatedCreatedAt(): Attribute
{
return Attribute::make(
get: fn ($value, $attributes) => Carbon::parse($attributes['created_at'])->format('Y年m月d日')
);
}
アクセサでフォーマット処理を実装したことにより、画面側ではアクセサを呼び出す処理だけで同じことが実現できます。
<div class="date">{{ $tweet->formatedCreatedAt }}</div>
実装方法はその時々の状況によりますが、無駄のない可読性の高いコードは自分にとってもチーム開発において重要である。
まとめ
初めて自分の学びを投稿してみましたが、記事を書く中で改めて知ることも多く、アウトプットの大切さを実感しています。
まだまだ学ぶことがたくさんあるので、引き続きアウトプットしていきたいと思います!!