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

Go Pattern Design

Go Pattern Design

Avatar for LINE Developers Thailand

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