Upgrade to Pro — share decks privately, control downloads, hide ads and more …

値オブジェクトでアプリケーションコードを改変しよう

 値オブジェクトでアプリケーションコードを改変しよう

車内のミートアップの発表資料

67de06c6cee3ece0f56494e91e48117e?s=128

tkitsunai

May 21, 2020
Tweet

Transcript

  1. 値オブジェクトで アプリケーションコードを改変しよう Takayuki Kitsunai

  2. 自己紹介 ・橘内 孝幸( Takayuki Kitsunai ) ・SaaS Product Division (

    SPEEDAの色々を開発してます ) ・Gopher
  3. 発表の目的 ・なんとなく値オブジェクトを作っていないか、考えるきっかけを作りたい ・値オブジェクトになっていないコードを見たら、一緒にうずうずしたい

  4. 値オブジェクトについて ・Domain-Driven Designの構成要素の一つ 【特徴・特性】 ・一意性を持たない ・不変である ・計測/定量化/説明ができる

  5. 値オブジェクト、使ってますか?

  6. 値オブジェクト、「ちゃんと」使えてますか?

  7. 値オブジェクトたらしめる条件、その価値 1. 値が同じであれば同一であることを保証しているか(等価性) 2. 値の範囲を限定し、許容値をコントロールする 3. 不変化により、インスタンス化後のバグ混入を防ぐ(交換性) 4. それらを扱う名前が「計測/定量化/説明」をしているか これらの条件を満たすと、

    表現力豊かに、コードがモノを矛盾なく説明できるようになる
  8. 値が同じであれば同一であることを保証する type PersonName struct { value string } func NewPersonName(value

    string) PersonName { return PersonName{ value: value, } } name1 := NewPersonName("tkitsunai") name2 := NewPersonName("tkitsunai") if name1 == name2 { // true } ポイント:同一インスタンスかではなく値が同じであるか
  9. 値の範囲を限定し、許容値をコントロールする type SecurityCode struct { value int } func NewSecurityCode(value

    int) (SecurityCode, error) { if value < 1300 || value > 9999 { return SecurityCode{}, errors.New("証券コードの値範囲外です ") } return SecurityCode{ value:value, }, nil } 例:東京証券取引所が扱う「証券コード」 ・1300番台〜9000番台から構成される
  10. 不変化により、インスタンス化後のバグ混入を防ぐ type SecurityCode struct { value int } func NewSecurityCode(value

    int) (SecurityCode, error) { if value < 1300 || value > 9999 { return SecurityCode{}, errors.New("証券コードの値範囲外です ") } return SecurityCode{ value:value, }, nil } uzabase := NewSecurityCode("3396") // このようなことはできないようにする uzabase.value = 3397 ファクトリー関数やコンストラクタで不変化する
  11. 値オブジェクト警察をしてみよう type Company struct { name string address1 string address2

    string listedFlag bool securityCode int phoneNumber string } こんなコードを見かけると、うずうずしてきませんか?
  12. 値オブジェクト警察への道 フェーズ1: プリミティブな値を探そう type Company struct { name string address1

    string address2 string listedFlag bool securityCode int phoneNumber string } type Company struct { name Name address1 Address address2 Address listedFlag ListedStatus securityCode SecurityCode phoneNumber PhoneNumber }
  13. 値オブジェクト警察への道 フェーズ2: 名前が適切かを考えてみよう type Company struct { name Name address1

    Address address2 Address listedFlag ListedStatus securityCode SecurityCode phoneNumber PhoneNumber } // 上場企業 type ListedCompany struct { } // 非上場企業 type UnlistedCompany struct { } // 企業の名前 type CompanyName struct { } // 人の名前 type PersonName struct { }
  14. 値オブジェクト警察への道 フェーズ3: それは値オブジェクトか?を考える 先の例では、「企業」を値オブジェクトとして作りました ・システムのコンテキスト範囲「企業」の扱い方によって、エンティティ (※1)になる ・値オブジェクトの特性から外れる場合に値オブジェクトのままで良いか? ※Eric Evans「ドメイン駆動設計」の「VALUE OBJECT」章のコラムをぜひご参照ください

  15. まとめ ・値オブジェクトを知る - 「特徴・特性」を満たしてはじめて値オブジェクトと言える ・値オブジェクトが生み出す価値 - 表現力(説明力を含む)をあげる - 矛盾なきコードをつくる -

    許容値のコントロールをする ・値オブジェクト警察 - プリミティブな値を使わない - 適切な名前か(値オブジェクトの条件「説明」ができるか) - これは値オブジェクトか否かを見極める
  16. おわり