🪬

【リーダブルコード要約】第1部 表面上の改善

2020/10/07に公開

プログラミングを始めた頃にリーダブルコードを読んだのですが、当時ではあまり理解ができていなかったため、改めて読み返してみました。

今読み返してみるととても参考になる情報ばかりだったので、要約としてざっくりまとめたいと思います。

リーダブルコード

https://amzn.to/3Y8mfIV

1章 理解しやすいコード

  • コードは他の人が最短時間で理解できるように書かなければならない
  • 数行のコードを 1 行に省略したとしても、理解するために時間を多く使ってしまうようでは前者の方が理解しやすいコードとなる

2章 名前に情報を詰め込む

ファイル名や変数名、関数名やクラス名などどの名前をつけるときにも当てはまるが、名前に情報を詰め込むようにする。

よい名前の付け方として以下のようなテーマがある。

  • 明確な単語を選ぶ
  • 汎用的な名前を避ける
  • 抽象的な名前よりも具体的な名前を使う
  • 接尾語や接頭語を使って情報を追加する
  • 名前の長さを決める
  • 名前のフォーマットで情報を伝える

明確な単語を選ぶ

「名前に情報を詰め込む」には、明確な単語を選ばなければいけない。「空虚な」単語は避けるべきだ。
例えば、「get」はあまり明確な単語ではない。

def GetPage(url):
...

「get」という単語からは何も伝わってこない。このメソッドはページをどこから取ってくるのだろう?ローカルキャッシュから?データベースから?インターネットから?インターネットから取ってくるのであれば、**FetchPage()DownloadPage()**の方が明確だ。

『リーダブルコード』p.10-11より引用

このように具体的な動きに合わせて明確な名前をつけることが良いとされています。

本書ではシソーラス(類語辞典)を使っていくつかの単語を状況に合わせて使うようにと紹介されています。

単語 代替案
send deliver, dispatch, announce, distribute, route
find search, extract, locate, recover
start launch, create, begin, open
make create, set up, build, generate, compose, add, new

『リーダブルコード』p.11の表より引用

汎用的な名前を避ける

  • tmp・retval・fooのような空虚な名前は避け、エンティティの値や目的を表した名前を選ぶようにする
  • 生存期間の短いローカル変数(一時的な保管)などで使用する場合は tmp などを使用しても問題はない

抽象的な名前よりも具体的な名前を使う

変数や関数などの構成要素の名前は、抽象的ではなく具体的なものにしよう。
例えば、**ServerCanStart()**という名前のメソッドがあったとする。任意のTCP/IPポートをサーバがリッスンできるかを確認するメソッドである。でも、**ServerCanStart()**という名前はちょっと抽象的だ。具体的な名前にすれば、**CanListenOnPort()**になるだろう。これならメソッドの動作をそのまま表している。

『リーダブルコード』p.16より引用

名前に情報を追加する

変数の意味を間違えてしまったときにバグとなりそうな場合は、状態や注意喚起などの情報を名前に追加したほうがいい。

本書では以下のように、情報を変数名に追加した方が良い例を紹介している。

状況 変数名 改善後
passwordはプレインテキストなので、処理をする前に暗号化すべきである。 password plaintext_password
ユーザーが入力したcommentは表示する前にエスケープする必要がある。 comment unescaped_comment
htmlの文字コードをUTF-8に変えた。 html html_utf8
入力されたdataをURLエンコードした。 data data_urlenc

『リーダブルコード』p.21の表より引用

名前の長さを決める

  • 長い名前は避けた方がいいという暗黙的なルールがあるが、重要なのは「意味のある名前」をつけるということ
  • スコープが短ければ省略した短い名前でも良い
  • 名前が長くてもテキストエディタには「単語補完」機能がついているため問題ない
  • クラス名などを省略する場合、新しいチームメンバーが混乱するような場合は極力避けるようにする
    • BackEndManager ではなく BEManager に省略したりすると、新しいチームのメンバーは名前の意味が理解できない
  • ConvertToString()を ToString()にしても必要な情報は何も損なわれないので、不要な単語は削除する。

名前のフォーマットで情報を伝える

  • キャメルケースやスネークケース等でクラス名や変数名などに意味を含める
  • 言語によってクラス名や変数名等の命名規則があるので基本的にその規則にしたがっていれば問題ない

https://zenn.dev/yyykms123/articles/2019-11-20-naming-convention

3章 誤解されない名前

「理解しやすい意味のある名前」をつけるのが良いので、名前は誤解されないように注意する。

本書では具体的な例として以下をあげている。

データベースの問い合わせ結果を処理するコードを書いているとしよう。

results = Database.all_objects.filter("year <= 2011")

このresultsには何が含まれているだろうか?

・「year <= 2011」のオブジェクト
・「year <= 2011」ではないオブジェクト

どちらかよくわからないのは、filterがあいまいな言葉だからだ。これでは「選択する」のか「除外する」のかわからない。filterという名前は避けるべきだ。簡単に誤解を招いてしまう。
「選択する」のであれば、**select()**にしたほうがいい。「除外する」のであれば、**exclude()**にしたほうがいい。

『リーダブルコード』p.30より引用

また誤解を招かないような名前として、以下のような例がある。

  • 限界値を含める時は min と max を使う
  • 範囲を指定する時、終端を範囲に含めるのであれば first と last を使う
  • 範囲を指定する時、終端を範囲に含めないのであれば begin と end がイディオムなのでそれを使う
  • Bool 値の変数や Bool 値を返す関数には、is / has / can / should などの単語をつけて使う
  • 否定形の名前は避ける

4章 美しさ

  • 一貫性のレイアウトへするために改行したり、コードの列を整列する
  • A・B・C と並んでいるコードを他の場所で B・A・C のように並び替えずに順番を揃える
  • 関連するコードは空行を使用してまとめてブロックに分ける

5章 コメントすべきことを知る

コメントはコードを説明するのではなく、書き手の意図を読み手に知らせること

コードを書いているときにそのコードがどういう意図で書いているのかは自分自身ではもちろんわかるが、誰かがそのコードを読むときにはコードからしか情報を読み取れない。

コードから読み取れないような意図やそのコードを書いた理由などはコメントとして残し、書き手の意図を読み手へ伝えるようにする。

コメントすべきでは「ない」こと

  • コードからすぐにわかることをコメントに書かない
  • 変数や関数などの名前に対してコメントする場合は、コメントで補助するのではなくそもそもの命名(コード)を考え直す

自分の考えを記録する

  • コメントに TODO などの記法を使用して状態を知らせる
記法 典型的な意味
TODO: あとで手をつける
FIXME: 既知の不具合があるコード
HACK: あまりキレイじゃない解決策
XXX: 危険。 大きな問題がある

『リーダブルコード』p.61の表より引用

  • 定数を定義するときにはなぜその値を持っているのかという「背景」が多く存在するため、必要がありそうな定数には意図や考えをコメントに書く

読み手の立場になって何が必要かを考える

  • 「なぜこのように書いているのか」と読み手側の立場になって考え、必要である場合にコメントをつける
  • ハマりそうなコードの場合は注意としてコメントをつける
  • ファイルやクラスには全体像のコメントを書く
  • 必要であれば関数の内部でも要約コメントをつける

6章 コメントは正確で簡潔に

  • コメントはコード量が増えてしまい、読むのに時間がかかってしまうため正確で簡潔に書く必要がある
  • 複数のものを指す「この」や「それ」といったような曖昧な言葉は避ける
  • 関数は動作を正確に書き、入出力がある場合は必要によって実例を使用する
  • コードの意図を書く
  • 名前付き引数が使用できる場合は、引数の説明をコメントで書くのではなく引数の名前で伝える

Discussion