話しをしたいポイントは3つ。
- 条件分岐を避けましょう
- 一時変数の使い方に注意しましょう
- 状態の使い方に気を使いましょう
これを徹底することで、バグの入り込む余地を最小限に保つプログラミングをしましょう。
バグを生む最大の要因は条件分岐です。どこでもバグの原因調査というのはすると思いますが、その中から条件分岐のバグをのぞいてみてください。半分くらいは減るのではないでしょうか。
- バリデーション
- ルール
- フロー制御
フロー制御を明示的に行いましょう。フラグによるフローのコントロールは、凝集性でいう論理凝集にあたり、プログラムを複雑にするガンです。
あわせて読みたい 条件分岐とのつきあい方
条件を式として追い出しましょう。そして、その条件の表現したい名前をつけましょう。名前付けに迷ったら、日本語でコメントを書くならどう書くかを考えてください。そして、コメントの内容を要約して名前をつけましょう。
変数の使い方によって、変数の役割を分類することができます。
- 別名 (alias)
- 状態 (state)
- 単なる可変の入れ物 (mutable variable)
別名は多くの場合、好ましい変数の使い方です。別名を使うことで、コードが説明的に、明示的になります。
値も関数も、時間が経っても変化しない。明示的状態は、時と共に変化するものをモデル化する一法である。その中身が更新できるような容器を提供することである。 via 「コンピュータプログラミングの概念・技法・モデル」
避けられない明確な理由がない場合、なるべく再代入を避けましょう。複数箇所で値を保持する入れ物として変数を使いたいことがあるかもしれません。その場合も、パフォーマンス上の問題がないかぎり、式を呼び出して再計算させましょう。
データベースへのアクセスやファイルへのアクセスが発生する場合はこのかぎりではありません。ただし、その場合もキャッシュをさせるなどの手段で繰り返しのアクセスを避けることはできます。さらに、キャッシュが必要なケースはおそらく何らかの新しいクラスが必要だというシグナルです。
条件をのぞいたときに、バグを起こすことができる一番強力な要因が状態です。
状態はデータベースに永続化されたり、オブジェクトが内部的に管理したり、いろいろなところに表れます。手続き型やオブジェクト指向プログラミングをしているかぎり、実質的に避けることはできないですが、自分は今状態を扱っているのだということを意識しながらプログラミングしましょう。
また、そこでは本当に状態を使ったプログラミングをすべきかを自問自答(もちろん、他の人に意見を聞いても OK)しながらプログラムを書きましょう。
上記を守って良い設計を保つのは大切です。でも、いろいろな事情で短期的にはそれを徹底しきれないケースもあると思います。そんなときに重要なのは「悪い設計は悪く見えるようにしておく。」ということです。
悪い設計をごまかすために短くシンプルな名前をつけたりすると、悪い設計であることが隠されてしまいます。悪い設計であるときは、明示的に悪いように書いておきます。そして、少しでも短い期間でそこを改善できるようにしてください。
RT @KentBeck: if you don't have a good name for it, give it a bad name. a really, really bad name so you'll fix it later.