セキュア・バイ・デザイン

最近セキュア・バイ・デザインという本を2週間くらいかけて読んでいた。

感想

社内の輪読会で読むことになり、少し先取りして読んでみたところ、面白いし読みやすかったため、一気に読み進めてしまった。前回の「単体テストの感想/使い方」に並んで、大当たりの本だった。

内容

タイトルからは想像つかないけど、感覚的には7割くらいはDDDの実装パターンの話で、残りはセキュリティの話という印象だった。DDDに則った設計を推し進めることでセキュアなサービスにつながるという感じだった。

以下は印象にのこったことを書いていく。

汎用データ型が適切な場面はほとんどない

intstringといった汎用データ型がドメインモデルの表現として適切であることはほとんどない、という強烈なパンチラインが最初の方に出てくる。

例えば、ユーザー名を表すデータ型としてstringを使うのは当然だと思われるが、ユーザー名に使える文字種や長さといったドメインルールをUserクラスなどそれを包含する概念で検証するのではなく、UserNameクラスを新たに作りそこで検証させる方が凝集度が高くfail-fastな設計になるということだった。当然ながら、このUserNameクラスの中で文字列の表現としてstringを使うことにはなるが、それを直接使うことはないということだろう。

確か「Domain modeling made functional」にも同じような話が出てきた記憶がある。ただのstringではなく型エイリアスを使ってドメインを型として表現することの重要性について書かれていたはず。

契約プログラミング

自分は例の分厚い「オブジェクト指向入門」を読んだことがなく、ちゃんと契約プログラミングについて書かれた本を読んだことがなかったのだけど、本書には部分的に契約プログラミングについて書かれた箇所があり、とても勉強になった。

以前読んだ「単体テストの考え方/使い方」の中でも「事前条件」「事後条件」「不変条件」といった用語は登場しており、契約プログラミングはプログラミングにおける基本的な考え方の一つとして捉えられるのだろう。

本書では値オブジェクトの不変条件を守るために、コンストラクタにおいて引数を検証する実装を紹介している。そして、immutableであり、かつ不変条件が常に保証された値オブジェクトを特にドメイン・プリミティブと呼んでいる。

コードレビューと確証バイアス

本書では一致する特徴を探してしまう人間の習性のことを確証バイアスと呼んでおり、それがコードレビューにも影響するという話が面白かった。

レビューするコードの99%が正しかったとすると、無意識のうちに残り1%も正しいだろうと思い込んでしまう。逆に、バグをいくつか見つかると、他のコードも疑わしく見えてくる。

警察官はこういった確証バイアスに陥らないように特殊な訓練を受けているそうだけど、僕たちプログラマーも確証バイアスに陥らない工夫が必要になるのだろうと思った。

コレクションを持つエンティティの完全性

エンティティのメンバーにListなどのコレクションがある場合、エンティティの完全性を保つ工夫が必要という話。

エンティティは、immutableである値オブジェクトとは異なり、mutableな存在なので、コンストラクタで不変条件を検証するだけでは不十分で、setterや状態を更新するメソッドにおいて不変条件が守られているかを検証する必要がある。なので、mutableなメンバーをpublicにせず状態を更新するメソッドにカプセル化するといった基本的な工夫をとることになる。

ただ、コレクションをメンバーに持つ場合はさらに踏み込んで考える必要がある。コレクションそのものをgetter等で外部に公開すると、そのコレクションの中身を外部から更新できてしまうため、エンティティの不変条件を守れなくなってしまう。

そこで、外部にコレクションを公開する場合は、コレクションそのものではなくimmutableな参照を返すようにする。Javaにはこれを可能にするCollection.unmodifiableListといった便利メソッドがある。これにより、外部の利用者に読み取り専用のコレクションを公開できるようになる。

ドメインDoS攻撃

ドメインDoS攻撃というのは、ドメインルールを悪用してサービスを提供できない状態に追い詰める攻撃のことで、本書ではホテルに5000件予約してキャンセル料が発生する直前で全件キャンセルするといった攻撃が紹介されていた。

こういった攻撃が存在することを知っているだけでも、ドメインルールを悪用してみようという発想が生まれ、そこから隠されたドメインルールを発見する手がかりが生まれると思う。

11章全部

11章は保険アプリケーションを開発する企業においてチーム間で「支払い」に関わる認識のずれに誰も気づかないまま機能をリリースした結果、裁判沙汰にまで発展したという話で、一見同じに見えるドメインモデルでもそのコンテキストを意識しなくてはならないという示唆があったし、コンテキストごとにチームを分割することで独立して動けるようになったが、そのコンテキストマッピングを疎かにしたことによる弊害に気付かされた。個人的に非常に刺さる内容だった。