torutkのブログ

ソフトウェア・エンジニアのブログ

Java読書会「セキュア・バイ・デザイン」を読む会(第4回)開催

10月15日(土)、Java読書会BOF主催の「セキュア・バイ・デザイン」を読む会(第4回)を開催しました。

本日は、ドメイン・プリミティブの残り、Read-Onceオブジェクト(一度しか読み込めないオブジェクト)、エンティティの触りの部分(5章の途中から6章の途中)を読み進めました。

読書メモ
  • 機密性の高いデータの流出を低減する設計として、Read-Onceオブジェクトと呼ぶ設計パターンがある

    • 機密性の高い値または概念を表現する
    • 対象データが意図しない使われ方をしたことを検出しやすくする
    • ドメイン・プリミティブの一種とすることが多い
    • 値は1度しか読み込めない、シリアライズさせない、サブクラスを作成できない
      • 値を読み出すと、その値を消すことで2度目は読めないようにする
  • エンティティが、intやStringなどのプリミティブな(値の制約がない)データで構成されていると、エンティティ本来の処理(ビジネスロジック)に加えて、データの妥当性確認、不変条件確認などをする必要が増え複雑になってしまう

  • ドメイン・プリミティブの再確認(前回の範囲の復習)

    • p.139 「ソフトウェアの設計に事前条件と契約による設計(design by contract)を施すことで、ソフトウェアを効果的により安全にすることができる」
      • 契約による設計がサポートされていない言語では開発者自身がコード上に実装しなければならない
      • publicなメソッドで引数の事前条件確認
      • コンストラクタで不変条件確認
    • p.151 「システムの安全性を保つためには、データの妥当性を確認することが重要」
      • 妥当性確認の分類・順序として、オリジン(発生源)、サイズ、字句的内容(lexical content)、構文(syntax)、意味(semantics)がある。ドメイン・プリミティブでは、意味を除く他の妥当性の確認を含める(意味はエンティティで確認)
    • ドメイン駆動で紹介された値オブジェクト(value object)の重要な特徴である不変(immutable)と完結した概念(conceptual whole)に加えて、オブジェクト生成時に不変条件の確認を導入することで、生成されたオブジェクトが常に不変条件を維持する
  • ドメイン・プリミティブを適用するのに反対の声も大きい

    • 書くのが手間?
    • クラスが増え過ぎて理解容易性が下がる
  • ドメイン・プリミティブを適用しない場合、エンティティでデータの妥当性確認、不変条件の確認、機密性の高いデータのRead-Onceを実装する。

    • 複数のエンティティで同じ妥当性確認、不変条件確認、Read-Onceを実装する場合、DRY原則が崩れるのでドメイン・プリミティブを導入σルト良い
    • 単独のエンティティでしか実装しないとしても、これによりエンティティが複雑化(肥大化)するなら導入する価値がある
    • 妥当性確認・不変条件確認を共通関数ライブラリで外出しするのはいけていない。データとロジックが分離し、データを扱うときにそのロジックが適用されるのを忘れる
  • エンティティの生成

    • 引数なしコンストラクタは危険
      • O/Rマッパーの制約で引数なしコンストラクタが必須(ではない、回避方法あり)
      • O/Rマッパーは永続層に隔離し、ドメイン・オブジェクトは別途生成
      • privateコンストラクタでアノテーション付与すればO/Rマッパー適用可能、など
      • ビルダーパターンで内部クラスに実装
Javaの今後で検討されている言語機能の拡張

Value objectを言語機能に取り入れる JEPが検討中です。

JEP draft: Value Objects (Preview)

value classは、インスタンスの一意識別を持たず、デフォルトでfinal class、全てのフィールドがfinalとなり、==で全てのフィールドの値が一致するかを判定、synchronizedを持てないという仕様のようです。

セキュア・バイ・デザインで設計パターンとして紹介しているドメイン・プリミティブの実装に役立つ機能です。

次に、プログラマーが定義できるプリミティブ型を言語機能に取り入れるJEPが提案されています。

JEP 401: Primitive Classes (Preview)

これまでJava言語仕様に欠けていた、符号なし整数や、128bit整数、座標、複素数、単位を持つ数値、タプルなどをユーザー定義型で導入できるようになるようです。int型などのプリミティブ型同様nullを保持できない。 オブジェクトヘッダーを持たず、メモリ上に値が直接並ぶような構造になる模様。 これも、ドメイン・プリミティブの実装に役立つ機能となると思います。