はじめに
こんにちは。takunと申します。
プログラマー界隈では有名な著書、「リーダブルコード」を読みました。(1ヶ月前に...
やはり初学者からみても良著だと感じたので、忘れないために私のレベルで感じたこと・学んだことを記録していきます。
当方は初心者エンジニアです。間違ったことや不適切な内容となってしまう可能性もあることをご承知ください。また、助言など頂けると嬉しいです。
また、得意な言語はJavaです。この本では、様々な言語が出るため理解が及ばないところもあると思いますが、暖かく見守っていただけると幸いです。
1.名前を分かりやすく
-
抽象的な名前を使わない(例:getメソッド)
インターネットから取ってくるのならgetではなくfetch/Downloadの方がわかりやすい
とはいっても、英語が苦手な方もいますよね。(私もです。)
そんな方に私がお勧めしたいのがcodicというサイト。
google翻訳感覚で使えて、キャメルケースやスネイクケースで出力できるのでありがたい。
-
tmpなど意味のない変数名は使わない
スコープが小さく、一時保存的な使い方ならOK
-
スコープが大きい変数には長い名前をつける
1単語で理解できる名前にならないのなら、形容詞や動詞となるような単語をつけるのも必要。
現場に合わせて_や大文字の活用も検討する。
-
範囲などを指定するときは誤解されないように
名前を見直し、使ってどこからどこまでなのか、'< or <='なのか判別できる形にする。
例:max,minやfirst,last
2.コメントの扱い
-
「優れたコード > ひどいコード + 優れたコメント」ということ
ひどい名前がついていたとしても、埋め合わせでコメントしない。まず名前を変える。
-
コードの欠陥にコメントをつける。
// TODO:汚くなってきているから、サブクラスが必要かもしれない。
プロジェクトによると思うが、このコードをどうしたいかを自由にコメントを書くことが大事。
-
定数にコメントをつける(なぜこの数値か)
定数の名前からわからないことは、背景をコメントする。
例:// ファイルサイズもユーザーも満足できる品質。妥協値。
- 利用者が驚く、誤って使うリスクを考える
// メールを送信する外部サービス呼び出し(1分でタイムアウト)
sendMail(String〜){...}
これを知っておけば、HTTPリクエスト中にこの関数を呼び出さないで済む。
-
コードを要約する
適宜関数を作る等して、コードをブロックごとに分けてコメントをつける。
要約してコメントできれば全体像の把握がしやすく、チームに新しく参加する人にも優しい。
-
コメントは簡潔に
できるだけ複数行にならないように気を付ける。専門用語やプログラムの文法で表現できるなら、それでも問題ない。
-
インライン(名前付き引数)コメント
言語にもよるが、何を示しているかわからない引数値を以下のように説明できる。
Install(/* time_out = */ 10,/* useable = */ false)
3.ロジックを簡単に
-
条件式の並び順
著者は「もし私が18歳以上ならば」は良いが、「もし18年が私の年齢以下ならば」は不自然だと述べている。
例えとしては秀逸だなと感動した。そのため、多くの人にとっては
if(18 <= age) ではなく、 if(age >= 18) の方が読みやすい。
つまりフォーマットとしては、以下となる。
(左辺:調査する変数 比較演算子 右辺:比較する定数)
-
if/elseブロックの並び順を意識する
基本は肯定的で単純な条件を先にする。
私:その条件式でどんな処理を達成したいかをイメージして順番を考える必要があるんだろうな
-
早く返してネストを浅くする
つまり、関数ならreturn。ループブロックならcontinue。例えば、以下のようなコードとなる。
for(int i = 0;i < list.size();i++){
if(list[i] == null){
continue;
}
if(list[i] != target){
continue;
}
totalCorrect += 1;
}
関数におけるreturnも同様。
P.S.
わかりやすいという利点だけではなく、'テストのしやすさ'や'バグの発見'にも役立ちました!
4.タスクを小さく
-
条件文を無理に1行にまとめない
論理演算子を使って長すぎる条件式を作らない。長すぎるのであれば、- 適切な名前をつけた変数を前もって定義する。
- if文をもったいぶらないで使う。
-
領域別でコードを切り分ける。可能であれば関数にする。
(これは本書の11章あたりで触れている内容なのですが、私にとっては正直コードが難しく感じました。
曖昧な理解かもしれません。ご注意ください。)
関数を作ることは、小さな問題(タスク)を切り分けることになる。
一方でいきなり関数にできないほど複雑になっている場合もあるので、コードをブロックごとに分ける作業が必要だと理解した。具体的には、以下の手順だと考える。- 各処理で扱う変数をまとめて上部に定義する
- 文章の段落のように1つ1つの処理の境界線を見極め改行する
- 処理内容から共通項を探す
また、適切に関数を作ることでコードとコードの結合度合いも下がり、可読性だけでなく他プロジェクトでの再利用性やテストのしやすさが向上することも理解できる。
5.テストを意識する
本書14章で取り上げられた内容で特に印象に残った筆者の記述を挙げると、
「後でテストを書くつもりでコードを書くと、テストしやすいようにコードを設計するようになる。」
当たり前のことかもしれませんが、例えプロジェクト上で自分がテストに関わる機会がないとしても、意識していかなきゃなと思いました。
(以下はコード内容への理解曖昧なので参考にしないでください)
また、テストコードも前述(1〜4)してきたように読みやすさが大切。読みやすいコードはみんなのテストコードの追加を易しくしてくれる。テストコードでは前述してきた以外に、以下の手法も重要となる。
-
テストには綺麗で単純な数値を選ぶ
例えば、関数の引数に入力値と期待される出力値をカンマ区切りで渡す。結果がtrueであれば問題ない。
checkScoresBeforeAfter("1,-2,3","3,1")
恐らくこれはマイナスの入力値がフィルタリングされているのだろうとわかる。
よって、わざわざ-99999のような大きな数字にする必要はないということ。
-
1つの機能に複数のテスト
完璧な入力値ではなく、小さなテストを複数作る方が効果的でわかりやすい。以下のように1つ1つ上から確かめていく。
checkScoresBeforeAfter("2,1,3","3,2,1") // ソート機能問題なし。
checkScoresBeforeAfter("0,-0.1,-10","0")// マイナス削除される。
checkScoresBeforeAfter("1,-2,1,-2","1,1") // 重複OK。
checkScoresBeforeAfter("","") // 空の入力OK。
おわりに
正直この本難しかったです(笑)
実務に入れていない私からすると、言語・書き方への理解は半分半分でしたorz
そんな私でも感じ取れた学びを大切にしつつ、実務に活かして行こうと思います。
こんな新米エンジニアの記事をここまで見て頂けて嬉しいです。拙い文章で恐縮ですが、見ていただいてる方に分かりやすい内容となるよう努めていきます!
コメントやアドバイスなど頂けたら嬉しいです!
きっと、期間をあけて再度読み直してみます!