# クリーンコード 第5章、第6章 ## 第5章 書式化 ### 書式化の目的 **コードの書式化=情報伝達:プロの開発者として最も重要なこと** コードは変更されても、コーディングスタイルは残る。読みやすさは良いコーディングスタイルから! ### 縦方向の書式化 実際に使用されている7つのプロジェクト(1プロジェクトで約50000行程度)の場合、 クラスのサイズの多くは100行~多くて500行の範囲内に収まっている。 巨大なクラス1個よりも、小さなまとまりを持つ複数個のクラスで構成するほうが分かりやすい。 #### 新聞に例える 新聞は、見出し、リード文、本文と続く体系的な構造で、読者の興味を引き付けている。 プログラムも、単純かつ説明的な名前、高レベルの概念とアルゴリズム、低レベルの関数と詳細…と、読み進めるごとに詳細がわかる体系的な構造を取ることが有効である。 #### 垂直概念分離性 * コードを作るそれぞれの行が式と節を成し、ひとまとまりの行があるまとまった考えを成す。 * ひとまとまりの行が終わるごとに空行を入れる。 **空行は、新しい別の概念の合図**となる。読み手は空行に続く行に引き付けられる。 #### 垂直密度 関連性の密接さを表す指標。ソースの各行が強く関連している場合、垂直密度は高い。 無駄なコメントは、垂直密度の低下につながってしまう。 #### 垂直距離 密接に関連した概念は、できる限りまとまっていなければならない。 * **変数宣言**:変数を宣言する時は、その**変数が使用されるなるべく近い位置で行う**べきである。関数の最初、あるいはループ文の中、まれに長いfor文の最初で宣言を行う。 * **インスタンス変数**:**クラスの頭**で行う。非常に多くのメソッドで使用されるため、合理性がある。重要なのは、**良く知られた場所に置く**ことである。 * **依存関数**:関数が別の関数を呼び出している場合、その関数は**垂直方向に近い位置**に置くべきである。また、可能な限り**呼び出し側を呼び出される側の上に置く**べきである。 * **概念の密接な関係**:依存性以外にも、同様の操作を行う場合など、**関連性が高い概念はなるべく近い位置に置く**。 ### 横方向の書式化 縦方向の書式化は、1クラスの大きさ及び関数・変数の関連性に基づいていた 対して横方向の書式化は、1文の長さやスペース、インデント等に基づくものである。 縦方向と同様に、実際に使用されている7つのプロジェクトの1行の文字数の割合を調べると、10文字未満のものが1~10%、20~60文字で1%前後、60~80文字で0.7%前後なのに対し、80文字以上では0.1%未満へと急速に割合が低下していた。 すなわち、**大半のコードが80文字未満に収まっており**、それを上回る文字数はごく少数である。 #### 水平分離性と密度 スペースの使い方は、要素の関連性に基づいて決まる。 * 例えば演算子を用いた計算(例:1 + 1 = 2)の場合、計算する**それぞれの要素及び、左辺と右辺を明確にするため、スペースを入れる。** * 対して関数名とかっこ(例:public String train(){})の場合、**両者には密接な関連があるため、両者間にスペースは入らない。** * また、**計算の優先度に応じて演算子と値のスペースの有無を区別**する方法もある。(**スペース無し:優先度高**)ただ、自動フォーマットを行うとスペースが平等に入ってしまうため、失わなれてしまう傾向にある。 #### 水平方向の位置合わせ 同じような処理に対して、文字数の長さに寄らず水平方向の位置を統一して、特定の構造を強調する方法。 式の構造の強調には役立つが、誤った点を強調し真の意図に目を向けられない弊害がある。型や演算子を見落とす原因にもなる。 結局オートフォーマットが普及するに従い、水平方向の位置合わせは衰退した。 ### インデント ソースファイルはコード内で階層構造を成し、それぞれがスコープを持つ。 その階層構造を表したものがインデントである。 もしインデントが無く詰めたコードになると、理解がかなり困難になる。 インデントは構造をすぐにはっきりと見分けるために必須である。 短いif文やwhile文等、1行にまとめてしまいたい時もあるが、 インデントで区切るほうが理解向上につながる。 ### チームの規則 チーム内の開発者は、1つの書式規則に従うべきである。 メンバー毎にバラバラではマージの際に困る。 読みやすく、整合性がとれて、よどみのない書式が必要である。 ## 第6章 オブジェクトとデータ構造 ### データの抽象化 **データはなるべく抽象化する**のが望ましい。 具体的な値に対しただ単純にオブジェクトを作り、getter, setterを用意するだけでは、カプセル化によるデータの隠蔽を行ったとはいえない。 **データを抽象化し、内部にどのようなデータが保持されているのかが分からないようにする仕組み**を真剣に考慮する必要がある。 ### データ・オブジェクトの非対称性 **データ構造:データ公開のための構造。意味を持った機能は無い。** **オブジェクト:裏にあるデータを隠して抽象化し、データを操作する機能を提供するもの。** データ構造とオブジェクトは**補完関係**にあり、両者の特徴は**全く反対**である。 データ構造を利用する手続き型のプログラムと、オブジェクトを利用するオブジェクト指向型のプログラムの両者にも、**相反する明確な違いがある。** * **手続き型プログラム**:データ構造のみを表すクラスと、振る舞いを表すクラスが分離している。 * 振る舞いを表すクラスに新しい関数を追加:既存のデータ構造に影響なし。 * 新しいデータ構造を追加:振る舞いクラス内の関数全てに**新しいデータ構造の場合を追加する**必要がある。 * **オブジェクト指向型プログラム**:各クラス毎にデータ構造とその振る舞いを持つ。 * 新しいクラスを追加:既存のクラスに影響なし。 * 新しい関数を追加:全クラスに対して**新しい関数を追加する必要**がある。 データ型を追加することが多いのか、それとも新しい関数を追加することが多いのか。**プログラムの性質に応じて、両者を使い分ける必要がある。** ### デメテルの法則 オブジェクト指向型におけるデータの隠蔽について、**そのオブジェクトの内部を知るべきではない**とした法則。 クラスcのメソッドfは、**次のオブジェクトのメソッドのみを呼び出す**べきである。 * cそのもの * fで生成されたオブジェクト * fの引数で渡されたオブジェクト * cのインスタンス変数に保持されたオブジェクト #### 電車の衝突 **許可されたメソッドから返されるオブジェクトのメソッドの呼び出し(呼び出しの呼び出し)を行ってはならない。** 呼び出しの連鎖はあたかも連結された車両のようにみえるため、電車の衝突と呼ばれることがある。 アクセサ関数はオブジェクトの呼び出しなのか、データ構造なのかを分からなくしてしまい、事態をややこしくさせる。 #### 混血児 **オブジェクトとデータ構造が混ざってしまう混血児**が生成されることがある。 こうした混血児は、**privateなはずであるオブジェクトに対して、アクセサとミューテータを用意することで、実質的にpublicなデータ構造として手続き的にアクセスするようになる。** 混血児は、オブジェクトとデータ構造の両者のデメリットがそのまま跳ね返り、関数も新しいデータ構造も追加が難しくなる。 ### データ転送オブジェクト public変数のみを持ったデータ転送オブジェクトは、典型的なデータ構造クラスである。 データベースから読み込んだ生データを変換していく過程の最初の段階として利用される。 #### アクティブレコード データ転送オブジェクトに、ナビゲーション用の典型的なメソッドが存在するものである。 これらの構造をオブジェクトのように扱おうとすると混血児を生むため、別でオブジェクトを用意する必要がある。 ###### tags: `読書`