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

Goでやや大きいプロダクトのアーキテクチャを検討したり実装したりしたおはなし

C53304007703d7eb2410ba9880d62ac8?s=47 yami20
July 17, 2020

 Goでやや大きいプロダクトのアーキテクチャを検討したり実装したりしたおはなし

C53304007703d7eb2410ba9880d62ac8?s=128

yami20

July 17, 2020
Tweet

Transcript

  1. GoͰ΍΍େ͖͍ϓϩμΫτͷ ΞʔΩςΫνϟΛݕ౼ͨ͠Γ࣮૷ͨ͠Γͨ͠ ͓͸ͳ͠ Remote.go#1 2020.07.17 @yami20

  2. ͩΕʁ • @yami20 (ΠϯλʔωοτҾ͖͜΋ΓͳͷͰಛʹ৘ใ͸ग़ͯ͜ͳ͍Ͱ͢) • Engineer@Finatext • อݥࣄۀͰαʔόʔαΠυ։ൃ • Go͸1.6?1.7?͋ͨΓͰͪΐͬͱ͞Θͬͯ཭Ε͍ͯͨ

    • ڈ೥ͷ฻Ε͔Β·ͨ৮Γ࢝Ίͨͱ͜Ζ • ͜ͷձͷλΠτϧʹʮ্ڃऀ޲͚ʯͱ͔ॻ͔ΕͯͯŜƄŞŲƄſͯ͠·͢
  3. ͖ΐ͏͓͸ͳ͢͠Δ͜ͱ • ͦͦ͜͜େ͖͍ɾෳࡶͳϓϩμΫτΛGoͰͭ͘Γ·ͨ͠ɻ • ࣮૷ΞʔΩςΫνϟͷબఆ΍tipsΛɺͦͷҙਤΛ৫Γަͥͳ͕Β͓࿩ ͯ͠ΈΑ͏ͱࢥ͍·͢ɻ

  4. ͦͷ͜͜Ζ͸ʁ • ʮ͖Ε͍ͳͷ͸͜͏͍͏࣮૷ͩʯͱ͍͏৘ใ͸ͨ͘͞Μ͋Δɻ • ͖Ε͍ͳ࣮૷Λ௥͍ٻΊଓ͚Δ͜ͱ͕࣮຿ʹ͓͍ͯ࠷దղͰ͸ͳ͍ɻ • ʮ͋Δ࣮૷ʹΑͬͯͲͷ༷ͳ՝୊͕ղܾ͞ΕΔ͔ʯͱ͍͏༗ػతͳͭͳ͕ Γ΍ɺԡ͑͞Δ΂͖ϙΠϯτ/ࣺͯͯΑ͍ϙΠϯτΛڞ༗͢Δ͜ͱͰɺΑΓ Α͍࣮૷Λ໨ࢦ͢ਓʑͷࢀߟʹͳΕ͹͍͍ͳ͊ɻ

  5. ͓͸ͳ͠͠ͳ͍͜ͱ ͘͢͝໨৽͍͠৘ใɺΠέΠέͳ࣮૷͸ग़͖ͯ·ͤΜɻ ޠΓਚ͘͞Εͨ෢ثͨͪΛखʹɺଥ౰ͳ࣮૷Λ໨ࢦ͓͢͸ͳ͠Ͱ͢ɻ

  6. ຊ୊

  7. ཁ݅ɾن໛ɾಛੑ ʙอݥϓϥοτϑΥʔϜγεςϜʙ •(͜ͷล͸ࢀߟఔ౓ʹॻ͍͚ͨͩͳͷͰඈ͹͠·͢) • ཁ݅ • APIαʔόʔ(SPAͷbackend) • ͪͳΈʹରʹͳΔfrontendͷ͸ͳ͠͸ https://speakerdeck.com/slont/bokufalsekangaetasaikiyoufalsevueakitekutiya

    • ෳ਺ͷอݥձ͕ࣾ঎඼Λઃܭɾొ࿥͠ɺސ٬ͷਃࠐΛड͚෇͚ͨΓɺܖ໿৹ࠪͨ͠Γ؅ཧͨ͠Γɺͦͷଞ෇ਵ͢Δػೳ͕΋ʹΐ΋ʹΐɻ • ن໛ • ΞυςΫ΍ήʔϜʹൺ΂ΔͱτϥϑΟοΫ͸֨ஈʹ͓ͱͳ͍͠ɻ1ਓ͕1೔ʹԿेճ΋Ճೖͨ͠Γ͠ͳ͍͠ɺ࿈ଧͯ͠౗͢ఢ΋͍ͳ͍ɻ • PFͰ͋Δ͜ͱΛ౿·͑ͯ΋ҰൠతͳECͱ͔ͷن໛ײΛΠϝʔδ͍͚ͯͨͩ͠Ε͹ɻ • ಛੑ • σʔλͷϥΠϑαΠΫϧ͕௕͍ɻ೥୯Ґ͕جຊɺਓੜ୯ҐͷऔҾ΋͋Δ • σʔλͷߏ଄͕ෳࡶ. ଐੑ΋ϦϨʔγϣϯ΋ͱʹ͔͘ଟ͍. • γεςϜͷण໋͕௕͍ɻσʔλͷϥΠϑαΠΫϧ͕௕͍ͷ΋͋Δ͠ɺPFͳͷͰ͓͍ͦΕͱด͡ΒΕͳ͍ͱ͍͏ͷ΋͋Δɻ • PFͰ͋ΔͨΊɺॳظʹग़Δཁ͕݅͢΂ͯͱ͸ݶΒͳ͍ • ࢥ͍΋ΑΒͳ͍֦ு͕ඞཁʹͳΔՄೳੑ͕͋Δ
  8. ࠾༻ͨ͠ߏ੒ • ϞϊϦε • ׬શʹ୯ҰγεςϜͱ͍͏Θ͚Ͱ͸ͳ͍Ͱ͕͢ɻ • ໌Β͔ʹੑ࣭ͷҟͳΔ෦෼͸෼཭͕ͨ͠ɺAPI਺ेຊͷίϯϙʔωϯτ3ͭͱ͍͏ঢ়ଶɻ • ϨΠϠʔυΞʔΩςΫνϟ(෩) •

    ݫີͳͦΕͰ͸ͳ͍ • DIP(ґଘੑͷٯస)΋૊ΈࠐΉ
  9. ϞϊϦεͱ͍͏બ୒

  10. ϞϊϦεͱϚΠΫϩαʔϏε • ϞϊϦεʹ਌Λࡴ͞Εͨܦݧ͸͋Δɻ • ϑϩϯτ͔Β؅ཧը໘·Ͱ͢΂͕ͯಉࠝ͞Εɺ100ਓҎ্ͷ։ൃऀ͕ҰͭͷϦϙδτϦʹ commit͠ʮdeployฒͼ·͢ʯͱ੠Λ͔͚߹͍ɺσϓϩΠࣦഊ͢Δͱଞ෦ॺʹౖΒΕΔσΟ ετϐΞ • ϚΠΫϩαʔϏεʹଜΛম͔Εͨܦݧ΋͋Δɻ •

    1~3ςʔϒϧ૬౰ͷσʔλຖʹઐ༻ͷAPI͕ཚཱͯ͠૬ޓʹԿ౓΋ࢀর͍͋͠ɺ͍ͭͲ ͜ͰԿͷॲཧ͕ى͖͍ͯΔ͔Θ͔Βͳ͍σΟετϐΞ • ݁ہɺ͓࡞๏ʹࠩͷ͋Δଟ਺ͷγεςϜΛ͢΂ͯ೺Ѳ͠ͳ͚Ε͹Կ΋Θ͔Βͳ͍ɻ
  11. ϞϊϦεͱϚΠΫϩαʔϏε • ϞϊϦε • ϝϯςෆՄೳͳ΄Ͳίʔυɾؔ܎ऀ͕ଟ͘ͳΔͱͭΒ͍ • ಉҰϦϙδτϦ಺͔ͩΒͱແࠩผʹࢀরΛΏΔ͢ͱΘ͚Θ͔ΒΜ͘ͳΔ • ϚΠΫϩαʔϏε •

    ෆద੾ͳ෼ׂʹΑͬͯຊདྷඞཁͷͳ͍ॲཧ͕૿Ճ͢Δͱͱͯ΋ͭΒ͍ • Ұൠతʹ࣮૷ྔ͸૿͑Δ͠ɺΠϯϑϥߏ੒໘Ͱͷݕ౼ࣄ߲ɾઃఆ΋૿͑Δ
  12. ϞϊϦεͱ͍͏બ୒ • ࠷దͳϚΠΫϩαʔϏεͷཻ౓Λࣄલʹݟग़͢͜ͱ͸ඇৗʹ೉қ౓͕ߴ͍ɻ • ࢓༷௨Γʹ࣮૷͍ͯͨ͠ͷʹʮ࣮͸Aͷσʔλ͚ͩͩͱ଍Γͳͯ͘ɺৗʹBͱC΋ҰॹʹཁΔΜͩ...ʯͱ͔ݴΘΕ͕ͪ • Goͬͯهड़ྔࣗମ͸গͳ͘ͳ͍Ͱ͢ΑͶ? (ڞײΛٻΊΔѹྗ) • γϯϓϧͰಡΈॻ͖͠΍͍͢෼ɺʮָΛͤͯ͘͞ΕΔʯ࢓૊Έ͸߇͑Ίɻ

    • ϚΠΫϩαʔϏεͰͷهड़૿Ճͱ߹ΘͤΔͱͪΐͬͱϔϏʔɻ • αʔϏεͷ্ཱͪ͛࣌఺ͰϞϊϦε๊͕͑Δ໰୊͕ੜ͡ΔϦεΫ͸খ͍͞ • ʮϞϊϦεͷ··ʯҭͯͳͯ͘͢ΉΑ͏ʹద੾ͳઃܭɾ੍໿Λ͠ɺ͕࣌དྷͨΒ෼ׂ͢Ε͹Α͔Ζ͏ͳ ͷͩ • αʔϏεΛҭ͍ͯͯ͘தͰద੾ͳ෼ׂཻ౓͕ݟ͑ͯ͘Δͱ͍͏ϝϦοτ΋͋Δɻ
  13. ͱ͜ΖͰ • ϞϊϦε(স)ͬͯݴΘΕΔ͘Β͍ͷ֮ޛͰ࣮૷͍ͯͨ͠ΜͰ͕͢ɺ
 ͜͜൒೥͘Β͍?ͰϞδϡϥϞϊϦεͱ͍͏֓೦͕ఏএ͞Ε͍ͯͨͷ Ͱ͢Ͷɻ • ͦͷͱ͓Γʹ΍͍ͬͯΔͱ·Ͱ͸ݴ͑·ͤΜ͕ɺΞϓϩʔνͱͯ͠ ͸Θ͔ΓΈ͕;͔͍

  14. ϨΠϠʔυΞʔΩςΫνϟ(෩)ͱ͍͏બ୒

  15. ϨΠϠʔυΞʔΩςΫνϟ(෩) • ࣮૷ΞʔΩςΫνϟʹۜͷ஄ؙ͸ͳ͘ɺνʔϜͱϓϩδΣΫτͷঢ়گ ʹΑͬͯ࠷దղ͸มΘΔɻ • ֎෦઀ଓ͕ͳ͘ɺ͔ͭ20APIʹຬͨͳ͍Α͏ͳγεςϜΛগਓ਺Ͱ࡞ ΔͷͰ͋Ε͹MVCͰ΋શવྑ͍ͱࢥ͏ɻ • αʔϏε͕େن໛Ͱෳࡶɺ͔ͭ૊৫ͷ੒ख़౓͕ߴ͚Ε͹ΫϦʔϯΞʔ ΩςΫνϟͰ࡞ΓࠐΈͨ͘ͳΔͱࢥ͏ɻ

  16. ϨΠϠʔυΞʔΩςΫνϟ(෩) • લఏ • ߏ੒ΛϞϊϦεͱ͢Δ͜ͱʹ෇ਵͯ͠ɺத௕ظతʹ͸ʮϢʔεέʔεʹ Ԡͯ͡αʔϏεΛ෼཭͍ͨ͠ʯͱߟ͍͑ͯΔɻ • Ϣʔεέʔε͕໌֬ʹͳΔΑ͏ͳ࣮૷ΞʔΩςΫνϟ/੍໿Λઃ͚͍ͨ • อݥͱ͍͏఻౷తͳϏδωεʹج͍ͮͯ࡞ΔαʔϏεͰ͋ΓɺϏδωε

    ϩδοΫ͕ෳࡶɾॏཁͱͳΓಘΔɻ => DDDͱ਌࿨ੑͷߴ͍ΞʔΩςΫνϟ͕ྑ͍ͱߟ͑ͨɻ
  17. ϨΠϠʔυΞʔΩςΫνϟ(෩) • ͳͥΫϦʔϯΞʔΩςΫνϟ(ҎԼCA)Λબ͹ͳ͔ͬͨͷ͔? • CA͸͔ͨ͠ʹΑ͘Ͱ͖͍ͯΔͱ͓΋͏ • ͔͠͠ͳ͕ΒɺΞʔΩςΫνϟࣗମͷֶशίετͷߴ͕͞൱Ίͳ͍ • ૚෼͚͕ݫີɾৄࡉͰ͋Δ͕Ώ͑ʹɺʮ͏·͘Θ͚ͳ͚Ε͹͍͚ͳ͍ʯڧ੍͍໿Λײ͡Δ ʢݸਓͷײ૝Ͱ͢)

    • ݫີʹΘ͚ΒΕΔ͜ͱ͸ڧΈ͕ͩɺڧΈΛڗड͢Δʹ͸࠷ॳ͔Βߴ͍஌ݟ͕ٻΊΒΕΔɻ গਓ਺ɾ্ཱͪ͛ஈ֊ͷϓϩδΣΫτʹ͓͍ͯͷίεύ͸͍͔΄Ͳ͔?
  18. ϨΠϠʔυΞʔΩςΫνϟ(෩)ͱ͍͏બ୒ • DDD޲͖ͷΞʔΩςΫνϟͷதͰ͸ൺֱతૉ௚(ݸਓͷײ૝Ͱ͢)ͳϨΠϠʔυ ΞʔΩςΫνϟͰ΋υϝΠϯΛ͖Ε͍ʹอͪɺϢʔεέʔεΛΘ͔Γ΍͘͢දݱ ͢Δ͜ͱ͸Ͱ͖Δɻ • ७ਮͳϨΠϠʔυΞʔΩςΫνϟ͸infra΁ͷґଘΛ࣋ͭͨΊςετͮ͠Β͍ • DIPΛՃ͑Ε͹΍Γ͍ͨ͜ͱ͸े෼ʹͰ͖Δɺ͸ͣɻ

  19. ґଘੑͷٯస(DIP) ```go:application/policy.go package application type Policy struct { // DIP.

    infraʹґଘͤͣ͞ʹdomainͷinterfaceʹґଘͤ͞Δ policyRepo domain.PolicyRepository } func (p *Policy) Get(id string) (*model.Policy, error) { // ... res, err := p.policyRepo.Get(id) if err != nil { return nil, err } return res, nil } ``` ```go:domain/repository.go package domain // application͔Βݟ͑Δ৔ॴʹinterfaceΛஔ͘ type PolicyRepository interface { Get(id string) (*model.Policy, error) } ```
  20. ϨΠϠʔυΞʔΩςΫνϟ෩ʹຬͨ͢ͱ... ```go:infra/db/policy.go package infra // infra/db ʹ interface Λຬͨ͢۩ମతͳ࣮૷Λஔ͘ type

    PolicyRepository struct { sess *dbr.Session } func (p *PolicyRepository) Get(id string) (*model.Policy, error) { // SQLͱ͔ // p.sess. ... } ```
  21. ΫϦʔϯΞʔΩςΫνϟ෩ʹຬͨ͢ͱ... ```go:infra/db/policy.go // infra type DBSess struct { sess *dbr.Session

    } func NewDBSess() *DBSess { // DB઀ଓ } func (d *DBSess) Query(stmt string, args ...interface{}) () {} ``` ```go:interfaces/db.go // interfaces type DBSess interface { Query(stmt string, args ...interface{}) (Rows, error) } type Rows interface { Scan(...interface{}) error Next() bool Close() error } type PolicyRepository struct { sess DBSess } func (p *PolicyRepository) Get(id string) (*model.Policy, error) { // SQLͱ͔ // p.handler.... } ```
  22. CAͪΐͬͱΉ͔͍ͣ͠ ཆ৩෺ͷ՝୊/ٖࣅίʔυͰൺֱ͢Δͷ͸ͪͱͣΔ͍Ͱ͕͢...ͱ͖ͬͭʹ ͍͘͜ͱ͸൱Ίͳ͍...ɻ ͖Ε͍ͳந৅ԽͰ͋Δ͜ͱ͸Θ͔Δɻ ͔͠͠interfacesͱinfra͕ผΕ͍ͯΔԸܙͬͯԿ͚ͩͬ?
 ͦΕʹΑͬͯ޾ͤʹͳΔہ໘͸ࣗ෼ͨͪʹͲΕ͚ͩ๚ΕΔΜ͚ͩͬ?

  23. ݁ہ࡞ͬͨߏ੒ (αϯϓϧ. ΈͮΒ͍) ϨΠϠʔυΞʔΩςΫνϟ΍DIPͷ ৘ใ͸ੈͷதʹͨ͘͞Μ͋Δ͠໨৽ ͍͜͠ͱΛ͍ͯ͠ΔΘ͚Ͱ΋ͳ͍Ͱ ͕͢...

  24. ઃܭͷझࢫ • ࣮ફDDDʹ͍͏ʮ؇΍͔ͳϨΠϠʔԽΞʔΩςΫνϟʯ͕ϕʔε • ʮ؇΍͔ʯͱ͸ɺ௚Լͷ૚͚ͩͰͳ͘Լํ޲ͷ૚͸͍ͣΕ΋࢖ͬͯΑ͍ͱ͍͏ҙຯɻ • ໋໊ɾσΟϨΫτϦͷ੾Γํ͸ΘΓͱ;Μ͍͖ɻ • ڭՊॻతʹ͸ interfaces/handler

    ͱ͔͕ͩɺinterfaces͕όϦΤʔγϣϯʹ෋Ήҹ৅͕͋·Γ ͳ͘ɺtopϨϕϧͷσΟϨΫτϦ͕1ͭ2ͭ૿͑ͨͱͯࠔΔ͜ͱ΋ͳ͍ͷͰtopʹhandlerͰ ͖ͬͨɻ·͊ͲͬͪͰ΋͍͍͔ͳɻ • application͡Όͳͯ͘usecase͚ͬͯͭΔ͜ͱ͕ଟ͍ؾ΋͢Δɻ
 ݸਓతʹusecaseͬͯଧͭͱࠨख͕ർΕΔ͔ΒڭՊॻΛ໔ࡑූʹapplicationʹͨ͠ɻ
  25. ઃܭͷझࢫ(Ά͑Ή) • DDD/ΞʔΩςΫνϟΛݫີʹकΖ͏ͱ͗͢͠Δͱɺࣗ෼ͨͪʹͱͬͯ ඞཁͰແ͍ෳࡶ͞Λ࣋ͪࠐΜͰ͠·ͬͨΓɺӨڹͷͳ͍ࣄฑʹ͍ͭͯ ʮͲ͜ʹॻ͘΂͖͔ʯʮͲ͏ॻ͘΂͖͔ʯͰա৒ʹ೰ΜͰ͠·͍͕ͪɻ • ࣗ෼͕ͨͪकΓ͍ͨ΋ͷΛकΔ΂͖Ͱ͋ͬͯɺڭՊॻతͳ໋໊ɾߏ଄Λ ݫक͢Δ͜ͱ͕໨తͰ͸ͳ͍ɻ • कΔ΂͖͜ͱΛ໌֬ʹɻ

  26. ·΋Δ΂͖͜ͱ(࣮૷ͷ੍໿) 1. domain͸app,infra,handlerΛࢀর͠ͳ͍ 1. value͸model,serviceΛࢀর͠ͳ͍ 2. model͸serviceΛࢀর͠ͳ͍ 2. app͸infra,handlerΛࢀর͠ͳ͍

  27. ੍໿Λ·΋ΔͨΊʹ 1. framework, httpʹؔ͢Δॲཧ͸handler಺Ͱ׬݁ͤ͞Δ 2. ϓϩάϥϜͷ֎ͷग़དྷࣄΛҙࣝ͢Δ࣮૷͸infra಺Ͱ׬݁ͤ͞Δ 1. ࣮ߦ؀ڥ,֎෦API,DB,... 3. app͸Լ૚(domain)ʹఆٛͨ͠interfaceʹґଘͤ͞Δ(DIP)

    4. ͦΕҎ֎ͷࡉ͔͍͜ͱ͸Α͠ͳʹɻࠔΔਓ͕͍ͳ͚Ε͹Α͍ɻ
  28. ੍໿ʹΑͬͯಘΔ΋ͷᶃ • domainʹ͸֎෦API΍DBΛҙࣝ͢Δهड़͕શ͘ͳ͘ͳΔɻ • ७ਮͳϏδωεϩδοΫ͚͕ͩଘࡏ͢ΔͷͰͱͯ΋͖Ε͍(খฒײ) • γϯϓϧͳunit testΛ؆୯ɾ໢ཏతʹॻ͚Δɻ • DBͷσʔλΛͲ͏༻ҙͨ͠ΒΑ͍͔?local΍CIͰ؀ڥͷࠩ෼͸ແ͍͔?ͲΜ

    ͳϦΫΤετ͕དྷΔ͔?ͳͲͷٕज़త/؀ڥతͳ੍໿,ςετͷ೉͔͠͞Βղ์ ͞Ε͍ͯΔ͸ͣɻ • mock΋ෆཁͳͷͰɺʮςετͷ΍ΓํΛؒҧ͏ʯݒ೦΋ͳ͍
  29. ੍໿ʹΑͬͯಘΔ΋ͷᶄ • application͸repositoryͷinterfaceͷΈʹґଘ͠infraʹ͸ґଘ͍ͯ͠ͳ͍ɻ • infraΛࠩ͠ସ͑Δࣄ͕Ͱ͖Δɻ • mockΛࠩ͠ࠐΜͰͷunit test͕Մೳ • ͜ͷ৔߹ɺྫ͑͹ʮσʔλ͕ਖ਼͘͠อଘ͞ΕΔ͔ʯͷςετͰͳ͘ɺʮσʔλΛਖ਼͘͠૊ΈཱͯͯอଘΛݺ΂Δ͔ʯͷςετʹͳΔ

    • ࣮ࡍʹʮDBʹॻ͖ࠐ·ΕΔ͔·Ͱ֬ೝ͍ͨ͠ʯͱ͍͏࿩͸Θ͔Δ͕ʮapplication୯ମͷ੹຿ͷςετʯͱͯ͠͸͜ΕͰΑ͍͸ͣɻ infra࣮૷͚͕ͩbugͬͨ৔߹ʹ΋ɺapp͕bug͍ͬͯͳ͍͜ͱ͕อূ͞ΕΔɻ • localͰ࢖͑ͳ͍APIΛμϛʔʹࠩ͠ସ͑ͯಈ͔ͨ͠Γ͢Δ͜ͱ΋Մೳ
  30. ੍໿ʹΑͬͯಘΔ΋ͷᶅ • infra/handlerʹϏδωεϩδοΫ͕͍ͳ͍ͷͰɺٕज़తͳؔ৺ (http,sql,...)ʹϑΥʔΧεͰ͖Δɻ • ͨͱ͑͹handler͸͢΂ͯҎԼͷΑ͏ͳըҰతͰബ͍࣮૷ʹͳΔ • HTTP RequestͷParse •

    applicationݺग़ • Responseฦ٫
  31. αʔϏεͷ੾Γग़͕͠Ͱ͖ͦ͏͔? • app/domain͕͓ޓ͍ʹઐ༻ͱͳ͍ͬͯΔ(ଞͷdomainΛ࢖Θͣɺଞͷapp͔Β࢖Θ Εͳ͍)΋ͷ΍ɺΘ͔ͣͳൣғͰ͔͠ڞ༗͍ͯ͠ͳ͍࣮૷͕͍͔ͭ͘ੜͨ͡ɻ • ͜ͷ༷ͳՕॴ͸࣮૷తʹಠཱੑ͕͔͍ͨɻ • ςετ΋ॻ͚͍ͯΔͷͰ੾Γग़͠͸༰қɻ • Ұ࿈ͷinfra/handler/app/domainΛ·Δͬͱ੾Γग़ͯ͠ϚΠΫϩαʔϏεʹͯ͠

    ͠·ͬͯΑͦ͞͏ɻ • ͦ͏Ͱͳ͍Օॴ͸҆қʹ੾Γग़ͦ͏ͱߟ͑ͣɺ·ͣ͸ϦϑΝΫλ΍Ϣʔεέʔεͷ੔ ཧΛ৻ॏʹਐΊΔͷ͕Α͍Α͏ʹࢥ͏ɻ
  32. Α΋΍·

  33. Α΋΍·: repositoryϑΝΠϧΘ͚ͳ͍ͷ? • repositoryͬͯinterfaceཏྻ͢Δ͚ͩͰத਎͕΄΅ͳ͍ͷͰϑΝΠϧ ཚཱͤͯ͞΋ͪΐͬͱڏ͍͔͠ͳ...ͱ͓΋ͬͯ·ͱΊ͍ͯΔɻ
 ָͩ͠ɻ • domain/repository/ Ͱ͖ͬͨ΄͏͕ਖ਼͍͠ͱ͸ࢥ͏

  34. Α΋΍·: handlerͷςετ • application΍handlerͷinterfaceԽ͸΍͍ͬͯͳ͍ • ΍ͬͨ΄͏͕handler,routingͷUT͸͠΍͍͢...͔ͳ? • (ബ͍࣮૷ͳΒ͹) handlerͷςετ͸UTΑΓe2eΛؤுͬͨ΄͏͕Α͍ͱࢥ͍ͬͯΔɻ •

    handler, ࣮ࡍͷreq/resͰࢼͨ͘͠ͳΔͷ͕ਓ৘Ͱ͸͋Γ·ͤΜ͔ • ʮinfraͷҟৗʹର͢ΔhandlerͷڍಈͷςετΛৗʹಈ͔͍ͨ͠ʯͱ͔ͳΒඞཁͦ͏ɻ • mockࠩ͠ࠐΜͰαʔόʔ্͛ͯe2eͰҰ౓ಈ࡞֬ೝ͢Ε͹ݸਓతʹ͸ຬ଍
  35. Α΋΍·: handlerͷςετ • ͪͳΈʹe2eͱ͍ͬͯ΋ͦΜͳʹϋΠΧϥͳ΋ͷͰ͸ͳ͍ɻ • postmanͰಈ࡞֬ೝͯ͠ઃఆΛอଘ͠ɺnewmanͰ΋࢖͑ΔΑ͏ʹ͍ͯ͠Δɻ • ։ൃதʹʮͪΐͬͱcurlͯ͠ΈΔʯ୅ΘΓʹ࡞ͬͯͨΊ͓͚ͯ͹ಛʹ࣌ؒΛ͔ͭ Θͳͯ͘΋͔ͳΓͷ໢ཏੑʹͳΔͱࢥ͏ɻ

  36. Α΋΍·: gomockͱDDD • gomock • https://github.com/golang/mock • InterfaceΛॆ଍͢Δmock࣮૷Λࣗಈੜ੒ͯ͘͠ΕΔπʔϧ • ʮInterfaceΛॻ͔ͳ͚Ε͹ͳΒͳ͍ʯDDD࣮૷ͱ૬ੑ͕Α͍

    • repositoryΛࢦఆͯ͋͛͠Ε͹mock͕Ψοͱ࡞ΒΕΔ • ʮͲͷΑ͏ʹrepository͕ݺ͹Εͯ΄͍͔͠ʯΛࢦఆͯ͠ςετͰ͖Δ
  37. Α΋΍·: gomockͱDDD func TestGetProduct(t *testing.T) { ctrl := gomock.NewController(t) defer

    ctrl.Finish() // ੜ੒͞Εͨmock package m := mock_repo.NewMockProductRepository(ctrl) /* * Get("hoge")͕call͞ΕΔ͜ͱΛςετ͠ɺ * ݺ͹Εͨ৔߹ID:"hoge"ͷmodelΛฦͯ͘͠ΕΔ * / id := "hoge" m.EXPECT().Get(id).Return(&model.Product{ID: id}, nil) // mock͸RepoͷIFΛຬ͍ͨͯ͠ΔͷͰinfraͱͯ͠࢖͑Δ app := application.NewProduct(m) res, err := app.GetProduct(id) ... }
  38. Α΋΍·: testͱtime.Now() • goʹݶͬͨ࿩/େͨ͠࿩Ͱ͸ͳ͍Ͱ͕͢... • ͍Ζ͍Ζͳͱ͜Ζʹ time.Now() ͕͋ΔͨΊʹ҆ఆͨ͠ςετ͕ॻ͚ͣ ʹఘΊͨܦݧ͸͋Γ·ͤΜ͔ •

    ςετ͠΍͍͢ΞʔΩςΫνϟͰؤுͬͯॻ͍ͯ΋ɺͦ͜Ͱͭ·͍ͣͯ ͸ҙຯ͕͋Γ·ͤΜɻ • ࣌ؒ͸উखʹॻ͖׵ΘΓଓ͚Δglobalม਺ͳͷͰॳظஈ֊͔Βੵۃతʹ ௥͍ग़͓ͯ͘͠ͷ͕ྑ͍ͱࢥ͍ͬͯ·͢ɻ
  39. Α΋΍·: testͱtime.Now() package clock import "time" // Clock ࣌ؒͷinjection༻IF type

    Clock interface { Now() time.Time } // RealClock ࣮࣌ؒΛฦ͢. αʔόʔ্Ͱ͸appʹ͜ΕΛ౉͢. type RealClock struct {} func (r *RealClock) Now() time.Time { return time.Now() } func NewRealClock(loc *time.Location) *RealClock { return &RealClock{} } // MockClock ݻఆ࣌ؒΛฦ͢μϛʔ࣌ܭ.ςετͰ͸appʹ͜ΕΛ౉͢. type MockClock struct { now *time.Time } func NewMockClock(t *time.Time) *MockClock { return &MockClock{now: t} } func (m *MockClock) Now() time.Time { return time.Now() } timeΛ௥͍ग़͢Ұͭͷྫ. ͕࣌ؒඞཁͳapplicationʹ͸࣌ܭ(Now ΛऔΕΔϞϊ)Λ౉͢Α͏ʹ͓ͯ͘͠ɻ ౎౓࣌ܭ౉͢ͷΊΜͲ͍ͱ͍͏ͷ͸͋Δ͕࣌ؒ΁ͷґ ଘΛ໌ࣔతʹ͢ΔҙຯͰ͸ଥ౰ͩͱࢥ͍ͬͯΔɻ
 
 ʘ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ʗ
  40. Αͨ͹ͳ͠

  41. infraͷࠩ͠ସ͑,ϚϧνΫϥ΢υͱ͍͏ເ • ʮinfraҎԼʹٕज़తؔ৺Λด͡ࠐΊΔͱσʔλϕʔε΍ج൫ΛҠߦ͠Α͏ͬͯͳͬͨ࣌ʹָʯ • ࣮ࡍ໰୊ͱͯͦ͠Μͳͷ͕ඞཁʹͳΔ͜ͱͳ͍΍Ζʁ΍ͬͨ͜ͱ͋Δ΍͓ͭΓΎʙ? • ΍ͬͨɻ • ࣾ಺ͷٕज़ϙʔτϑΥϦΦଟ༷Խ΍ݱߦͷΠϯϑϥʹ໰୊͕ੜͨ͡৔߹ʹඋ͑ͯɺ৽͍ٕ͠ज़ͷݕূ΋ͯ͠Έͨ ͍ΑͶͱ͍͏࿩͕͋ͬͨɻ

    • PJͷλΠϛϯά΍ܦݧతͳ౎߹΋͋ͬͯɺGCP/CloudDatastoreΛར༻ͯ͠MVP࣮૷Λߦͬͨɻ • ͦͷޙॾʑͷࣄ৘ΛצҊͯ͠AWS/Auroraʹࡌͤସ͑ͨɻ • ࣮૷্ͷӨڹൣғ͸͔֬ʹinfraҎԼʹݶఆ͞Εɺॻ͖׵͑ࣗମ͸2೔͔͔Βͳ͍͘Β͍ͰࡁΜͩɻ • (࣮૷͠ͳ͍Ͱࣄલͷݕ౼Ͱશ෦ચ͍ग़ͤΑɺͱݴΘΕΔͱ͕ࣖ௧͍ͱ͜ΖͰ͸͋Δ...·͊ૉৼΓ΋ͨ·ʹ͸Ͷ?)