shikaku的オブジェクト指向設計メモ

なにかの機会にオブジェクト指向に関する資料を書いたのですが

ひょっこりでてきたのでメモっておきます。

「オブジェクト指向」のいいところ

  • 扱いやすく設計することで、可読性も拡張性も寿命も全てが向上する
    • 正しく設計≠扱いやすく設計
  • 扱いやすいとは?
    • 少ない情報で扱える
      • 大量のドキュメントの内容を全て把握してないとダメ とかない
      • そのAPIを使うために、100個のAPIの仕様をしらないといけない とかない
    • パターンがある
      • ひとたび覚えれば、似たような手法で機能を拡張できる
    • 心配ごとがない
      • 意図しない動作の可能性が0である
    • 頭を使う量を最小限に済ませる
    • simple is best

「オブジェクト指向言語」のいいところ

  • コードに設計者のメッセージを込めることができる
    • 設計者の意図しない変数/関数アクセスを防止できる
  • APIをprivateにした設計者のメッセージ
    • 「内部で勝手にいじるから、触っちゃだめよ」
    • 「これを勝手にpublicにしたいなら責任は持ちなさいよ」
      • 関連の仕様書は全てよめ
      • このクラスの全ての仕様を知れ
      • デグレったらあなたがなおしてよね
      • 勝手に触ってデッドロックおきても知らないよ
  • APIをpublicにした設計者のメッセージ
    • 「あなたに必要な情報はコレですよ」
    • 「これらの情報だけでどうにも実装できないってことは、 私との意思疎通が足りてませんよ」
      • 「電話かメールしなさい」
  • クラスなどの概念によりコードの可読性が上がる
    • 名前からこのソースにある機能や役割を容易に推測できる
      • 上手にわかりやすくしないとだめですが
      • 既存の方法でも同じこと

「オブジェクト指向」のデメリット

  • 「再利用性」という名の甘い蜜。でも罠。 再利用設計にはコストがかかる

ソフトウエア開発 55の真実と10のウソ

ソフトウエア開発 55の真実と10のウソ

  • 「ソフトウェア開発55の真実と10のウソ」より
    • 真実18
      • 再利用可能なコンポーネントを作るのは、 単一のプログラムで使うモジュールを開発する場合に比べ、 3倍難しい
      • 再利用可能なコンポーネントは、 ライブラリに取り込む前に、 3つの異なるプログラムでテストする必要がある
    • 真実19
      • プログラムを再利用する場合、流用母体の変更は、バグの要因になる
      • 20-25%も変更する必要があるなら、最初から作った方が、効率も上がるし、品質も良い
  • 再利用を前提とすると高速開発に不向き
    • ソフトウェア開発は大抵、仕様決定までに時間がかかる
  • 下手にオブジェクト指向言語の機能を使いまくると大混乱
    • 使い手を選ぶ
    • 扱いやすく設計しないと、地獄に堕ちる
  • トラブル例
    • 機能が多すぎるクラス(ゴッドクラス)が誕生。
      • publicな get/set メソッドだらけ
      • 結局アクセスが面倒なだけになる
    • クラス分けしすぎてコードが分散
      • どこに該当コードがあるのか探すの大変
    • 継承しすぎ
      • どの階層のクラスに該当コードがあるのか探すの大変
    • オーバーライドの罠
      • 上の階層でコード直して全体を直したつもりが、オーバーライドされてたクラスだけ不具合が残る

shikaku的設計方針

  • オブジェクト指向のいいとこ取りを目指す
  • 扱いやすく作るのに部分だけ採用
  • 大切だとしても時間がかかる手順は捨てる
  • UMLによる詳細な設計にはこだわらない
    • あくまで開発者間のコミュニケーションが進めばOK
    • 簡単な図しか使わない
      • クラス図
      • シーケンス図
      • ステート図
    • 多少ルールがおかしくたっていい
    • 概要しか書かない
    • 詳細はまた別の資料で
  • 人間はミスをする生き物だということを常に頭に入れておく
  • 情報の不要(隠蔽)/必要(公開)を コントロールし、扱いやすい設計を促す
    • 隠蔽すべき情報
      • 意識させると開発者にコストがかかる情報は隠す
    • APIは極力少なく
      • 他のモジュールの情報を取得する = そのデータを扱うための責任(コスト)が発生する
      • そのデータが有効である期間(寿命)を知らなくてはいけない
      • そのデータにアクセスしてよいタイミングも知らなくてはいけない
      • つまりそのデータを扱う上での仕様、特性、不文律を全て把握しなくてはいけない
  • 不具合を誘発しそうな実装は極力避ける
    • タスク処理やメモリ管理
    • 不要になったコードは極力削除
    • 今現在使う予定が無ければばっさり削除
      • grepしたときなどに混乱の元
  • 公開すべき情報
    • モジュール情報の公開
  • クラス内の情報は出し惜しむ
    • 他モジュールがどうしても必要な情報だけ公開
  • コメントは書きまくる
    • なぜこういう実装なのか、後にコード読む人へのヒントをちりばめる
    • これはオブジェクト指向と関係なさそうだけど重要
  • 責任(コスト)の分散
    • 情報集中部分(モジュール)を作らない
    • いろんなタスクからアクセスされる グローバル変数の大群を一掃する
  • セマフォ地獄からの解放
    • グローバル変数と変わらないようなモジュールも0を目指す
    • 必要な部分(モジュール)に必要な情報だけを置く
  • ソフト構造は現場主義で
    • 現場が必要な情報は現場内で処理する
      • 上層モジュールが必要な情報のみ上に投げる
      • 上層モジュールは現場モジュールが必要な情報のみ現場に渡す
    • 設計トラブルがあったら?
      • 開発者みんなの責任
      • 検討(コミュニケーション)不足
  • 少ないリソースで大きな効果を得る設計ができるはず
    • 上手にやれば・・・ね
  • 人間も省エネ大切
    • 人間(開発者)の基本情報
    • 限界のあるリソースを持っている
      • 時間
      • 体力
      • 記憶力
    • コミュニケーションにもコストがかかる
      • 打ち合わせ、会議
      • 仕様書などのドキュメント読破
      • メール処理
  • 人間の理解を超えた奇跡(バグ)を生み出す可能性が少しでもあるプログラミングテクニックはなるべく使わない
    • 大量のタスク管理
      • デッドロック
    • 大量の動的メモリ管理
      • バッファオーバーフロー
      • メモリ破壊
      • フラグメンテーションの発生
    • もう本当にどうしようもないときだけ使うようにすべき