---
# System prepended metadata

title: オブジェクト指向設計実践ガイド読書会 - 第50回
tags: [オブジェクト指向設計実践ガイド読書会]

---

オブジェクト指向設計実践ガイド読書会 - 第50回
===
###### tags: `オブジェクト指向設計実践ガイド読書会`

# 開催概要

* 日程: 2023/03/11 Sat 21:00〜23:00
* 会場: https://discord.com/channels/432531367427964929/898843794101911622
* [README](https://hackmd.io/sSmTRzcQSCuvqiO7uDUkFg)
* [タイムキーバー用テンプレート](https://hackmd.io/E0HZBN9OS9GBAtnsYXjDsw)

## 課題図書

『オブジェクト指向設計実践ガイド ～Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方』(Sandi Metz 著, 髙山泰基 訳, 技術評論社)

- 技術評論社, pdf版あり
    - https://gihyo.jp/book/2016/978-4-7741-8361-9
- Amazon
    - https://www.amazon.co.jp/dp/B01L8SEVYI

## 実施要領

- 事前読書なし。都度その場で読んで、感想を書いて、議論する、を繰り返す。
- 参加スタイルは自由形。チャットでも音声でもご自由に。
  - 主催はチャット参加です。
  
## タイマーについて
時間管理はタイマーbotで行います。
VCチャンネルに入っている人を対象にメンションが飛ぶので、VCチャンネルへの参加をお願いします。
また、タイマーは終了時に **音声がなる** ので、ご注意ください。

## 当日までの準備
1. 課題図書を手元に用意する
    - 買う、借りる、etc(?)
2. 当日までに読んだり読まなかったりする
    - 当日その場で読むので、事前に読んでおく必要は無し
    - 気になったら事前に読んでおいても良し
    
---
    
# 当日の進行
## 進行フロー
https://hackmd.io/sSmTRzcQSCuvqiO7uDUkFg?view#%E9%80%B2%E8%A1%8C%E3%83%95%E3%83%AD%E3%83%BC

## :goti: or :okawari: について
- 各パートごとに :goti: or :okawari: を投票する.
- :okawari: が1つでも有れば、パートを続行する.

## 開催コール
https://1.bp.blogspot.com/-YrhlmWQ4uIQ/UrlmxoUdDeI/AAAAAAAAcLw/M6VFUKHnTos/s400/text_start.png

## タイムキーパー募集
https://hackmd.io/E0HZBN9OS9GBAtnsYXjDsw#%E3%82%BF%E3%82%A4%E3%83%A0%E3%82%AD%E3%83%BC%E3%83%91%E3%83%BC%E5%8B%9F%E9%9B%86

## 読書パート
https://hackmd.io/E0HZBN9OS9GBAtnsYXjDsw#%E8%AA%AD%E6%9B%B8%E3%83%91%E3%83%BC%E3%83%88

## 投票パート
https://hackmd.io/E0HZBN9OS9GBAtnsYXjDsw#%E6%8A%95%E7%A5%A8%E3%83%91%E3%83%BC%E3%83%88

## トークパート
### 議論(:thinking_face:)パート
https://hackmd.io/E0HZBN9OS9GBAtnsYXjDsw#%E8%AD%B0%E8%AB%96%E3%83%91%E3%83%BC%E3%83%88

### 任意トーク(:+1:)パート
https://hackmd.io/E0HZBN9OS9GBAtnsYXjDsw#%E4%BB%BB%E6%84%8F%E3%83%88%E3%83%BC%E3%82%AF%E3%83%91%E3%83%BC%E3%83%88

### 次回繰越(:eyes:)パート
https://hackmd.io/E0HZBN9OS9GBAtnsYXjDsw#%E6%AC%A1%E5%9B%9E%E7%B9%B0%E8%B6%8A%E3%83%91%E3%83%BC%E3%83%88

## 終了コール
http://3.bp.blogspot.com/-zgTNWF_hBmI/UZYlh9RhuDI/AAAAAAAATQ8/dymPl5P4eAs/s500/undoukai_relay_animal.png



# 読書メモ
## 9.2_受信メッセージをテストする_ロールとして依存オブジェクトを注入する_テストダブルをつくる_p.259_p.261

[前回](https://hackmd.io/qWjp_5R8ToSwrPokbBzg0A?view#92_%E5%8F%97%E4%BF%A1%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%82%92%E3%83%86%E3%82%B9%E3%83%88%E3%81%99%E3%82%8B_%E3%83%AD%E3%83%BC%E3%83%AB%E3%81%A8%E3%81%97%E3%81%A6%E4%BE%9D%E5%AD%98%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E6%B3%A8%E5%85%A5%E3%81%99%E3%82%8B_%E3%83%86%E3%82%B9%E3%83%88%E3%83%80%E3%83%96%E3%83%AB%E3%82%92%E3%81%A4%E3%81%8F%E3%82%8B_p259_p261)からの引き継ぎ

### discord開始地点
https://discord.com/channels/432531367427964929/898843794101911622/1084086901834797097

### 感想
> このようなダブルはとてもかんたんにつくれます。

- こうしたオブジェクト生成と交換の気軽さは、ダックタイピングを利用する言語ならでは、という感じ
    - 静的型付け & nominal typingのみだと、ちょっと面倒になることが多い（詰まるところは言語次第ではあるけれど）:+1: :+1: :+1:
    - 静的型付けでも、TSみたいな structual typing を採用している言語なら、継承ツリーは気にせずI/Fだけ合わせれば良い. なので、単なるstubならプレーンなオブジェクトを作って済ませることも多い
        - Mockの仕組みが欲しいときは、流石にモックライブラリを使う

> DiameterDoubleはモックではありません。気を抜くと「モック」という言葉でこのダブルを表現しがちになりますが、実際はまったく別のものです。これについては「9.4 送信メッセージをテストする」で取り扱います。 - p.260

- スタブとモックをえらい注意深く、正確に扱おうとしている！
    - ~~ここ書きながら、なんか良いものでも食べたのか~~ :innocent: :kusa:
    - スタブ(stub)とモック(mock)の違いは、『xUnit Test Patterns』Chapter 23に記載あり（というより、『テスト駆動開発』付録Cによるなら、『xUnit〜』によって整理された模様）
    - SinonJSのドキュメントも、Stub・Mock・Spyは明確に区別して説明しているので、良いかも :+1:
        - https://sinonjs.org/releases/v15/

### 疑問
> このテストでは、Diameterizableのインターフェースはもともとのdiameterメソッドに戻されたとしましょう。 - p.259

- はて、なんのために width に名前を変えたのだったっけか…… :+1:
    - 「失敗するべくして失敗」することを例示するためだけの例で、なんらかの要請によるものではない、架空の変更 :naruhodo:
    - なので、「戻されたとしましょう」という文章がよくなくて、そんな変更は無かったものとしましょう、くらいの内容の方が誠実 :point_left: 
        - プラス、「widthへの変更は例のための例で、それ以上のものではありません」というのも明示的に添えておいてもらえると、読者としては「何のための変更だったの……」と無駄に悩まなくて済んで素敵

- もし`DiameterDouble`の`diameter`で返す値にバリエーションが出てくると、いつでも10を返すという事実がなくなるので、別のクラスを作ったほうが良いのだろうか？ :thinking_face: :thinking_face: 
    - [discord](https://discord.com/channels/432531367427964929/898843794101911622/1084090736481402931)
    - 「10を返す」というケース自体が重要なのでもない限り、DiameterDoubleを拡張して任意の値を返り値として指定可能にする、ぐらいで済ませることが多い
        - DiameterDoubleのコンストラクタでdiameterを指定 & DiameterDouble#diameter はコンストラクタで設定された値をそのまま返すだけ
            - RubyならStructでも十分そう
        - バリエーションは parameterized test を使ってぶん回す

> このダブルは、diameterを「スタブ」します。

- [discord](https://discord.com/channels/432531367427964929/898843794101911622/1084093778081619969)
- DiameterDouble が wheel の代替になっているけれど、そこに wheel っぽい情報を何も出さないのが何なのか読み取れずにいる。Wheel を渡してるのはあくまでDiameterize させたいためで、wheel っていう途中経過はいらないということ？ :thinking_face: 
    - Gearが依存している（=Gearにわたすべき）オブジェクトはここでは Diameterizable なものである、という前提があるから、WheelというDiameterizableのいち具体例を全面に押し出すべきではない、ということかと :+1: :+1: :+1:
        - p.258 図9.4
    - 例えば DBConnection といったI/Fがあって、それに依存したオブジェクトをテストしようとしたとき、テストダブルに MySQLConnectionDouble という名前をつける必要があるか、とか

## 9.2_受信メッセージをテストする_ロールとして依存オブジェクトを注入する_夢の世界に生きる_テストを使ってロールを文書化する_p.261_p.263
### discord開始地点
https://discord.com/channels/432531367427964929/898843794101911622/1084098254188318740

### 感想
> p.261 アプリケーションがはっきりと間違っているのにもかかわらず、テストはのんきに、すべてうまくいっていると報告します。

- [discord](https://discord.com/channels/432531367427964929/898843794101911622/1084106612324712518)
- 破壊的変更の前にテストコードを更新するようにすれば防げるのかな。:thinking_face:
    - このケースの場合、テストコードとテストダブルは更新したがWheelは更新されていない、という可能性はやはり残りますね. より突っ込んだ議論は9.5に回されてしまってますが……
        - そうでしたね……
        - まあこのあたりの問題は、（静的型付け言語など）静的解析が強力な言語なら概ね回避できそうな問題ではあり、動的言語の弱いところではある
            - と思ったけど、テストするオブジェクトを隔離するためにテストダブルを用いる場合は、静的型付け言語でも同様の問題は抱えそう（とすると、型付け云々の話ではないのかも）
            - 思ったよりややこしそう. 静的型付けの場合、そもそもテストダブルを突っ込むときの手順が変わってきちゃう → トータルで「静的型付けならノープロブレム」とは言いにくそう
                - モックライブラリで直接注入オブジェクトを(クラス名だけ拝借する格好で)生成した場合、expectationの設定は文字列になるだろうから同じ問題が起きうる
                - interfaceを切って別途クラス定義したDoubleを使うとコンパイルエラーで回避はできるけど、それはそれで「テストのためだけのinterface定義」が発生して別の問題ががが
 
> テストをする行為自体は、設計の改善を強制しなかったことに注目してください。テストをしたからといって、結合を取り除いたり、依存オブジェクトを注入したくなったりはしません。 - p.263

- まあこれ自体は（少なくとも本文の流れにおいては）その通りで、Gear-Wheelの結合をDiameterizableを介することで緩めたのも「テストしてる内に自然としたくなった」のではなくて、割と教条主義的な（やや強引な）展開によるものだった(p.257-258ぐらいのあたり)
    - テストをすると勝手に結合を緩めようとしたり分離したりしたくなるのではなくて、精々「テストしづらいので、テストしやすいように構造を変更したくなる」ぐらい
        - テストをする ≠ テストしづらい
    - また、「結合を弱めたり分離したりする = 設計の改善」かというとそこも怪しくて、「テストのためだけに、過剰に疎結合にしたり分離したりする」というケースを考えたりすると、やはり「テストが設計の改善を強制するとは限らない」という事自体は十分言えそう :+1:
        - テストのためだけに構造を変更した結果、設計がむしろ悪化する（過剰設計になる）とか
            - 疎結合にしすぎた結果、何が与えられて、具体的に何をするのかというのがわかりづらくなるのはありますよね。（デバッガ、IDEの機能任せでのデバッグ作業が始まる） :+1:

- 最後の２項（「夢の世界に...」〜「テストを使って」）は、「こういう問題もこうすれば解決できるよ」ではなくて、「こういう問題が今度は出てくるよ、こういう手段もありそうだけど不完全だよ、残念だね」で終わりなのね
    - そして続きは9.5で~~すぐ書けー~~

> この節の目的は、受信メッセージをテストすることによってパブリックインターフェースの証明をすることでした。 - p.263

- ~~受信メッセージが意味不明なブツなので~~「メソッドの戻り値」と読みかえるとして、ここでやりたかったことはあくまで「メソッドの戻り値を確認しよう」でしかないのだとしたら、本題はp.253でもう終わってた？
    - ~~また本題 << 余談~~？
    - まあ、今回は余談というより前フリだが、それにしたって二節も空ける必要ある？

### 疑問

## {読書範囲}
### discord開始地点

### 感想

### 疑問

---

# ふりかえり
- 感想/次回の課題それぞれで5分
- 要望に応じて :okawari:

## 感想
https://hackmd.io/E0HZBN9OS9GBAtnsYXjDsw#%E6%84%9F%E6%83%B3

### 気づいたこと、気になったこと
- 言語機能によってテストダブルを作るコストだとかメリット・デメリットが異なることを忘れ、Rubyの話に静的型付けの話を持ってきたのは間違ったかもしれない……
    - この感じ、テストの実行時間云々のような薄い理由だけでテストダブルを採用するのは危険そう。 :+1:
- 具象を直接使うとテスト対象のオブジェクトが隔離されず（ロンドン学派的な問題意識）、テストダブルを使うと「テストは通るがアプリケーションが動かない」という事態になりうる. 静的型付け言語を使ったところで、(特に、nominal typingの場合)回避できない or 別の問題が生じる :+1:
    - この問題について、9.5~~までもったいぶって~~で詳細に説明してくれるようなので、なかなか楽しみ
        - ~~ここまでの著者の前科は忘れるものとする~~
        - この章は特に、「後でのお楽しみ」が多い... :sorena:

### 疑問点

### 仕事に活用してみたいこと

## 次回の課題
https://hackmd.io/E0HZBN9OS9GBAtnsYXjDsw#%E6%AC%A1%E5%9B%9E%E4%BB%A5%E9%99%8D%E3%81%AE%E8%AA%B2%E9%A1%8C

[まとめ用mdに追記](https://hackmd.io/wfDfaf4nRQuPG1BYtcy_jA)


# 次回
https://hackmd.io/RqpZ9hH4Shml66iGjT--Qw?both
