SlideShare a Scribd company logo
Services, Dependencies, and
You
A guide to writing maintainable code in Go
(and other languages, really)
Sean Kelly
@StabbyCutyou
Obligatory "Who am I" slide
● Sean Kelly (Hi!)
○ But everyone calls me Stabby
● I work for Tapjoy
○ We serve hundreds of millions of ads a day on a global scale
● I have a new puppy and a new kitty
○ Some of these slides might accidentally veer into tips on Crate Training
● I maintain a bunch of open source libraries
○ That literally nobody uses
○ It's actually kind of fun, since I can break things with less repurcussions
What am I here to talk about?
● Service Oriented Architecture
● Defining Dependencies
● Separation of Concerns
● Practical example of applying the above in a Go webservice
Service Oriented Architecture
You mean like, microservices and stuff?
(Spoiler Alert: Not really)
Service Oriented Architecture
● Many ways to define and apply this
● Internally architecting your application for SOA is a great pattern for maintaining
application code
● Keep crucial business logic out of Models and Controllers
○ Helpers like combining First + Last into FullName can live on a Model
○ Try to avoid ivory-towering yourself into code no one wants to maintain
● Centralize it in reusable Service objects
● These objects define domain boundaries in your systems
● These objects also define dependency maps between the parts of your systems
● Eventually, if you do break your app up into microservices, internal SOA has
already got your code in a "ready to extract" state
Dependencies
Ugh, is he gonna tell us to use some interface{} abusing DI
framework?
(Spoiler Alert: Nah)
Dependencies
● External resources you rely upon to execute code
● Common examples:
○ MySQL
○ Memcached
○ Riak
● Less Common examples:
○ Configuration data
○ Other code modules
● "Hmm, I need access to X here…"
○ That is probably a dependency
● Passing dependencies down via a constructor makes for more testable, reliable
code.
● Avoid "new-ing up" a dependency unless it's in your main() and handed to others
Separation of Concerns
Is that like when your code isn't a jumbled mess?
(Spoiler Alert: Yes!)
Separation of Concerns
● Modules of code should have 1 purpose
● Don't lump things together out of convenience
● Each distinct piece of your domain should get it's own Service object
● You can compose Service objects to create "Higher Order" Services
○ If Service A needs Service B, but Service B needs Service A…
○ You need Service C, composed of A and B
● So, if you had some basic Services like these:
○ UserService
○ ErrorService
○ ThirdPartyMailerService
● You might compose some Services like these:
○ AccountManagementService(UserService, ThirdPartyMailerService)
○ AlertingService(AccountService, ErrorService, ThirdPartyMailerService)
Testing
Ugh, Booooriiiing
(I know, but these designs will make testing easier)
Testing
● Service Objects with their dependencies declared in their New method: 80% of
the way there
● The other 20%: Interfaces!
● If instead of this…
○ NewAlertingService(*AccountService, *ErrorService, *SomeEmailProvider) *AlertingService
● You did this…
○ NewAlertingService(IAccountService, IErrorService, IEmailService) IAlerteringService
● You could replace any of the critical dependencies in a unit test with mocks or no-
op implementations
● You can now use tools like `gomock` to generate test implementations for you
○ Or, just do it yourself if your services are small / have specialized testing needs
● Conversely, you could mock out the dependencies of those Services
○ But usually, whole-mocking is easier and more straightforward
Wrapping Up
Wait, already?
(The rest of the talk is some code examples)
Services, Dependencies, and You
● Primary focus is to keep code "clean" and DRY
● Each service does one thing, and does it well
● They define dependencies in the constructor / New method
● Create "Higher Order" Services by combining existing Services
● More easily testable with both unit and integration tests
○ Especially if you use Interfaces
● Lays the groundwork for extraction into microservices, should you choose to
○ If the code is cleanly separated, and has well defined dependencies, it's more straightforward to port
● And Now… Sample code!
Thanks!
Services, Dependencies, and
You
A guide to writing maintainable code in Go
(and other languages, really)
Sean Kelly
@StabbyCutyou

More Related Content

Services, dependencies, and you

  • 1. Services, Dependencies, and You A guide to writing maintainable code in Go (and other languages, really) Sean Kelly @StabbyCutyou
  • 2. Obligatory "Who am I" slide ● Sean Kelly (Hi!) ○ But everyone calls me Stabby ● I work for Tapjoy ○ We serve hundreds of millions of ads a day on a global scale ● I have a new puppy and a new kitty ○ Some of these slides might accidentally veer into tips on Crate Training ● I maintain a bunch of open source libraries ○ That literally nobody uses ○ It's actually kind of fun, since I can break things with less repurcussions
  • 3. What am I here to talk about? ● Service Oriented Architecture ● Defining Dependencies ● Separation of Concerns ● Practical example of applying the above in a Go webservice
  • 4. Service Oriented Architecture You mean like, microservices and stuff? (Spoiler Alert: Not really)
  • 5. Service Oriented Architecture ● Many ways to define and apply this ● Internally architecting your application for SOA is a great pattern for maintaining application code ● Keep crucial business logic out of Models and Controllers ○ Helpers like combining First + Last into FullName can live on a Model ○ Try to avoid ivory-towering yourself into code no one wants to maintain ● Centralize it in reusable Service objects ● These objects define domain boundaries in your systems ● These objects also define dependency maps between the parts of your systems ● Eventually, if you do break your app up into microservices, internal SOA has already got your code in a "ready to extract" state
  • 6. Dependencies Ugh, is he gonna tell us to use some interface{} abusing DI framework? (Spoiler Alert: Nah)
  • 7. Dependencies ● External resources you rely upon to execute code ● Common examples: ○ MySQL ○ Memcached ○ Riak ● Less Common examples: ○ Configuration data ○ Other code modules ● "Hmm, I need access to X here…" ○ That is probably a dependency ● Passing dependencies down via a constructor makes for more testable, reliable code. ● Avoid "new-ing up" a dependency unless it's in your main() and handed to others
  • 8. Separation of Concerns Is that like when your code isn't a jumbled mess? (Spoiler Alert: Yes!)
  • 9. Separation of Concerns ● Modules of code should have 1 purpose ● Don't lump things together out of convenience ● Each distinct piece of your domain should get it's own Service object ● You can compose Service objects to create "Higher Order" Services ○ If Service A needs Service B, but Service B needs Service A… ○ You need Service C, composed of A and B ● So, if you had some basic Services like these: ○ UserService ○ ErrorService ○ ThirdPartyMailerService ● You might compose some Services like these: ○ AccountManagementService(UserService, ThirdPartyMailerService) ○ AlertingService(AccountService, ErrorService, ThirdPartyMailerService)
  • 10. Testing Ugh, Booooriiiing (I know, but these designs will make testing easier)
  • 11. Testing ● Service Objects with their dependencies declared in their New method: 80% of the way there ● The other 20%: Interfaces! ● If instead of this… ○ NewAlertingService(*AccountService, *ErrorService, *SomeEmailProvider) *AlertingService ● You did this… ○ NewAlertingService(IAccountService, IErrorService, IEmailService) IAlerteringService ● You could replace any of the critical dependencies in a unit test with mocks or no- op implementations ● You can now use tools like `gomock` to generate test implementations for you ○ Or, just do it yourself if your services are small / have specialized testing needs ● Conversely, you could mock out the dependencies of those Services ○ But usually, whole-mocking is easier and more straightforward
  • 12. Wrapping Up Wait, already? (The rest of the talk is some code examples)
  • 13. Services, Dependencies, and You ● Primary focus is to keep code "clean" and DRY ● Each service does one thing, and does it well ● They define dependencies in the constructor / New method ● Create "Higher Order" Services by combining existing Services ● More easily testable with both unit and integration tests ○ Especially if you use Interfaces ● Lays the groundwork for extraction into microservices, should you choose to ○ If the code is cleanly separated, and has well defined dependencies, it's more straightforward to port ● And Now… Sample code!
  • 14. Thanks! Services, Dependencies, and You A guide to writing maintainable code in Go (and other languages, really) Sean Kelly @StabbyCutyou