nikkie-ftnextの日記

イベントレポートや読書メモを発信

読書&写経ログ | #ちょうぜつ本 6.6 5章で見たFizzBuzzはどう作られた? モックを使って設計の仮説検証をしながら!

はじめに

変更しやすいコードが書けないのにソフトウェア開発とか舐めているのですか
天使様1ごめんなさい〜、nikkieです

「かわいい」と技術書が夢の合体を果たした、ちょうぜつ本(『ちょうぜつソフトウェア設計入門』)!🤗
読書会と絡めて読み進めており、今回は第6章「テスト駆動開発」の6.6を写経しつつ読みました。

目次

前回のちょうぜつ本!

いわしまんさんの書評エントリがきっかけで、手に取りました。
6.5まで読み進め、BDDを体験。

次の読書会の予習の一環で、今回は6.6に取り組みます

仕様変更を考慮したFizzBuzz

5章のOCP(開放閉鎖原則)で、仕様変更を考慮したFizzBuzza.k.a. ジェネリックFizzBuzz)の実装例が登場します2
このFizzBuzzがどうできたのか、それが6.6で明かされるのです!

6.5からつなぐ言葉は設計手法としてのTDDでした。
テスト駆動開発を設計に使って、5章で見たFizzBuzzが実装されていきます!

TDDでジェネリックFizzBuzz

ポイントは、モックを使って仮説検証していくことだと思いました。

  • 抽象についての仮説(初案)
    • 整数を文字列に置換するルールがある (Kindle版 p.245)

    • replaceメソッドを定義したReplaceRuleInterface3
      • 整数を文字列にreplace
  • ReplaceRuleInterface(抽象)をモックして具象を用意しFizzBuzzのロジックのテストを書く
    • replaceメソッドが引数1で呼ばれたら、"hoge"を返すのようにモックを設定
    • 具象のルールが実装されていなくても、テストではモックを具象として動作検証できる
    • FizzBuzzのロジックはできた!
  • ReplaceRuleInterface(抽象)を実装した具象4
    • 倍数のreplaceを扱う具象
    • 数字を文字列にreplaceする具象
  • できたー!! BDD的なテストで動作確認するぞー
    • 「Fizz3だと!?」(Kindle版 p.258)

初案をもとに、テストファーストFizzBuzzを実装していきますが、最後BDDで予期せぬ動きとなります。
このエラーを分析し、抽象についての仮説の2案目に至ります。

  • 抽象についての仮説(第2案)
    • ReplaceRuleInterfaceは(replaceの代わりに)applyメソッドとmatchメソッドを定義
    • FizzBuzzのロジックの実装を、ruleにmatchしたらapplyと変える
      • applyは累積する(畳み込み演算!)
  • インターフェースを変えたのでテストは落ちる。1つ1つ直していく
  • 直し切ると、BDD的なテストも通る!!🙌

写経したコードはこちら:

ここで紹介されたモックの使い方(抽象をモック)を、私はほとんどしてきませんでした。
写経してやってみたときにハッとしたのはこの一節です。

仕様を頭の中で考えているうちは、どれだけ知恵をしぼろうと、完全な設計を得ることはできません。(Kindle版 p.262)

たしかに、仕様を頭の中でしか考えていなかったな〜、と。
「開発完了!テストも通ってる!動かすぞ〜」となって、実データに対して動かない経験をしてきました。
これって抽象をモックして検証できておらず5、手を動かして仮説検証が足りなかったから、完全な設計に至ってなかったってことじゃないかと思います。
抽象をモックすると、「実データに対して動かない!」の検出タイミングが前倒しになると理解しました(具象を作るより前に気づける!)。

シンプルさ

設計手法としてのTDDで至ったFizzBuzzシンプルだと思います。
これはRich Hickeyが語る意味でのシンプル6、イメージはレゴブロックです。

Pythonで表すと以下のようになるのですが、

fizz_buzz = NumberConverter(
    [
        CyclicNumberRule(3, "Fizz"),
        CyclicNumberRule(5, "Buzz"),
        PassThroughRule(),
    ]
)

1つ1つは小さなRuleを組合せてFizzBuzzを実現しているという点がシンプルだと思うのです。
Ruleがレゴブロックの1つ1つで、Ruleを組合せてFizzBuzzができあがります。
そして作ったものの作り直しも簡単です!

ここに至るには、TDDのTODOリスト7からして違うのではないかと思うのです。
FizzBuzzの仕様からTODOを書き起こしたのではなく、長生きすると分かっていて(もしくは確度高くそう信じられて)変更容易な=シンプルなFizzBuzzの仕様として書き起こしたのではないでしょうか。
そして実装中も抽象についての仮説をモックで検証していき、仮説検証のフィードバックを元にTODOリストを更新しているように思えます。

テスト駆動開発を味方につけた設計には、気づきのヒントが何度も登場しました。(Kindle版 p.276)

終わりに

ちょうぜつ本 6.6で、設計手法としてのTDDを体験しました。
モックを使って抽象(仮説)を検証し、シンプルなFizzBuzzに到達します。

6章の扉には「変更に対して安全なアーキテクチャの設計を、確かに動くものとして作っていく方法」とあり、6章までできれいに示されたなと感服です👏
ここで紹介された方法は私はあまり経験がないのですが、「変更容易な設計にするには、こういう抽象がいいんじゃないかな」という仮説を早期に検証できるのがよさそうなので、自分のプロジェクトなどで練習していきたいですね。

P.S. 9/22(金) 第6章「テスト駆動開発」後半のちょうぜつ本_読書py!

次回ちょうぜつ本_読書py(Python使い視点でちょうぜつ本を読む、みんなのアウトプット中心の読書会)は9/22(金)です!

常連さんも、お久しぶりの方も、はじめましての方もテスト駆動開発に興味ある方、大歓迎です!
ぜひぜひお気軽にお越しください〜


  1. ちょうぜつ本読書ログシリーズではおなじみのこちらの書き出し。元は『お隣の天使様にいつの間にか駄目人間にされていた件』の「家事ができないのに一人暮らしとか舐めているのですか」です
  2. 本質を抜き出して変更に対して閉ざし、仕様は拡張に対して開きます。読書ログ | #ちょうぜつ本 第5章 〜SOLID原則、この章までの積み重ねと豊富なサンプルコードでこれまでで一番分かりやすかった解説!〜 - nikkie-ftnextの日記
  3. ソースコードにおいて、抽象はcoreに置かれています
  4. ソースコードにおいて、具象はspecに置かれています
  5. 実力不足で、そもそも抽象が浮かばなかったこともありました
  6. 直近ではこちらで取り上げました
  7. 直近書いた おーい、t-wadaさん、ペアプロしようぜ!TDD Boot Camp 2020 Online #1 基調講演/ライブコーディング 視聴ログ🦁 - nikkie-ftnextの日記 をどうぞ