Save 37% off PRO during our Black Friday Sale! »

I've Made a Huge Mistake - GoRuCo 2018

I've Made a Huge Mistake - GoRuCo 2018

How we got services wrong and what we learned along the way

B6aa05a7368c42f7797296e84172cf84?s=128

Kelly Sutton

June 16, 2018
Tweet

Transcript

  1. I’ve Made a Huge Mistake How we got services wrong

    and what we learned along the way Kelly Sutton — GoRuCo 2018
  2. Overview I. About Me II. Breaking the Monolith III. 5

    Sweet Tips IV. Wrap Up
  3. Part I: About Me

  4. About Me

  5. About Greta

  6. About Greta

  7. About Greta

  8. About Greta

  9. But that’s not why we’re here

  10. We’re here to talk about Rails projects that push the

    limits
  11. None
  12. Time Geography Money People

  13. Correctness > Performance

  14. So let’s talk about how things go wrong, and when

    things get too big
  15. Part II: Breaking the Monolith

  16. The Swamp

  17. None
  18. None
  19. The Swamp Payroll HR Benefits Infra

  20. “Let’s Extract a Service!”

  21. Photo by Thomas Halfmann

  22. The Swamp Payroll HR Benefits Infra

  23. The Swamp Payroll HR Benefits Infra

  24. The Swamp Payroll HR Benefits Infra HR v2

  25. The Swamp Payroll HR Benefits Infra HR v2

  26. The Swamp Payroll Old HR Benefits Infra HR v2

  27. But there is a better way

  28. None
  29. Applications vs. Services

  30. None
  31. Applications vs. Services

  32. Applications vs. Services Have their own process Might have their

    own process
  33. Applications vs. Services Have their own process Might have their

    own process Have their own database Probably share a database
  34. Applications vs. Services Have their own process Might have their

    own process Have their own database Probably share a database Scale independently Scales with the host app
  35. Applications vs. Services Have their own process Might have their

    own process Have their own database Probably share a database Scale independently Scales with the host app Might be an another language Share the same language
  36. The Swamp Payroll HR Benefits Infra

  37. The Swamp Payroll HR Benefits Infra

  38. The Swamp Payroll HR Benefits Infra

  39. The Swamp Payroll HR Benefits Infra

  40. The Swamp Payroll HR Benefits Infra

  41. The Swamp Payroll HR Benefits Infra

  42. The Swamp Payroll HR Benefits Infra

  43. The Swamp Payroll HR Benefits Infra

  44. The Swamp Payroll HR Benefits Infra

  45. The Swamp Payroll HR Benefits Infra

  46. The Swamp Payroll HR Benefits Infra

  47. The Swamp Payroll HR Benefits Infra

  48. Conceptual Compression

  49. None
  50. Conceptual Expansion

  51. Part III: 5 Sweet Tips

  52. Recommendation #1 Mind and Avoid Circular Dependencies

  53. As your Rails code base grows, question bidirectional relationships

  54. 1 # app/models/company.rb 2 class Company < ApplicationRecord 3 has_many

    :employees 4 end 5 6 # app/models/employee.rb 7 class Employee < ApplicationRecord 8 belongs_to :company 9 end
  55. 1 # app/models/company.rb 2 class Company < ApplicationRecord 3 has_many

    :employees 4 end 5 6 # app/models/employee.rb 7 class Employee < ApplicationRecord 8 belongs_to :company 9 end Do we need this?
  56. Company Employee

  57. Company Employee

  58. Recommendation #2 Use Value Objects to Traverse Edges

  59. 1 # app/services/company_signed_up.rb 2 class CompanySignedUp 3 def self.call(company) 4

    CompanyMailer.welcome_email(company) 5 StatsTracker.company_signed_up(company) 6 end 7 end
  60. 1 # app/services/company_signed_up.rb 2 class CompanySignedUp 3 def self.call(company) 4

    user_first_name = company.admin_first_name 5 email = company.admin_email 6 7 CompanyMailer.welcome_email(email, user_first_name) 8 StatsTracker.company_signed_up(company.id) 9 end 10 end
  61. Recommendation #3 Avoid Callbacks

  62. 1 # app/models/company.rb 2 class Company < ApplicationRecord 3 after_create

    :send_update_email, if: :has_email? 4 5 private 6 7 def send_update_email 8 CompanyMailer.welcome_email(self) 9 end 10 end
  63. Company CompanyMailer

  64. 1 # app/services/create_company.rb 2 class CreateCompany 3 def self.call(company_params) 4

    company = Company.create!(company_params) 5 6 CompanyMailer.welcome_email(company) 7 end 8 end
  65. Company CompanyMailer CreateCompany

  66. Recommendation #4 Extract Services first, then extract Applications

  67. Recommendation #5 Move slowly!

  68. Part IV: Wrap Up

  69. –Kent Beck “Make the hard change easy (this may be

    hard), then make the easy change.”
  70. Thanks! Slides and more available at kellysutton.com

  71. References • Bernhardt, Gary. “Boundaries.” 2012. • Bernhardt, Gary. “Functional

    Core, Imperative Shell.” 2012. • Evans, Eric. “Domain-Driven Design: Tackling Complexity in the Heart of Software.” 2003. • Fowler, Martin, et al. “Refactoring: Improving the Design of Existing Code.” 1999. • Feathers, Michael. “Working Effectively with Legacy Code.” 2004. • Hickey, Rich. “Simple Made Easy.” 2011. • Scott, James C. “Seeing Like a State.” 1999. • Searls, Justin. “My Preferred Method of TDD.” 2017 • Spolsky, Joel. “Things You Should Never Do, Part I.” 2006.
  72. Special Thanks • Noa Elad • Matan Zruya • Sihui

    Huang • Natalie Wong • Karlo Hoa • Amelie Meyer-Robinson • Quentin Balin