Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

More than 5 years have passed since last update.

リーダブルコード2章 輪読会

Last updated at Posted at 2019-07-23

#第一部 表面上の改善
##2. 名前に情報を詰め込む
名前つける対象:変数、関数、クラスetc

名前は短いコメントと思え。
名前に情報を詰め込む

2章の構成

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

###2.1 明確な単語を選ぶ
「空虚」な単語は避けるべき。「明確」な単語を検討しよう。

ex1/get
def GetPage(url):
...

どこからgetしてくるの?
インターネットからgetするのであれば、**FetchPage()DownloadPage()**の方が明確

ex2/size
class BinaryTree{
   int Size();
   ...
}

何のサイズなの?
ツリーの高さ?ノードの数?ツリーのメモリ消費量?
それぞれの意味合いに沿うように変更すると
TreeHeight()
NumNodes()
MemoryBytes()
などの候補があがる。

ex3/stop
class Thread{
   void Stop();
   ...
}

stopでもいいんだけど
動作に合わせてもっと明確な名前を
Kill(),Pause() etc

もっと「カラフル(明確)」な単語を探す

類語辞典を使って動作や状況によりマッチした単語を選択しよう。

行き過ぎた悪い例:PHPのexplode()とsplit()
気取った言い回しよりも明確で正確な方がいい。

###2.2 tmpやretvalなどの汎用的な名前を避ける
tmp,retval,fooなどの空虚な名前をつけずに、
エンティティ(実体)の値や目的を表した名前を選ぼう

ex4/retval
var euclidean_norm = function(v){
   var retval = 0.0;
   for (var i = 0; i < v.length; i += 1)
       retval += v[i] * v[i];
   return Math.sqrt(retval);
};

retval自体には戻り値(return value)という情報しかない。
値の意味に則した名前をつけた方がベター。
vの2乗の合計を返しているのでsum_squaresを推奨。

ex5/バグが見つけやすい
retval += v[i];
// よりも
sum_squares += v[i];
// の方が2乗がないと気づける

retvalという名前には情報はない。変数の値を表すような名前を使おう。

tmp

ex6/tmpでOKなケース
// ここでのtmpは一時的な保管。しかも、生存期間は数行なのでtmpでもOK。
// 「この変数には役割がない」ことを明確に伝えている。
if(right > left){
   tmp = right;
   right = left;
   left = tmp;
}
ex7/怠惰なtmpの使用例
// 生存期間は短いが、「一時的な保管」ではない。
// user_infoが妥当。
String tmp = user.name();
tmp += " " + user.phone_number();
tmp += " " + user.email();
...
template.set("user_info", tmp);
ex8/tmp+αで有効なケース
# もしtmpのみであれば、ファイル名なのかデータなのか不明
tmp_file = tempfile.NamedTemporaryFile()
...
SaveData(tmp_file, ...)

tmpという名前は、生存期間が短くて、一時的な保管が最も大切な変数にだけ使おう。

ループイテレータ

i,j,k,iterなどの名前はインデックスやイテレータでよく使われる。
逆にそれ以外では使用してはダメ。

ex9/通常のイテレータ(i,j,k
for(int i = 0; i < clubs.size(); i++)
    for(int j = 0; j < clubs[i].members.size(); j++)
        for(int k = 0; k < users.size(); k++)
            if(clubs[i].members[j] == users[k])
                cout << "user[" << j << "] is in club[" << i << "]" << endl;
ex9/わかりやすいイテレータ(ci,mi,ui
// i,j,jをci,mi,uiに変更するだけでミスを削減しやすくなる
for(int ci = 0; ci < clubs.size(); ci++)
    for(int mi = 0; mi < clubs[i].members.size(); mi++)
        for(int ui = 0; ui < users.size(); ui++)
            if(clubs[ci].members[mi] == users[ui])
                cout << "user[" << mi << "] is in club[" << ci << "]" << endl;

汎用的な名前のまとめ

tmp,it,retvalのような汎用的な名前を使うときは、それ相応の理由を用意しましょう

###2.3 抽象的な名前よりも具体的な名前を使う
任意のTCP/IPポートをサーバーがリッスンできるかを確認するメソッドの最適な名前は?
ServerCanStart() or CanListenOnPort()

例:DISALLOW_EVIL_CONSTRUCTORS

訳:悪のコンストラクタを禁止する
C++の仕様で、クラスはコピーコンストラクタと代入演算子を再定義しないと、デフォルトの設定が使われ、メモリリークなどのリスクがある。

#####問題

  • C++の仕様を悪としてそのままEVILを使用していること
  • コンストラクタを扱ってない
  • 禁止(DISALLOW)する対象が具体的ではない

解決策
DISALLOW_COPY_AND_ASSINGN(コピーと割り当てを禁止する) に変更

例:--run_locally

あるコマンドのオプションとしての例。
実際にはプログラムがデバッグ情報(ログ)を表示するためのもの。
ただし、処理が遅くなるためローカルマシンでテストを実行する際に使用していた。
リモートではパフォーマンス重視なので使用しなかった。

#####問題

  • 名前から処理内容を理解できない
  • リモートでも動かすのにlocallyって変
  • ローカルでパフォーマンステストを実行する際にオプションを使用しない場合もある

解決策

  • --extra_logging(追加ログ)に改名
  • 別の用途があるなら、無理に1つにまとめようとしないでオプションを増やして対応

###2.4 名前に情報を追加する
再喝:名前は短いコメント

ex10/名前に情報を追加
// 例:af84ef845cd8
string id;

// 16進数の値が入っているなら以下の方がわかりやすい
string hex_id;

値の単位

時間やバイト数のように計測できるものであれば、変数名に単位を入れよう。

ex11/ページの読み込み時間を計測
// msを返すため正常に動作しない
var start = (new Data()).getTime(); // ページ上部
...
var elapsed = (new Date()).getTime(); - start; // ページ下部
document.writeln("読み込み時間:" + elapsed + "");
ex12/msに対応
var start_ms = (new Data()).getTime(); // ページ上部
...
var elapsed_ms = (new Date()).getTime(); - start_ms; // ページ下部
document.writeln("読み込み時間:" + elapsed_ms / 1000 + "");

#####改善例

  • Start(int delay)
    • Start(int dalay_secs)
  • CreateCache(int size)
    • CreateCache(int size_mb)
  • ThrottleDownload(float limit)
    • ThrottleDownload(float max_kbps)
  • Rotate(float angle)
    • Rotate(float degrees_cw)

その他の重要な属性を追加する

名前に付与する情報は単位だけではなく、
危険や注意を喚起する情報も含まれる

セキュリティが確保してない情報を含める場合は
untrustedUrl,unsafeMessageBody

セキュリティが担保された状態になれば
trustedUrl,safeMessageBody
と置き換える

#####改善例

  • password
    • plaintext_password
  • comment
    • unescaped_comment
  • html
    • html_urf8
  • data
    • data_unlenc

###2.5 名前の長さを決める
長い名前は避ける

#####デメリット

  • 覚えにくい
  • 画面を大きく占領
  • 折り返しが必要でコード行が増える

####長い名前を避ける基準

  • 変数の使い方によって違ってくる。
  • ガイドラインはある。

スコープが小さければ短い名前でもいい

その変数が有効な範囲の広さ(名前が見えるコードの行数)
によって長さは変わってくる。

ex13/名前が短くても問題ない
// 理解できるコードがすぐ近くにある
if(debug){
   map < string, int > m;
   LookUpNamesNumbers(&m);
   Print(m);
}
ex14/名前が短いとNG
// クラスのメンバ変数やグローバル変数はNG
LookUpNamesNumbers(&m);
Print(m);

長い名前を入力するのは問題じゃない

入力しにくいは理由にならない。
単語補完機能を使おう。

頭文字と省略形

例:BackEndManagerをBEManager
その省略内容を新人が理解できるか?
で判断すると使用基準がわかりやすい。

#####良い例

  • evaluation
    • eval
  • document
    • doc
  • string
    • str

BEManagerは悪い例。

不要な単語を投げ捨てる

#####良い例

  • ConvertToString
    • ToString
  • DoServerLoop
    • ServerLoop

###2.6 名前のフォーマットで情報を伝える
googleのフォーマット:
アンダースコア、ダッシュ、大文字で名前に情報を詰めている

ex15/googleのフォーマット例
static const int kMaxOpenFile = 100; // #defineマクロと区別:CONSTANT_NAME

class LogRender{ // クラスはキャメルケース
    public:
        void OpenFile(string local_file); // 変数はスネークケース
    private:
        int offset_; // 普通の変数と区別
        DISALLOW_COPY_ASSIGN(LogRender);
}
ex16/stats
// メンバ変数はmember_にする
// という規約を守っていたため、
// statsはメンバ変数ではなく、ローカル変数と判断できる
stats.clear(); // メンバ変数ならstats_となる

その他のフォーマット規約

ex17
// new で始まるコンストラクタは大文字で始まる
var x = new DataPicker();
// 通常の関数は小文字で始まる
var y = pageHeight();

// jQueryのオブジェクトを格納する変数は頭に$を付与
var $all_images = $("img");
// これはノーマル
var height = 250;
ex18
<!-- idはアンダースコア、classはハイフンが有力 -->
<div id="middle_column" class="main-content">

###2.7 まとめ

  • 明確な単語を選ぶ
  • tmpやretvalなどの汎用的な名前を避ける
  • 具体的な名前を使って、物事を詳細に説明する
  • 変数名に大切な情報を追加する
  • スコープの大きな変数には長い名前をつける
  • 大文字やアンダースコアなどに意味を含める
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?