読者です 読者をやめる 読者になる 読者になる

Clean Code アジャイルソフトウェア達人の技メモ

Clean Code アジャイルソフトウェア達人の技

Clean Code アジャイルソフトウェア達人の技

前書き

  • コードを読んでいて関数等が「ここにあるだろうと推測した場所」に無い時、リファクタリングしてあるべき場所に移動すべき
  • 今曰の-針、明日の+針。早起きは三文の得。今日リファクタリングをやれ
    • レブランの法則「後で、とはやらないに等しい」
  • 言語がプログラムを単純に見せるのではなく、プログラマが言語を単純に見せる

意味のある名前

  • 似た概念に似た綴りを与える
  • 1文字の変数名は小さなメソッドやブロック内でのみ用いる
    • 変数名の長さはスコープに対応する
    • 変数名に意味のある文脈を与える(state => addrState)
    • しかしaddrと付けまくるとIDEの補完機能を邪魔するので Address のインスタンス変数にする等して文脈を与える

関数

  • 関数内のインデントレベルは1つか2つ
    • 関数を増やすということは処理に名前を付けるので。ドキュメントとしての価値を持つことになる
  • 関数の中で複数の抽象レベルのことを一緒に行うと混乱を生じる
  • 抽象度が低くなる順番にコードを並べる
  • switchが必要な場合にはファクトリメソッドでディスパッチする
  • 長い名前を付けるのを怖がらない。
    • 内容をよく表す長い名前は不可解な短い名前より優れている。
    • エディタの補完機能を使う
  • 引数は理想的には0(ニラディック)
    • 1(モナディック)、2(ダイアディック)までは良いが、それ以降は避ける
    • 関数名と引数の間には共通の文脈が必要
    • assertEquals(expected, actual)というテストの関数があるとき、expected に actual を渡してしまうなど、学習コストが高くなる
      • writeField(outputStream, mame) は outputStream.writeField(name) として引数を減らす
    • 引数が増えるなら、いくつかを1つの概念としてラップする
      • makeCircle(double x, double y, double radus) => makeCircle(Point center, double radius)
  • 関数は1つのことを行うと保証する
    • 副作用があると追いかけるのが難しい
  • 戻りコードで例外を判別する時は通常の処理内にifによるネストが発生するので、try/catchで例外を返すようにすれば通常の処理とエラー処理を分離することができる
    • それでも処理が混ざってしまうので、通常の処理とエラー処理を関数化して分離する
  • 一発で上記のようなコードを書けると思わない。リファクタリングすべし。

コメント

  • コメントは古くなり、不正確なコメントは人を惑わす
  • 「ダメなコードをコメントで取り繕ってはいけない。書きなおすのだ」
  • 「コメントを書くのであれば、そのときは顔を歪め、あなたの表現力のなさに敗北感を覚えるべきです」

クラス

  • 凝集性を高くする
    • 全変数が全メソッドに使用されるクラスは凝集性が最大限に高い
    • 凝集性が高ければ、全体として1つのロジックを成す => 1クラスで1つのことを行なっている
  • 単一責務の法則
  • クラスの責務を表すクラス名をつける
    • クラス名が曖昧なほど責務が多くなる(Processorなど)

テスト

  • 1つのテストに1つのアサート
  • TDD三原則 第二則 コンパイルが通り、適切に失敗する単体テストができるまでは、次の単体テストを書いてはならない
  • 外部のライブラリを使用する時は「学習テスト」を書くと良い
    • 最終的にはそのライブラリのAPIを使うのだから、ついでにライブラリのテストを書く
    • 新しいバージョンがリリースされたときに、自分たちが把握している振る舞いに変更がないかテストできる

正常ケースのフロー

  • nullを返さない
    • nullチェックが多くなってしまうので例外を発生させることで対処

オブジェクトとデータ構造

  • データ転送オブジェクト(DTO)
    • public変数のみを持ったクラス、振る舞いがない
    • ビジネスレイヤー等、レイヤー間の受け渡しをする
  • デメテルの法則
    • オブジェクトを使用する場合、そのオブジェクトの内部について知るべきではない
    • 戻り値のオブジェクトのメソッドを呼び出さない
    • 内部構造を理解する必要がある。
    • 法則を守ろうとすると辛い http://d.hatena.ne.jp/IwamotoTakashi/20090508/p1

横方向の書式化

  • 代入で右辺の位置を揃える必要はない
    • そもそも、揃える必要があるほど変数代入のリストが長いのが問題
  • スペースは分離を意味する
    • 関数と引数は強く関連しているので、スペースを入れない
  • ある関数が別の関数を呼び出している時、呼び出している関数を垂直方向に近い位置に置く
  • 変数宣言は使用される位置から近いところで行う