!!!コード行数を減らすのではなくロジック量を減らすように心がける コード行数を減らすためにコメントを省いたり、インデントしなかったりしても現在のコンパイラーでは最適化されるので何の意味も無い。 むしろ、コードのメンテナンス性・可読性を著しく悪くし、後からバグを増やしたり応用ができなくなったりする。 勘違いによる人為的なバグの原因にもなり得る。(例:メソッド引数の意味のとり間違い) コードを書く時は「自分の後輩にわかるように」書くように心がける。 '''人間は1ヶ月前に自分で書いたコードは覚えていない。''' さらにコンピュータはコメントを読まないが人間はコメントがないとこのプログラムが何者だかわからなくなる。 また、ロジックとは「if」「switch」「for」などの分岐やメソッド呼び出しの出現回数であるが、これが多ければ多いほどそのMethod・Classは「多機能」ということになる。 「機能」が増えればそれだけ前提条件が複雑になりテスト時にカバーできないコードの量が増える。 比例して発見できないバグが増えるし、そもそもテスト項目が増えてやってられない。 現在はJUnitやFindBugsなどのテストサポートツールが無料でイロイロあるので、Methodが増えたとしてもテストは半自動で作成・対応が可能になるのでさして問題にはならない。 1Method、1Classあたりのロジックが多くなるように思えるときにはそれ以前にClassの設計が間違っている。 !!利点 +++テストパターンが減るのでテスト工数が減る。 +++各種ツールでテストを自動化する際に自動化が楽になる。 +++可読性が高いコードを書くことによって「自分以外」もデバッグやテストに容易に参加できる。 +++「忘れてしまったのでもうメンテできない」という危険性を減らすことができる。 +++インデントをつけることによってforブロック、ifブロックなどのブロック閉じ忘れをなくすことができる。 +++ロジックが少ないということは「1Method1機能」の理想に近づけることになる。 !!欠点 +++インタプリタ型の言語の場合、実行速度が遅くなることがまれにありうる。(古い言語や言語実装を使う時には注意) +++ソースコードを印刷したときに紙がいっぱい必要になる。(→2in1ページ印刷や両面印刷を使いましょう。) !!!操作の対象はObjectではなくInterfaceを使う 特定の具象Classに対する実装ではなく、Interfaceに対する実装を心がける。 !!利点 +++個々のClassでの部分テストを行う際、(JUnitなどにより)テストがやりやすくなる。 +++実装が変更になったり操作対象が増えた場合にロジック変更を行う必要性が減る。(仕様変更時の修正個所の局所化) +++Classが依存するClassを減らすことができる。 !!欠点 +++ソースコードの数が増える。 +++実行時のType safeに考慮する必要がある。(→但し、JavaなどではGenerics宣言をしておくことである程度回避は可能) +++Interface自体の仕様変更を行った場合修正個所が増える。(→1Class1機能を心がけることである程度回避可能) !!例 【変更前】 private void printList(ArrayList list) { for (int i = 0; i < list.length; ++i) { System.out.println(list.get(i).toString()); } } ↓ 【変更後】 private void printList(List list) { for (int i = 0; i < list.length; ++i) { System.out.println(list.get(i).toString()); } } 変更前の状態ではList Interfaceの具象ClassのArrayListを引数でとっているが、例えばIndexListや他のList派生Classを取り扱うことになった場合MethodをOverrideするか他のMethodを使用しなくてはならずコード量が増える。 又、処理の中で具象Classの独自Method、Propertyを使ってしまっている場合、移植性が悪くなる。 !!!継承を使うときは良く考える '''オブジェクト指向は継承よりもコンポジション(Composition:構成)を好む。''' 一旦具象Classを継承してしまうとその機能まで継承してしまう。 継承されるClassにMethodが追加されたりInterface変更があった場合に継承先のClass全体を再テストする必要が生じ、混乱が発生する。 また、同じ継承元を持つからといって派生Class同士の追加機能が共通化されるわけではない。 むしろコードを分散させ、メンテナンス性を悪くする。 さらに、継承は派生先に継承元のInterfaceを'''強要'''する。 これは結果的に関連Classを増やすことになり、Classの分離性を落とす結果になる。 具象Classの継承はなるべく行わないようにし、もししなくてはならない場合は継承元のClassの機能は最低限にする。 ある具象Classの機能を使用しその振る舞いを変更したい場合は具象ClassのInstanceを内部に持つようにし、そのInstanceのMethod・Propertyへのアクセッサを用意する。 オブジェクト指向言語を覚えたときには継承をやたらと使いたくなるが、まずはCompositionを使用することを考え、どうしても無理なときは継承するようにする。 !!!履歴 2007/04/12 - 初版作成