Contextアンチパターン

 Contextアンチパターン

golang.tokyo#5でのLT資料です。

5bfed9aa3a9ebccb0c0f0cb65ee9e012?s=128

Seiji Takahashi

April 27, 2017
Tweet

Transcript

  1. ContextΞϯνύλʔϯ @__timakin__ golang.tokyo#5

  2. ࣗݾ঺հ

  3. ࣗݾ঺հ • twitter: @__timakin__ • github: timakin • גࣜձࣾGunosy ৽نࣄۀ։ൃࣨ(Go/Swift)

    • ओͳGoϥΠϒϥϦ։ൃ෺ • gopli (DBϨϓϦέʔγϣϯπʔϧ) • gonvert (จࣈίʔυม׵ϥΠϒϥϦ) • octop (githubͷissue, PRϏϡʔ༻CLIπʔϧ) • ts (ٕज़ɾϏδωεܥχϡʔε८ճCLIπʔϧ) • ϓϥΠϕʔτͰΫϩʔϥʔ࡞੒ɺ࠷ۙಈը഑৴पΓ͕ؾʹͳͬͯ·͢ɻ
  4. Copyright© Gunosy Inc. All Rights Reserved 4 Go / Python

    ΤϯδχΞืूத ▶https://gunosy.co.jp/recruit/ Gunosy͸ɺ౦ژେֶʹ௨͏3ਓͷֶੜͷ
 ʮ৘ใΛੈքதͷਓʹ࠷దʹಧ͚͍ͨʯͱ͍͏૝͍͔Β࢝·Γ·ͨ͠ɻ ౦ূϚβʔζ্৔ɺ࿡ຊ໦ώϧζ΁ͷΦϑΟεҠసΛܦͯɺ
 େ͖͘੒௕͍ͯ͠ΔձࣾͰ׆༂͍ͨ͠ϝϯόʔΛืू͍ͯ͠·͢ɻ
  5. ຊ೔ͷओࢫ

  6. ContextΛ͋͋ͯ͜͠͏ͯͨ͠Β
 ΰουΦϒδΣΫτͰ͖ͨ ͢·Μ

  7. Զ͕Ξϯνύλʔϯͩ ٩( ᐛ )و

  8. ΞδΣϯμ • context.ContextͷऔΓѻ͍ʹ͍ͭͯ • Ξϯνύλʔϯͷ࣮ྫʢ΍ͬͪΌͬͨʂ٩( ᐛ )وʣ • ެࣜͷGoDocͰਪ঑͞ΕΔίϯηϓτ •

    ൓লͱվળ
  9. Ξϯνύλʔϯͷ࣮ྫ

  10. @GoConference 2017

  11. ͍ͭ͜Λݟͯ͘ΕɺͲ͏ࢥ͏ʁ

  12. None
  13. <- echoͷcustom context <- context in context (!!)

  14. ͞Βʹ͍ͭ͜Λݟͯ͘Εʂ

  15. ͍ͭ͜Λݟͯ͘ΕɺͲ͏ࢥ͏ʁ

  16. ͍ͭ͜Λݟͯ͘ΕɺͲ͏ࢥ͏ʁ <- repository in context (!?)

  17. ͏͢͏͢ײ͍ͮͯ͸͍ͨΑʂʂ ̍̍

  18. ͢·ΜͱࢥͬͯΔ ٩( ᐛ )و

  19. ݴ͍༁

  20. context(context.Context) in context(ϑϨʔϜϫʔΫͷContext) • echoͷϑϨʔϜϫʔΫͷcontextͰ͸ͳ͘ඪ४ύοέʔδ ͷcontextΛ࢖ͬͯɺ಺෦ͷϩδοΫͰར༻͍ͯ͠Δ
 goroutineͷλΠϜΞ΢τ੍ޚΛ͍ͨ͠ • ͕ɺϦΫΤετϋϯυϥʹ౉ͬͯ͘Δͷ͸
 echo.Contextͩ͠ɺGAEͩͱhttp.Request͔Β


    contextΛऔΓग़ͤͳ͍ɻ • ϋϯυϥʹcontextΛ౉͢ʹ͸echo.Contextʹ
 context.ContextΛؚΊɺͦΕΛϋϯυϥҎԼͷ
 ϨΠϠʔͰར༻͢Δඞཁ͕͋Δ
  21. <- echoͷcustom context <- context in context (!!)

  22. repository in context • ਃ͠։͖͍͟͝·ͤΜʂʂ̍̍
 ͍͕ͭ͜ਆͩʂ • ·͊ͿͬͪΌ͚طଘͷ࣮૷(or ࢿྉ)ࢀߟʹ
 ࡞ͬͨΜͰ͕͢ɺέʔεόΠέʔεͰɺ


    ΘΓͱ͜͏͍͏globalͳΦϒδΣΫτΛೖΕͯΔ
 ݹ͍࣮૷ͱ͔͋ͬͯɺਅࣅͪΌͬͨɻ • ඪ४ύοέʔδͱͯ͠૊Έࠐ·ΕΔલͷ࣮૷Ͱ͸
 ͜͏͍͏ͷ΋͋ͬͨΑɺ͋ͬͨ͸ͣͳΜͩɻ • ਖ਼௚repository͚ͩ͡Όͳ͘configͱ͔΋٧ΊͪΌͬͨ
  23. Ҏ্ʹରͯ͠օ͞Μौ͍൓Ԡ

  24. None
  25. ͦ͏͍͑͹GoDocͰ͸

  26. GoDoc • Package context defines the Context type, 
 which

    carries deadlines, cancelation signals, and other request-scoped values across API boundaries and between processes. • Use context Values only for request-scoped data that transits processes and APIs, not for passing optional parameters to functions. • Do not store Contexts inside a struct type; instead, pass a Context explicitly to each function that needs it. • ͢·Μͯɻ
  27. GoDoc • ओʹgoroutine͕བྷΉॲཧɺAPIΛ·͙ͨॲཧΛߦ͏࣌ɺ
 λΠϜΞ΢τ੍ޚΛద੾ʹߦ͏ͨΊʹ࢖͏ • UserIDɺଞJWT౳ͷɺͦͷϦΫΤετʹݶఆ͞ΕΔ஋ΛGet/Set͢Δ ͱ͖ʹͷΈValueΛ࢖͏ • Go1.7Ҏલ(ࠓͷGAEͱ͔)
 func

    GetHandler(ctx context.Context, 
 w http.ResponseWriter, r *http.Request)
 
 Go1.7Ҏ߱
 ctx := r.Context() • ଞͷ༻్ɺड͚౉͠ํͰ࢖Θͳ͍ɻ
 ઈରͩͧɻ
  28. ൓লͱվળ

  29. GoDoc • ແବʹߏ଄ମʹcontextೖΕͳ͍ • echo -> net/http • ContextΛద੾ʹϋϯυϥʹ౉͢ •

    λΠϜΞ΢τઃఆ͸ServeHTTPͰߦ͏ʢMiddlewareͰ΋Մʣ • func Handler(ctx context.Context, w http.ResponseWriter, r *http.Request) • request-scopedͳ஋ʹݶఆ • repository.FromContextͱ͔શ෦ফ͢ • ϋϯυϥͰ౎౓ctxΛ౉ͯ͠ੜ੒ • ֤छΫϥΠΞϯτ΍Βlogger͸HandlerͷϨγʔόΛఆٛͯͦ͠ͷதʹೖΕΔ • function (app *App) GetItemHandler(ctx context.Context, …)
  30. ແବʹߏ଄ମʹcontextೖΕͳ͍ • echoΛnet/httpʹશஔ͖׵͑ • GAE(SE)ͩͱrequestʹContext͕ೖͬͯͳ͍ɻ
 ͞Βʹɺecho.ContextͷͲ͔͜Β΋context.Context͕ͱ Γͩͤͳ͍ɻ • ͦ΋ͦ΋GAEΛ࢖͍ͬͯͨͷͰɺechoඋ͑෇͚ͷϩΨʔ ͱ͔࢖Θͳ͍͠ɺrouting͘Β͍Ͱ͔͠Ըܙͳ͍

    • ϑϨʔϜϫʔΫ͕଍͔ͤʹͳ͍ͬͯͨͷͰɺ֎͢ɻ • ϋϯυϥʹඪ४ͷcontext͚ͩ౉͢Լ४උɻ
  31. ContextΛద੾ʹϋϯυϥʹ౉͢ • λΠϜΞ΢τઃఆ͸ServeHTTPͰߦ͏ʢMiddleware Ͱ΋Մʣ ServeHTTPΛ࣮૷ͨ͠AppHandlerΛఆٛͯ͠ɺ
 தͰappengineͷContext(context.Context)Λ λΠϜΞ΢τઃఆ෇͖Ͱϋϯυϥʹ౉͢

  32. request-scopedͳ஋ʹݶఆ • ͔ͯrequest-scopedͳ஋ͱ͔ಛʹͳ͍APIͩͬͨɻ • ͳͷͰWithValueશ෦ফͨ͠ɻ • repository.FromContextͱ͔શ෦ফ͢ • ϋϯυϥͰ౎౓ctxΛ౉ͯ͠ੜ੒ •

    GAEͩͱloggerͱ͔datastoreͰcontext͕ඞཁ • ͳͷͰɺglobalʹѻ͍͍ͨ஋ͩͱͯ͠΋ɺ
 ϋϯυϥҎ߱Ͱຖճݺͼग़ͯ͠·͢ɻ
 ʢ͜Ε͸ϕετϓϥΫςΟε͋Δͷ͔ʁʣ
  33. Ϩγʔόʹglobalͳ஋ΛೖΕΔ

  34. • (app *App)ΛϨγʔόͱͯ͠ઃఆ͢Δʹ͸handlerʹ ౰ͨΔϝιου͸શͯಉҰpackageͱͯ͠ఆٛ͞ΕΔ ඞཁ͕͋Δ • cannot define new methods

    on non-local type • ͳͷͰɺݸผͷυϝΠϯϩδοΫΛ࣋ͭσΟϨΫτϦ ͱ͸ผʹɺhandlerσΟϨΫτϦΛஔ͖ɺͦ͜ʹApp ͷఆٛͱݸผͷϦΫΤετϋϯυϥΛ࣋ͨͤΔɻ Ϩγʔόʹglobalͳ஋ΛೖΕΔ
  35. app.go

  36. main.go handler.AppHandler{Impl: app.HogeHandler}
 ͱ͍͏ܗࣜͰɺServeHTTPΛ࣋ͭAppHandlerʹ App structΛ࣋ͭHogeHandlerΛ౉͢ɻ

  37. ·ͱΊ • ਆ͸ࢮΜͩɻcontextড়Խ׬ྃɻ • request-scopedͳ஋ͱɺλΠϜΞ΢τҎ֎࢖Θͳ͍ɻ • άϩʔόϧͳΦϒδΣΫτΛར༻͢ΔͨΊʹ
 ϋϯυϥڞ௨ͷstructΛ༻ҙ͢Δɻ
 ͦͷӨڹͰϋϯυϥ͸ಉҰpackageʹ·ͱΊΔɻ