# クリーンコード 第10章,第11章 ## 第10章 クラス Javaの標準コーディング規約によれば、クラスは変数のリストで始める必要がある。 次にpublic staticな定数、private staticな変数、privateなインスタンス変数が続く。publicな変数は通常は避けるべきである。 publicな関数は変換リストの後に置く。筆者はpublicな関数から利用されるprivateユーティリティー関数をpublic関数の後に置いている。これは、下に向かって詳細化する規則に合致している。 なお、テストからアクセス可能にするためにprotectedを利用する場合もある。 ### クラスは小さくしなければならない! クラスの規則も、関数と同じく小さくすることである。 関数の場合は物理的な行数を測定した。クラスは責務の数で測定する。 わかりやすい名前をつけなければ、責務が大きすぎる状態になりがちである。 クラスの名前は、25語以内(日本語であれば100文字以内)で、曖昧な要素や分岐を含む言葉(もし、そして、あるいは、しかし)を用いずに作成するべきである。 この基準を上回る場合、責務の置きすぎと言える。 #### 単一責務の原則 クラス、モジュールは、変更の原因となるものが一つでなければならない。これを単一責務の原則(SRP)という。 クラスはただ一つの責務(変更の原因となるもの)を持たなければならない。 多くの開発者が小さなクラスが溢れかえって全体を見失うのではないかと危惧している。しかし、小さなクラスの集まりは、大きな少数のクラスで形成されたシステムより可動部分が少ないメリットがある。 全体を構成するのであれば、小さなクラスの方が望ましい。 #### 凝集性 凝集性とは、クラス内に置かれているメソッドが操作する変数の多さである。変数が多いほど凝集性は高くなる。 こうした凝集性の高さは、変数とメソッドの依存度が高く、全体として一つのロジックを成すため良いとされる。 関数を小さくする鉄則を守ればインスタンス変数が急増してしまうが、ほとんどの場合は大きめのクラスから最低1クラスは分離可能である合図である。 その場合には、変数とメソッドを2つ以上のクラスに分割して凝集性を高めるべきである。 #### 凝集性に目を凝らすと、大量の小さなクラスが生まれる 小さな関数やインスタンス変数を大量に作り、凝集性を最大限高められるように小さいクラスに分離していく作業を繰り返すことにより、小さなクラスが大量に生まれる。 これによりプログラムはより適切に構成され、透明な構造を持つようになる。 ### 変更のために最適化する 変更時は、常にシステム内の別の部分が動かなくなってしまうリスクがある。洗練されたシステムでは、クラスは変更に対するリスクが最小限になるように構成される。 開放・閉鎖原則(クラス拡張時には開かれており、変更時に閉じていなければならない原則)に適するクラス構成であれば、変更による影響を最小限に抑えられる。 #### 変更から切り離す 抽象クラスの利用は、利用者のクラスが具象クラスとの依存性が高い場合、詳細の抽象クラスの変更の際に影響を受ける恐れがある。 インターフェースを作成して変更と切り離すことで、具象クラスへの依存を防ぐことができる。これにより柔軟性が高まり、再利用が簡単にできるようになる。 ## 第11章 システム ### システム作りと街づくり 街づくりでは、数人が全体像に対する責任があり、残りは詳細部分に関心を持つ。 また、全体像を理解していなくても、個々人や管理対象である「コンポーネント」が効率的に作業を進めることを可能にする。 ソフトウェアのチームも同様に構成されるが、作業対象のシステムは同じような関心ごと、抽象化レベルの分離が行われていないことが多い。 ### システムの利用と構築の分離 システムの開始処理は、全てのアプリケーションが扱わざるを得ない「関心事」である。しかし、大抵のアプリケーションは、関心事を分離していない。開始処理のコードはその場しのぎでランタイムロジックと混ざってしまっている。 便利で小さなイディオムがモジュール構造を壊してしまうのを防ぐべきである。 #### mainの分離 mainには構築に関わる全ての局面を移動させ、残りの部分は、全てのオブジェクトが適切に生成され、関連づけられている前提として設計するものである。 mainでオブジェクトを生成し、それをアプリケーションに渡して使用されるだけである。 #### ファクトリ アプリケーション側でインスタンス生成を行う必要がある場合、 アプリケーション側で生成タイミングを制御できるようにしつつ、抽象ファクトリパターンを用いて、生成の詳細をアプリから切り離すことができる。 #### 依存性注入 依存性注入(DI)は、依存性管理に対する制御の反転の適用である。 オブジェクトを単一責務とする一方で、自分自身の生成に関する情報は、依存を防ぐためにmainルーチン及びコンテナに委ねるものである。 DIコンテナの一つとして、Springフレームワークがある。オブジェクトの依存関係はXMLの設定ファイルに記述され、Javaのコードからは、特定の名前でオブジェクトを要求する。 また、遅延初期化についてもDIと同様に遅延評価の用途に用いることで、同様の最適化効果が得られる。 ### スケールアップ 物理的な街づくりでは、後から拡張する必要が生じた場合、代償として工事期間中の利用不可などの痛みを伴う。 これらの拡張を最初から予期して設計することは不可能である。 一方、システムの拡張の場合、適切に関心事を分離していれば、アーキテクチャをインクリメンタルに成長させることができる。 #### 横断的関心事 永続性のあるものや命名規約、トランザクションの整合性の維持などは、プログラム全てにおいて横断的な関心事として捉えられる。 これらのフレームワークはモジュール構造となっており、ドメインロジックとは独立している。したがって、同じコードを全てに適用せねばならない。 EJBアーキテクチャの場合は、横断的関心事に対して、アスペクト指向プログラミング(AOP)の活用が予想される。これは、特定の関心事を実現するために、システム内のどの振る舞いのどの点に対し整合性を維持したままで変更を加えるかをアスペクトというモジュールで指定するものである。 以下はアスペクト及びアスペクト的な仕組みを3つ紹介する。 ### Javaプロキシ 個々のオブジェクトやクラスのメソッドをラップしたいケース等、単純な状況に適している。 JDKで提供されるダイナミックプロキシは、インターフェースのみ利用可能であるため、別途バイトコード操作ライブラリを用いる必要がある。 単純な処理でもコードが複雑化しやすいため、クリーンコードには不向き。 ### Pure JavaのAOPフレームワーク Spring AOPや、JBoss AOPは、Pure JavaというAspect Jを利用しない世界でアスペクトを実装している。 他のフレームワークへの依存が無く、より単純でテストもより簡単に行えるメリットがある。 横断的関心事は、予め設定ファイルやAPIによって宣言的に組み込む。 EJB3では、このフレームワークを継承している。 ### AspectJアスペクト AspectJは、アスペクト機能がフルに搭載されたツールである。 非常に豊富で強力なツールであるが、言語に慣れる必要がある。 ### システムアーキテクチャのテスト実行 関心事がコードレベルで分離されれば、自分が構築したアーキテクチャのテスト実行が可能となる。 これにより、必要に応じて新しい技術に対応することで、単純なものからより洗練されたものへと進化させていける。 事前の大規模設計は不要である。馬鹿馬鹿しいほど単純な設計からスタートして、関心事を分離し、動作するユーザーストーリーを素早く提供し、規模を拡大していくことができるのである。 互いの依存性が少なく抽象化とスコープのレベルが単純な形にすることで、高い可用性とパフォーマンスが実現できる。 ### 意思決定の最適化 意思決定は手遅れになる直前まで引き延ばすことが最善である。 早急に決定してしまうと変更が効かなくなる。できる限り最終の意思決定を引き伸ばして、その間にどのような変更があっても柔軟に対応できるようにすると良い。 ### 論証可能な価値を追加するには、標準を賢く利用する 標準は、アイデアやコンポーネントの再利用及びカプセル化、コンポーネントの結び付けを簡単にする。 しかし、標準の策定には長い期間がかかり、標準を使うことで顧客の真のニーズと乖離してしまう場合もある。 ### システムはドメイン特化言語を必要とする ドメイン特化言語(DSL)は、独自のスクリプト言語あるいは標準言語のAPIで、ドメインの専門家が書くような散文構造のようにコードを読めるようになる。 ドメインとコードの間のコミュニーケーションギャップを極小化する。 ###### tags: `読書`