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

Go Pattern Design

Go Pattern Design

LINE Developers Thailand

September 06, 2022
Tweet

More Decks by LINE Developers Thailand

Other Decks in Technology

Transcript

  1. type cart struct{} 
 func (c *cart) checkout() (string, error)

    { // do something before update inventory... body := strings.NewReader(`{ "id": "line_sticker_001", "quantity": -1 }`) res, _ := http.Post("https://line.me/myshop/v1/inventory", "application/json", body) return res.Status, nil } Checkout
  2. Matías Varela “Before writing the first line of code, one

    may ask: How should I organize the project? or, Which component should I write first?. If these questions are difficult to answer is because you are not following a software architecture pattern.” https://medium.com/@matiasvarela/hexagonal-architecture-in-go-cfd4e436faa3
  3. Port and Adapters 
 ( A.K.A Hexagonal Architecture ) 


    The hexagonal architecture was defined by Alistair Cockburn in 2005
  4. Driver • Usb C
 
 Driven • 3.5 jack Port

    https://medium.com/@matiasvarela/hexagonal-architecture-in-go-cfd4e436faa3
  5. Adapters Driver • Usb C 
 
 Driven • 3.5

    jack https://medium.com/@matiasvarela/hexagonal-architecture-in-go-cfd4e436faa3
  6. GO

  7. type macBook struct{} func (*MacBook) chargeWithUsbC() { fmt.Println("MacBook is charging")

    } type person struct{} func (*person) charge(laptop macBook) { laptop.chargeWithUsbC() } func main() { person := &person{} myMacBook := macBook{} person.charge(myMacBook) } Comparing type usbC interface { chargeWithUsbC() } type macBook struct{} func (*macBook) chargeWithUsbC() { fmt.Println("MacBook is charging") } type person struct{} func (*person) charge(u usbC) { u.chargeWithUsbC() } func main() { person := &person{} myMacBook := &macBook{} person.charge(myMacBook) }
  8. type macBook struct{} func (*MacBook) chargeWithUsbC() { fmt.Println("MacBook is charging")

    } type person struct{} func (*person) charge(laptop macBook) { laptop.chargeWithUsbC() } func main() { person := &person{} myMacBook := macBook{} person.charge(myMacBook) } Comparing
  9. Comparing type usbC interface { chargeWithUsbC() } type macBook struct{}

    func (*macBook) chargeWithUsbC() { fmt.Println("MacBook is charging") } type person struct{} func (*person) charge(u usbC) { u.chargeWithUsbC() } func main() { person := &person{} myMacBook := &macBook{} person.charge(myMacBook) }
  10. type usbC interface { chargeWithUsbC() } type macBook struct{} func

    (*macBook) chargeWithUsbC() { fmt.Println("MacBook is charging") } type person struct{} func (*person) charge(u usbC) { u.chargeWithUsbC() } func main() { person := &person{} myMacBook := &macBook{} person.charge(myMacBook) } Port
  11. type usbC interface { chargeWithUsbC() } type macBook struct{} func

    (*macBook) chargeWithUsbC() { fmt.Println("MacBook is charging") } type person struct{} func (*person) charge(u usbC) { u.chargeWithUsbC() } func main() { person := &person{} myMacBook := &macBook{} person.charge(myMacBook) } Port
  12. type usbC interface { chargeWithUsbC() } type macBook struct{} func

    (*macBook) chargeWithUsbC() { fmt.Println("MacBook is charging") } type person struct{} func (*person) charge(u usbC) { u.chargeWithUsbC() } func main() { person := &person{} myMacBook := &macBook{} person.charge(myMacBook) } Port
  13. type usbC interface { chargeWithUsbC() } type macBook struct{} func

    (*macBook) chargeWithUsbC() { fmt.Println("MacBook is charging") } type person struct{} func (*person) charge(u usbC) { u.chargeWithUsbC() } func main() { person := &person{} myMacBook := &macBook{} person.charge(myMacBook) } Port
  14. type iPhone struct{} func (*iPhone) chargeWithLightingPort() { fmt.Println("iPhone is charging")

    } type lightingToUsbC struct { iPhone *iPhone } func (*lightingToUsbC) chargeWithUsbC() { l.iPhone.chargeWithLightingPort() } Adapters
  15. type usbC interface { chargeWithUsbC() } 
 type iPhone struct{}

    func (*iPhone) chargeWithLightingPort() { fmt.Println("iPhone is charging") } type lightingToUsbC struct { iPhone *iPhone } func (l *lightingToUsbC) chargeWithUsbC() { l.iPhone.chargeWithLightingPort() } func main() { person := &person{} myPhone := &lightingToUsbC{&iPhone{}} person.charge(myPhone) } Port & Adapter
  16. type cart struct{} 
 func (c *cart) checkout() (string, error)

    { // do something before update inventory... body := strings.NewReader(`{ "id": "line_sticker_001", "quantity": -1 }`) res, _ := http.Post("https://line.me/myshop/v1/inventory", "application/json", body) return res.Status, nil } cart.go
  17. func Test_CheckoutSuccess(t *testing.T) { testCart := cart{} status, _ :=

    testCart.checkout() want := "200 OK" if status != want { t.Errorf("status should be %s but got %s", want, status) } } cart_test.go
  18. func Test_CheckoutSuccess(t *testing.T) { testCart := cart{} status, _ :=

    testCart.checkout() want := "200 OK" if status != want { t.Errorf("status should be %s but got %s", want, status) } } cart_test.go
  19. type httpClient interface { Post(url, contentType string, body io.Reader) (*http.Response,

    error) } type cart struct { httpClient } func (c *cart) checkout() string { // do something before update inventory... body := strings.NewReader(`{ "id": "line_sticker_001", "quantity": -1 }`) res, _ := c.Post("https://line.me/myshop/v1/inventory", "application/json", body) return res.Status } func main() { cli := http.DefaultClient cart := &cart{cli} cart.checkout() } cart.go
  20. type httpClient interface { Post(url, contentType string, body io.Reader) (*http.Response,

    error) } type cart struct { httpClient } func (c *cart) checkout() string { // do something before update inventory... body := strings.NewReader(`{ "id": "line_sticker_001", "quantity": -1 }`) res, _ := c.Post("https://line.me/myshop/v1/inventory", "application/json", body) return res.Status } func main() { cli := http.DefaultClient cart := &cart{cli} cart.checkout() } cart.go
  21. type httpClient interface { Post(url, contentType string, body io.Reader) (*http.Response,

    error) } type cart struct { httpClient } func (c *cart) checkout() string { // do something before update inventory... body := strings.NewReader(`{ "id": "line_sticker_001", "quantity": -1 }`) res, _ := c.Post("https://line.me/myshop/v1/inventory", "application/json", body) return res.Status } func main() { cli := http.DefaultClient cart := &cart{cli} cart.checkout() } cart.go
  22. type httpClient interface { Post(url, contentType string, body io.Reader) (*http.Response,

    error) } type cart struct { httpClient } func (c *cart) checkout() string { // do something before update inventory... body := strings.NewReader(`{ "id": "line_sticker_001", "quantity": -1 }`) res, _ := c.Post("https://line.me/myshop/v1/inventory", "application/json", body) return res.Status } func main() { cli := http.DefaultClient cart := &cart{cli} cart.checkout() } cart.go
  23. type httpClient interface { Post(url, contentType string, body io.Reader) (*http.Response,

    error) } type cart struct { httpClient } func (c *cart) checkout() string { // do something before update inventory... body := strings.NewReader(`{ "id": "line_sticker_001", "quantity": -1 }`) res, _ := c.Post("https://line.me/myshop/v1/inventory", "application/json", body) return res.Status } func main() { cli := http.DefaultClient cart := &cart{cli} cart.checkout() } cart.go
  24. type mockSuccessClient struct{} func (m *mockSuccessClient) Post(url, contentType string, body

    io.Reader) (*http.Response, error) { res := &http.Response{ Status: "200 OK", } return res, nil } func Test_CheckoutSuccess(t *testing.T) { myClient := &mockSuccessClient{} cart := &cart{myClient} status := cart.checkout() want := "200 OK" if status != want { t.Errorf("status should be %s but got %s", want, status) } } cart_test.go
  25. type mockSuccessClient struct{} func (m *mockSuccessClient) Post(url, contentType string, body

    io.Reader) (*http.Response, error) { res := &http.Response{ Status: "200 OK", } return res, nil } func Test_CheckoutSuccess(t *testing.T) { myClient := &mockSuccessClient{} cart := &cart{myClient} status := cart.checkout() want := "200 OK" if status != want { t.Errorf("status should be %s but got %s", want, status) } } cart_test.go
  26. type myResty struct { *resty.Client } func NewRestyClient() httpClient {

    return myResty{} } func (client myResty) Post(url, contentType string, body io.Reader) (*http.Response, error) { resp, _ := client.R(). SetBody(body). ForceContentType(contentType). Post(“https://line.me/myshop/v1/inventory") return resp.RawResponse, nil } . . . func main() { newCli := NewRestyClient() cart := &cart{newCli} cart.checkout() } my_restry.go