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

やはり俺の Go アプリケーション設計はまちがっている。 / My Go Application Design Is Wrong, As I Expected

ktr
September 23, 2018

やはり俺の Go アプリケーション設計はまちがっている。 / My Go Application Design Is Wrong, As I Expected

Student Go #1

ktr

September 23, 2018
Tweet

More Decks by ktr

Other Decks in Technology

Transcript

  1. at Student Go #1 ΍͸ΓԶͷ Go ΞϓϦέʔγϣϯઃܭ͸
 ·͕͍ͪͬͯΔɻ

  2. LUS !LUS@!LUS  6OJWFSTJUZPG"J[V XIPBNJ

  3. w (Pͷࢥ૝ͱඪ४ύοέʔδͷಛ௃ w (PΞϓϦέʔγϣϯͷઃܭ ࠓ೔͓࿩͢Δ͜ͱ

  4. w Զͷߟ͑ͨ࠷ڧͷΞʔΩςΫνϟ w ΞϓϦέʔγϣϯ֎෦ͷ͜ͱ %#ɺ8FCαʔόɺ FUD ࠓ೔͓࿩͠ͳ͍͜ͱ

  5. w ͳͥઃܭΛ͢Δͷ͔ʁ w ΦϒδΣΫτࢦ޲ͱϞδϡʔϧ w (Pͷࢥ૝ͱύοέʔδઃܭ w (PΞϓϦέʔγϣϯઃܭ ΞδΣϯμ

  6. w ͳͥઃܭΛ͢Δͷ͔ʁ w ΦϒδΣΫτࢦ޲ͱϞδϡʔϧ w (Pͷࢥ૝ͱύοέʔδઃܭ w (PΞϓϦέʔγϣϯઃܭ ΞδΣϯμ

  7. ͳͥઃܭΛ͢Δͷ͔ʁ

  8. w ਓؒ͸ඞͣؒҧ͑Δ w Ϧιʔε͸ৗʹ༗ݶ ιϑτ΢ΣΞ͸ਓ͕͍ؒͭͬͯ͘Δ

  9. w ૝ఆ֎ͷৼΔ෣͍ όά ΁ͷίετΛ࠷খݶʹ w मਖ਼΁ͷίετΛ࠷খݶʹ ݶΒΕͨϦιʔεͰιϑτ΢ΣΞΛ
 ͭ͘ΔͨΊʹ

  10. w Ϗδωεʹجͮ͘࡞ۀɾۀ຿ɾ࢓ࣄ υϝΠϯ  ΛࣗಈԽ͢Δͷ͕ΞϓϦέʔγϣϯ։ൃ w ͜ΕΒ͸ৗʹมԽ͠ଓ͚Δ ΞϓϦέʔγϣϯ։ൃͷδϨϯϚ

  11. w Ϗδωεʹجͮ͘࡞ۀɾۀ຿ɾ࢓ࣄ υϝΠϯ  ΛࣗಈԽ͢Δͷ͕ΞϓϦέʔγϣϯ։ൃ w ͜ΕΒ͸ৗʹมԽ͠ଓ͚Δ ΞϓϦέʔγϣϯ։ൃͷδϨϯϚ ΞϓϦέʔγϣϯΤϯδχΞ͸
 ৗʹมԽ͠ଓ͚Δ΋ͷΛ


    ௥͍ଓ͚ͳ͚Ε͹ͳΒͳ͍
  12. ଎͘ਐΉ།Ұͷํ๏͸ɺ͏·͘ਐΉ͜ͱͰ͋Δɻ — Clean Architecture ୡਓʹֶͿιϑτ΢ΣΞͷߏ଄ͱઃܭ

  13. w ࢓༷௨Γʹಈ࡞͢Δ͔ w ࢓༷มߋʹదԠͰ͖Δ͔ w ιϑτ΢ΣΞͷ࠶ར༻ੑ w FUD ιϑτ΢ΣΞʹٻΊΔ͜ͱ

  14. w ίʔυͷมߋ͠΍͢͞ w ίʔυͷཧղ͠΍͢͞ɺՄಡੑ w FUD ͦͷͨΊʹඞཁͳ΋ͷ

  15. w ։ൃऀ͕υϝΠϯϩδοΫʹूதͰ͖Δ w ਖ਼ղͰ͸ͳ͘ͱ΋ܾΊΔ͜ͱࣗମʹՁ஋͕͋Δ  ઃܭɾΞʔΩςΫνϟͷՁ஋ *1: https://speakerdeck.com/sonatard/next-currency-gaego

  16. w ͳͥઃܭΛ͢Δͷ͔ʁ w ΦϒδΣΫτࢦ޲ͱϞδϡʔϧ w (Pͷࢥ૝ͱύοέʔδઃܭ w (PΞϓϦέʔγϣϯઃܭ ΞδΣϯμ

  17. ΦϒδΣΫτࢦ޲ͱϞδϡʔϧ

  18. ΦϒδΣΫτࢦ޲Ϋϥεࢦ޲

  19. w :FTBOEOP  w $ݴޠΑΓΦϒδΣΫτࢦ޲ͳݴޠ w ΦϒδΣΫτࢦ޲͔Ͳ͏͔͸ਅِ஋Ͱ͸ͳ͍  (P͸ΦϒδΣΫτࢦ޲ݴޠ͔ʁ *1:

    https://golang.org/doc/faq#Is_Go_an_object-oriented_language *2: ΦϒδΣΫτࢦ޲ೖ໳ ୈ 2 ൛ ݪଇɾίϯηϓτ
  20. w ιϑτ΢ΣΞͷ࣋ͭ΂͖ػೳͷ࢓༷͸ඇৗʹ੬͍ w ৗʹιϑτ΢ΣΞશମ͕มߋ͞ΕΔՄೳੑ͕
 ෇͖·ͱ͏ ػೳϕʔεͷϞσϦϯά

  21. ྫ ίϯύΠϥ w MFYFS w QBSTFS w "45 ΦϒδΣΫτϕʔεͷϞσϦϯά

  22. ίϯύΠϥʹ৽͍͠ػೳ͕௥Ճ͞Εͨͱͯ͠΋
 ΦϒδΣΫτʹมߋ͸ੜ͡ʹ͍͘ ΦϒδΣΫτϕʔεͷϞσϦϯά

  23. ιϑτ΢ΣΞͷ࣋ͭ΂͖ػೳͰ͸ͳ͘ɺ
 ૢ࡞͢ΔΦϒδΣΫτͷܕ͔Βಋ͔ΕΔϞδϡʔϧ ΛجຊʹΞʔΩςΫνϟΛߏங͢Δ։ൃख๏ ΦϒδΣΫτࢦ޲ʹΑΔ։ൃ — ΦϒδΣΫτࢦ޲ೖ໳ ୈ 2 ൛ ݪଇɾίϯηϓτ

    (Ұ෦վม)
  24. ιϑτ΢ΣΞͷ࣋ͭ΂͖ػೳͰ͸ͳ͘ɺ
 ૢ࡞͢ΔΦϒδΣΫτͷܕ͔Βಋ͔ΕΔϞδϡʔϧ ΛجຊʹΞʔΩςΫνϟΛߏங͢Δ։ൃख๏ ΦϒδΣΫτࢦ޲ʹΑΔ։ൃ — ΦϒδΣΫτࢦ޲ೖ໳ ୈ 2 ൛ ݪଇɾίϯηϓτ

    (Ұ෦վม)
  25. w /P w ػೳΛ஌Βͳ͚Ε͹ιϑτ΢ΣΞΛߏஙͰ͖ͳ͍ w ػೳΑΓઌʹΦϒδΣΫτͷܕΛ෼ੳ͢Δ ػೳʹ͍ͭͯߟ͑Δ΂͖Ͱ͸ͳ͍ʁ

  26. w QBDLBHF࠷খͷϞδϡʔϧ୯Ґ w (PNPEVMFTQBDLBHFͷίϨΫγϣϯ୯Ґ (PͷϞδϡʔϧγεςϜ

  27. w มߋʹڧ͍ߏ଄Λͭ͘ΔͨΊ w ཧղ͠΍͍͢ߏ଄Λͭ͘ΔͨΊ w ૊Έ߹Θͤ΍͍͢ߏ଄Λͭ͘ΔͨΊ ͳͥϞδϡʔϧ͕ඞཁ͔ʁ

  28. w ͳͥઃܭΛ͢Δͷ͔ʁ w ΦϒδΣΫτࢦ޲ͱϞδϡʔϧ w (Pͷࢥ૝ͱύοέʔδઃܭ w (PΞϓϦέʔγϣϯઃܭ ΞδΣϯμ

  29. (Pͷࢥ૝ͱύοέʔδߏ੒

  30. w l1BDLBHFYYYQSPWJEFT PSJNQMFNFOUT z͔Β
 ࢝·ΔυΩϡϝϯτ ඞ໊ͣࢺ͕ύοέʔδ໊ʹͳΔ w 4IPSU DPODJTF FWPDBUJWF

     w "WPJETUVUUFS w 40-*%ݪଇʹجͮ͘ (Pͷඪ४ύοέʔδͷಛ௃ *1: https://golang.org/doc/effective_go.html?#package-names
  31. !IUUQ)5514FSWFS IUUQ4FSWFS "WPJETUVUUFS ٣Ի https://blog.golang.org/package-names

  32. w 4JOHMF3FTQPOTJCJMJUZ1SJODJQBM w Ϟδϡʔϧ͸ͨͬͨҰͭͷΞΫλʔʹରͯ͠
 ੹຿Λෛ͏΂͖Ͱ͋Δ 4୯Ұ੹೚ݪଇ

  33. w ύοέʔδ໊͕ද͢υϝΠϯʹͷΈ੹຿Λ࣋ͭ w JPˠೖग़ྗΛந৅Խͨ͠ΠϯλʔϑΣʔεͷఏڙ w GNUˠೖग़ྗͷϑΥʔϚοτ 4୯Ұ੹೚ݪଇ

  34. w 0QFO$MPTFE1SJODJQBM w Ϟδϡʔϧ͸֦ுʹରͯ͠։͍͍ͯͯɺ
 मਖ਼ʹରͯ͠ด͍ͯ͡ͳ͚Ε͹ͳΒͳ͍ 0։์ด࠯ݪଇ

  35. type nopCloser struct { io.Reader } func (nopCloser) Close() error

    { return nil } func NopCloser(r io.Reader) io.ReadCloser { return nopCloser{r} }
  36. package cli func Run(cmd string, args []string) { switch cmd

    { case "echo": fmt.Println(strings.Join(args, " ")) case "reverse": reversed := reverse(args) fmt.Println(strings.Join(reversed, " ")) default: fmt.Println("unknown command") } } $ ./app echo foo bar foo bar
  37. package cli type Command interface { Run(args []string) } func

    Run(cmd Command, args []string) { cmd.Run(args) }
  38. package main type echoCommand struct{} func (c *echoCommand) Run(args []string)

    { // logic } type reverseCommand struct{} func (c *reverseCommand) Run(args []string) { // logic }
  39. package main func main() { cmdName := os.Args[1] args :=

    os.Args[2:] var cmd cli.Command switch cmdName { case "echo": cmd = &echoCommand{} case "reverse": cmd = &reverseCommand{} default: // unknown command } cli.Run(cmd, args) }
  40. w ιϑτ΢ΣΞ͕બ୒ࢶΛఏڙ͠ͳ͚Ε͹ͳΒͳ͍ ࣌ɺͨͩҰͭͷϞδϡʔϧ͚͕ͩͦͷબ୒ࢶͷ͢ ΂ͯΛ೺Ѳ͢΂͖Ͱ͋Δ ୯Ұબ୒੹೚

  41. package cli type CLI struct { Commands map[string]Command } func

    (c *CLI) Run(args []string) error { cmdName := args[0] cmd, ok := c.Commands[cmdName] if !ok { return errors.New("unknown command") } cmd.Run(args[1:]) return nil }
  42. package main func main() { args := os.Args[1:] c :=

    &cli.CLI{} c.Commands = map[string]cli.Command{ “echo": &echoCommand{}, "reverse": &reverseCommand{}, } c.Run(args) }
  43. w 4ܕͷΦϒδΣΫτPͱ5ܕͷΦϒδΣΫτ P͕͋Γɺ5Λ࢖ͬͯఆٛ͞ΕͨϓϩάϥϜʹ ରͯ͠Pͷ୅ΘΓʹPΛ࢖ͬͯ΋ϓϩάϥϜ ͷৼΔ෣͍͕มΘΒͳ͍৔߹ɺ4͸5ͷ೿ੜܕ ͱݴ͑Δ -Ϧείϑͷஔ׵ݪଇ

  44. 3FDUBOHMF 4RVBSF $MJFOU

  45. type Rectangle interface { SetX(x int) SetY(y int) } type

    Square struct { x, y int } func (s *Square) SetX(x int) { s.x, s.y = x, x } func (s *Square) SetY(y int) { s.x, s.y = y, y }
  46. func TestRectangle(t *testing.T) { var r Rectangle = &Square{} expectedX,

    expectedY := 100, 200 r.SetX(100) r.SetY(200) if x := r.GetX(); x != expectedX { t.Errorf("x expected %d, but got %d", expectedX, x) } if y := r.GetY(); y != expectedY { t.Errorf("y expected %d, but got %d", expectedX, y) } }
  47. w ΠϯλʔϑΣʔεͷΫϥΠΞϯτʹΫϥΠΞϯτ ͕ར༻͠ͳ͍ϝιου΁ͷґଘΛڧ੍ͯ͠͸ͳΒ ͳ͍ *ΠϯλʔϑΣʔε෼཭ͷݪଇ

  48. w 5IFCJHHFSUIFJOUFSGBDF UIFXFBLFSUIF BCTUSBDUJPO  w ඪ४ύοέʔδͷΠϯλʔϑΣʔε͸ඇৗʹ
 খ͘͞ɺগͳ͘อͨΕ͍ͯΔ  *ΠϯλʔϑΣʔε෼཭ͷݪଇ

    *1: Go Proverbs (https://go-proverbs.github.io/) *2: The Go Blog - Organizing Go code
  49. w JP3FBEFS JP8SJUFS w IUUQ)BOEMFS w FUD *ΠϯλʔϑΣʔε෼཭ͷݪଇ

  50. w ্ҐϨϕϧͷϞδϡʔϧ͸ԼҐϨϕϧͷϞδϡʔϧʹґ ଘͯ͠͸ͳΒͳ͍ɻ྆ํͱ΋ந৅ʹґଘ͢΂͖Ͱ͋Δɻ w ந৅͸ৄࡉʹґଘͯ͠͸ͳΒͳ͍ɻৄࡉ͕ந৅ʹґଘ͢ ΂͖Ͱ͋Δɻ %ґଘؔ܎ٯసͷݪଇ

  51. w *NQPSUDZDMFOPUBMMPXFE w ҆ఆͨ͠ந৅͸ґଘάϥϑͷԼҐϨϕϧ΁ɺ
 ৄࡉ͸্ҐϨϕϧ΁ %ґଘؔ܎ٯసͷݪଇ

  52. w ΞʔΩςΫνϟΛઃܭ͠ɺ w ద੾ͳ໊લΛϞδϡʔϧ΁͚ͭɺ w ͦΕҎ֎ͷৄࡉ͸υΩϡϝϯτʹ࢒͢ w ݸਓతʹ ࠷΋कΒΕ͍ͯͳ͍ݪଇͩͱࢥ͏ %FTJHOUIFBSDIJUFDUVSF

    
 OBNFUIFDPNQPOFOUT EPDVNFOUUIFEFUBJMT
  53. (PΞϓϦέʔγϣϯͷઃܭ

  54. w ϥΠϒϥϦͱ͸ҧ͍ɺ࣮ߦՄೳϑΝΠϧ ֎෦ʹΫϥΠΞϯτ͕ଘࡏ͢Δ
  ϒϥ΢βɺϞόΠϧɺϚΠΫϩαʔϏεɺFUD  w ΫϥΠΞϯτʹఏڙ͢ΔϢʔεέʔε͕ଘࡏ͢Δ ΞϓϦέʔγϣϯ

  55. w ϢʔεέʔεϩδοΫ
 ϢʔεέʔεΛ࣮ݱ͢ΔͨΊͷϩδοΫ w υϝΠϯϩδοΫ
 Ϣʔεέʔεʹґଘ͠ͳ͍ϩδοΫ ϢʔεέʔεϩδοΫɺυϝΠϯϩδοΫ

  56. w 6*΍"1*ΠϯλʔϑΣʔεʹґଘ͢Δ w ϖʔδϯά෇͖ͷҰཡը໘ w ೖྗ஋Λݩʹͨ͠Ϣʔβొ࿥ w FUD ۩ମతͳϢʔεέʔεϩδοΫ

  57. w Ϣʔεέʔεʹґଘ͠ͳ͍ w υϝΠϯ஌ࣝΛϞσϦϯά͠ɺ֤ཁૉΛ
 Ϟδϡʔϧ΁෼཭͢Δ w ৄ͘͠͸%%%*%%%Λࢀর υϝΠϯϩδοΫ

  58. w (Pͷඪ४ύοέʔδͱಉ͡ํ਑Ͱ w 40-*%ݪଇΛकΔ w ໌֬ͳ໊ࢺΛύοέʔδ໊ʹ͢Δ w ύοέʔδ໊ͱΤϯςΟςΟ໊ΛৗʹηοτͰߟ͑Δ Ϟδϡʔϧ෼ׂͷ୯Ґ

  59. w ίʔυ͚ͩͰ͸Θ͔Βͳ͍ɺΘ͔ΓͮΒ͍ৄࡉ΍ ࢓༷Λ࢒͢ w ϞδϡʔϧͷΫϥΠΞϯτʹͰ͖ΔݶΓ
 ࣮૷Λಡ·ͤͳ͍Α͏ʹ͢Δ υΩϡϝϯτ

  60. type ResponseWriter interface { // WriteHeader sends an HTTP response

    header with the provided // status code. // // If WriteHeader is not called explicitly, the first call to Write // will trigger an implicit WriteHeader(http.StatusOK). // Thus explicit calls to WriteHeader are mainly used to // send error codes. // // The provided code must be a valid HTTP 1xx-5xx status code. // Only one header may be written. Go does not currently // support sending user-defined 1xx informational headers, // with the exception of 100-continue response header that the // Server sends automatically when the Request.Body is read. WriteHeader(statusCode int) }
  61. type ResponseWriter interface { // WriteHeader sends an HTTP response

    header with the provided // status code. // // If WriteHeader is not called explicitly, the first call to Write // will trigger an implicit WriteHeader(http.StatusOK). // Thus explicit calls to WriteHeader are mainly used to // send error codes. // // The provided code must be a valid HTTP 1xx-5xx status code. // Only one header may be written. Go does not currently // support sending user-defined 1xx informational headers, // with the exception of 100-continue response header that the // Server sends automatically when the Request.Body is read. WriteHeader(statusCode int) }
  62. ·ͱΊ

  63.  υϝΠϯ஌ࣝΛे෼ʹಘΔ  ҆ఆͨ͠ந৅Λݟ͚ͭͯɺܕͱ໊લΛ͚ͭΔ w ΞϓϦέʔγϣϯʹґଘ͠ͳ͍͜ͱ  ಘΒΕͨܕΛ40-*%΍(Pͷࢥ૝ʹج͍ͮͯ
 ϞδϡʔϧԽ͢Δ Ϟδϡʔϧͷఆٛɾߏங

  64.  ػೳ Ϣʔεέʔε Λ೺Ѳ͢Δ  ϞδϡʔϧΛ૊Έ߹Θ࣮ͤͯݱ͢Δ w ఆٛͨ͠Ϟδϡʔϧ಺ʹ࣮૷͠ͳ͍͜ͱ ΞϓϦέʔγϣϯͷߏங

  65. w ͱ͸͍͑ɺઃܭ͸೉͍͠ w ϕετͳઃܭ͸ଘࡏ͠ͳ͍ w ঢ়گʹԠͯ͡ϕλʔͳઃܭΛݟ͚͍ͭͯ͜͏ ·ͱΊ

  66. w ΞʔΩςΫνϟύλʔϯ΍ɺઃܭͷݪଇ w ͔ͳΓΘ͔Γ΍͍͕͢ɺ֤ݪଇͷৄࡉ͸
 ผͷຊͷ΄͏͕ৄ͍͠ $MFBO"SDIJUFDUVSF ୡਓʹֶͿιϑτ΢ΣΞͷߏ଄ͱઃܭ

  67. w ΦϒδΣΫτࢦ޲ͷ໨తɺఆٛɺݪଇ w ϖʔδʂ w จষ͕೉ղ͕ͩɺΦϒδΣΫτࢦ޲ʹؔ͢Δ ͍͍ͩͨͷ͜ͱ͸ॻ͍ͯ͋Δ ΦϒδΣΫτࢦ޲ೖ໳ୈ൛ ݪଇɾίϯηϓτ

  68. w %%%ຊ w υϝΠϯΛத৺ʹઃܭ͢Δ͜ͱͷॏཁੑ΍ཧ ࿦ɺͦͷख๏Λѻ͏ w ந৅తͳදݱ͕ଟͯ͘೉͍͠ ΤϦοΫɾΤϰΝϯεͷυϝΠϯ ۦಈઃܭ

  69. w *%%%ຊ w %%%Λ࣮ࡍͷઃܭʹԠ༻͢Δ w %%%ຊΛಡΜͰͳ͍ͱΘ͔Βͳ͍఺΋͋Δ ࣮ફυϝΠϯۦಈઃܭ

  70. w 5IF(P#MPHIUUQTCMPHHPMBOHPSH w 5IF(P1SPHSBNNJOH-BOHVBHF%PDVNFOUBUJPOIUUQTHPMBOHPSHEPD w 40-*%(P%FTJHOIUUQTEBWFDIFOFZOFUTPMJEHPEFTJHO w ʮ(PݴޠΒ͠͞ʯͱ͸Կ͔ʁ4JNQMJDJUZͷ఩ֶΛཧղ͠ɺ(P8BZʹԊͬͨ։ൃΛ ਐΊΔ͜ͱͷྑ͞
 IUUQTFNQMPZNFOUFOKBQBODPNFOHJOFFSIVCFOUSZ

    8FC