Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

391 views

Published on

For developers used to working with frameworks like Spring, and Rails, Go's lack of advice on how to structure your application can be bewildering. Many new developers, reach for their favourite Spring, or Rails equivalent, and rely on its structure, but that is a mistake! Go gives us wonderful tools to put Domain-driven design into practice, and create beautiful applications.

Published in: Technology
  • Well done, also...GROW YOU DOWNLINE OVERNIGHT - Works with any mlm. Have dozens joining whatever mlm your doing today! Go to: www.mlmrc.com
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

  1. 1. How To Structure Go Applications Paul Bellamy MILAN 25-26 NOVEMBER 2016
  2. 2. HOW BIG IS YOUR APPLICATION?
  3. 3. GO DIFFERENCES
  4. 4. META
  5. 5. package privacy type private struct{} type Public struct { PublicField string privateField string }
  6. 6. IS GO AN OBJECT-ORIENTED LANGUAGE? Go FAQ
  7. 7. IS GO AN OBJECT-ORIENTED LANGUAGE? YES AND NO. Go FAQ
  8. 8. CAR FIAT
  9. 9. FIAT CAR type Fiat struct { Car w Warranty }
  10. 10. type Fiat struct { Car w Warranty } type Car struct{} func (c Car) MarshalJSON() ([]byte, error) { … }
  11. 11. ~/GOPATH
  12. 12. FRAMEWORKS
  13. 13. # Get 'revel' framework and command $ go get github.com/revel/cmd/revel # Create a new app $ revel new github.com/paulbellamy/myapp # Run revel application $ revel run github.com/paulbellamy/myapp
  14. 14. myapp/ App root app/ App sources controllers/ App controllers init.go Interceptor registration models/ App domain models routes/ Reverse routes (generated code) views/ Templates tests/ Test suites conf/ Configuration files app.conf Main configuration file routes Routes definition
  15. 15. WHAT WEAVE TRIED
  16. 16. MVC
  17. 17. myapp/ App root app/ App sources controllers/ App controllers models/ App domain models views/ Templates public/ Public assets
  18. 18. myapp/ App root app/ App sources controllers/ App controllers models/ App domain models views/ Templates public/ Public assets lib/ Other stuff ???
  19. 19. myapp/ App root app/ App sources controllers/ App controllers models/ App domain models views/ Templates public/ Public assets lib/ Other stuff ??? generate_certificates_tool.go
  20. 20. myapp/ App root app/ App sources controllers/ App controllers models/ App domain models views/ Templates public/ Public assets lib/ Other stuff ??? generate_certificates_tool.go uuid.go
  21. 21. myapp/ App root app/ App sources controllers/ App controllers models/ App domain models views/ Templates public/ Public assets lib/ Other stuff ??? generate_certificates_tool.go uuid.go conn_with_read_timeout.go
  22. 22. myapp/ App root app/ App sources controllers/ App controllers models/ App domain models views/ Templates public/ Public assets lib/ Other stuff ??? generate_certificates_tool.go uuid.go conn_with_read_timeout.go max_bytes_reader.go
  23. 23. myapp/ App root app/ App sources controllers/ App controllers models/ App domain models views/ Templates public/ Public assets lib/ Other stuff ??? generate_certificates_tool.go uuid.go conn_with_read_timeout.go max_bytes_reader.go
  24. 24. myapp/ App root myapp.go App binary app/ App sources controllers/ App controllers models/ App domain models views/ Templates public/ Public assets lib/ Other stuff ??? generate_certificates_tool.go uuid.go conn_with_read_timeout.go
  25. 25. myapp/ App root myapp.go App binary app/ App sources controllers/ App controllers models/ App domain models views/ Templates public/ Public assets lib/ Other stuff ??? generate_certificates_tool.go uuid.go conn_with_read_timeout.go
  26. 26. import . "github.com/myaccount/myapp/lib" u := NewUUID()
  27. 27. myapp/ App root myapp.go App binary app/ App sources controllers/ App controllers models/ App domain models views/ Templates public/ Public assets lib/ Other stuff ??? generate_certificates_tool.go uuid.go conn_with_read_timeout.go
  28. 28. myapp/ App root app/ App sources controllers/ App controllers users_controller.go models/ App domain models views/ Templates
  29. 29. import "github.com/myaccount/myapp/app/controllers" controllers.UsersController
  30. 30. GROUP-BY-MODULE
  31. 31. scope/ App root app/ Runs “in the cloud” probe/ Runs in the users’s cluster common/ Shared code between app and probe xfer/ Defines the communication protocol
  32. 32. scope/ App root app/ Runs “in the cloud” probe/ Runs in the users’s cluster common/ Shared code between app and probe xfer/ Defines the communication protocol
  33. 33. scope/ App root app/ Runs “in the cloud” probe/ Runs in the users’s cluster common/ Shared code between app and probe xfer/ Defines the communication protocol
  34. 34. scope/ App root app/ Runs “in the cloud” probe/ Runs in the users’s cluster common/ Shared code between app and probe xfer/ Defines the communication protocol
  35. 35. BEST PRACTICE
  36. 36. DOMAIN
  37. 37. DOMAIN ADAPTERS
  38. 38. DOMAIN ADAPTERS BINARY
  39. 39. DOMAIN ADAPTERS BINARY
  40. 40. users/ App root user.go organization.go errors.go cmd/ App binaries api/ HTTP API emailer/ Email providers oauth/ OAuth Providers db/ App database(s)
  41. 41. users/ App root README.md Dockerfile src/ Top-level container for go files user.go organization.go errors.go cmd/ App binaries api/ HTTP API emailer/ Email providers oauth/ OAuth Providers
  42. 42. // Without src/ directory import "github.com/paulbellamy/users" t := users.Organization{}
  43. 43. // Without src/ directory import "github.com/paulbellamy/users" t := users.Organization{} // With src/ directory import users “github.com/paulbellamy/users/src" t := users.Organization{}
  44. 44. users/ App root user.go organization.go errors.go cmd/ App binaries api/ HTTP API emailer/ Email providers oauth/ OAuth Providers db/ App database(s)
  45. 45. users/ App root add_user_to_organization.go user.go organization.go errors.go cmd/ App binaries api/ HTTP API emailer/ Email providers oauth/ OAuth Providers db/ App database(s)
  46. 46. // add_user_to_organization.go package users func AddUserToOrg( db DB, email Emailer, userID, orgID string, ) error { u, err := db.FindUser(userID) // make sure they exist o, err := db.FindOrg(orgID) db.AddUserToOrg(userID, orgID) email.SendWelcomeEmail(u, o) }
  47. 47. package users type DB interface { FindUser(userID string) (User, error) FindOrg(orgID string) (Organization, error) AddUserToOrg(userID, orgID string) error } type Emailer interface { SendWelcomeEmail(User, Organization) error }
  48. 48. users/ App root add_user_to_organization.go user.go organization.go errors.go cmd/ App binaries api/ HTTP API emailer/ Email providers smtp.go SMTP email provider oauth/ OAuth Providers db/ App database(s)
  49. 49. package emailer type SMTP struct { server string }
  50. 50. package emailer import "github.com/paulbellamy/users" type SMTP struct { server string }
  51. 51. package emailer import "github.com/paulbellamy/users" type SMTP struct { server string } func (s SMTP) SendWelcomeEmail( u users.User, o users.Organization, ) error { return errors.New(“TODO”)
  52. 52. users/ App root add_user_to_organization.go user.go organization.go errors.go cmd/ App binaries api/ HTTP API http.go emailer/ Email providers smtp.go SMTP email provider oauth/ OAuth Providers
  53. 53. package api import "github.com/paulbellamy/users" import "net/http" type HTTP struct { DB users.DB Emailer users.Emailer } …
  54. 54. … func (h HTTP) ServeHTTP( w http.ResponseWriter, r *http.Request, ) { err := users.AddUserToOrganization( h.DB, h.Emailer, r.FormValue(“user_id”), r.FormValue(“org_id”), ) }
  55. 55. … func (h HTTP) ServeHTTP( w http.ResponseWriter, r *http.Request, ) { err := users.AddUserToOrganization( h.DB, h.Emailer, r.FormValue(“user_id”), r.FormValue(“org_id”), ) }
  56. 56. … func (h HTTP) ServeHTTP( w http.ResponseWriter, r *http.Request, ) { err := users.AddUserToOrganization( h.DB, h.Emailer, r.FormValue(“user_id”), r.FormValue(“org_id”), ) }
  57. 57. … func (h HTTP) ServeHTTP( w http.ResponseWriter, r *http.Request, ) { err := users.AddUserToOrganization( h.DB, h.Emailer, r.FormValue(“user_id”), r.FormValue(“org_id”), ) }
  58. 58. users/ App root add_user_to_organization.go user.go organization.go errors.go cmd/ App binaries users/ main.go api/ HTTP API emailer/ Email providers oauth/ OAuth Providers
  59. 59. # Get 'revel' framework and command $ go get github.com/revel/cmd/revel # Create a new app $ revel new github.com/paulbellamy/myapp # Run revel application $ revel run github.com/paulbellamy/myapp
  60. 60. users/ App root add_user_to_organization.go user.go organization.go errors.go cmd/ App binaries users/ main.go api/ HTTP API emailer/ Email providers oauth/ OAuth Providers
  61. 61. // cmd/users/main.go package main func main() {
  62. 62. // cmd/users/main.go package main import “net/http” func main() {
  63. 63. // cmd/users/main.go package main import “github.com/paulbellamy/users/api” import “net/http” func main() { a := api.HTTP{Emailer: e, DB: d}
  64. 64. // cmd/users/main.go package main import “github.com/paulbellamy/users/emailer” import “github.com/paulbellamy/users/api” import “net/http” func main() { e := emailer.SMTP{server: “smtp://mailcatcher.local”} a := api.HTTP{db: d, emailer: e}
  65. 65. // cmd/users/main.go package main import “github.com/paulbellamy/users/emailer” import “github.com/paulbellamy/users/db” import “github.com/paulbellamy/users/api” import “net/http” func main() { e := emailer.SMTP{server: “smtp://mailcatcher.local”} d := db.New(databaseURL) a := api.HTTP{db: d, emailer: e}
  66. 66. // cmd/users/main.go package main import “github.com/paulbellamy/users/emailer” import “github.com/paulbellamy/users/db” import “github.com/paulbellamy/users/api” import “net/http” func main() { e := emailer.SMTP{server: “smtp://mailcatcher.local”} d := db.New(databaseURL) a := api.HTTP{db: d, emailer: e}
  67. 67. # Build our binary ready for deployment $ go build github.com/paulbellamy/users/cmd/users # Run our app $ ./users
  68. 68. users/ App root cmd/ App binaries api/ HTTP API emailer/ Email providers oauth/ OAuth Providers db/ App database(s) mocks/ Testing mocks emailer.go Mock emailer db.go Mock db
  69. 69. users/ App root add_user_to_organization.go user.go organization.go errors.go cmd/ App binaries users-server/ Server binary users-client/ Client binary api/ HTTP API emailer/ Email providers oauth/ OAuth Providers
  70. 70. users/ App root add_user_to_organization.go user.go organization.go errors.go cmd/ App binaries api/ HTTP API emailer/ Email providers oauth/ OAuth Providers db/ App database(s)
  71. 71. MORE READING MEDIUM.COM/@BENBJOHNSON
  72. 72. SOCIALS TWITTER: @PYRHHO GITHUB: PAULBELLAMY

×