リーダブルコードを読まないでリーダブルコードを要約してみる
はじめに
この記事はリーダブルコードをまだ読んでいない人間が書いています.要約記事の要約みたいなものです.軽く流し見してもらえると幸いです.今度しっかり読んで記事を書きたいですね.
自己紹介
Zincといいます.UT-virtual部員として,駒場祭ではCall Their Name!という音声認識を用いたゲームを作りました.
この記事を書いた理由
さて,突然ですが,以下の関数コードをご覧ください.
IEnumerator MyCommand(){
StartCommand();
_MicIcon.SetActive(true);
Debug.Log("MyCommandStart");
yield return new WaitForSeconds(7.0f);
StopCommand();
Debug.Log("MyCommandStop");
_CallIcon.SetActive(false);
_MicIcon.SetActive(false);
yield return new WaitForSeconds(1.0f);
_EnemyStatus.HPSlider.value=_EnemyStatus._HP;
}
...実行順序,変数や関数の名前もぐちゃぐちゃで,何を言っているかわかりにくいですね.
これ,Call Their Name!のコード内にある関数をそのまま引っ張って来たものなのですが,まー汚い.読みづらい.今後の開発のこととか1mmも考えてない.ひどいコードです.(プログラムに慣れてない状態で書いたコードを使っている自分の研究ではもっとひどいことになっています.引き継ぎどうしよう...)
で,今後ゲーム開発をもっと頑張りたいなーと思っている自分にとって,この問題は深刻です.自分でも何かいているかわからないのに,他の人に共有することなんて無理だ!,と.
そこで「リーダブルコードを読みたいな」と思うようになりました.年末に読もうかな~と考えていたのですが,せっかくなので予習という意味で,ここにある程度,世間にある要約を自分なりに解釈してアウトプットしてみようと思います.まー自習ノートみたいなものです.この記事含め,なるべく読みやすくなるように心がけます.読み物として楽しんでいただけると幸いです.前置き長いって?...ごめんなさい...
1章(のまとめ)
コードは他の人が最短時間で理解できるようにしましょう. 理解しやすくするためには冗長なコードを避けたほうがいい(できる限り短いほうがいい)ですが,「理解するまでにかかる時間」を短くするほうが適切です.
とにかく,「他の人が読むとき,自分のコードは簡単に理解できるか?」を常に念頭に置くことが大切ですね.
2章(のまとめ)
名前に情報を詰め込みましょう. 例えばtmpやxなど,汎用的すぎる名前はできる限り避け,「何を表しているのか」を明白にするようにしましょう,とのこと.(変数スコープが短い場合は使ってもヨシ!)
長い名前などはIDEやエディタ(Visual StudioやVSCodeなど)が補完してくれるので,つけることをためらわないで!
参考リンク:C#(Unity),Python(Qiita),Python(PEP8)
Unityでの例をみてみると,今すぐつかえる命名規則として,
- PascalCase:単語の頭文字を大文字に,あとは小文字に
- 関数名(ex. MyCommand)
- クラス名(ex. MyMonsterStatus)
- camelCase:PascalCaseの最初の文字だけ小文字にしたもの
- メンバ変数
- ローカル変数
- 引数(パラメータ)
などがあるみたいですね.あと,チーム独自の略称などは,できる限り控えたほうがいいみたいです(独自の環境に慣れるのはあぶないですからね...).
3章(のまとめ)
誤解されない名前をつけることを心がけましょう. 例えば,
- min_,max_は変数の限界値(取りうる範囲)
- first_,last_は変数の範囲(変数が取る範囲)
といった具合です.このへんのニュアンスはちょっと僕も不明瞭な部分があるので,しっかり確認したいところです.なんにせよ,「自分が意図しているものと別の意味合いでとられないか?」 ということを自問自答しつつ作成したほうがいいですね.
4章(のまとめ)
美しいコードに見えるように整形しましょう. インデント(コードの段落)を適切に,美しくなるように改行しましょう.例えば,以下の例はPythonですが,
value = function_name(var_one, var_two,
var_three, var_four)
よりも,
value = function_name(var_one, var_two,
var_three, var_four)
のほうが,かっこが揃っていて見やすいと思います.このように,ぱっと見でまとまりなどがわかりやすくすることが大切です.
5章(のまとめ)
コメントを有効活用しましょう. C#なら//,Pythonなら#でコメントを記述することができますが,ここに情報を詰め込みましょう,という話ですかね.例としては,
- この設計にした背景(他の方法ではない,この設計にした理由,という感じ)
- コードの欠陥(ここをもっとスマートにできるから,いつか直す,みたいなことを書く)
- 定数の意味(デフォルトの値がこれである理由を簡潔に)
とかが当てはまるでしょうか.関数やクラスの意味を説明することにも使えますね.Unity(C#)では<summary>タグというものがあるので,これと合わせて説明をわかりやすく記述できると良いですね!
6章(のまとめ)
コメントの情報の密度を高くしましょう. もちろんわかりやすくすることが先決ではあるのですが,例えば前提知識の専門用語等をある程度盛り込んで情報を少ない文字数に圧縮しましょう,ということですかね.
7章(のまとめ)
制御(条件分岐やループなど)の流れを読みやすくしましょう. 例えば条件式については
if(1000>price){ // 比較対象>調査対象
//操作
}
よりも
if(price>1000){ // 調査対象>比較対象
//操作
}
のほうが,「もし価格が1000円以下なら」という言葉の流れに沿うため,読みやすいですよね.
他にも,
- if/elseを使用するときに,条件としてなるべく肯定系を用いる(
if(!isBoot)
よりif(isBoot)
の形に揃える) - 関数内で早めに
return
できるところではreturn
して処理を早めに区切る - ネストを浅くする(例えば
if/else
の入れ子構造をできる限り浅くする)
といった工夫を取り入れることで,制御の流れがすっきりします.これで読み手側の脳への負担を減らせますね!
8章(のまとめ)
巨大な式は分割しましょう. 例えば,
if(gameObj.GetComponent<xxx>().function(a,b)<10){
//操作
}
とするより,
var returnValue=gameObj.GetComponent<xxx>().function(a,b); //説明変数を定義
if(returnValue<10){
//操作
}
というように,適宜変数をはさんで式を分割し,コードをスマートにしていくことが大切です.
また,
if (item.info.name == "sword") {
item.info.price = 300;
item.info.type = "weapon";
}
else if(item.info.name == "shield") {
item.info.price = 400;
item.info.type = "weapon";
}
else if(item.info.name == "potion"){
item.info.price = 100;
item.info.type = "medicine";
}
というようにいちいち変数を書いていたら大変ですよね.ここで,変数を要約してあげると一気に記述も確認も楽になります.
string itemName=item.info.name;
int itemPrice=item.info.price;
string itemType=item.info.type;
if (itemName == "sword") {
itemPrice = 300;
itemType = "weapon";
}
else if(itemName == "shield") {
itemPrice = 400;
itemType = "weapon";
}
else if(itemName == "potion"){
itemPrice = 100;
itemType = "medicine";
}
おお,すっきりしましたね!
9章(のまとめ)
変数は必要な分だけ使いましょう. 変数をテキトーに設定してしまうと,追跡しきれない,スコープの把握困難,格納されるであろう値の追跡が困難になるなどの問題が発生してしまうので,
- 不要な変数は定義しない
- スコープを縮める
というような対策をとろうとのこと.8章とあわせると,「巨大な式分割のための変数でもなく,頻繁に再利用される変数でもなければ削除しましょう」ということですかね.
おわりに
とりあえず,1~9章をざっと記事をみつつ,自分なりに要約してみました.本当は10章と11章もあったのですが,力尽きてしまったので今度追記しようと思います.
ここの解釈間違っているよとかあったらぜひ教えてください.
Discussion