リーダブルコード 未来の自分を助ける 03

今回はリーダブルコードの3章より「読みやすいコード」を書く方法として「誤解されない名前」について触れていきます。

www.oreilly.co.jp

本シリーズ:リーダブルコードの解説 各記事のリンクはこちらをクリック リーダブルコード 未来の自分を助ける 01 - こだわりデベロッパーズノート
リーダブルコード 未来の自分を助ける 02 - こだわりデベロッパーズノート
リーダブルコード 未来の自分を助ける 03 - こだわりデベロッパーズノート
リーダブルコード 未来の自分を助ける 04 - こだわりデベロッパーズノート
リーダブルコード 未来の自分を助ける 05 - こだわりデベロッパーズノート
リーダブルコード 未来の自分を助ける 06 - こだわりデベロッパーズノート

内容紹介

3章 誤解されない名前

  • 3章 誤解されない内容
    • 3.1 例:filter()
    • 3.2 例:Clip(text, length)
    • 3.3 限界値を含めるときはminとmaxを使う
    • 3.4 範囲を指定するときはfirstとlastを使う
    • 3.5 包括/排他的範囲にはbeginとendを使う
    • 3.6 ブール値の名前
    • 3.7 ユーザの期待に合わせる
    • 3.8 例:複数の名前を検討する
    • 3.9 まとめ

3章では2章で取り扱った「命名」に対して、命名時に気を付ける点を深掘りして

  • どのような名前だと「誤解される」のか?
  • どういうことに気を付ければ「誤解されない」ようになるのか?

を解説しています。

本章はリーダブルコードにて具体例を上げているものが多いため、それらをささっと紹介しつつ「3.6 ブール値の名前」「3.7 ユーザの期待に合わせる」の内容を取り上げて、もう少し分かりやすくなるようにブレイクダウンします!

リーダブルコード「3.1 ~ 3.5」の具体例

filterをかけたら選択される?除外される?

DBへの問い合わせ、C#LINQJavaのStreamAPIなどでデータをフィルタリングする場合、素直に「filter」と命名するのは避けましょう。 何故なら、フィルタリングは「手段」だからです。

なぜこのデータをフィルタリングしたのでしょうか? 特定のデータが欲しかったから?特定のデータを省きたかったから?

特定のデータが欲しかったのであれば、それは沢山あるデータの中から一部を「選択」しています。つまり目的である「select(選択)」の方が明確です。

特定のデータを省きたかったのなら、それは沢山あるデータの中から一部を「除外」しています。つまり目的である「exclude(除外)」の方が明確です。

限界値(境界値)にはminとmaxを利用する

限界値には「min(minimum)」「max(maximum)」を利用することで「最小のhoge」、「最大のfuga」と最小値、最大値が含まれることを表現できます。

限界値が含まれるのか?含まれないのか?を取り違えて起こす「off-by-oneエラー」は本当にあるあるの不具合です。

Off-by-oneエラー - Wikipedia

この「off-by-oneエラー」を防止するためにも「min」「max」を利用して値が含まれることを明確に表現しましょう。境界値テストも大事です!忘れずに行いましょうね!

範囲を指定する場合の工夫

○○以上、××以下

範囲を指定したい場合に「○○以上、××以下」を表現したい場合は「first」「last」を使用しましょう。

first

最初は
ここ
                        last

最後は
ここ

「first(最初)、last(最後)」を利用することで「最初と最後が含まれる」つまり「以上、以下」であることが表現できます。

○○以上、××未満

終点を含めたくない場合の「○○以上、××未満」を表現したい場合は「begin」「end」を使用しましょう。

begin

開始
                        end

終了

ファイルが終了する文字コードのことを「End Of File(略してEOF)」と言います。EOFに到達することでファイルから文字列の読み込みが終了します。そして、ファイルから読み込んだ文字列はEOF直前の文字までになります。

このようにITでは「End」で「Endの直前までが対象」と解釈することが多いです。そのため「begin」「end」を利用することで「○○以上、××未満」であることが表現できます。

3.6 ブール値の名前

ブール値に名前を付けるときは「trueの意味が明確となる名前」を付けましょう。

変数名、引数名

以下の変数名は、trueとなったときの意味が明確ではありません。

boolean readPassword;
  • パスワードを読み込む必要がある
  • 既にパスワードを読み込んでいる

どちらを表しているのか判断に悩むため、実際に変数が利用されているコードを読む必要があります。

  • パスワードを読み込む必要があることを表したい:「needPassword」
  • 既にパスワードを読み込んでいて認証を行う:「isAuthenticated」

とすると、trueとなった時の意味が明確になります。

メソッド名

メソッド名にも同様のことが言えます。

public boolean validationCheck( ... ) { ... }
  • trueを返したら問題が無い
  • trueを返したらバリデーションエラーが起きている

どちらであるか判断に悩みます。そもそも「validationCheck」という名前も何をチェックしているのか分かりません。

メールアドレスのバリデーションチェックを行っているのであれば「isMailAddress()」とすれば、trueが返ってきたらメールアドレスとして問題ないと分かります。

boolean型に利用する接頭語一覧

よく見かけるboolean型の接頭語をまとめてみました。

# 接頭語 意味 trueの場合 falseの場合
1 is 状態 isDelete 削除されている 削除されていない
2 can 可能、不可能 canDelete 削除できる 削除できない
3 has ある、ない hasLicence 免許を持っている 免許を持っていない
4 contains 含む、含まない containsKey Keyが含まれる Keyが含まれない
5 shoud 必要、不要 shoudPassword パスワードが必要 パスワードが不要
6 need 必要、不要 needPassword パスワードが必要 パスワードが不要
7 use 利用する、利用しない useSsl SSLを利用する SSLを利用しない
8 exists 存在する、存在しない userExists ユーザが存在する ユーザが存在しない

3.7 ユーザの期待に合わせる

ITに根ずく文化が原因で自然とコードに期待を持ってしまう場合があります。この期待が原因で誤解を招くことがあります。

このような先入観を取り除くのは非常に難しいです。そのため、無理に頑張らずに受け流してしまいましょう!

頑張らずに「誤解を招いてしまう場合は名前を変えて対応」です!

get****()

getで始まるメソッドはメンバの値を返すだけの「軽量なメンバアクセスメソッド」をイメージします。そのため、getメソッドが重たい処理をしていると思いません。 値を取得する際にコストが重い処理を行う場合は「get」を使わずに「compute」などに変えましょう。

また、getメソッドは値を戻り値で返す処理をイメージします。そのため、getメソッドを利用して値が変更される部分は戻り値を受け取った変数だけで、引数で入力した値が変わるとは思いません。 引数で入力した値に副作用がある場合は「get」を使うのはやめましょう。

size()

大体の言語の標準ライブラリでは「size()」の計算量が「O(1)」となるように実装されています。そのため、sizeメソッドの計算量がデータ件数に依存するとは思いません。 sizeメソッドで重い処理を行うのはやめましょう。

引数の副作用で値を返す場合はreturnしない

getメソッドの解説ともリンクしますが、メソッドが戻り値を返している場合、そのメソッドが処理を行った結果は戻り値で受け取ると考えます。

逆に、戻り値が無いメソッドの場合は、そのメソッドが何か値を変更したとき、その変更を受け取れるものは入力した引数の副作用しかありません。

そうすると、メソッド戻り値の有無によって以下の期待が生まれます。

  • 戻り値があるから「引数は変更されない」
  • 戻り値が無いから「引数が変更されるかもしれない」
    • もし、このメソッドが内部で値を変更していたら、引数が変更されていないと呼び出し元が処理結果を受け取れない

戻り値もあるけど、引数も副作用で変更しているという場合は、上述した期待で「引数は変更されない」と思っていると不具合を作り込んでしまいます。

引数に副作用を起こしている場合、そのメソッドは戻り値が無い方が誤解が起きません。

まとめ

本記事では、リーダブルコード3章の内容を解説しました。

3章の内容も明日から即実践できるものになっています。まずはできる範囲から取り入れてみてください。

本記事の中で記載しました中でも「○○Check」は特によく見る機会が多いです。

「○○Check」はチェックした結果が「良いのか?」「悪いのか?」が分かりにくいことが多いので気を付けましょう!ほとんどの「○○Check」は「is○○」「can○○」「has○○」で解決すると思います!