<輪読会>オブジェクト指向でなぜつくるのか - 第9~12章 -

輪読会メンバー

  • Izumi Haruya

github.com

  • Sekine Yutaro

github.com

  • Abe Kaisei

github.com

第9章 現実世界とソフトウェアのギャップを埋めるモデリング

  • ステップ❶(業務分析) : 現実世界の仕事の作り方
  • ステップ❷(要件定義) : コンピュータに任せる仕事の範囲を決める
  • ステップ❸(設計)   : ソフトウェアをどう作るかを決める

第10章 擬人化して役割分担されるオブジェクト指向設計

  • 設計の目標
    • 重複を排除する
    • 部品の独立性を高める(疎結合にする)
      • クラスの機能やメソッド命名を適切に行う
      • クラスが外部に公開する情報を最小限にする
      • 個々のクラスやメソッドを小さく作る
    • 依存関係を循環させない

参考書籍

オブジェクト指向でなぜつくるのか 第3版 知っておきたいOOP、設計、アジャイル開発の基礎知識 | 平澤 章 |本 | 通販 - Amazon.co.jp

<輪読会>オブジェクト指向でなぜつくるのか - 第5−8章 -

輪読会メンバー

  • Izumi Haruya

github.com

  • Sekine Yutaro

github.com

  • Abe Kaisei

github.com

第5章 メモリの仕組みの理解はプログラマのたしなみ

  • OOPを使って書いたプログラム

    • メモリの使い方に特徴があるので、メモリの使い方の理解が最低限必要になってくる
  • プログラムのメモリ領域

    • メソッドエリア(静的領域)

    OOPで書いたプログラムは、有限のメモリ領域であるヒープ領域を大量に使う

    静的領域は、従来のメモリ領域で管理する方法 メソッドエリアとは上記で説明した、ヒープ領域で管理する方法

    • ヒープ領域
    • スタック領域
  • ガレージコレクションとは

    • どのインスタンスが削除対象になるか決める仕組みをガレージコレクタという
    • ガレージコレクタとは、スタック領域とメソッドエリアからたどれなくなった不要なインスタンスを削除する

第6章 OOPがもたらしたソフトウェアとアイデアの再利用

第8章 UMLは形のないソフトウェアを見る道具

  • UMLとは

    システムの振る舞いや構造をオブジェクト指向で分析したり設計したりする際、図を用いることで視覚的に把握できるようになり、効果的に表現できます。しかし、その図の描き方が人によって違っては困るので、標準規格として作られた図の記法(モデリング言語)

    引用:Cacooブログ編集部

  • UMLの使い方

    • OOPのプログラムの構造や動作を表現する
      • クラス図でOOPのプログラム構造を表現(クラスの定義情報とクラス間の関係の表現など)
      • シーケンス図ではプログラムの実行の動きを表現(インスタンス間の相互作用の時系列の表現など)
      • コミュニケーション図ではプログラムの実行の動きを表現(インスタンス間の相互作用のインスタンスの関係中心の表現など)
    • 汎用の整理術としての成果物を表現する
      • クラス図で集合に含まれる要素の性質、現実世界の物事の関係を簡潔に表現
      • シーケンス図では役割分担された人や組織が協調して全体の仕事を達成する様子を時系列に表現
      • コミュニケーション図では役割分担された人や組織が協調して全体の仕事を達成する様子を構造中心に表現
    • オブジェクト指向で表現できない情報を表現する
      • ユースケース図ではコンピュータにまかせる仕事の範囲を表現
      • アクティビティ図では現実世界の仕事の流れを表現
      • ステートマシン図では外部からのイベントによる状態変化を表現

参考書籍

オブジェクト指向でなぜつくるのか 第3版 知っておきたいOOP、設計、アジャイル開発の基礎知識 | 平澤 章 |本 | 通販 - Amazon.co.jp

<輪読会>オブジェクト指向でなぜつくるのか -第4章 OOPは無駄を省いて整理整頓するプログラミング技術-

輪読会メンバー

  • Izumi Haruya

github.com

  • Sekine Yutaro

github.com

  • Abe Kaisei

github.com

第4章 OOPは無駄を省いて整理整頓するプログラミング技術

  • ポイント
    • OOPの基本的な仕組み
    • 以前と比べどこが優れているのか

OOPが持つ構造化言語にはない3つの仕組み

  • クラス、ポリモーフィズム、継承がある
    • 重複した無駄なロジックを排除し、必要な機能を整理整頓する仕組み
    • 3つの仕組みは、構造化言語で解決できなかった「グローバル変数」と「貧弱な再利用」という2つの問題を解決するためのものである

三代要素1ークラスに関わる3つの仕組み

  • クラスは「まとめて、隠して、たくさん作る」仕組み
    • サブルーチンと変数を「まとめる」
      • 結びつきの強い複数のサブルーチンと複数のグローバル変数を1つのクラスにまとめることができる
        • 部品の数が減る
        • メソッド(サブルーチン)の名前づけが楽になる
        • メソッド(サブルーチン)が探しやすくなる
    • クラスの内部だけで使う変数やサブルーチンを「隠す」
      • private、publicでアクセスする範囲を指定できる
        • private → クラスの外部からアクセス不可
        • public → クラスの外部からもアクセス可
    • 1つのクラスのインスタンスを「たくさん作る」

        // 従来の呼び出し方法
        クラス名
      
        // インスタンスが使用できるようになってからの呼び出し方法
        インスタンス名 = new クラス名
        インスタンス名.メソッド
      

三代要素2ー呼び出し側を共通化するポリモーフィズム

  • メソッドを呼び出す側を共通化すること
  • インターフェースの継承のこと

三代要素3ークラス定義の重複を排除する継承

  • 重複するクラス定義を共通化すること
  • 実装の継承のこと

    共通するクラスはスーパークラス、それを利用するのがサブクラスである

型にはめられるとプログラマは楽になる

  • 型を宣言する目的
    • コンパイラにメモリ領域の大きさを教えるため
    • プログラムのエラーを防止するため

クラスを型として利用する

  • OOPではクラスを型として扱える
  • 型付けには静的と動的の2つがある

さらに進化したOOPの仕組み

  • パッケージ
    • クラスをさらにまとめたもの
    • 関連する役割を持つクラスを集め、全体の見通しを良くできる
  • 例外
    • 戻り値とは違う形で、メソッドから特別なエラーを返す仕組み
    • 無駄を省くこと、間違いを防止することの2つの効果
    • コンパイルエラー(静的型付言語)や実行時エラー(動的型付言語)がある
  • ガベージコレクション
    • インスタンスを削除する処理をシステムが自動的に実行する仕組み

OOPを生かすも殺すも心がけ次第

品質が高く、保守に強く、再利用しやすいソフトウェア作成はOOPを使おう!

ただしOOPは手段であり、それらはプログラマの腕にかかっている

参考書籍

オブジェクト指向でなぜつくるのか 第3版 知っておきたいOOP、設計、アジャイル開発の基礎知識 | 平澤 章 |本 | 通販 - Amazon.co.jp

<輪読会>オブジェクト指向でなぜつくるのか - 第3章 OOPを理解する近道はプログラミング言語の歴史にあり -

輪読会メンバー

  • Izumi Haruya

github.com

  • Sekine Yutaro

github.com

  • Abe Kaisei

github.com

第3章 OOPを理解する近道はプログラミング言語の歴史あり

OOPは必然性を持って登場した

  • 機械語から構造化プログラミングまでの進化の歴史を振り返る
  • なぜOOPが必要になったか

1940年代~

黎明期には機械語でプログラムを書いていた

このときコンピュータは、2進数で書いた機械語しか解釈できなかった

以下は算術計算を実行する命令であり、これを見ても直感的にわからないので、一部の物凄く優秀なプログラマしか扱えなかった

// 16進数
A10010
01D0

1950年代~

プログラミング言語の最初の一歩はアセンブリ

  • 人が解釈しやすいような記述方法
// アセンブリ言語

MOV  AX, Y
MOV  DX, Y

上記はコンパイルするアセンブラという別のプログラムを読み込ませて機械語を生成していた また、命令をほんの少し間違えるとプログラムが暴走する懸念があった

1950年代 ~ 1960年代

高級言語の発明でプログラムはより人間に近づいた

  • 高級言語になるとかなり人間が読みやすくなった
// FORTRAN
Z=X+Y

1970年代 ~

分かりやすさを重視する構造化プログラミング

構造化プログラミングにも課題があった(メモリ、CPU速度) 上記のような問題は、ハードウェアの改善とともに問題も改善していった

19XX年代(その後) ~

サブルーチンの独立性を高めて保守に強くする

・ グローバル変数をいかに減らすか
・ 上記が多いと影響範囲が大きいので、変更コストが莫大にかかった
・ ビルドして、エラーハンドリングしようとしてもビルドに1日以上かかって現実的でなかった
  • 問題を避けるための2つの仕組み
    • ローカル変数(サブルーチンの中だけで使用される変数)
    • 引数の値を渡す

上記をうまく使用することでサブルーチンの独立性を高めることが可能になった!!

GOTOレスプログラミングを実現する構造化言語

  • 構造化言語(GOTOレスプログラミング言語)が登場した

    上記の中でC言語が1番注目された

    • ビット演算やメモリ領域を効率的に使用するためのポインタなどの細かな機能があった
    • 関数ライブラリで組み上げるようにした
    • 上記のことが理由で既存の言語コンパイラを改良しなくてもよくなった

進化の方向は保守性と再利用性を重視に変化した

  • 生産性向上
    • 命令を簡単に表現するための進化
      • 高級言語までの進化では、命令の「高級化」による表現力の向上
  • 保守性向上
    • プログラムをわかりやすくするための進化
      • 構造化言語における進化では、基本三構造
  • 品質向上
    • 制約をつけて複雑さを避ける為ための進化
      • 構造化言語における進化では、GOTOレスプログラミング
  • 再利用促進
    • 重複ロジックを排除して、部品化と再利用を促進するための進化
      • 高級言語までの進化では、サブルーチン
      • 構造化言語における進化では、サブルーチンの独立性強化

ここまでのプログラミング言語の残された課題はグローバル変数問題と貧弱な再利用

  • グローバル変数問題
    • 現状のローカル変数の仕組みでは、サブルーチンを跨ぐ処理ができなかった(ローカル変数はサブルーチンの呼び出しが終わると消えてしまう一時的なものだった)
    • 上記を解決するには、グローバル変数に頼るしかない現状だった
  • 貧弱な再利用
    • ライブラリが充実していなかった
    • ライブラリにないものを実現しようとしたらサブルーチンで実現しなければならなかった

参考書籍

オブジェクト指向でなぜつくるのか 第3版 知っておきたいOOP、設計、アジャイル開発の基礎知識 | 平澤 章 |本 | 通販 - Amazon.co.jp

<輪読会>オブジェクト指向でなぜつくるのか -第2章 オブジェクト指向と現実世界は似て非となるもの-

輪読会メンバー

  • Izumi Haruya

github.com

  • Sekine Yutaro

github.com

  • Abe Kaisei

github.com

第2章 オブジェクト指向と現実世界は似て非となるもの

オブジェクト指向を現実世界に対比して説明する

クラスは種類、インスタンスは具体的なモノ

メッセージパッシングとは、メソッドを呼び出すこと

ポリモーフィズムはメッセージの送り方を共通にする

  • ポリモーフィズムの意味/仕組み
    • (英語)「いろいろな形に変わる」
    • (日本語)「多態性」「多相性」
    • (仕組み)類似したクラスに対するメッセージの送り方を共通にする仕組み

継承は共通点と相違点を体系的に分類して整理する

  • 継承の仕組み
    • モノの種類の共通点と相違点を体系的に整理する仕組み

比喩を強調した説明は混乱を招きやすい

  • 比喩の弊害
    • 比喩を強調した結果、比喩の強烈な印象ばかりが残りがち
    • プログラミング言語としてのOOPの利便性と活用場面が具体的にイメージしにくい

オブジェクト指向と現実世界は似て非なるもの

プログラミングのための仕組みと割り切って理解する

  • 三大要素を保守性や再利用性を上げる為の仕組みとして割り切る
    • クラス
      • 変数とサブルーチンをひとまとめにして独立性の高い部品を作る為の仕組み

      サブルーチン(英: subroutine)は、コンピュータプログラミングにおいて、プログラム中で意味や内容がまとまっている作業をひとつの手続きとしたものである。 繰り返し利用されるルーチン作業をモジュールとしてまとめたもので、呼び出す側の「主」となるもの(メインルーチン)と対比して「サブルーチン」と呼ばれる。

    • ポリモーフィズムと継承
      • コードを重複を排除して汎用性の高い部品を作る為の仕組み

そもそもソフトウェアは現実世界をそのまま表現しない

  • システム化範囲の議論
    • (一般論)ソフトウェアが人間の仕事をまるごと置き換えてしまう
    • (本書の結論)ソフトウェアがカバーするのは人間の仕事の一部でしかない

      上記の続きは第9章で詳しく議論予定(後ほど引用作成します)

現実世界と似ていることが可能性を広げた

参考書籍

オブジェクト指向でなぜつくるのか 第3版 知っておきたいOOP、設計、アジャイル開発の基礎知識 | 平澤 章 |本 | 通販 - Amazon.co.jp

<輪読会>オブジェクト指向でなぜつくるのか -第1章 オブジェクト指向はソフトウェア開発を楽にする技術-

輪読会メンバー

  • Izumi Haruya

github.com

  • Sekine Yutaro

github.com

  • Abe Kaisei

github.com

まえがき

  • 旧版と比べて第3版の変更点
    • オブジェクト指向がなぜ難しいのか」をより客観的な視点で説明することに注力するようになった

引用:オブジェクト指向でなぜつくるのか P10


(本書で気になる問い)

  • モデリングとコミュニケーションを重要視する
  • 「一見凄そう」で終わらない(理解しようとする)姿勢が大事

第1章 オブジェクト指向はソフトウェア開発を楽にする技術

オブジェクト指向はソフトウェア開発の総合技術

  • オブジェクト指向でなぜ作るのか
    • ソフトウェアを楽に作るため
  • 難しいソフトウェア開発を楽に行うための総合技術である

モノ中心にソフトウェアを組み上げる開発手法

  • 手続き型(システム全体を集合的に扱っている)
    • (デメリット)仕様変更や機能追加の際の修正範囲が広い
    • (デメリット)ソフトウェアの再利用が難しい
  • オブジェクト指向(システムを部品に分け、独立性を持たせ、システム全体を構築している)
    • (メリット)仕様変更や機能追加の際の修正範囲が狭い
    • (メリット)ソフトウェアの再利用が容易

プログラミング言語から総合技術に進化した

オブジェクト指向の歴史

引用:オブジェクト指向でなぜつくるのか P23

オブジェクト指向が難しい理由

  • プログラミング言語の仕組みが複雑

    • 今までは仕組みが単純だったが、技術発展と共に仕組みが複雑になっていった
      • 単純にコードを上から読むでは済まなくなってしまった
      • 上記の理由から使いこなすまでには時間がかかるようになった
    • 用語自体が難しい
  • 比喩を使った説明による混乱

    • 説明時の比喩が独特なことが多く、情報の中身よりも比喩の印象が強く残ってしまう
  • オブジェクト指向というコンセプトが抽象的

    • モノ中心というコンセプトが抽象的である
    • 現実世界とコンピュータの世界は似て非なるものである

      上記のことからそのまま当てもはめてもうまくいかない

(独自の解釈)業務委託などの場合では、手続き型とオブジェクト指向の中間など、明確なポジションを取ることが少ない場合があるため、実務との乖離が生じ、理解しにくいケースもある

オブジェクト指向技術のwhatとwhyを説明する

  • 本書の目標

    • 論理の飛躍をせずわかりやすく説明すること
  • オブジェクト指向を難しくしている理由3つに対する方針

    • プログラミング言語の歴史を踏まえて、メリットを具体的に説明する
    • 比喩による説明は最小限に抑えて説明をする(比喩を使う場合はその旨を明示する)
    • プログラミングの仕組みと、「モノ中心」で汎用的に物事を捉える考え方は別物として、分けて説明する

本書の構成

引用:オブジェクト指向でなぜつくるのか P30

上記の図で示す通り

参考書籍

オブジェクト指向でなぜつくるのか 第3版 知っておきたいOOP、設計、アジャイル開発の基礎知識 | 平澤 章 |本 | 通販 - Amazon.co.jp

<輪読会> オブジェクト指向実践ガイド -第9章費用対効果の高いテストを設計する-

輪読会メンバー

  • Izumi Haruya

github.com

  • Sekine Yutaro

github.com

第9章費用対効果の高いテストを設計する

9.1意図を持ったテスト

  • 一般的なテストのメリット
    • テストを持つことの根拠として、最も一般的に言われていることは、テストはバグを減らすとか、文書になるだとか、テストを「最初」に書くことでアプリケーションの設計がより良いものになる、といったことでしょう。

    Sandi Metz. オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方 (Japanese Edition) (Kindle の位置No.5274-5276). Kindle 版.

テストをすることの真の目的は、設計の真の目的がまさにそうであるように、コストの削減である

テストがなかった場合にかかるバグの修正に必要な時間や文書を書く時間、アプリケーションを設計する時間などに比べて、テストの記述、メンテナンス、実行に多くの時間がかかるのであれば、テストを書く価値はありません。

Sandi Metz. オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方 (Japanese Edition) (Kindle の位置No.5277-5281). Kindle 版.

  • テストにコストがかかることの解決方法

    テストをやめることではありません。うまくなることです。テストから優れた価値を得るには、意図の明確さが求められます。そして、何を、いつ、どのようにテストするかも知らなければなりません。

    Sandi Metz. オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方 (Japanese Edition) (Kindle の位置No.5288-5290). Kindle 版.

テストの意図を知る

  • 本書におけるテストの真のメリット
    • バグを見つける
      • バグの初期段階での修正は、いつでもコストの削減になる
    • 仕様書となる
      • 人の記憶と異なり、忘却や改ざんに依存せず、唯一信用できる設計の仕様書となる
    • 設計の決定を安全に遅らせる
      • 抽象的な(インターフェースに依存する)テストを書くことで、設計の決定を安全に遅らせることができる
    • 抽象を支える
      • より良い設計に近づけていく為に、徐々に抽象度を上げる形でコードを修正していく
      • テストをすることで、あらゆる抽象のインターフェースを記録する
    • 設計の欠陥を明らかにする
      • テストのセットアップに苦痛が伴うようであれば、コードはコンテキストを要求しすぎていることが分かる
      • 1つのオブジェクトをテストするために、ほかのオブジェクトをいくつも引き込まなければならないのであれば、そのコードは依存関係を持ちすぎてる
      • テストを書くのが大変なのであれば、ほかのオブジェクトから見ても再利用が難しい
      • 上記なような課題が見えてきたら、疎結合なテストを書くべきである

何をテストするかを知る

一般規則として、オブジェクトは、自身のパブリックインターフェースを構成するメッセージに対して「のみ」テストをするべきである

パブリックインターフェイス以外をテストする必要がないからといって、それらのテストをまったくしなくてよいというわけではない

いつテストをするかを知る

テストの方法を知る

  • テストの方法

  • テストをするときのオブジェクトのカテゴリー

    • 自身がテストをするオブジェクトであること
    • そのほかのものすべて

9.2受信メッセージをテストする

  • 受信メッセージ
    • オブジェクトのパブリックインターフェースを構成し、原則テストを必要とする
    • 依存されていない受信メッセージは削除する

パブリックインターフェースを証明する

  • 受信メッセージのテストに求められること

    • 考えられ得るすべての状況において正しい値を返すことを証明すること
  • オブジェクトが単一責任になっていないケースでのテストの懸念

    • テストの実行時間がかかる
    • 想定外の結果が起こる可能性が高まる

9.3プライベートメソッドをテストする

パブリックインターフェイス以外は、送られたことがテストされるべきである

テスト中ではプライベートメソッドを無視する

  • プライベートメソッドのテストをしないことを支持する理由
    • パブリックでもテストされる事が多く、冗長になる為
    • プライベートメソッドは、依存関係がある場合が多いので不安定である
    • 依存関係があるので、テスト対象オブジェクト以外も記述する必要が出る可能性があり、テストの文脈が伝わらない

プライベートメソッドのテストをするという選択

  • 設計の決定を遅らせることが目的の場合

9.7まとめ

  • テストを書くのが難しい時は設計に問題がある
  • 上記は依存関係が複雑であり、疎結合でない為難しくしてしまっている
  • 設計全体が疎結合で単一責任になっている(パブリックインターフェイスの)時は、いかなる状況でも期待する値が返ってくるか検証するテストを書く
  • 依存関係が複雑(プライベートメソッド)の場合は、基本的にはテストをしない
  • 上記でも例外があり、設計の決定を遅せるのが目的の場合は、テストを記述する方が良い時もある。ただし、そのテストは「振る舞い」をテストすべきである
  • テストの内容が具象すぎる時は、ダックタイピングやモジュール・継承の考えを用いてテストそのものを疎結合なものとする

参考書籍

オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方 | Sandi Metz, 髙山泰基 | 工学 | Kindleストア | Amazon