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

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

Kelly Sutton

June 16, 2018
Tweet

More Decks by Kelly Sutton

Other Decks in Programming

Transcript

  1. I’ve Made a Huge Mistake
    How we got services wrong and what we learned along the way
    Kelly Sutton — GoRuCo 2018

    View Slide

  2. Overview
    I. About Me

    II. Breaking the Monolith

    III. 5 Sweet Tips

    IV. Wrap Up

    View Slide

  3. Part I:

    About Me

    View Slide

  4. About Me

    View Slide

  5. About Greta

    View Slide

  6. About Greta

    View Slide

  7. About Greta

    View Slide

  8. About Greta

    View Slide

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

    View Slide

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

    View Slide

  11. View Slide

  12. Time Geography
    Money People

    View Slide

  13. Correctness > Performance

    View Slide

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

    View Slide

  15. Part II:

    Breaking the Monolith

    View Slide

  16. The Swamp

    View Slide

  17. View Slide

  18. View Slide

  19. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View Slide

  20. “Let’s Extract a Service!”

    View Slide

  21. Photo by Thomas Halfmann

    View Slide

  22. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View Slide

  23. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View Slide

  24. The Swamp
    Payroll
    HR
    Benefits
    Infra
    HR v2

    View Slide

  25. The Swamp
    Payroll
    HR
    Benefits
    Infra
    HR v2

    View Slide

  26. The Swamp
    Payroll
    Old HR
    Benefits
    Infra
    HR v2

    View Slide

  27. But there is a better way

    View Slide

  28. View Slide

  29. Applications vs. Services

    View Slide

  30. View Slide

  31. Applications vs. Services

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  36. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View Slide

  37. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View Slide

  38. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View Slide

  39. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View Slide

  40. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View Slide

  41. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View Slide

  42. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View Slide

  43. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View Slide

  44. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View Slide

  45. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View Slide

  46. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View Slide

  47. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View Slide

  48. Conceptual
    Compression

    View Slide

  49. View Slide

  50. Conceptual
    Expansion

    View Slide

  51. Part III:

    5 Sweet Tips

    View Slide

  52. Recommendation #1

    Mind and Avoid Circular
    Dependencies

    View Slide

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

    View Slide

  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

    View Slide

  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?

    View Slide

  56. Company Employee

    View Slide

  57. Company Employee

    View Slide

  58. Recommendation #2

    Use Value Objects to
    Traverse Edges

    View Slide

  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

    View Slide

  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

    View Slide

  61. Recommendation #3

    Avoid Callbacks

    View Slide

  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

    View Slide

  63. Company CompanyMailer

    View Slide

  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

    View Slide

  65. Company CompanyMailer
    CreateCompany

    View Slide

  66. Recommendation #4

    Extract Services first,
    then extract Applications

    View Slide

  67. Recommendation #5

    Move slowly!

    View Slide

  68. Part IV:

    Wrap Up

    View Slide

  69. –Kent Beck
    “Make the hard change easy
    (this may be hard),
    then make the easy change.”

    View Slide

  70. Thanks!
    Slides and more available at kellysutton.com

    View Slide

  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.

    View Slide

  72. Special Thanks
    • Noa Elad

    • Matan Zruya

    • Sihui Huang

    • Natalie Wong

    • Karlo Hoa

    • Amelie Meyer-Robinson

    • Quentin Balin

    View Slide