Refactor Your Monolithic Rails App to a SOA

11,714 views

Published on

Published in: Technology
0 Comments
20 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
11,714
On SlideShare
0
From Embeds
0
Number of Embeds
648
Actions
Shares
0
Downloads
96
Comments
0
Likes
20
Embeds 0
No embeds

No notes for slide

Refactor Your Monolithic Rails App to a SOA

  1. 1. Refactoring Your Monolithic Rails App To A SOA: Risks and RewardsThursday, March 17, 2011
  2. 2. Chris Wyckoff Alliance Health Networks cbwyckoff@gmail.com @cwyckoffThursday, March 17, 2011
  3. 3. The Birth Of A Monolithic Rails AppThursday, March 17, 2011
  4. 4. Thursday, March 17, 2011
  5. 5. Thursday, March 17, 2011
  6. 6. Thursday, March 17, 2011
  7. 7. Thursday, March 17, 2011
  8. 8. Thursday, March 17, 2011
  9. 9. Thursday, March 17, 2011
  10. 10. Thursday, March 17, 2011
  11. 11. Thursday, March 17, 2011
  12. 12. Thursday, March 17, 2011
  13. 13. Thursday, March 17, 2011
  14. 14. Thursday, March 17, 2011
  15. 15. Thursday, March 17, 2011
  16. 16. Thursday, March 17, 2011
  17. 17. Thursday, March 17, 2011
  18. 18. Thursday, March 17, 2011
  19. 19. Thursday, March 17, 2011
  20. 20. Thursday, March 17, 2011
  21. 21. Monolithic Rails App Company Controller Contact Lead Invitation Contact Demographic Status Enrollment Degree LeadProcess Level Controller Lead Study Program Company Area Referral Leads School Delivery Controller Budget Client Search Programs Campus Budget Budget Controller Reports Caps Caps Search Controller Result Campus Location Campus Schools Budgets Locations Controller Controller ControllerThursday, March 17, 2011
  22. 22. Lead Lead Email Lead Qualification Delivery Remarketing Conversion RabbitMQ Operational Reporting Data Stores Survey Budget Admin Engine ServiceThursday, March 17, 2011
  23. 23. Lead Lead Email Lead Qualification Delivery Remarketing Conversion RabbitMQ Operational Reporting Data Stores Survey Budget Admin Engine ServiceThursday, March 17, 2011
  24. 24. Lead Lead Email Lead Qualification Delivery Remarketing Conversion RabbitMQ Operational Reporting Data Stores Survey Budget Admin Engine ServiceThursday, March 17, 2011
  25. 25. Lead Lead Email Lead Qualification Delivery Remarketing Conversion RabbitMQ Operational Reporting Data Stores Survey Budget Admin Engine ServiceThursday, March 17, 2011
  26. 26. The Strangler Approach Good Code Bad CodeThursday, March 17, 2011
  27. 27. Keys to Our Approach • Separate Responsibilities • Operate Asynchronously • Make Incremental ChangesThursday, March 17, 2011
  28. 28. Separate ResponsibilitiesThursday, March 17, 2011
  29. 29. Qualification Monolithic Rails Logic App Company Controller Contact Lead Invitation Contact Demographic Status Enrollment Degree LeadProcess Level Controller Lead Study Program Company Area Referral Leads School Delivery Controller Budget Client Search Programs Campus Budget Budget Controller Reports Caps Caps Search Controller Result Campus Location Campus Schools Budgets Locations Controller Controller ControllerThursday, March 17, 2011
  30. 30. Qualification Monolithic Rails Logic App Company Controller Contact Lead Invitation Contact Demographic Status Enrollment Degree LeadProcess Level Controller Lead Study Program Company Area Referral Leads School Delivery Controller Budget Client Search Programs Campus Budget Budget Controller Reports Caps Caps Search Controller Result Campus Location Campus Schools Budgets Locations Controller Controller ControllerThursday, March 17, 2011
  31. 31. Qualification Monolithic Rails App Logic Company Controller Contact Lead Invitation Contact Demographic Status Enrollment Degree LeadProcess Level Controller Lead Study Program Company Area Referral Leads School Delivery Controller Budget Client Search Programs Campus Budget Budget Controller Reports Caps Caps Search Controller Result Campus Location Campus Schools Budgets Locations Controller Controller ControllerThursday, March 17, 2011
  32. 32. Monolithic Rails Qualification App Company Logic Controller Contact Lead Invitation Contact Demographic Status Enrollment Degree LeadProcess Level Controller Lead Study Program Company Area Referral Leads School Delivery Controller Budget Client Search Programs Campus Budget Budget Controller Reports Caps Caps Search Controller Result Campus Location Campus Schools Budgets Locations Controller Controller ControllerThursday, March 17, 2011
  33. 33. Monolithic Rails App Delivery Logic Company Controller Contact Lead Invitation Contact Demographic Status Enrollment Degree LeadProcess Level Controller Lead Study Program Company Area Referral Leads School Delivery Controller Budget Client Search Programs Campus Budget Budget Controller Reports Caps Caps Search Controller Result Campus Location Campus Schools Budgets Locations Controller Controller ControllerThursday, March 17, 2011
  34. 34. Monolithic Rails Delivery Logic App Company Controller Contact Lead Invitation Contact Demographic Status Enrollment Degree LeadProcess Level Controller Lead Study Program Company Area Referral Leads School Delivery Controller Budget Client Search Programs Campus Budget Budget Controller Reports Caps Caps Search Controller Result Campus Location Campus Schools Budgets Locations Controller Controller ControllerThursday, March 17, 2011
  35. 35. describe Contact do describe "#validate" do it "requires 10 digit phone numbers" do ... end it "rejects blank phone numbers" do ... end it "rejects areacodes that start with 0 or 1" do ... end it "requires 5 digit zip" do ... end it "rejects invalidly formatted emails" do ... end it "rejects blank emails" do ... end it "rejects emails with bad words" do ... end ... endThursday, March 17, 2011
  36. 36. describe Contact do describe "#validate" do it "requires 10 digit phone numbers" do Phone ... end it "rejects blank phone numbers" do ... end it "rejects areacodes that start with 0 or 1" do ... end it "requires 5 digit zip" do ... end it "rejects invalidly formatted emails" do ... end it "rejects blank emails" do ... end it "rejects emails with bad words" do ... end ... endThursday, March 17, 2011
  37. 37. describe Contact do describe "#validate" do it "requires 10 digit phone numbers" do ... end it "rejects blank phone numbers" do ... end it "rejects areacodes that start with 0 or 1" do ... end it "requires 5 digit zip" do ... Zip end it "rejects invalidly formatted emails" do ... end it "rejects blank emails" do ... end it "rejects emails with bad words" do ... end ... endThursday, March 17, 2011
  38. 38. describe Contact do describe "#validate" do it "requires 10 digit phone numbers" do ... end it "rejects blank phone numbers" do ... end it "rejects areacodes that start with 0 or 1" do ... end it "requires 5 digit zip" do ... end it "rejects invalidly formatted emails" do ... Email end it "rejects blank emails" do ... end it "rejects emails with bad words" do ... end ... endThursday, March 17, 2011
  39. 39. describe Phone do describe "#is_satisfied_by?" do it "returns false if the number is not 10 digits long" do ... end it "returns false if number matches invalid number list" do ... end it "returns true if area code is valid" do ... end ... end end describe Zip do describe "#is_satisfied_by" do it "returns false if zip is not 5 digits" do ... end it "returns false if zip does not exist in postal_codes database table" do ... end ... end endThursday, March 17, 2011
  40. 40. describe Contact do describe "#validate" do it "requires 10 digit phone numbers" do ... end it "rejects blank phone numbers" do ... end it "rejects areacodes that start with 0 or 1" do ... end it "requires 5 digit zip" do ... end it "rejects invalidly formatted emails" do ... end it "rejects blank emails" do ... end it "rejects emails with bad words" do ... end ... endThursday, March 17, 2011
  41. 41. scrubber = Scrubber.configure do |s| s.scrub(:first_name).as(:invalid).if(:blank) s.scrub(:last_name).as(:invalid).if(:blank) s.scrub(:email).as(:invalid).if(:blank) s.scrub(:phone).as(:invalid).if(:blank) s.scrub(:first_name).as(:invalid).unless(:kid_friendly) s.scrub(:last_name).as(:invalid).unless(:kid_friendly) s.scrub(:email).as(:invalid).unless(:kid_friendly) s.scrub(:country).as(:filtered).if {|lead| lead.contact.country == Other}.and_warn ("Only requests from the United States can be accepted at this time") s.scrub_with(:email).as(:filtered) s.scrub_with(:education_level).as(:filtered) s.scrub_with(:duplicate).as(:filtered) end scrubber.process({ :first_name => "Chris", :last_name => "Wyckoff", :email => "foo@yahoo.com", :phone => "8011231234", :country => "US" })Thursday, March 17, 2011
  42. 42. scrubber = Scrubber.configure do |s| s.scrub(:first_name).as(:invalid).if(:blank) s.scrub(:last_name).as(:invalid).if(:blank) s.scrub(:email).as(:invalid).if(:blank) s.scrub(:phone).as(:invalid).if(:blank) s.scrub(:first_name).as(:invalid).unless(:kid_friendly) s.scrub(:last_name).as(:invalid).unless(:kid_friendly) s.scrub(:email).as(:invalid).unless(:kid_friendly) s.scrub(:country).as(:filtered).if {|lead| lead.contact.country == Other}.and_warn ("Only requests from the United States can be accepted at this time") s.scrub_with(:email).as(:filtered) s.scrub_with(:education_level).as(:filtered) s.scrub_with(:duplicate).as(:filtered) end scrubber.process({ :first_name => "Chris", :last_name => "Wyckoff", :email => "foo@yahoo.com", :phone => "8011231234", :country => "US" })Thursday, March 17, 2011
  43. 43. scrubber = Scrubber.configure do |s| s.scrub(:first_name).as(:invalid).if(:blank) s.scrub(:last_name).as(:invalid).if(:blank) s.scrub(:email).as(:invalid).if(:blank) s.scrub(:phone).as(:invalid).if(:blank) s.scrub(:first_name).as(:invalid).unless(:kid_friendly) s.scrub(:last_name).as(:invalid).unless(:kid_friendly) s.scrub(:email).as(:invalid).unless(:kid_friendly) s.scrub(:country).as(:filtered).if {|lead| lead.contact.country == Other}.and_warn ("Only requests from the United States can be accepted at this time") s.scrub_with(:email).as(:filtered) s.scrub_with(:education_level).as(:filtered) s.scrub_with(:duplicate).as(:filtered) end scrubber.process({ :first_name => "Chris", :last_name => "Wyckoff", :email => "foo@yahoo.com", :phone => "8011231234", :country => "US" })Thursday, March 17, 2011
  44. 44. scrubber = Scrubber.configure do |s| s.scrub(:first_name).as(:invalid).if(:blank) s.scrub(:last_name).as(:invalid).if(:blank) s.scrub(:email).as(:invalid).if(:blank) s.scrub(:phone).as(:invalid).if(:blank) s.scrub(:first_name).as(:invalid).unless(:kid_friendly) s.scrub(:last_name).as(:invalid).unless(:kid_friendly) s.scrub(:email).as(:invalid).unless(:kid_friendly) s.scrub(:country).as(:filtered).if {|lead| lead.contact.country == Other}.and_warn ("Only requests from the United States can be accepted at this time") s.scrub_with(:email).as(:filtered) s.scrub_with(:education_level).as(:filtered) s.scrub_with(:duplicate).as(:filtered) end scrubber.process({ :first_name => "Chris", :last_name => "Wyckoff", :email => "foo@yahoo.com", :phone => "8011231234", :country => "US" })Thursday, March 17, 2011
  45. 45. Monolithic Rails App Lead QualificationThursday, March 17, 2011
  46. 46. Monolithic Rails App Lead Lead Qualification DeliveryThursday, March 17, 2011
  47. 47. CohesionThursday, March 17, 2011
  48. 48. Qualification Service Factory Scrubber Scrubbing DSL Conditions Operands Scrubbing Engine Parameterized Zip Phone Email RuleThursday, March 17, 2011
  49. 49. Delivery Service Field Mapper Lead Formatter Phone Date Case Truncate Get/Post Email FTP/SFTP Custom Lead Deliverer Response Handler Get/Post Email FTP/SFTP CustomThursday, March 17, 2011
  50. 50. AdhesionThursday, March 17, 2011
  51. 51. Monolithic Rails App Company Controller Contact Lead Invitation Contact Demographic Status Enrollment Degree LeadProcess Level Controller Lead Study Program Company Area Referral Leads School Delivery Controller Budget Client Search Programs Campus Budget Budget Controller Reports Caps Caps Search Controller Result Campus Location Campus Schools Budgets Locations Controller Controller ControllerThursday, March 17, 2011
  52. 52. Operate AsynchronouslyThursday, March 17, 2011
  53. 53. Client 1 Monolithic Rails AppThursday, March 17, 2011
  54. 54. Client 1 Monolithic Rails App Client 2Thursday, March 17, 2011
  55. 55. Client 1 Monolithic Rails App Client 2 Client 3Thursday, March 17, 2011
  56. 56. Client 1 Monolithic Rails App Lead Delivery Client 2 Client 3Thursday, March 17, 2011
  57. 57. Lead Client 1 Monolithic Rails Delivery App Lead Client 2 Delivery Lead Client 3 DeliveryThursday, March 17, 2011
  58. 58. Lead Client 1 Monolithic Rails Delivery App Lead 200 ms Client 2 Delivery Lead Client 3 DeliveryThursday, March 17, 2011
  59. 59. Lead Client 1 Monolithic Rails Delivery App Lead 200 ms Client 2 Delivery Lead 4000 ms Client 3 DeliveryThursday, March 17, 2011
  60. 60. Lead 10000 ms Client 1 Monolithic Rails Delivery App Lead 200 ms Client 2 Delivery Lead 4000 ms Client 3 DeliveryThursday, March 17, 2011
  61. 61. Make Incremental ChangesThursday, March 17, 2011
  62. 62. Client 1 Monolithic Rails App Lead Delivery Client 2 Client 3Thursday, March 17, 2011
  63. 63. Monolithic Rails Client 1 App Client 1 Router Lead Client 2 Delivery Client 3Thursday, March 17, 2011
  64. 64. Monolithic Rails Client 1 App Client 1 Router Lead Client 2 Delivery Client 3Thursday, March 17, 2011
  65. 65. class DeliveryRouter def self.route(lead) if(publishable_to_new_delivery?(self)) DeliveryRouter.publish(lead) else lead.submit end end def self.publish(lead) Bunny.publish(:lead_delivery, DeliveryMapper.map(lead)) end def self.publishable_to_new_delivery?(lead) lead.school.active_for_new_delivery? end endThursday, March 17, 2011
  66. 66. class DeliveryRouter def self.route(lead) if(publishable_to_new_delivery?(self)) DeliveryRouter.publish(lead) else lead.submit end end def self.publish(lead) Bunny.publish(:lead_delivery, DeliveryMapper.map(lead)) end def self.publishable_to_new_delivery?(lead) lead.school.active_for_new_delivery? end endThursday, March 17, 2011
  67. 67. class DeliveryRouter def self.route(lead) if(publishable_to_new_delivery?(self)) DeliveryRouter.publish(lead) else lead.submit end end def self.publish(lead) Bunny.publish(:lead_delivery, DeliveryMapper.map(lead)) end def self.publishable_to_new_delivery?(lead) lead.school.active_for_new_delivery? end endThursday, March 17, 2011
  68. 68. class DeliveryMapper def self.map(lead) { :first_name => lead.contact.first_name, :last_name => lead.contact.last_name, :address => lead.contact.address, :city => lead.contact.city, :state => lead.contact.state, :zip => lead.contact.zip, :phone => lead.contact.phone, :email => lead.contact.email, :client_id => lead.client.id, :lead_id => lead.id, ... } end endThursday, March 17, 2011
  69. 69. class DeliveryRouter def self.route(lead) if(publishable_to_new_delivery?(self)) DeliveryRouter.publish(lead) else lead.submit end end def self.publish(lead) Bunny.publish(:lead_delivery, DeliveryMapper.map(lead)) end def self.publishable_to_new_delivery?(lead) lead.school.active_for_new_delivery? end endThursday, March 17, 2011
  70. 70. Monolithic Rails Client 1 App Client 1 Router Lead Client 2 Delivery Client 3Thursday, March 17, 2011
  71. 71. Client 1 Monolithic Rails App Lead Legacy Delivery Code Delivery Client 2 Client 3Thursday, March 17, 2011
  72. 72. What Did We Gain?Thursday, March 17, 2011
  73. 73. SpeedThursday, March 17, 2011
  74. 74. MaintainabilityThursday, March 17, 2011
  75. 75. TestabilityThursday, March 17, 2011
  76. 76. ComposabilityThursday, March 17, 2011
  77. 77. Lead Lead Source Qualification DeliveryThursday, March 17, 2011
  78. 78. Lead Lead Lead Source Qualification Assignment DeliveryThursday, March 17, 2011
  79. 79. Lead Lead Call Source Qualification Delivery Center Call Lead Delivery Client CenterThursday, March 17, 2011
  80. 80. Lead Lead Assignment Delivery Lead Lead Qualification Delivery Lead Call Lead Delivery Delivery Client CenterThursday, March 17, 2011
  81. 81. Education Employment Lead Lead Qualification Delivery Loan FinancingThursday, March 17, 2011
  82. 82. Lead Lead Email Lead Qualification Delivery Remarketing Conversion RabbitMQ Reporting Budget Admin ServiceThursday, March 17, 2011
  83. 83. { event:delivery, status:accepted, lead_id:1234, timestamp:2011-02-23 08:09:01, lead_details:{ ... } }Thursday, March 17, 2011
  84. 84. Lead Lead Email Lead Qualification Delivery Remarketing Conversion RabbitMQ Reporting Budget Admin ServiceThursday, March 17, 2011
  85. 85. Lead Lead Email Lead Qualification Delivery Remarketing Conversion RabbitMQ Reporting Budget Admin ServiceThursday, March 17, 2011
  86. 86. Lead Lead Email Lead Qualification Delivery Remarketing Conversion RabbitMQ Reporting Budget Admin ServiceThursday, March 17, 2011
  87. 87. Lead Lead Email Lead Qualification Delivery Remarketing Conversion RabbitMQ Reporting Budget Admin ServiceThursday, March 17, 2011
  88. 88. What Did We Risk?Thursday, March 17, 2011
  89. 89. MaintainabilityThursday, March 17, 2011
  90. 90. TestabilityThursday, March 17, 2011
  91. 91. Overly Decomposed Services Combat over-decomposition by consolidating code w/o necessarily isolating it as a ser vice 1) gems 2) local CouchDB stores that sync w/ a master storeThursday, March 17, 2011
  92. 92. Lead Lead Email Qualification Delivery Remarketing Survey Engine Field Rules Formatting EngineThursday, March 17, 2011
  93. 93. Lead Lead Email Qualification Delivery Remarketing Survey Engine Field Rules Formatting EngineThursday, March 17, 2011
  94. 94. Lead Lead Email Qualification Delivery Remarketing Survey Engine Field Rules Formatting EngineThursday, March 17, 2011
  95. 95. Lead Lead Email Qualification Delivery Remarketing Survey Engine Field Rules Formatting EngineThursday, March 17, 2011
  96. 96. Lead Lead Email Qualification Delivery Remarketing Survey Engine Field Rules Formatting EngineThursday, March 17, 2011
  97. 97. Lead Lead Email Qualification Delivery Remarketing Survey EngineThursday, March 17, 2011
  98. 98. Lead DeliveryThursday, March 17, 2011
  99. 99. Lead Lead Email Qualification Delivery Remarketing Survey EngineThursday, March 17, 2011
  100. 100. Thursday, March 17, 2011
  101. 101. Map Your ArchitectureThursday, March 17, 2011
  102. 102. 1) http://www.vanderburg.org/Blog/Software/Development/ cohesion.rdoc 2) http://www.martinfowler.com/blikiStranglerApplication.html 3) http://www.eaipatterns.com/docs/EDA.pdfThursday, March 17, 2011
  103. 103. Thursday, March 17, 2011
  104. 104. Thank You. Questions?Thursday, March 17, 2011
  105. 105. Thank YouThursday, March 17, 2011

×