Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

21
Dependency Injection in Go

Transcript of Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

Page 1: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

Dependency Injection in Go

Page 2: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

About Me

Justus Perlwitz, Software Developer

Email: [email protected]

Page 3: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

The Problem

Page 4: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

Big applications have hidden dependencies

Hidden dependencies make code hard to test

High maintenance cost in strong coupling

Page 5: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

Example

Page 6: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

Mail Delivery Application

package main

type Mail struct {  content   string  recipient string}

Page 7: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

Mail Sending Function

// External Mailer APIimport "mailbib" // Treat this a black box

func (e *Mail) Send() error {  err := mailbib.Mailer.Send(e.content, e.recipient)  if err != nil {    return fmt.Errorf("MailBib error: %+v", err)  }  return nil}

Page 8: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

MailBib

func (m MailBib) Send(c string, r string) error {  if r == "Santa" {    return fmt.Errorf("Recipient too far away")  }

  m.mails = append(m.mails, c)  fmt.Printf("Sent '%s' to %s\n", c, r)  return nil}

Page 9: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

Let's use it

mail := Mail{    content:   "Hello, World!",    recpient: "Bigfoot",}if err := mail.Send(); err != nil {    fmt.Printf("Error: %+v\n", err)}

Page 10: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

This just works fine

Sent 'Hello, World!' to Bigfoot

Page 11: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

A Letter to Santa

// Let's try sending the same mail to Santamail.recipient = "Santa"

// What if Mailbib cannot deliver mail to the Arctic Circle?if err := mail.Send(); err != nil {    fmt.Printf("Error: %+v\n", err)}

Page 12: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

Santa is living too far away

Error: MailBib error: Recipient too far away

Page 13: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

Dependency Injection

Page 14: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

Let's inject our mailer dependency into the Mail struct:

type MailDelivery interface {  Send(string, string) error}

The interface requires the mailer to have one function  Send() 

type Mail struct {  content   string  recipient string  delivery  MailDelivery}

Page 15: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

Trying Different Dependencies

Now, we have to initialize a  Mail  as follows

mail := Mail{    content:   "Hello, World!",    recipient: "Santa",    delivery:  mailbib.Mailer,}

Page 16: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

And we adjust the mailing method

func (e *Mail) Send() error {  err := e.delivery.Send(e.content, e.recipient)  if err != nil {    return fmt.Errorf("Error: %+v", err)  }  return nil}

Page 17: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

Of course, MailBib still refuses to deliver our mail:

if err := mail.Send(); err != nil {    fmt.Printf("Could not deliver mail ‐> %+v\n", err)}

outputs

Could not deliver mail ‐> Error: Recipient too far away

Page 18: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

Injecting a different dependency

Let's pretend, there is a second delivery API, that delivers mail to thearctic circle

import "mailarctica"

Now we can inject a different service

mail.delivery = mailarctica.Mailer

Page 19: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

Let's send the email again

mail.delivery = mailarctica.Mailer

// This time, MailArctica will deliver our letterif err := mail.Send(); err != nil {    fmt.Printf("Error: %+v\n", err)}

will output

Sent 'Hello, World!' to Santa

Page 20: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

Useful Packages

There are two packages with similar names that make dependencyinjection a lot easier:

inject by Facebook

Inject

Page 21: Pilot Tech Talk #12 — Dependency Injection in Go by Justus Perlwitz

Questions?