Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

ͩΕʁ • @yami20 (ΠϯλʔωοτҾ͖͜΋ΓͳͷͰಛʹ৘ใ͸ग़ͯ͜ͳ͍Ͱ͢) • Engineer@Finatext • อݥࣄۀͰαʔόʔαΠυ։ൃ • Go͸1.6?1.7?͋ͨΓͰͪΐͬͱ͞Θͬͯ཭Ε͍ͯͨ • ڈ೥ͷ฻Ε͔Β·ͨ৮Γ࢝Ίͨͱ͜Ζ • ͜ͷձͷλΠτϧʹʮ্ڃऀ޲͚ʯͱ͔ॻ͔ΕͯͯŜƄŞŲƄſͯ͠·͢

Slide 3

Slide 3 text

͖ΐ͏͓͸ͳ͢͠Δ͜ͱ • ͦͦ͜͜େ͖͍ɾෳࡶͳϓϩμΫτΛGoͰͭ͘Γ·ͨ͠ɻ • ࣮૷ΞʔΩςΫνϟͷબఆ΍tipsΛɺͦͷҙਤΛ৫Γަͥͳ͕Β͓࿩ ͯ͠ΈΑ͏ͱࢥ͍·͢ɻ

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

ຊ୊

Slide 7

Slide 7 text

ཁ݅ɾن໛ɾಛੑ ʙอݥϓϥοτϑΥʔϜγεςϜʙ •(͜ͷล͸ࢀߟఔ౓ʹॻ͍͚ͨͩͳͷͰඈ͹͠·͢) • ཁ݅ • APIαʔόʔ(SPAͷbackend) • ͪͳΈʹରʹͳΔfrontendͷ͸ͳ͠͸ https://speakerdeck.com/slont/bokufalsekangaetasaikiyoufalsevueakitekutiya • ෳ਺ͷอݥձ͕ࣾ঎඼Λઃܭɾొ࿥͠ɺސ٬ͷਃࠐΛड͚෇͚ͨΓɺܖ໿৹ࠪͨ͠Γ؅ཧͨ͠Γɺͦͷଞ෇ਵ͢Δػೳ͕΋ʹΐ΋ʹΐɻ • ن໛ • ΞυςΫ΍ήʔϜʹൺ΂ΔͱτϥϑΟοΫ͸֨ஈʹ͓ͱͳ͍͠ɻ1ਓ͕1೔ʹԿेճ΋Ճೖͨ͠Γ͠ͳ͍͠ɺ࿈ଧͯ͠౗͢ఢ΋͍ͳ͍ɻ • PFͰ͋Δ͜ͱΛ౿·͑ͯ΋ҰൠతͳECͱ͔ͷن໛ײΛΠϝʔδ͍͚ͯͨͩ͠Ε͹ɻ • ಛੑ • σʔλͷϥΠϑαΠΫϧ͕௕͍ɻ೥୯Ґ͕جຊɺਓੜ୯ҐͷऔҾ΋͋Δ • σʔλͷߏ଄͕ෳࡶ. ଐੑ΋ϦϨʔγϣϯ΋ͱʹ͔͘ଟ͍. • γεςϜͷण໋͕௕͍ɻσʔλͷϥΠϑαΠΫϧ͕௕͍ͷ΋͋Δ͠ɺPFͳͷͰ͓͍ͦΕͱด͡ΒΕͳ͍ͱ͍͏ͷ΋͋Δɻ • PFͰ͋ΔͨΊɺॳظʹग़Δཁ͕݅͢΂ͯͱ͸ݶΒͳ͍ • ࢥ͍΋ΑΒͳ͍֦ு͕ඞཁʹͳΔՄೳੑ͕͋Δ

Slide 8

Slide 8 text

࠾༻ͨ͠ߏ੒ • ϞϊϦε • ׬શʹ୯ҰγεςϜͱ͍͏Θ͚Ͱ͸ͳ͍Ͱ͕͢ɻ • ໌Β͔ʹੑ࣭ͷҟͳΔ෦෼͸෼཭͕ͨ͠ɺAPI਺ेຊͷίϯϙʔωϯτ3ͭͱ͍͏ঢ়ଶɻ • ϨΠϠʔυΞʔΩςΫνϟ(෩) • ݫີͳͦΕͰ͸ͳ͍ • DIP(ґଘੑͷٯస)΋૊ΈࠐΉ

Slide 9

Slide 9 text

ϞϊϦεͱ͍͏બ୒

Slide 10

Slide 10 text

ϞϊϦεͱϚΠΫϩαʔϏε • ϞϊϦεʹ਌Λࡴ͞Εͨܦݧ͸͋Δɻ • ϑϩϯτ͔Β؅ཧը໘·Ͱ͢΂͕ͯಉࠝ͞Εɺ100ਓҎ্ͷ։ൃऀ͕ҰͭͷϦϙδτϦʹ commit͠ʮdeployฒͼ·͢ʯͱ੠Λ͔͚߹͍ɺσϓϩΠࣦഊ͢Δͱଞ෦ॺʹౖΒΕΔσΟ ετϐΞ • ϚΠΫϩαʔϏεʹଜΛম͔Εͨܦݧ΋͋Δɻ • 1~3ςʔϒϧ૬౰ͷσʔλຖʹઐ༻ͷAPI͕ཚཱͯ͠૬ޓʹԿ౓΋ࢀর͍͋͠ɺ͍ͭͲ ͜ͰԿͷॲཧ͕ى͖͍ͯΔ͔Θ͔Βͳ͍σΟετϐΞ • ݁ہɺ͓࡞๏ʹࠩͷ͋Δଟ਺ͷγεςϜΛ͢΂ͯ೺Ѳ͠ͳ͚Ε͹Կ΋Θ͔Βͳ͍ɻ

Slide 11

Slide 11 text

ϞϊϦεͱϚΠΫϩαʔϏε • ϞϊϦε • ϝϯςෆՄೳͳ΄Ͳίʔυɾؔ܎ऀ͕ଟ͘ͳΔͱͭΒ͍ • ಉҰϦϙδτϦ಺͔ͩΒͱແࠩผʹࢀরΛΏΔ͢ͱΘ͚Θ͔ΒΜ͘ͳΔ • ϚΠΫϩαʔϏε • ෆద੾ͳ෼ׂʹΑͬͯຊདྷඞཁͷͳ͍ॲཧ͕૿Ճ͢Δͱͱͯ΋ͭΒ͍ • Ұൠతʹ࣮૷ྔ͸૿͑Δ͠ɺΠϯϑϥߏ੒໘Ͱͷݕ౼ࣄ߲ɾઃఆ΋૿͑Δ

Slide 12

Slide 12 text

ϞϊϦεͱ͍͏બ୒ • ࠷దͳϚΠΫϩαʔϏεͷཻ౓Λࣄલʹݟग़͢͜ͱ͸ඇৗʹ೉қ౓͕ߴ͍ɻ • ࢓༷௨Γʹ࣮૷͍ͯͨ͠ͷʹʮ࣮͸Aͷσʔλ͚ͩͩͱ଍Γͳͯ͘ɺৗʹBͱC΋ҰॹʹཁΔΜͩ...ʯͱ͔ݴΘΕ͕ͪ • Goͬͯهड़ྔࣗମ͸গͳ͘ͳ͍Ͱ͢ΑͶ? (ڞײΛٻΊΔѹྗ) • γϯϓϧͰಡΈॻ͖͠΍͍͢෼ɺʮָΛͤͯ͘͞ΕΔʯ࢓૊Έ͸߇͑Ίɻ • ϚΠΫϩαʔϏεͰͷهड़૿Ճͱ߹ΘͤΔͱͪΐͬͱϔϏʔɻ • αʔϏεͷ্ཱͪ͛࣌఺ͰϞϊϦε๊͕͑Δ໰୊͕ੜ͡ΔϦεΫ͸খ͍͞ • ʮϞϊϦεͷ··ʯҭͯͳͯ͘͢ΉΑ͏ʹద੾ͳઃܭɾ੍໿Λ͠ɺ͕࣌དྷͨΒ෼ׂ͢Ε͹Α͔Ζ͏ͳ ͷͩ • αʔϏεΛҭ͍ͯͯ͘தͰద੾ͳ෼ׂཻ౓͕ݟ͑ͯ͘Δͱ͍͏ϝϦοτ΋͋Δɻ

Slide 13

Slide 13 text

ͱ͜ΖͰ • ϞϊϦε(স)ͬͯݴΘΕΔ͘Β͍ͷ֮ޛͰ࣮૷͍ͯͨ͠ΜͰ͕͢ɺ
 ͜͜൒೥͘Β͍?ͰϞδϡϥϞϊϦεͱ͍͏֓೦͕ఏএ͞Ε͍ͯͨͷ Ͱ͢Ͷɻ • ͦͷͱ͓Γʹ΍͍ͬͯΔͱ·Ͱ͸ݴ͑·ͤΜ͕ɺΞϓϩʔνͱͯ͠ ͸Θ͔ΓΈ͕;͔͍

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

ϨΠϠʔυΞʔΩςΫνϟ(෩) • ͳͥΫϦʔϯΞʔΩςΫνϟ(ҎԼCA)Λબ͹ͳ͔ͬͨͷ͔? • CA͸͔ͨ͠ʹΑ͘Ͱ͖͍ͯΔͱ͓΋͏ • ͔͠͠ͳ͕ΒɺΞʔΩςΫνϟࣗମͷֶशίετͷߴ͕͞൱Ίͳ͍ • ૚෼͚͕ݫີɾৄࡉͰ͋Δ͕Ώ͑ʹɺʮ͏·͘Θ͚ͳ͚Ε͹͍͚ͳ͍ʯڧ੍͍໿Λײ͡Δ ʢݸਓͷײ૝Ͱ͢) • ݫີʹΘ͚ΒΕΔ͜ͱ͸ڧΈ͕ͩɺڧΈΛڗड͢Δʹ͸࠷ॳ͔Βߴ͍஌ݟ͕ٻΊΒΕΔɻ গਓ਺ɾ্ཱͪ͛ஈ֊ͷϓϩδΣΫτʹ͓͍ͯͷίεύ͸͍͔΄Ͳ͔?

Slide 18

Slide 18 text

ϨΠϠʔυΞʔΩςΫνϟ(෩)ͱ͍͏બ୒ • DDD޲͖ͷΞʔΩςΫνϟͷதͰ͸ൺֱతૉ௚(ݸਓͷײ૝Ͱ͢)ͳϨΠϠʔυ ΞʔΩςΫνϟͰ΋υϝΠϯΛ͖Ε͍ʹอͪɺϢʔεέʔεΛΘ͔Γ΍͘͢දݱ ͢Δ͜ͱ͸Ͱ͖Δɻ • ७ਮͳϨΠϠʔυΞʔΩςΫνϟ͸infra΁ͷґଘΛ࣋ͭͨΊςετͮ͠Β͍ • DIPΛՃ͑Ε͹΍Γ͍ͨ͜ͱ͸े෼ʹͰ͖Δɺ͸ͣɻ

Slide 19

Slide 19 text

ґଘੑͷٯస(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) } ```

Slide 20

Slide 20 text

ϨΠϠʔυΞʔΩςΫνϟ෩ʹຬͨ͢ͱ... ```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. ... } ```

Slide 21

Slide 21 text

ΫϦʔϯΞʔΩςΫνϟ෩ʹຬͨ͢ͱ... ```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.... } ```

Slide 22

Slide 22 text

CAͪΐͬͱΉ͔͍ͣ͠ ཆ৩෺ͷ՝୊/ٖࣅίʔυͰൺֱ͢Δͷ͸ͪͱͣΔ͍Ͱ͕͢...ͱ͖ͬͭʹ ͍͘͜ͱ͸൱Ίͳ͍...ɻ ͖Ε͍ͳந৅ԽͰ͋Δ͜ͱ͸Θ͔Δɻ ͔͠͠interfacesͱinfra͕ผΕ͍ͯΔԸܙͬͯԿ͚ͩͬ?
 ͦΕʹΑͬͯ޾ͤʹͳΔہ໘͸ࣗ෼ͨͪʹͲΕ͚ͩ๚ΕΔΜ͚ͩͬ?

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

ઃܭͷझࢫ • ࣮ફDDDʹ͍͏ʮ؇΍͔ͳϨΠϠʔԽΞʔΩςΫνϟʯ͕ϕʔε • ʮ؇΍͔ʯͱ͸ɺ௚Լͷ૚͚ͩͰͳ͘Լํ޲ͷ૚͸͍ͣΕ΋࢖ͬͯΑ͍ͱ͍͏ҙຯɻ • ໋໊ɾσΟϨΫτϦͷ੾Γํ͸ΘΓͱ;Μ͍͖ɻ • ڭՊॻతʹ͸ interfaces/handler ͱ͔͕ͩɺinterfaces͕όϦΤʔγϣϯʹ෋Ήҹ৅͕͋·Γ ͳ͘ɺtopϨϕϧͷσΟϨΫτϦ͕1ͭ2ͭ૿͑ͨͱͯࠔΔ͜ͱ΋ͳ͍ͷͰtopʹhandlerͰ ͖ͬͨɻ·͊ͲͬͪͰ΋͍͍͔ͳɻ • application͡Όͳͯ͘usecase͚ͬͯͭΔ͜ͱ͕ଟ͍ؾ΋͢Δɻ
 ݸਓతʹusecaseͬͯଧͭͱࠨख͕ർΕΔ͔ΒڭՊॻΛ໔ࡑූʹapplicationʹͨ͠ɻ

Slide 25

Slide 25 text

ઃܭͷझࢫ(Ά͑Ή) • DDD/ΞʔΩςΫνϟΛݫີʹकΖ͏ͱ͗͢͠Δͱɺࣗ෼ͨͪʹͱͬͯ ඞཁͰແ͍ෳࡶ͞Λ࣋ͪࠐΜͰ͠·ͬͨΓɺӨڹͷͳ͍ࣄฑʹ͍ͭͯ ʮͲ͜ʹॻ͘΂͖͔ʯʮͲ͏ॻ͘΂͖͔ʯͰա৒ʹ೰ΜͰ͠·͍͕ͪɻ • ࣗ෼͕ͨͪकΓ͍ͨ΋ͷΛकΔ΂͖Ͱ͋ͬͯɺڭՊॻతͳ໋໊ɾߏ଄Λ ݫक͢Δ͜ͱ͕໨తͰ͸ͳ͍ɻ • कΔ΂͖͜ͱΛ໌֬ʹɻ

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

੍໿Λ·΋ΔͨΊʹ 1. framework, httpʹؔ͢Δॲཧ͸handler಺Ͱ׬݁ͤ͞Δ 2. ϓϩάϥϜͷ֎ͷग़དྷࣄΛҙࣝ͢Δ࣮૷͸infra಺Ͱ׬݁ͤ͞Δ 1. ࣮ߦ؀ڥ,֎෦API,DB,... 3. app͸Լ૚(domain)ʹఆٛͨ͠interfaceʹґଘͤ͞Δ(DIP) 4. ͦΕҎ֎ͷࡉ͔͍͜ͱ͸Α͠ͳʹɻࠔΔਓ͕͍ͳ͚Ε͹Α͍ɻ

Slide 28

Slide 28 text

੍໿ʹΑͬͯಘΔ΋ͷᶃ • domainʹ͸֎෦API΍DBΛҙࣝ͢Δهड़͕શ͘ͳ͘ͳΔɻ • ७ਮͳϏδωεϩδοΫ͚͕ͩଘࡏ͢ΔͷͰͱͯ΋͖Ε͍(খฒײ) • γϯϓϧͳunit testΛ؆୯ɾ໢ཏతʹॻ͚Δɻ • DBͷσʔλΛͲ͏༻ҙͨ͠ΒΑ͍͔?local΍CIͰ؀ڥͷࠩ෼͸ແ͍͔?ͲΜ ͳϦΫΤετ͕དྷΔ͔?ͳͲͷٕज़త/؀ڥతͳ੍໿,ςετͷ೉͔͠͞Βղ์ ͞Ε͍ͯΔ͸ͣɻ • mock΋ෆཁͳͷͰɺʮςετͷ΍ΓํΛؒҧ͏ʯݒ೦΋ͳ͍

Slide 29

Slide 29 text

੍໿ʹΑͬͯಘΔ΋ͷᶄ • application͸repositoryͷinterfaceͷΈʹґଘ͠infraʹ͸ґଘ͍ͯ͠ͳ͍ɻ • infraΛࠩ͠ସ͑Δࣄ͕Ͱ͖Δɻ • mockΛࠩ͠ࠐΜͰͷunit test͕Մೳ • ͜ͷ৔߹ɺྫ͑͹ʮσʔλ͕ਖ਼͘͠อଘ͞ΕΔ͔ʯͷςετͰͳ͘ɺʮσʔλΛਖ਼͘͠૊ΈཱͯͯอଘΛݺ΂Δ͔ʯͷςετʹͳΔ • ࣮ࡍʹʮDBʹॻ͖ࠐ·ΕΔ͔·Ͱ֬ೝ͍ͨ͠ʯͱ͍͏࿩͸Θ͔Δ͕ʮapplication୯ମͷ੹຿ͷςετʯͱͯ͠͸͜ΕͰΑ͍͸ͣɻ infra࣮૷͚͕ͩbugͬͨ৔߹ʹ΋ɺapp͕bug͍ͬͯͳ͍͜ͱ͕อূ͞ΕΔɻ • localͰ࢖͑ͳ͍APIΛμϛʔʹࠩ͠ସ͑ͯಈ͔ͨ͠Γ͢Δ͜ͱ΋Մೳ

Slide 30

Slide 30 text

੍໿ʹΑͬͯಘΔ΋ͷᶅ • infra/handlerʹϏδωεϩδοΫ͕͍ͳ͍ͷͰɺٕज़తͳؔ৺ (http,sql,...)ʹϑΥʔΧεͰ͖Δɻ • ͨͱ͑͹handler͸͢΂ͯҎԼͷΑ͏ͳըҰతͰബ͍࣮૷ʹͳΔ • HTTP RequestͷParse • applicationݺग़ • Responseฦ٫

Slide 31

Slide 31 text

αʔϏεͷ੾Γग़͕͠Ͱ͖ͦ͏͔? • app/domain͕͓ޓ͍ʹઐ༻ͱͳ͍ͬͯΔ(ଞͷdomainΛ࢖Θͣɺଞͷapp͔Β࢖Θ Εͳ͍)΋ͷ΍ɺΘ͔ͣͳൣғͰ͔͠ڞ༗͍ͯ͠ͳ͍࣮૷͕͍͔ͭ͘ੜͨ͡ɻ • ͜ͷ༷ͳՕॴ͸࣮૷తʹಠཱੑ͕͔͍ͨɻ • ςετ΋ॻ͚͍ͯΔͷͰ੾Γग़͠͸༰қɻ • Ұ࿈ͷinfra/handler/app/domainΛ·Δͬͱ੾Γग़ͯ͠ϚΠΫϩαʔϏεʹͯ͠ ͠·ͬͯΑͦ͞͏ɻ • ͦ͏Ͱͳ͍Օॴ͸҆қʹ੾Γग़ͦ͏ͱߟ͑ͣɺ·ͣ͸ϦϑΝΫλ΍Ϣʔεέʔεͷ੔ ཧΛ৻ॏʹਐΊΔͷ͕Α͍Α͏ʹࢥ͏ɻ

Slide 32

Slide 32 text

Α΋΍·

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

Α΋΍·: handlerͷςετ • application΍handlerͷinterfaceԽ͸΍͍ͬͯͳ͍ • ΍ͬͨ΄͏͕handler,routingͷUT͸͠΍͍͢...͔ͳ? • (ബ͍࣮૷ͳΒ͹) handlerͷςετ͸UTΑΓe2eΛؤுͬͨ΄͏͕Α͍ͱࢥ͍ͬͯΔɻ • handler, ࣮ࡍͷreq/resͰࢼͨ͘͠ͳΔͷ͕ਓ৘Ͱ͸͋Γ·ͤΜ͔ • ʮinfraͷҟৗʹର͢ΔhandlerͷڍಈͷςετΛৗʹಈ͔͍ͨ͠ʯͱ͔ͳΒඞཁͦ͏ɻ • mockࠩ͠ࠐΜͰαʔόʔ্͛ͯe2eͰҰ౓ಈ࡞֬ೝ͢Ε͹ݸਓతʹ͸ຬ଍

Slide 35

Slide 35 text

Α΋΍·: handlerͷςετ • ͪͳΈʹe2eͱ͍ͬͯ΋ͦΜͳʹϋΠΧϥͳ΋ͷͰ͸ͳ͍ɻ • postmanͰಈ࡞֬ೝͯ͠ઃఆΛอଘ͠ɺnewmanͰ΋࢖͑ΔΑ͏ʹ͍ͯ͠Δɻ • ։ൃதʹʮͪΐͬͱcurlͯ͠ΈΔʯ୅ΘΓʹ࡞ͬͯͨΊ͓͚ͯ͹ಛʹ࣌ؒΛ͔ͭ Θͳͯ͘΋͔ͳΓͷ໢ཏੑʹͳΔͱࢥ͏ɻ

Slide 36

Slide 36 text

Α΋΍·: gomockͱDDD • gomock • https://github.com/golang/mock • InterfaceΛॆ଍͢Δmock࣮૷Λࣗಈੜ੒ͯ͘͠ΕΔπʔϧ • ʮInterfaceΛॻ͔ͳ͚Ε͹ͳΒͳ͍ʯDDD࣮૷ͱ૬ੑ͕Α͍ • repositoryΛࢦఆͯ͋͛͠Ε͹mock͕Ψοͱ࡞ΒΕΔ • ʮͲͷΑ͏ʹrepository͕ݺ͹Εͯ΄͍͔͠ʯΛࢦఆͯ͠ςετͰ͖Δ

Slide 37

Slide 37 text

Α΋΍·: 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) ... }

Slide 38

Slide 38 text

Α΋΍·: testͱtime.Now() • goʹݶͬͨ࿩/େͨ͠࿩Ͱ͸ͳ͍Ͱ͕͢... • ͍Ζ͍Ζͳͱ͜Ζʹ time.Now() ͕͋ΔͨΊʹ҆ఆͨ͠ςετ͕ॻ͚ͣ ʹఘΊͨܦݧ͸͋Γ·ͤΜ͔ • ςετ͠΍͍͢ΞʔΩςΫνϟͰؤுͬͯॻ͍ͯ΋ɺͦ͜Ͱͭ·͍ͣͯ ͸ҙຯ͕͋Γ·ͤΜɻ • ࣌ؒ͸উखʹॻ͖׵ΘΓଓ͚Δglobalม਺ͳͷͰॳظஈ֊͔Βੵۃతʹ ௥͍ग़͓ͯ͘͠ͷ͕ྑ͍ͱࢥ͍ͬͯ·͢ɻ

Slide 39

Slide 39 text

Α΋΍·: 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 ΛऔΕΔϞϊ)Λ౉͢Α͏ʹ͓ͯ͘͠ɻ ౎౓࣌ܭ౉͢ͷΊΜͲ͍ͱ͍͏ͷ͸͋Δ͕࣌ؒ΁ͷґ ଘΛ໌ࣔతʹ͢ΔҙຯͰ͸ଥ౰ͩͱࢥ͍ͬͯΔɻ
 
 ʘ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ʗ

Slide 40

Slide 40 text

Αͨ͹ͳ͠

Slide 41

Slide 41 text

infraͷࠩ͠ସ͑,ϚϧνΫϥ΢υͱ͍͏ເ • ʮinfraҎԼʹٕज़తؔ৺Λด͡ࠐΊΔͱσʔλϕʔε΍ج൫ΛҠߦ͠Α͏ͬͯͳͬͨ࣌ʹָʯ • ࣮ࡍ໰୊ͱͯͦ͠Μͳͷ͕ඞཁʹͳΔ͜ͱͳ͍΍Ζʁ΍ͬͨ͜ͱ͋Δ΍͓ͭΓΎʙ? • ΍ͬͨɻ • ࣾ಺ͷٕज़ϙʔτϑΥϦΦଟ༷Խ΍ݱߦͷΠϯϑϥʹ໰୊͕ੜͨ͡৔߹ʹඋ͑ͯɺ৽͍ٕ͠ज़ͷݕূ΋ͯ͠Έͨ ͍ΑͶͱ͍͏࿩͕͋ͬͨɻ • PJͷλΠϛϯά΍ܦݧతͳ౎߹΋͋ͬͯɺGCP/CloudDatastoreΛར༻ͯ͠MVP࣮૷Λߦͬͨɻ • ͦͷޙॾʑͷࣄ৘ΛצҊͯ͠AWS/Auroraʹࡌͤସ͑ͨɻ • ࣮૷্ͷӨڹൣғ͸͔֬ʹinfraҎԼʹݶఆ͞Εɺॻ͖׵͑ࣗମ͸2೔͔͔Βͳ͍͘Β͍ͰࡁΜͩɻ • (࣮૷͠ͳ͍Ͱࣄલͷݕ౼Ͱશ෦ચ͍ग़ͤΑɺͱݴΘΕΔͱ͕ࣖ௧͍ͱ͜ΖͰ͸͋Δ...·͊ૉৼΓ΋ͨ·ʹ͸Ͷ?)