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 full-size slide

  2. Overview
    I. About Me

    II. Breaking the Monolith

    III. 5 Sweet Tips

    IV. Wrap Up

    View full-size slide

  3. Part I:

    About Me

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  6. Time Geography
    Money People

    View full-size slide

  7. Correctness > Performance

    View full-size slide

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

    View full-size slide

  9. Part II:

    Breaking the Monolith

    View full-size slide

  10. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View full-size slide

  11. “Let’s Extract a Service!”

    View full-size slide

  12. Photo by Thomas Halfmann

    View full-size slide

  13. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View full-size slide

  14. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View full-size slide

  15. The Swamp
    Payroll
    HR
    Benefits
    Infra
    HR v2

    View full-size slide

  16. The Swamp
    Payroll
    HR
    Benefits
    Infra
    HR v2

    View full-size slide

  17. The Swamp
    Payroll
    Old HR
    Benefits
    Infra
    HR v2

    View full-size slide

  18. But there is a better way

    View full-size slide

  19. Applications vs. Services

    View full-size slide

  20. Applications vs. Services

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  23. 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 full-size slide

  24. 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 full-size slide

  25. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View full-size slide

  26. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View full-size slide

  27. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View full-size slide

  28. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View full-size slide

  29. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View full-size slide

  30. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View full-size slide

  31. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View full-size slide

  32. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View full-size slide

  33. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View full-size slide

  34. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View full-size slide

  35. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View full-size slide

  36. The Swamp
    Payroll
    HR
    Benefits
    Infra

    View full-size slide

  37. Conceptual
    Compression

    View full-size slide

  38. Conceptual
    Expansion

    View full-size slide

  39. Part III:

    5 Sweet Tips

    View full-size slide

  40. Recommendation #1

    Mind and Avoid Circular
    Dependencies

    View full-size slide

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

    View full-size slide

  42. 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 full-size slide

  43. 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 full-size slide

  44. Company Employee

    View full-size slide

  45. Company Employee

    View full-size slide

  46. Recommendation #2

    Use Value Objects to
    Traverse Edges

    View full-size slide

  47. 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 full-size slide

  48. 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 full-size slide

  49. Recommendation #3

    Avoid Callbacks

    View full-size slide

  50. 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 full-size slide

  51. Company CompanyMailer

    View full-size slide

  52. 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 full-size slide

  53. Company CompanyMailer
    CreateCompany

    View full-size slide

  54. Recommendation #4

    Extract Services first,
    then extract Applications

    View full-size slide

  55. Recommendation #5

    Move slowly!

    View full-size slide

  56. Part IV:

    Wrap Up

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  59. 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 full-size slide

  60. Special Thanks
    • Noa Elad

    • Matan Zruya

    • Sihui Huang

    • Natalie Wong

    • Karlo Hoa

    • Amelie Meyer-Robinson

    • Quentin Balin

    View full-size slide