前件否定

水がないと生きられない。水さえあれば生きられる。

形式

PならばQである。Pではない。だからQではない。

補足

「PならばQ」が暗黙の前提となっていることもある。
「PならばQ かつ QならばP」の場合は間違いではない。

別名

関連

参考

前件否定 - Wikipedia

書籍「リーダブルコード」の紹介

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)
作者: Dustin Boswell,Trevor Foucher,須藤功平,角征典
出版社/メーカー: オライリージャパン


きれいなプログラム、良いプログラムのための本というのは、今までも色々出版されている。いろんなプロジェクトでコーディング標準が作られて「変数の命名規約」や「グローバル変数禁止」とか細かく書かれている場合もある。

この本が優れているのは

良いコードとは『他の人が再短時間で理解できるようなコード』である

という考えを常に中心にして、表面的な”お作法”ではなく、実際に効果のある考え方を分かりやすく紹介している所だと思う。

  • なぜ短いコードがよいのか?短ければよいのか?
  • 括弧や改行の位置はどうする?
  • どんなことをコメントに書くのか?
  • メソッドを分ける基準は?
  • なぜきれいなコードが必要なの?

すべて、他の人(数日後の自分を含む)が理解しやすいプログラムを作るためという基準で本書は統一されている。 コーディングについての書籍ではあるが、この理念は設計にも活かして行けると感じた。

翻訳も含めて非常に読みやすい、軽めの文章と挿絵で書かれているので1週間もあれば読めるのもうれしいところである。

「理解」とは

本書では「コード理解する」とは「変更を加えたり、バグを見つけたりできる」という、単純に読んで何となく処理を追えるというレベル以上の意味だとしている。

Wikipediaでは

理解(りかい)とは、物事の理由、原因、意味を正しく知ることである。 http://ja.wikipedia.org/wiki/%E7%90%86%E8%A7%A3

となっている。

さらに調べると”理”という言葉には「整える、収める、分ける」という意味があり、”解”は「解(と)く」という読み方がある。

複雑な事柄を分ける、解きほぐす。そして、正しい形へ整える。正しい場所へ収める。それが「理解する」ということではないか思った。

名前の付け方

明確な単語を選ぶ。

stop()は曖昧。取り消しできない場合はkill()、あとで再開できる場合はpause()の方が明確。

具体的な名前を使う。

  • serverCanStart()よりcanListenOnPort()の方が明確。
  • 具体的な個別の項目に分けるのも有効。

汎用的な名前を避ける。

retvalやtempより、具体的に処理内容に沿った名前を付ける。

名前に情報を追加する。

  • 時間やバイト数の単位
  • 文字変数がhtmlエスケープされているか?
  • パスワードを含む変数が暗号化されているか?

省略形についての基準

「新しいメンバがその名前の意味を理解できるか?」

変数のスコープの大きさと名前の長さを合わせる

短い範囲の変数は短い名前。

不要な単語は削れる

convertToString() -> toString()

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

  • 定数:大文字でアンダースコア区切り
  • クラス:先頭大文字
  • メンバ変数:アンダースコアを末尾につける など。

誤解される名前に気をつける

list.filter(from,to) は

  • 指定範囲の要素を抽出する?
  • 指定範囲の要素をフィルターで除外する?
  • 未満?以上?

使う人の期待に沿う

getXxx() は単純なアクセサと思われる。 重い処理を含む場合はcomputeXxx()など表現を変える。

コードの美しさについて

なぜ美しさが大切か?

  • 流し読みが出来る => 理解がしやすくなる。
  • 見た目の改善によってコードの構造も改善できる。

目立つノイズが消えると、本当の問題が見えてくる

というのもある

3つの原則

  • 読み手が慣れているパターンと一貫性のあるレイアウトを使う
  • 似ているコードは似ているように見せる
  • 関連するコードをまとめてブロックにする。

コードの列を整列する。

public class Foo {
    public static Bar b1 = new Bar(
        100,
        "abc",
        125.7,
        true);

    public static Bar b2 = new Bar(
        115,
        "",
        10.2,
        false);

    public static Bar b3 = new Bar(
        10,
        "xyz",
        103.0,
        false);
}

縦をそろえて見やすくする

public class Foo {
    public static Bar b1 
        = new Bar(100,  "abc",  125.7,  true);

    public static Bar b2 
        = new Bar(115,  "",     10.2,   false);

    public static Bar b3
        = new Bar(10,   "xyz",  103.0,  false);
}

メソッドを使った整列

Member vo = new Member();
vo.setFirstName("Robert");
vo.setLastName("Plant");
vo.setPart("Vocal");
members.add(vo);

Member gt = new Member();
gt.setFirstName("Jimmy");
gt.setLastName("Page");
gt.setPart("Guiter");
members.add(gt);

Member drms = new Member();
drms.setFirstName("John");
drms.setLastName("Bonham");
drms.setPart("Drums");
members.add(drms);

メソッドを追加

private void addMembers(String firstName, String lastName, String part) {
    Member member = new Member();
    member.setFirstName(firstName);
    member.setLastName(lastName);
    member.setPart(part);
    members.add(member);
}

addMembers("Robert",    "Plant",    "Vocal");
addMembers("Jimmy",     "Page",     "Guiter");
addMembers("John",      "Bonham",   "Drums");

整列すべき?

手間が増える? 試しにやってみたらいい。おそらくそれほど手間はかからない。 手間になるようならやめたらいい。

一貫性と意味のある並び

アルファベット順、重要度順、対応するHTMLフォームの順、なんでも良いので同じ並び順を使うべき

コードを「段落」に分割する。

// ユーザのメール帳をインポートして、システムのユーザと照合して、まだ友達になっていないユーザの一覧を表示する。
friends = user.friends();
friendMails = …
contacts = importContacts(…);
contactMails = …
nonFiriendEmails = …
suggestedFriends = …
display['xxx'] = xxx

長い手順を分割し、それぞれのブロックにコメントをつけ、適切に空行を入れる。

// ユーザのメールアドレスを取得する。
friends = user.friends();
friendMails = …

// ユーザのアカウントからすべてのアドレスをインポートする
contacts = importContacts(…);
contactMails = …

// まだ友達になっていないユーザを探す。
nonFiriendEmails = …
suggestedFriends = …

// 友達になっていないユーザを表示する
display['xxx'] = xxx
…

流し読みがしやすいように。(流し読みをしても誤解されないように) それぞれの段落ごとはメソッド分割の候補となる。

個人的な好みと一貫性

一貫性のあるスタイルは「正しい」スタイルより大切