Forget about classes, welcome objects

Cbde91d4ba37d495ce3084704a3f0458?s=47 kurko
July 28, 2013

Forget about classes, welcome objects

This is a talk about how to fight complexity using OO forgotten concepts.

Cbde91d4ba37d495ce3084704a3f0458?s=128

kurko

July 28, 2013
Tweet

Transcript

  1. 2.
  2. 3.
  3. 7.
  4. 8.

    VI

  5. 9.

    6

  6. 12.
  7. 14.
  8. 15.
  9. 16.
  10. 29.

    class ImportationService def process orgs = Organizations.new(client).import orgs.each do |org|

    projects = Projects.new(org).import end projects.each do |project| Members.new(client).import end end end
  11. 30.

    class ImportationService def process orgs = Organizations.new(client).import orgs.each do |org|

    projects = Projects.new(org).import end projects.each do |project| Members.new(client).import Stories.new(client).import end end end
  12. 31.

    class ImportationService def process orgs = Organizations.new(client).import orgs.each do |org|

    projects = Projects.new(org).import end projects.each do |project| Members.new(client).import Stories.new(client).import unless client.github? end end end
  13. 32.

    class ImportationService def process orgs = Organizations.new(client).import orgs.each do |org|

    projects = Projects.new(org).import end projects.each do |project| Members.new(client).import Stories.new(client).import unless client.github? end end end Beginning of the end
  14. 33.

    def process_extension!(extension_price, options={}) options.reverse_merge!({ :credit_card => user.default_credit_card, :billing_address => options[:credit_card].try(:billing_address)

    || user.default_address, :store => order.store, :tax => tax, :days => 14, :buyout => false }) ! creator = options[:creator] return process_extension_without_charge!(options) if options[:no_charge] ! response = Payment::Gateway.charge!( extension_price.cents.to_f/100, options[:credit_card].ext_cc_id, self.user.id, options[:store].try(:address).try(:country) ) ! # payment failed unless response[:ext_transaction_id].present? self.order.order_responses.create(:message => response[:error]) self.errors.add(:base, response[:error]) return false end ! data = { :ext_transaction_id => response[:ext_transaction_id], :parent_order_id => self.order.id, :parent_order_item_id => self.id, :ccauth_reply_authorization_code => response[:ccauth_reply_authorization_code] } ! if options[:buyout] # it's a buyout OrderTransaction.buyout!( self.order.currency, extension_price.cents - options[:tax].cents, self, data, creator ) ! OrderTransaction.tax_charged!( self.order.currency, options[:tax].cents, self, data, creator ) ! process_convert_to_purchase! ! else # it's a regular extension begin OrderTransaction.extension!( "#{options[:days]} days", self.order.currency, extension_price.cents - options[:tax].cents, self, data, creator ) OrderTransaction.tax_charged!( self.order.currency, options[:tax].cents, self, data, creator ) # Increment extension days for current Item self.increment(:extension_days, options[:days]) self.update_attribute(:state, 'shipped_with_customer_extended') OrderItemMailer.rental_extended(self).deliver rescue Net::SMTPSyntaxError => exception Airbrake.notify( :error_class => exception.class.to_s, :error_message => "Bad Email Address Format. Order Item: #{self.id}. Email: #{self.order.user.email}", :parameters => self.attributes, :backtrace => caller) end end ! return true end 100+ LoC Real Code™
  15. 42.

    Component 1 Component 2 Component 3 Component n Message Queue

    Component 4 Component 5 Component 6 Component z
  16. 52.
  17. 53.
  18. 61.

    “The key to scalability lies in how messaging is actually

    done. The key to abstraction and compactness lies in a felicitous combination of design and mathematics." ! - Alan Kay
  19. 74.
  20. 75.

    class ImportationService def process orgs = Organizations.new(client).import orgs.each do |org|

    projects = Projects.new(org).import end projects.each do |project| Members.new(client).import Stories.new(client).import end end end Before
  21. 76.

    module RemoteService class Organizations def initialize(remote_client) @client = remote_client end

    def import import_organizations Projects.new(@client).import end ! private ! def import_organizations organizations = @client.organizations OrganizationsTable.new(organizations).save end end end After
  22. 77.

    module RemoteService class Projects def initialize(remote_client) @client = remote_client end

    def import import_projects Members.new(@client).import Stories.new(@client).import end ! private ! def import_projects projects = @client.projects ProjectsTable.new(projects).save end end end
  23. 78.

    module RemoteService class Projects def initialize(remote_client) @client = remote_client end

    def import import_projects Members.new(@client).import Stories.new(@client).import unless @client.github? end ! private ! def import_projects projects = @client.projects ProjectsTable.new(projects).save end end end What now?
  24. 79.

    module PivotalTracker class Client def organizations HTTParty.get(‘url’).map { |i| Response::Organization.new(i)

    } end ! def projects HTTParty.get(‘url2’).map { |i| Response::Project.new(i) } end ! def members HTTParty.get(‘url3’).map { |i| Response::Member.new(i) } end ! def stories HTTParty.get(‘url4’).map { |i| Response::Story.new(i) } end end end
  25. 81.

    module Github class Client def organizations HTTParty.get(‘url’).map { |i| Response::Organization.new(i)

    } end ! def projects HTTParty.get(‘url2’).map { |i| Response::Project.new(i) } end ! ! ! ! ! ! ! ! end end
  26. 82.

    module Github class Client def organizations HTTParty.get(‘url’).map { |i| Response::Organization.new(i)

    } end ! def projects HTTParty.get(‘url2’).map { |i| Response::Project.new(i) } end ! def members HTTParty.get(‘url3’).map { |i| Response::Member.new(i) } end ! ! ! ! end end
  27. 83.

    module Github class Client def organizations HTTParty.get(‘url’).map { |i| Response::Organization.new(i)

    } end ! def projects HTTParty.get(‘url2’).map { |i| Response::Project.new(i) } end ! def members HTTParty.get(‘url3’).map { |i| Response::Member.new(i) } end ! def stories [] end end end