本記事はQualiArts Advent Calendar 2022 17日目の記事です。
22新卒Unityエンジニアのmapleです。
現在所属しているIDOLY PRIDEのチームでは、1つのプルリクエストに対して最低2人のコードレビューを受けてApproveをもらう必要があります。
そんな環境で私が約半年間、コードレビューで指摘されて重要だと思った読みやすいコーディングについてまとめてみました。
命名
命名を考える上で大事なことは、役割がハッキリ分かる名前をつけることです。
十分に意味が伝わらない命名、複数の意味合いが取れるような曖昧な命名は避けることが好ましいです。
変数、プロパティ
変数やプロパティの命名は、どんな目的で使用するものなのかを意識すると良いです。
どのような場面で用いられるのかをすぐにイメージできる命名が適切と言えます。
必要な情報を含める
例えば、Data
、Info
、Item
、File
などは、どんな情報が含まれているのか分からず、どんな使い方をしたいのか想像しにくいと思います。
「修飾語+名詞」の形式で命名すると伝わりやすくなります。
例:
CharacterName
→ キャラクターの名前であることが分かる
→ 名前だからString型だと想像できる
StageClearRewards
→ ステージをクリアした際にもらえる報酬であることがわかる
→ 複数形だから配列やList系だと想像できる
メソッド
メソッドは「何かをする」という動作がある処理なので、基本的に動詞を先頭に付けます。
何をどうする処理なのか、どんな値を返すのかを意識すると良いと思います。
よく使う動詞
データの反映系のメソッドによく使う動詞の使い分けを紹介します。
- Get
- 何かを取得して返す場合に使う
- 万能に使えそうだけど、取得の意味が広い単語なので使用する場面で要検討
- Initialize
- 最初の1回だけ処理を行う場合に使う
- Set
- データを入れたい場合に使う
- 最初の1回だけの場合はInitialize、何回か使いたい場合はSetで使い分ける
- Show
- 表示・非表示を切り替える場合に使う
- 引数にboolを指定して、切り替えるイメージ
- Save、Remove、Clear
- データを保存、削除、リセットする場合に使う
- Update、SetUp
- 何かしら更新、設定する場合に使う
- 上記のGet、Set、Show、Save...や、他の処理を複数まとめて入れたい時に使うといい
英単語選びに困ったら
上記の内容でどんなシチュエーションでも対応できるわけではないため、
どんな英単語だと伝わるのか迷ったらcodicというサイトが便利です。
条件式
早期リターン
複雑な条件式は冗長なコードになりがちで、読み解くことが難しくなる場合があります。
そんな時に、可読性・保守性を高めるテクニックのひとつとして早期リターンがあります。
early return、ガード節、Guardなどとも呼ばれています。
処理の先頭の方にreturnを置くことで、if文などのネストを浅くすることができます。
特に、例外的な処理を先に判定してreturnしておくと、処理を追いやすいし、無駄な処理を省くことにも繋がります。
if (/*例外判定*/)
{
// 例外処理を書く
return;
}
// 想定した処理を書く
if else をあまり使わない
上記の早期リターンを意識する上で、処理の本流を追えるようになることが重要です。
したがって、処理が真っ二つに割れるelse
は読み難い書き方になるため、あまり使われません。
しかし、本流が2つの処理を分けるとなったら話は別です。
処理の流れを真っ二つに分けたいのなら、else
を使った方が「これは逆の処理だぞ」といったメッセージ性が生まれて読みやすくなります。
メソッドを分ける
1つのメソッドでは、1つの目的の処理をすることが好ましいです。
この目的の処理を小さく分割できれば、1メソッドの処理がシンプルになっていき、一気に理解しやすくなります。
そして、処理を一言で表せるくらいに分けることで、メソッドの命名も分かりやすくなると思います。
大きな処理の流れをおおまかに把握する際に、メソッド名を順番に見ていくだけで流れを追うことができる状態になるととてもGOODです!
一時変数を使う
説明変数
欲しい変数を取得、参照する時に、コードが複雑だったり冗長になったりしてしまう場合に使います。
例:ユーザーのレベルによってプレイ可能なステージ情報が欲しい場合
var playableStages = StagesData.Where(stage => stage.requiredLevel <= UserData.Level);
要約変数
if文の条件式が複雑で何を判定しているものなのか分かり難い場合に使います。
例:スタミナを消費して何かしらプレイする場合
// プレイ可能か : 現在のスタミナが必要スタミナより多いか
bool canPlay = requiredStamina <= currentStamina;
if (canPlay)
{
// スタミナ消費してプレイする処理
}
最後に
本記事では、新卒エンジニアがコードレビューを受けて学んだ読みやすいコーディングについてご紹介しました。
本記事の内容は、リーダブルコードにも含まれている内容が多くなっています。
私自身、入社前にリーダブルコードを読んでいて、ある程度可読性のあるコードについて理解していたつもりだったのですが、実際に現場でコードを書いてレビューをもらうと、意識できていなかった部分が浮き彫りになりました。
そこで今回、身をもって学んで意識できるようになった要素をまとめるに至りました。
可読性に関する指摘をもらった際に、その前提知識があったことによって、レビュー内容をすんなり受け入れることができた思います。
コードの可読性・保守性について考えてたくなった方は、まずリーダブルコードを一読することをオススメします!
この記事が少しでもご参考になれば幸いです。ありがとうございました。