$30 off During Our Annual Pro Sale. View Details »

集約の設計と実装

 集約の設計と実装

かとじゅん
PRO

April 16, 2018
Tweet

More Decks by かとじゅん

Other Decks in Programming

Transcript

  1. ू໿ͷઃܭͱ࣮૷
    ͔ͱ͡ΎΜ(@j5ik2o)

    View Slide

  2. ΞδΣϯμ
    • ໨త
    • DDDͷઓज़తύλʔϯͷதͰൺֱతʹॏཁͰ೉ղͰ͋Δɺू໿
    ΛͲͷΑ͏ʹઃܭɾ࣮૷͢ΔͱΑ͍͔ɺ஫ҙ఺ͳͲ΋౿·͑ͳ
    ͕Βղઆ
    • ΞδΣϯμ
    • ू໿ͱ͸
    • ू໿ͷڥք
    • ࣗಈंमཧళͰͷࣄྫ
    • ܖ໿ʹΑΔઃܭ(DbC)
    • ू໿Λ࣮૷͢ΔͨΊͷϧʔϧ(Evans and Vernon)
    • ·ͱΊ

    View Slide

  3. ू໿ͱ͸
    • ϥΠϑαΠΫϧΛڞʹ͢Δɺؔ࿈͕ਂ
    ͍ෳ਺ͷΦϒδΣΫτΛɺͻͱ͔ͨ·
    Γͷ”ू໿”ͱͯ͠ѻ͏
    • ू໿ΛมߋͷҰ؏ੑΛอূ͢ΔҰͭͷ
    ୯Ґͱͯ͠ɺଞͷΦϒδΣΫτͷʮڥ
    քʯΛ໌֬ʹ෼͚Δ
    • ΦϒδΣΫτ͸ଞͷΦϒδΣΫτͱؔ
    ࿈Λ࣋ͭՄೳੑ͕͋Δ͕ɺෆద੾ͳϩο
    Ϋ͸ϢʔβϏϦςΟΛ௿Լͤ͞Δɻಉ
    ͡ߦΛฤू͍ͯ͠ͳ͍ͷʹจॻશମΛ
    ϩοΫͳͲ͸ϩοΫڝ߹ͷԹচʹͳΔ
    ू໿

    View Slide

  4. ڥք͸Ͳ͜ʁ
    • DB͔ΒैۀһΦϒδΣΫτΛ࡟আ͢Δέʔε
    • ैۀһͱڞʹ໊લɾੜ೥݄೔ɾ৬຿۠෼͸ͳ͘
    ͳΔ͕ɺ෦ॺ͸Ͳ͏ͩΖ͏͔ʁ
    • ෦ॺ͕ैۀһͷڥքʹؔ܎ͳ͍͜ͱ͸ࣗ໌͕ͩɺ
    ͦͷ൑அج४Λ࿦ཧతʹઆ໌Մೳ͔ʁ
    • ͨͱ͑͹ɺಉ͡෦ॺʹผͷैۀһ͕ॴଐ͍ͯ͠
    Δ͔΋͠Εͳ͍ɻͦͷ෦ॺΛ࡟আ͢Δͱผͷै
    ۀһΦϒδΣΫτ͸࡟আ͞ΕͨࢀরΛ࣋ͭ͜ͱ
    ʹͳΔɻٯʹ์ஔ͢Ε͹ɺDBʹෆཁͳ෦ॺΛ
    ͨΊࠐΉ͜ͱʹͳΔ
    ू໿

    View Slide

  5. ڥքະఆٛʹΑΔ໰୊
    • ଘࡏ͢Δෳ਺ͷΦϒδΣΫτ͕ɺ͍ͭ
    ࡞ΒΕɺ͍ͭͳ͘ͳΔͷ͔ʁ
    • σʔλΛมߋ͢Δൣғ(τϥϯβΫ
    γϣϯείʔϓͳͲ)΍σʔλͷҰ؏ੑ
    Λҡ࣋͢Δϧʔϧ͕ͳ͚Ε͹ͳΒͳ͍
    • ڥքະఆٛͷ··ɺDBͷϩοΫػߏ
    Λར༻͢Δ͜ͱ͕Ͱ͖Δ͕ɺͦͷ৔͠
    ͷ͗ͷղܾࡦͱݴΘ͟ΔΛಘͳ͍(ѻ
    ͍Λؒҧ͑Ε͹ϩοΫ͕ڝ߹͢ΔՄೳ
    ੑ͕͋Δ)
    • ຊ࣭͸Ϟσϧʹ͋Δɻ͜ΕΒͷ໰୊͸
    ڥքΛఆٛ͢Δ͜ͱͰղܾͰ͖Δ
    ू໿
    $BS
    5JSFT &OHJOF
    5JSFTͱ&OHJOF͸Ұॹʹ
    ࡞ΔʁͦΕͱ΋ผʑʁফ
    ͢ͱ͖͸ಉ͡ͳͷʁ
    λΠϠަ׵ޙʹλΠϠ͕ຊ͔͠ͳ͍
    ঢ়ଶ͚ͩͲʜɻͦΕυϝΠϯΦϒδΣ
    Ϋτ͕յΕ͍ͯΔঢ়ଶͰ͸ʜɻ
    ंʹऔΓ෇͚ΒΕΔલͳΒ͍͍ͷ͔ʁ
    // ू໿Λލ͕ΔΑ͏ͳτϥϯβΫγϣϯʁͦΕͱ΋Ұͭͷू໿ͱ͠
    ͯѻ͍ͬͯΔͷ͔ʁ
    def updateCar(car: Car) = {
    withTranscation { implicit con =>
    updateRecord(car.id, car.tires)
    updateRecord(car.engine.id, car.engine.typeName)
    }
    }
    // ͋Εʁͬͪ͜͸୯ಠͰߋ৽͢ΔΑ͏ͩɻڥք͕໌ࣔ͞Ε͍ͯͳ͍…
    def updateEngine(engine: Engine) = {
    withTranscation { implicit con =>
    updateRecord(engine.id, engine.typeName)
    }
    }

    View Slide

  6. ڥքΛͲͷΑ͏ʹఆٛ͢Δͷ͔
    • Ϟσϧ಺ʹ͋ΔࢀরΛΧϓηϧԽ͢ΔͨΊͷந৅Խ͕
    ඞཁɻؔ࿈͢ΔΦϒδΣΫτ܈Λͻͱ͔ͨ·Γͱ͠ɺ
    σʔλΛมߋ͢Δ୯Ґͱͯ͠ѻ͏ɻ͜Ε͕ू໿ͷ໾ׂ
    • ֤ू໿ʹ͸ڥքͱϧʔτ͕͋Δ
    • ڥք͸ू໿಺෦ʹԿ͕͋Δ͔Λఆٛ͢Δ
    • ϧʔτ͸ू໿ʹؚ·Ε͍ͯΔಛఆͷ1ΤϯςΟςΟ
    (ϧʔτΤϯςΟςΟ)
    ू໿
    ϧʔτ
    " #
    % &
    $
    ڥք

    View Slide

  7. ࣗಈंमཧళ޲͚γεςϜͷྫ
    • λΠϠͷϩʔςʔγϣϯͷه࿥
    ͱɺ֤λΠϠͷ૸ߦڑ཭ͱ઀஍
    ໘ͷຎ໣౓߹͍Λ௥੻͢Δ
    • ࣗಈं͸άϩʔόϧͳಉҰੑΛ
    ࣋ͭϧʔτΤϯςΟςΟɻࣝผ
    ࢠʹ͸ं྆൪߸Λར༻͢Δ
    • λΠϠ͸ࣗಈं͔Β཭ΕΔͱಉ
    ҰੑΛؾʹ͠ͳͯ͘Α͍ɻަ
    ׵͞Εͨݹ͍λΠϠ͸௥੻Λࢭ
    ΊΔ͔ɺͨͩͷ஋ΦϒδΣΫτ
    ͱͯ͠ࡏݿΛ؅ཧ͢Ε͹Α͍
    ڥք
    ࣗಈं
    λΠϠ λΠϠ
    λΠϠ λΠϠ
    ू໿

    View Slide

  8. FYI: ΦϒδΣΫτΛḷΔೋͭͷํ๏
    • ಛఆͷλΠϠΛ୳͢৔߹͸ɺ
    ·ͣࣗಈंΛಛఆ͔ͯ͠Βɻ
    ं྆൪߸Λ࢖ͬͯDBʹΫΤϦ
    Λ͔͚Δ
    • ͦͷͨΊɺλΠϠ͕ࣗಈंʹ
    ૷ண͞Ε͍ͯΔؒ΋άϩʔό
    ϧͳಉҰੑ͸ෆཁɻϧʔτΤ
    ϯςΟςΟ͔ΒࢀরΛḷΔ
    • ͢΂ͯͷΦϒδΣΫτ͕ू໿
    ͩͱɺ੔߹ੑͷҡ࣋؅ཧ͕൥
    ࡶԽ͢ΔՄೳੑ͕͋Δ
    ڥք
    ࣗಈं
    λΠϠ λΠϠ
    λΠϠ λΠϠ
    %#
    ΫΤϦ
    ࢀর
    ू໿

    View Slide

  9. Ϣʔεέʔε͔ΒڥքΛݟ͚ͭग़͢
    • ҰํɺΤϯδϯ͸ಠཱͨ͠ू໿ or ू
    ໿಺෦ͷΦϒδΣΫτʁ
    • ࣗಈंͱಠཱͯ͠௥੻͢ΔϢʔεέʔ
    εͰ͋Ε͹ɺΤϯδϯ͸ಠཱͨ͠ू
    ໿ͱͳΔɻ
    • ं͕ΤϯδϯΛ಺แ͢Δͱ͍͏ࢥ͍
    ࠐΈͱ͸૬൓͢Δ͔΋͠Εͳ͍͕ɺ
    ϢʔεέʔεΛແࢹͯ͠ϞσϧΛ࡞
    Δͱ໾ʹཱͨͳ͍Ϟσϧʹͳͬͯ͠
    ·͏
    • Ϣʔεέʔε͔ΒϞσϧΛ૑଄͢Δ
    ͜ͱ͸ඞཁ͕ͩɺϞσϧͷ੔߹ੑ͕
    ੒Γཱ͔ͭݕূ΋ඞཁɻ͜Ε͸྆ྠ
    ڥք
    ࣗಈं
    λΠϠ λΠϠ
    λΠϠ λΠϠ
    Τϯδϯ
    ڥք
    ू໿

    View Slide

  10. Evansϧʔϧ1
    • ϧʔτΤϯςΟςΟ͸ɺάϩʔό
    ϧͳಉҰੑΛ࣋ͪɺෆม৚݅(ͦ
    ͷϞσϧ͕࣋ͭੑ࣭)ΛνΣοΫ͢
    Δ੹຿Λෛ͏
    • λΠϠͷަ׵͸ϝιουͳͲΛհ
    ͯ͠ߦΘΕΔɻܾͯ͠಺෦ͷΦϒ
    δΣΫτΛ௚઀ૢ࡞ͤͯ͞͸ͳΒ
    ͳ͍(λΠϠϩʔςʔγϣϯϧʔϧ
    Λڧ੍ͤ͞ΔͳͲͷෆม৚݅Λҡ
    ࣋͢ΔͨΊʹ)
    ڥք
    ࣗಈं
    λΠϠ
    λΠϠͷަ׵
    λΠϠ
    λΠϠ λΠϠ
    ं྆൪߸
    λΠϠ
    ू໿

    View Slide

  11. ෆม৚݅ is Կ?

    View Slide

  12. ԣಓʹҳΕͯ
    ܖ໿ʹΑΔઃܭ(DbC)

    View Slide

  13. ઌ಄ͷࡾจࣈΛฦ͢ϝιου1
    package example
    object Example1 extends App {
    def getThree(s: String): String = s.substring(0, 3)
    println(getThree("12345"))
    }
    • Ҿ਺ͷจࣈྻ͔Βઌ಄ࡾจࣈΛൈ͖ग़͠ฦ͢ϝιου
    • ਖ਼͘͠ಈ࡞ͦ͠͏Ͱ͢…
    123
    %C$

    View Slide

  14. ઌ಄ͷࡾจࣈΛฦ͢ϝιου2
    package example
    object Example1 extends App {
    def getThree(s: String): String = s.substring(0, 3)
    println(getThree("12"))
    }
    • ͜Ε͸αʔϏεଆͷόάͰ͠ΐ͏͔ʁ
    • ͦΕͱ΋ΫϥΠΞϯτଆͷόάͰ͠ΐ͏͔ʁ
    Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 3
    at java.lang.String.substring(String.java:1963)
    at example.Example1$.getThree(Example1.scala:5)

    at scala.collection.immutable.List.foreach(List.scala:389)
    at scala.App.main(App.scala:76)
    at scala.App.main$(App.scala:74)
    at example.Example1$.main(Example1.scala:3)
    at example.Example1.main(Example1.scala)
    %C$

    View Slide

  15. ౴͑͸࢓༷ະఆٛ
    • ౴͑͸ɺ͍͍͑
    • ϝιουͷڍಈ͕ਖ਼͍͔ؒ͠ҧ͍ͬͯΔ͔͸͖ͬΓͯ͠
    ͍·ͤΜɻ͜ͷέʔεͰ͸࢓༷͕໌֬ʹఆٛ͞Ε͍ͯͳ
    ͍(࢓༷ະఆٛ)
    • ίʔυΛಡΊ͹࢓༷͸Θ͔ΔͷͰ͸ʁ
    %C$

    View Slide

  16. ίʔυ͔Β࢓༷͕Θ͔Βͳ͍ྫ
    package example
    case class User(id: Long, name: String, deptId: Long)
    trait UserRepository {
    def findByDeptId(depId: Long): Option[Seq[User]]
    }
    object UserRepository1 extends UserRepository {
    override def findByDeptId(depId: Long): Option[Seq[User]] = None
    }
    object UserRepository2 extends UserRepository {
    override def findByDeptId(depId: Long): Option[Seq[User]] = Some(Seq.empty)
    }
    object Example2 extends App {
    def printUser(userRepository: UserRepository, deptId: Long) =
    userRepository.findByDeptId(deptId) match {
    case None => println("users are empty")
    case Some(users) => println(s"users = $users")
    }
    printUser(UserRepository1, 1) // users are empty
    printUser(UserRepository2, 1) // users = List()
    }
    • ໭Γ஋ΛνΣοΫ͢Δ͚ͩͰ͸ɺਖ਼͠͞͸Θ͔Βͳ͍
    ͲͪΒͷ໭Γ஋Λฦ͢
    ͷ͕ਖ਼͍͠ʁ
    %C$
    Ұൠతʹɺ࢓༷ΛࣗવݴޠͰࣔ
    ͞ͳ͍ݶΓɺΘ͔Βͳ͍ɻ
    Ͳ͏ද͢ͱ͍͍͔ → DbC͕Ұͭ
    ͷ౴͑

    View Slide

  17. ܖ໿ʹΑΔઃܭ(Design by Contract)
    • όά(ʹ࢓༷ͱ࣮૷ͷໃ६)ͱ൑அ͢Δਖ਼͠͞ͱ͸͍͍ͬͨԿ͔ʁ
    • ”ਖ਼͠͞ͱ͸૬ରతͳ֓೦Ͱ͋Δ”
    • ΦϒδΣΫτࢦ޲ೖ໳ ୈ2൛ ݪଇɾίϯηϓτ ୈ11ষ ܖ໿ʹΑΔઃܭ:৴པੑͷߴ͍ιϑτ΢ΣΞΛߏங͢Δ
    • ιϑτ΢ΣΞཁૉͦͷ΋ͷ͕ਖ਼͍͔͠Ͳ͏͔Ͱ͸ͳ͘ɺରԠ͢Δ࢓༷ͱҰக͢
    Δ͔Λ࿦ͣΔ΂͖(ιϑτ΢ΣΞཁૉͱ࢓༷ͷϖΞͰߟ͑Δ)
    • ਖ਼͠͞ΛධՁ͢Δʹ͸ɺ”ද໌”Λ࢖ͬͨ࢓༷ͷهड़ํ๏Λར༻͢Δͷ͕Ұൠత
    • ਖ਼͠͞ͷެࣜ(ϗΞͷτϦϓϧ) = {P} A {Q}
    • ʮ೚ҙͷAͷ࣮ߦ͸ɺPͷঢ়ଶʹͳͬͨͱ͖ʹ࢝·ΓɺQͷঢ়ଶʹͳͬͨͱ͖ʹ
    ऴྃ͢Δʯ
    • P = ࣄલ৚݅(A͕ݺ͹ΕΔલʹຬͨ͢΂͖৚݅)ɻΫϥΠΞϯτΛଋറ͢Δ৚݅
    • A = ιϑτ΢ΣΞཁૉ(ॲཧຊମ)
    • Q = ࣄޙ৚݅(A͕ݺ͹Εͨޙʹຬͨ͢΂͖৚݅)ɻαʔϏεΛଋറ͢Δ৚݅
    %C$

    View Slide

  18. αʔϏεͱΫϥΠΞϯτ͕ަΘ͢ܖ໿
    • ސ٬(ΫϥΠΞϯτ)͕ఏڙऀ(αʔϏε)Λར༻͢Δલఏ
    ͷܖ໿
    • ͋ΔΫϥεʹରԠ͢Δϧʔνϯr͕ɺrequire preͱ
    ensure postΛએݴ͍ͯ͠Δ৔߹ɺͦͷΫϥε͸ސ٬(Ϋ
    ϥΠΞϯτ)ʹҎԼͷ͜ͱΛݴ͍ͬͯΔʹ౳͍͠
    • ʮ΋ͦͪ͠Β͕ pre Λຬͨͨ͠ঢ়ଶͰr ΛݺͿͱ໿ଋ͠
    ͯԼ͞ΔͳΒ͹ɺ͓ฦ͠ʹɺpost Λຬͨ͢ঢ়ଶΛ࠷ऴ
    తʹ࣮ݱ͢Δ͜ͱΛ͓໿ଋ͠·͢ʯ
    %C$

    View Slide

  19. ྫ: ࣄલɾࣄޙ৚݅Λද໌͢Δϝιου
    def getThree(s: String): String = {
    require(s.length >= 3, "length of s is too long!")
    s.substring(0, 3)
    }.ensuring(_.length == 3, "length of s doesn't equals 3")
    • requireΛ࢖ͬͯࣄલ৚݅Λද໌͢Δɻensuring͸ࣄޙ৚݅ͷද໌
    • ΫϥΠΞϯτଆ͕StringIndexOutOfBoundsExceptionʹґଘ͍ͯ͠ΔͳΒ͹ɺαʔϏε
    ଆͷ࣮૷ʹґଘ͍ͯ͠Δ͜ͱʹͳΔʂ
    Exception in thread "main" java.lang.IllegalArgumentException: requirement failed:
    length of s is too long!
    at scala.Predef$.require(Predef.scala:277)
    at example.Example1$.getThree(Example1.scala:6)


    at scala.App.$anonfun$main$1$adapted(App.scala:76)
    at scala.collection.immutable.List.foreach(List.scala:389)
    at scala.App.main(App.scala:76)
    at scala.App.main$(App.scala:74)
    at example.Example1$.main(Example1.scala:3)
    at example.Example1.main(Example1.scala)
    %C$

    View Slide

  20. ྫ) PHPͷmt_rand()ؔ਺
    • mt_rand()͸Ұ؏ͯ͠
    յΕ͍ͯΔ͕ɺࠔͬͯ
    ͍Δͷ͸ɺܖ໿Ͱ͸ͳ
    ͘αʔϏεଆͷ࣮૷ʹ
    ґଘͯ͠͠·ͬͨਓͨ
    ͪ
    %C$

    View Slide

  21. • ࣮ߦ࣌ͷද໌ҧ൓͸ɺͦͷιϑτ΢ΣΞʹόά͕͋Δ
    ূڌ
    • ࣄલ৚݅ҧ൓͸ɺΫϥΠΞϯτʹόά͕͋Δূڌ
    • ࣄޙ৚݅ҧ൓͸ɺαʔϏεʹόά͕͋Δূڌ
    ද໌͸੍ޚߏ଄ʹ͋Βͣ %C$

    View Slide

  22. ෆม৚݅ͱ͸
    • ϗΞͷτϦϓϧʹΑͬͯɺॲཧͷਖ਼͠͞Λ൑ఆ͢Δ͜ͱ
    ͕Ͱ͖Δ͕ɺΫϥεͷଐੑ(σʔλ)ʹ΋ຬͨ͢΂͖৚݅
    ͕͋ΔɻͦΕΛෆม৚݅ͱݺͿ
    • ྫ͑͹ɺࣗવ਺ͷෆม৚݅͸ʮ0Ҏ্ʯͰ͢ɻ
    • { INV & P } A { INV & Q} ͕੒Γཱͭͱ͖ɺ͢΂͕ͯ੒ޭ
    ͢Δ
    %C$

    View Slide

  23. ͦΕͧΕͷܖ໿Λද໌͢Δ
    case class Order(items: Seq[OrderItem]) {
    require(items.nonEmpty)
    def addOrderItems(otherItems: Seq[OrderItem]): Order = {
    require(otherItems.nonEmpty)
    copy(items = this.items ++ otherItems)
    }.ensuring(items.nonEmpty)
    }
    • ஫จΦϒδΣΫτͷ஫จΞΠςϜ͸ۭͰ͋ͬͯ͸ͳΒͳ͍ɻ
    • addOrderItem࣌ʹࣄલ৚݅ͱࣄޙ৚݅Λ֬ೝ͢Δ
    • ΋ͬͱ؆ܿʹهड़Ͱ͖ͳ͍͔
    %C$

    View Slide

  24. ίϯετϥΫλͰͷද໌
    case class OrderItems(values: Seq[OrderItem]) {
    require(values.nonEmpty)
    }
    object OrderItems {
    implicit object SeqmigroupInstance extends Semigroup[OrderItems] {
    override def combine(x: OrderItems, y: OrderItems): OrderItems =
    OrderItems(x.values ++ y.values)
    }
    }
    case class Order(items: OrderItems) {
    def addOrderItems(otherItems: OrderItems): Order =
    copy(items = this.items.combine(otherItems))
    }
    • ImmutableͰ͋Ε͹ίϯετϥΫλͰɺෆม৚݅Λද໌
    ͢Ε͹ɺͦΕΛ࢖͏ϝιουͰͷද໌ΛলུͰ͖Δ
    %C$

    View Slide

  25. FYI: ܕϨϕϧͰͷද໌
    object Order {
    type OrderItems = NonEmptyList[OrderItem]
    // NonEmptyList͸ɺઌ಄ཁૉͷheadΛඞͣඞཁͱ͢ΔͨΊɺܕͱۭͯ͠ʹ͸Ͱ͖ͳ͍
    // final case class NonEmptyList[+A](head: A, tail: List[A]) { …
    }
    case class Order(items: OrderItems) {
    def addOrderItem(otherItems: OrderItems): Order =
    copy(items = this.items.combine(otherItems))
    }
    • cats.data.NonEmptyListͰͷྫ
    • ܕϨϕϧͰෆม৚݅Λද໌Ͱ͖Δ
    • ͢΂ͯͷέʔεͰ͜ͷํ๏͕࢖͑ΔΘ͚Ͱ͸ͳ͍
    %C$

    View Slide

  26. ࠶ܝ: Evansϧʔϧ1
    • ϧʔτΤϯςΟςΟ͸ɺάϩʔό
    ϧͳಉҰੑΛ࣋ͪɺෆม৚݅(ͦ
    ͷϞσϧ͕࣋ͭੑ࣭)ΛνΣοΫ͢
    Δ੹຿Λෛ͏
    • λΠϠͷަ׵͸ϝιουͳͲΛհ
    ͯ͠ߦΘΕΔɻܾͯ͠಺෦ͷΦϒ
    δΣΫτΛ௚઀ૢ࡞ͤͯ͞͸ͳΒ
    ͳ͍(λΠϠϩʔςʔγϣϯϧʔϧ
    Λڧ੍ͤ͞ΔͳͲͷෆม৚݅Λҡ
    ࣋͢ΔͨΊʹ)
    ڥք
    ࣗಈं
    λΠϠ
    λΠϠͷަ׵
    λΠϠ
    λΠϠ λΠϠ
    ं྆൪߸
    λΠϠ
    ू໿

    View Slide

  27. FYI: ՄมϑΟʔϧυΛ๫࿐ͯ͠͸ͳΒͳ͍
    case class Order(private val _items: Seq[OrderItem]) {
    require(_items.nonEmpty, "items are empty!")
    val items: ListBuffer[OrderItem] = ListBuffer.empty[OrderItem]
    addOrderItems(_items)
    def addOrderItems(otherOrderItems: Seq[OrderItem]): Unit = {
    require(otherOrderItems.nonEmpty, "otherOrderItems are empty!")
    items.appendAll(otherOrderItems)
    items.ensuring(_.nonEmpty, "items are empty!")
    }
    }
    object Main extends App {
    val order = Order(Seq(OrderItem(1L, ProductName("red-pen"), 100, 1)))
    order.addOrderItems(
    mutable.Seq(OrderItem(2L, ProductName("blue-pen"), 100, 2)))
    println(order.items)
    // ListBuffer(OrderItem(1,ProductName(red-pen),100,1), OrderItem(2,ProductName(blue-
    pen),100,2))
    order.items.clear()
    println(order.items)
    // ListBuffer()
    }
    • ू໿ͷෆม৚݅ΛഁյͰ͖ͯ͠·͏ྫ
    ू໿
    ঢ়ଶΛՄมͰ͖Δ
    ϑΟʔϧυ͸ू໿ͷ
    ڥք֎ʹ๫࿐ͯ͠͸
    ͳΒͳ͍
    WBSͰ΋ಉ༷͕ͩɺ
    WBMͰ΋ՄมΫϥεͷ
    ৔߹΋஫ҙ͕ඞཁ

    ू໿ͷ༬͔Γ஌Βͳ͍ॲཧͰෆม৚݅ΛഁյͰ͖Δ

    View Slide

  28. Evansϧʔϧ2
    • ू໿֎ͷΦϒδΣΫτ͸ɺϧʔτΤϯςΟςΟΛআ
    ͖ɺڥք಺෦΁ͷࢀরΛอ࣋͢Δ͜ͱ͕Ͱ͖ͳ
    ͍ɻ಺෦ΦϒδΣΫτ΁ͷࢀরΛଞͷΦϒδΣΫτ
    ʹ౉͠Ұ࣌తʹར༻͢Δ͜ͱ͕Ͱ͖Δ͕ɺϑΟʔϧ
    υͱͯ͠ར༻Ͱ͖ͳ͍(ॴ༗ݖͷ໌֬Խ)
    • DB͔ΒΫΤϦΛ࢖ͬͯऔಘͰ͖Δͷ͸ɺϧʔτΤ
    ϯςΟςΟͷΈ
    • ࡟আͷࡍ͸ɺू໿ʹ಺ࡏ͢Δ͋ΒΏΔΦϒδΣΫ
    τΛҰ౓ʹ࡟আ͢Δ(ϧʔτҎ֎͸֎෦͔Βࢀর͞
    Ε͍ͯͳ͍ͷͰϧʔτΛ࡟আ͢Ε͹GC΋ޮ཰͕Α
    ͍)
    • ू໿಺෦ͷΦϒδΣΫτʹର͢Δมߋ͕ίϛοτ
    ͞ΕΔͱ͖͸ɺू໿શମͷෆม৚͕݅͢΂ͯຬͨ͞
    Ε͍ͯΔ͜ͱ
    ू໿
    Order
    OrderItems
    Purchase
    OrderItems
    ௚઀ͷࢀরΛอ࣋
    NG
    Order
    OrderItems
    Purchase
    Order
    ௚઀ͷࢀরΛอ࣋
    OK
    *%%%Ͱ͸0SEFS*E
    Λਪ঑

    View Slide

  29. ڥքఆٛͷળ͠ѱ͠

    View Slide

  30. ྫ:ڊେͳू໿
    • όοΫϩάɺϦϦʔεɺεϓϦϯτͷ͢΂ͯΛอ࣋͢Δϓϩ
    μΫτू໿ɻϓϩμΫτʹόʔδϣϯ͕͋Γָ؍ϩοΫ͞Ε
    Δ
    • AͱBͷϢʔβ͕ಉ͡όʔδϣϯͰ࢖͍࢝ΊΔˠA͕όοΫϩ
    άΛ௥Ճ͠ίϛοτ

    B͕ϦϦʔεΛมߋ͠

    ͯίϛοτ͢Δ͕ɺ

    ָ؍ϩοΫΤϥʔ
    • සൟʹෳ਺ͷϢʔβ͕ߋ৽͢ΔέʔεͰ͸ɺಉ࣌ʹมߋ͠Α
    ͏ͱͨ͠ͱ͖ɺ੒ޭ͢Δͷ͸1ਓ͚ͩ͸ड͚ೖΕΒΕͳ͍
    ू໿ 7FSOPO

    View Slide

  31. ྫ:ෳ਺ͷू໿
    • ڊେͳू໿Λ࢛෼ׂɻProductIdʹΑͬͯؔ࿈෇͚ΒΕΔɻ
    όοΫϩάͷ௥Ճ࣌͸ɺτϥϯβΫγϣϯڥք಺Ͱߦ͏ͨ
    Ίɺڝ߹͕ى͖ͣʹ҆શʹߋ৽Ͱ͖Δ
    • τϥϯβΫγϣϯ໘Ͱ͸༗རͰ΋ɺΫϥΠΞϯτଆ͔Β͢
    Δͱෆศ͔΋͠Εͳ͍(Product͕͋Δ͜ͱΛ֬ೝͯ͠
    BacklogItemΛ௥ՃͳͲ)
    • όοΫϩάͳͲͷN਺

    Λ੍ݶ͢Δෆม৚݅

    ͕कΕͳ͘ͳΔՄೳੑ͕͋Δ
    ू໿ 7FSOPO

    View Slide

  32. Vernonͷू໿ઃܭϧʔϧ

    View Slide

  33. ϧʔϧ1: ਅͷෆม৚݅Λɺ੔߹ੑͷڥք಺ʹϞσϦϯά͢Δ
    • ੔߹ੑʹ͸2छྨ͋Δ: τϥϯβΫγϣϯ੔߹ੑ(ڧ͍੔߹
    ੑ)ͱ݁Ռ੔߹ੑ(ऑ͍੔߹ੑ)ɻෆม৚݅ʹඞཁͳ੔߹ੑ
    ͸ɺτϥϯβΫγϣϯ੔߹ੑ
    • ू໿͸τϥϯβΫγϣϯ੔߹ੑͷڥքͱಉٛɻυϝΠϯ
    Ͱඞཁͱ͢Δ͋ΒΏΔมߋʹରͯ͠ɺτϥϯβΫγϣϯ
    ಺Ͱͷෆม৚݅ͷ੔߹ੑΛ҆શʹҡ࣋͢Δ
    • τϥϯβΫγϣϯͷ෼ੳޙʹɺू໿ͷઃܭͷળ͠ѱ͠Λ
    ਖ਼͘͠൑அ͢Δ͜ͱ͕Ͱ͖Δ
    ू໿ 7FSOPO

    View Slide

  34. ϧʔϧ2: খ͞ͳू໿Λઃܭ͢Δ
    • ڊେͳू໿Ͱ͸ɺجຊૢ࡞ͷଟ͘Ͱɺෳ਺ͷେ
    ن໛ͳίϨΫγϣϯͷಡΈࠐΈ͕ൃੜ͢Δɻύ
    ϑΥʔϚϯεʹѱӨڹ͕͋Δ
    • ”ଞͷཁૉͱͷ੔߹ੑΛอͭඞཁ͕͋Δ΋ͷ”͕
    ൑அج४ɻͨͩ͠ϢʔεέʔεΛҰํతʹແࢹ
    Ͱ͖ͳ͍(Evans)
    • ϞσϧͷҰ෦ΛΤϯςΟςΟԽ͢Δ৔߹
    • ͦΕ͕ࠓޙ΋มΘΓଓ͚ΔͳΒˠू໿Խ
    • มߋ࣌ʹ·Δ͝ͱஔ͖׵͑Ε͹Α͍ˠ஋Φ
    ϒδΣΫτ
    • ϧʔτΤϯςΟςΟͱҰॹʹγϦΞϥΠ
    ζͰ͖ɺΫΤϦ΋୯७ԽͰ͖ΔɻΤϯςΟ
    ςΟͷํ͕Φʔόʔϔου͕͋Δ
    ࣗಈं
    λΠϠ λΠϠ
    λΠϠ λΠϠ
    ं྆൪߸
    Τϯδϯ
    Τϯδϯ൪߸
    Τϯδϯ൪߸
    ܕࣜ ϨγϓϩϩʔλϦ

    ܕࣜ͸ৗʹࣗಈंͷଞͷଐੑͱ੔߹ੑΛ
    อͭඞཁ͕͋Δ৔߹͸ಉҰू໿ͱͳΔ
    ू໿ 7FSOPO

    View Slide

  35. FYI: ϢʔεέʔεΛӏವΈʹ͠ͳ͍
    • Ϣʔεέʔε෼ੳʹ͸ɺϏδωεΞφϦετ͕ॏཁͳ໾ׂΛՌͨ͢
    ͕ɺ։ൃऀͷࢹ఺Λ൓өͨ͠΋ͷͱ͸ݶΒͳ͍
    • ݸʑͷϢʔεέʔεͱϞσϧͷઃܭͷ੔߹ੑΛ߹ΘͤΔඞཁ͕͋Δ
    • ෳ਺ͷτϥϯβΫγϣϯ(ex. Product, BacklogItem)Λ୯Ұͷτϥ
    ϯβΫγϣϯͱͯ͠ѻ͏Α͏ͳϢʔεέʔεͰ໰୊͕ੜ͡Δ
    • ͜ͷΑ͏ͳϢʔεέʔε͸ӏವ
    Έʹ͠ͳ͍͜ͱ
    • ৔߹ʹΑͬͯ͸ɺϞσϧ΋͠
    ͘͸ϢʔεέʔεΛݟ௚͢ඞ
    ཁ͕͋Δ
    • Ͱ͖Ε͹ɺ࠷ॳ͔Βશһಉ੮
    ͰϞσϦϯάͨ͠ํ͕Α͍
    ू໿ 7FSOPO

    View Slide

  36. ϧʔϧ3: ଞͷू໿΁ͷࢀরʹ͸ɺͦͷࣝผࢠΛར༻͢Δ
    • ͋Δू໿͕ผͷू໿ͷϧʔτΤϯςΟςΟ΁
    ͷࢀরΛอ࣋ͯ͠΋͔·Θͳ͍͕ɺࢀরઌͷ
    ू໿ͱࢀরݩͷू໿͕ಉ͡ڥքʹଐ͢ΔΘ͚
    Ͱ͸ͳ͍
    • ಉҰτϥϯβΫγϣϯ಺Ͱ྆ํΛมߋͯ͠͸
    ͍͚ͳ͍ɻมߋͰ͖Δͷ͸ͲͪΒ͔Ұํ͚ͩ
    • ಉҰτϥϯβΫγϣϯͰ͸ɺ݁ہ ڊେͳू
    ໿ʹͳΔ
    • ଞͷू໿΁ͷࢀরΛอ࣋͠ͳ͚Ε͹ɺͦͷू
    ໿Λมߋ͢Δ͜ͱ͕Ͱ͖ͳ͍
    • ֎෦ͷू໿΁ͷࢀর͸ID͚ͩΛར༻͠ϙΠ
    ϯλ͸อ࣋͠ͳ͍Α͏ʹ͢Δ
    • ϝϞϦফඅྔ΋཈͑ΒΕΔɻׂΓ౰͚ͯͩ
    Ͱͳ͘ɺGC໘Ͱ΋޷Өڹ͕ٴͿ
    Order
    OrderItems
    Purchase
    Order
    ௚઀ͷࢀরΛอ࣋
    NG
    Order
    OrderItems
    Purchase
    OrderId
    ؒ઀ͷࢀরΛอ࣋
    OK
    0SEFS3FQPTJUPSZ
    ू໿ 7FSOPO

    View Slide

  37. ϧʔϧ4: ڥքͷ֎෦Ͱ͸݁Ռ੔߹ੑΛ༻͍Δ
    • ΫϥΠΞϯτ͔Βͷ୯ҰͷϦΫΤετͰɺෳ਺ͷू໿Λม
    ߋ͢Δ৔߹͸݁Ռ੔߹ੑΛ࢖͏͜ͱ
    • ͋Δू໿͕ࢀর͢Δ֎෦ͷू໿͸࡟আ͞Ε͍͔ͯ΋͠Ε
    ͳ͍͠ɺͦͷૢ࡞Ͱ૝ఆ͠ͳ͍ঢ়ଶʹભҠ͍ͯ͠Δ͔΋
    ͠Εͳ͍ɻ(ϓϩμΫτ͕࣋ͭλάʹؔ࿈෇͘ɺόοΫϩ
    άͱεϓϦϯτΛফͦ͏ͨ͠Βɺ͢Ͱʹফ͍͑ͯΔ͜ͱ
    ͕͋Δ)
    • ͋Δू໿͕ঢ়ଶΛมߋ͢ΔࡍʹɺαϒεΫϥΠόʹυϝ
    ΠϯΠϕϯτΛ௨஌͠ɺ੔߹ੑΛҡ࣋͢ΔॲཧΛ࣮ߦ͢
    Δ͜ͱ΋Մೳ
    ू໿ 7FSOPO

    View Slide

  38. ·ͱΊ
    • ϏδωεϧʔϧΛू໿ͷෆม৚݅ͱͯ͠࡞ΓࠐΉ͜ͱͰɺݎ࿚ͳγ
    εςϜͷ࣮ݱʹߩݙͰ͖Δ
    • ೉͍͜͠ͱ͕ͩɺϢʔεέʔεͱϞσϧͷ੔߹ੑͷ྆ํΛܰࢹ͠ͳ
    ͍͜ͱ
    • ू໿ͷΑΓৄࡉͳ৘ใΛಘΔ৔߹͸ɺEvansຊ ୈ2෦ୈ6ষ ू໿ɺ
    Vernonຊ ୈ10ষ ू໿ΛಡΉͱΑ͍

    View Slide