見出し画像

『脳に収まるコードの書き方』の感想など


本の概要と感想


タイトルのキャッチーさ、アンクルボブによるまえがき、吉羽さんと原田さんによる翻訳、ということで無条件にポチってた本が届いたので早速読みました。一気に読みました。
この本には、すごく目新しいことが書かれているわけではありません。著者自身、以下のように書いています。

・・・多くのナレッジはすでに存在しているものの点在していること、ソフトウェア開発の方法について一貫した説明になるようにそれらを明確につなげた人はほとんどいないことに気づきました。・・・バラバラの情報を集めて一貫性のある形で提示することに価値があるのはわかっています。本書は、そのようなパッケージを作ろうとする試みです。

『脳に収まるコードの書き方』はじめに

この本の特徴は、レストラン予約システムを題材とした一つのサンプルアプリケーションを使って各トピックを説明していることです。gitのリポジトリを作成することから始まり、ウォーキングスケルトン(Web層からデータ層までを縦断する、動作可能な最小限のプログラム)の実装、アウトサイドインのアプローチによるテスト駆動開発・・・といった具合に。
ソフトウェア開発の持続可能性のために、開発者の認知負荷を軽減することはこの本の主題の一つですが、一貫性のあるサンプル題材を利用することで、読者の認知負荷を軽減する意図もあるのでしょう。

この本は、一気に読み切ることができる読者もいれば、ところどころ躓く読者もいるのではないかと思います。この本で紹介されるたくさんのプラクティスに既に明るい方は、前者でしょう。それに該当する方も、改めて理解を深めるという意味において十分役立つ本ですし、それだけでなく新たな気づきも得られることと思います。後者の読者、よく知らないプラクティスがあるという方にとっては、より一層効果が高いのではないかと思います。
オライリーの書籍ページで目次を確認することができますので、知らないワードがたくさんあるようなら、それらを一気にまとめて学習するチャンスです。

章構成と読み方

章レベルの目次を以下に引用します。

第I部 加速
第1章 アートかサイエンスか
第2章 チェックリスト
第3章 複雑さに対処する
第4章 バーティカルスライス
第5章 カプセル化
第6章 三角測量
第7章 分解
第8章 API設計
第9章 チームワーク
第II部 持続可能性
第10章 コードの増大
第11章 ユニットテストを編集する
第12章 トラブルシューティング
第13章 関心事の分離
第14章 リズム
第15章 いつもの顔ぶれ
第16章 ツアー

同書 目次

『脳に収まるコードの書き方』という書籍タイトルに対応するトピックは、第3章〜第8章あたりとなります。まずはこの本のエッセンスを掴みたいという方は、第3章〜第8章を先に読むのもよいと思います。 
10章以降は独立したトピックとなっていますので、興味のあるトピックからつまみ食い、もありです。

第6章の補足

第5章と第6章は、ある程度テスト駆動開発(TDD)の知識がないと少し読むのが難しいかもしれません。特に第6章は、僕自身も初読でちょっとわかりづらかった部分があるので、勝手に補足説明します。もし書籍を読んで理解できなかったという場合に参考にして頂ければと思います。

例6-1は、オーバーブッキングできないことを確認するテストコードです。二回目の PostReservation メソッドの呼び出しが座席不足により失敗することを検証するものです。
対応するプロダクションコードの最も愚直な実装が例6-2に載せられていますが、以下のコード断片について意図が説明されていないため、以降の説明が若干わかりづらくなっています。

if (dto.Email == "shli@example.org")
    return new StatusCodeResult(
        StatusCode.Status500InternalServerError);

これは、座席不足によって二回目のメソッド呼び出しが失敗するというアサーションを通過(パス)することを目的とした、仮の実装です。二回目の呼び出しであることを判定するために、一意な情報となるメールアドレスを用いています。
このような、まずテストケースをパスさせることを目的とした適当な仮実装のことを、著者は「悪魔の代弁者」と呼んでいます。

そして、この仮実装が誤っていることを証明するために、例6-3では別の正常系のテストにケースを追加しています。

[InlineData("2022-03-18 17:30", "shli@example.org", "Shaghai Li", 5)]

パラメーター化テストのテクニックを使って追加したこのケースは、全て
妥当な値で構成されており、本来テストはパスするはずです。実際には失敗するということは、「悪魔の代弁者」による誤った実装によって、SUTの振る舞いが壊れたことの証左というわけです。

なお、パラメーター化テストはとても便利なのですが、テストの意図が不明瞭になってしまうリスクがあるので注意が必要です。テストケース毎にメソッドを分けていればメソッド名でテストの意図を明示できますが、それができなくなるということです。この事態を避けるには、パラメーターには必ずdescription(説明)を含めることです。

[InlineData("2022-03-18 17:30", "shli@example.org", "Shaghai Li", 5, "〜〜の検証")]
public async Task PostValidReservationWhenDatabaseIsEmpty(
    string at,
    string email,
    string name,
    int quantity,
    string description)

また、「悪魔の代弁者」を打ち破るために導入した追加ケースは、一時的なものであり、既存のテストケースと意味的に重複します。これは後からテストコードを読む人を混乱させる元となりますので、用済みになったら削除すべきです。このように、TDDは設計の道具であるため、スキャフォールド(足場)として仮置きするテストコードが存在します。あまり言及されることがないのですが、このようなテストコードの整理(後片付け)もTDDのアクティビティでは必要となります。

脱線してしまいましたが、続く例6-4では、「悪魔の代弁者」による仮実装を、本来のあるべき実装(Repositoryから取得した予約情報を見てオーバーブッキング判定)へ置き換えを行っています。


この記事が気に入ったらサポートをしてみませんか?