○第8章 境界
内部コードと外部コード(3rd party製のライブラリとか)をうまくつなぐ方法について。
直接使うのではなく、ラッパを一つかませると良い。使用者側は特定のニーズに特化したインターフェースを求めるが、ラッパがあれば万事解決。
外部コードをつなぐときには、テストコードを先に書くと振る舞いの勉強ができ、かつ次回以降のアップデートでテストケースができるためオススメ。こうしたテストには「学習テスト」という名前があるらしい。
よい設計は過大な投資ややり直しを求めること無しに変更への対処を可能とする。自分たちのコードの広範囲が3rd partyの実装詳細に関する知識を持たないようにする。
○第9章 単体テスト
テスト駆動開発(TDD: Test Driven Development)の3大原則
- 失敗する単体テストのコードを書く前に製品のコードを書いてはならない
- コンパイルが通り、適切に失敗する単体テストができるまでは次の単体テストを買いてはならない。
- 現在失敗している単体テストが通るまで、次の製品コードを書いてはならない。
テストコードと製品コードはほぼ同時に書く、テストコードの方が数秒先行するだけ。
きちんとやればテストコードの行数は製品コードの量に匹敵し、管理上の問題が必要になるぐらいのはず。
(同じぐらいの分量だと足りない気もするんだけど、適切な量はどれぐらいなんだろう・・・?)
テストも製品コードと同等の品質基準に従うべき。きちんとメンテナンスされ続ける必要がある。
テストがメンテナンスされてないと、新規コードを書く時間よりテストコードを書く時間の方がかかるようになってしまい、テストがされなくなってしまう。結果製品コードも腐ってしまう。
単体テストが以下の性質を実現する。
テストがあれば変更を恐れずできる。
テストに重要なのは何を置いても「読みやすさ」である。
製品コードほどの実行効率は必要ないことに気づく。読みやすさの工夫の余地が広がるはず。
きちんと整理された1つのテストは「構築ー操作ー検査」のパターンに合致するはず。
1つのテストでは1つの概念を扱う。
クリーンテストはF.I.R.S.T.の規則に従う
- Fast: テストは高速に実行できる
- Independent: テストは互いに関連しない。
- Repeatable: 再現性がある。
- Self-Validating: テストの結果は成功か失敗か明確に判断できる。
- Timely: 必要なときにすぐ書ける。
○第10章 クラス
クラスは小さくなければならない。行数ではなく、1つのクラスが担う責務に着目して測るのが重要。
クラス名は責務を表した名前を付け、実装は単一責務の原則(SRP: Single Responsibility Principle)に従うようにする。
責務に着目するとクラスの分割がやりやすくなる。
クラス内のメソッドが操作する変数が多い方がクラスの「凝集性」が高い。
凝集性が高いとメソッド変数は互いに依存し合っていることになり、全体として1つのロジックをなすようになる。
○第11章 システム
システムレベルでもきれいな状態に保つことは大事。
依存性注入(Dependency Injection)を考慮したフレームワークを使うといいよ。
最初から正しいシステムというのは神話、適切に関心ごとを分離して保守していくことでアーキテクチャも改善していくことができる。
モジュール化と関心ごとの分離は管理と意思決定を延期することができ、一般的に後で決断をする方が最善の情報に裏付けられた決断を行うことができる。
○第12章 創発
単純な設計のための4つの規則
- 全テストを実行する
- 重複が無い
- プログラマの意図が表現されてる
- クラスとメソッドを最小化する
・全テストの実行
システムがテスト可能でなければ検証可能でない。
SRPに従ったクラスはテストも容易。
システムを完全にテストしようとすると依存性注入などのテクニックが自然と使われるようになり、より優れた設計を生み出してくれる。
コードを壊す恐れが減るため、リファクタリングも思い切ってできる。
・重複の排除
重複は余計な作業、余計な危険、不必要な複雑さを引き起こすため悪である。
大きな再利用を実現するため、小さな再利用を理解することが大事。
・表現に富む
書き手の意図が明快であるほど、別の人が理解しやすくなる。
書いた本人が書いた時点で理解できるのは当たり前、なぜなら解く対象の問題を深く理解しているから。
ソフトウェア開発の大半は保守なのでメンテナンスのしやすさの方が大事。
表現に富んだコードを書くには以下が重要
- よい命名
- 関数とクラスを小さく保つ
- 標準の用語(デザインパターンとか)を使う
- 単体テストで使用例を文書化する
・クラスとメソッドを最小限にする
規則の中でも最も優先順位が低い。最小限にするあまり実際的でないルールや実装を行ってはならない。
○第13章 同時並行性
きれいな同時並行プログラムを書くことは困難を極める。
- 同時平行性は常にパフォーマンスが改善される訳ではない。待ち時間が大量にあって、複数処理で共有できる場合のみ。
- 同時並行プログラムはシングルスレッド時とアルゴリズムも設計も違ってしかるべき。
- 同時並行性の実現には余分なオーバーヘッド、複雑さを伴う。
- 同時並行性のバグは再現性がない。
それでも同時並行性が必要なときは以下の点に留意する。
- 単一責務の原則を守る。同時並行性に関するコードは他と分離する
- データスコープを限定する。クリティカルセッションの数を抑える
- 可能な場合はデータのコピーを利用する。
- スレッドはできるだけ独立させる。
同時平行性の大抵の問題は以下のいずれかか、組み合わせで表現できる。
- プロデューサー/コンシューマー:キューを使ってジョブをやりとり
- リーダー/ライター:飢餓状態、古い情報の集積、スループットの低下など問題が多い
- 食事する哲学者の問題 – Wikipedia
問題を早期に発見して作り込まないようにする。
- 怪しい問題があったらスレッドを疑う
- 最初にスレッド化されないコードを完成させる
- スレッド化されたコードの実行条件は変えられるようにする
- プロセッサの数よりもスレッド数を多くしてテストする
- 異なるプラットフォームでテストを実行する。
Clean Code アジャイルソフトウェア達人の技 (大型本)
