Implementações paralelas
        Willian Molinari
         a.k.a PotHix
WTF
1996!!




John Carmack
https://github.com/id-Software
#AltDevBlogADay
Várias formas de
implementações paralelas
1. Substitution
Master
Código no branch principal
class VirtualMachine
 def name
   hypervisor_session.VM.get_name(uuid)
 end
 .
 .
 .
end
Código código no branch novo
class VirtualMachine
 def name
   on_hypervisor.VM.get_name(uuid)
 end
 .
 .
 .
end
Master    NewFeature




Feature
"Virar a chave"
Dá para evitar?
2. Feature Toggle
2. Feature Toggle
Para adição de funcionalidade
Martin Fowler



       http://martinfowler.com/bliki/FeatureToggle.html
Master



Feature1

           Merge   Release

Feature2



Feature3
Martin Fowler



       http://martinfowler.com/bliki/FeatureToggle.html
Nando Vieira



     http://simplesideias.com.br/usando-presenters-no-rails/
2. Feature Toggle
Para várias implementações
Fabio Kung

 http://fabiokung.com/2010/10/16/dsls-one-interface-multiple-implementations/
Qual a idéia?
module Resque
 class Consumer
  class << self
    def queue(name)
     @queue = name
    end

   def timeout(seconds=nil)
    @lock_timeout = seconds unless seconds
    @lock_timeout || 1.hour
   end

   def exclusive(param)
    @exclusive = param
    self.extend(Resque::Plugins::LockTimeout) if exclusive?
    @lock_timeout ||= 1.hour
   end
   def publish(message={})
    Resque.enqueue(self, message)
   end
   ...
  end
 end
end
module ActiveMQ
 class Consumer
  class << self
    attr_reader :queue_name, :queued_process, :headers, :timeout_value

   def queue(name)
    @queue_name = "/queue/#{name}"
   end

   def timeout(seconds)
    @timeout_value = seconds
   end

   def exclusive(param)
    @exclusive = param
   end

   def publish(message = {})
     client = Stomp::Client.new(NephelaeConfig[:broker].merge(:max_reconnect_attempts => 1))
     client.publish(queue_name, message.to_yaml, {
       :persistent => true, :suppress_content_length => true
     })
   end
   ...
  end
 end
end
require 'xmpp4r'
module XMPP
 class Consumer
  class << self
    attr_reader :queue_name, :queued_process, :timeout_value

   def queue(name)
    @queue_name = "#{name}@localhost"
   end

   def timeout(seconds)
    @timeout_value = seconds
   end

   def exclusive(param)
    @exclusive = param
   end

   def publish(message={})
    publisher_client.send(Jabber::Message.new(queue_name, message.to_yaml))
   end
   ...
  end
 end
end
app/consumers/consumer.rb
  Consumer = ActiveMQ::Consumer
app/consumers/consumer.rb
  Consumer = XMPP::Consumer
app/consumers/consumer.rb
  Consumer = Resque::Consumer
Injeção de dependencia
MyQueue.new(Resque::Consumer)
Por configuração
3. Feature versioning
Manager




Ver1             Ver2
module Network
 class Ver1
  def insert_filter_rule(filter_rule)
    filter_rule.firewalls.in_parallel do |firewall|
      ssh_executor = SSHExecutor.new(firewall.ip_address, 'sservice')
      result = ssh_executor.exec(
        :insert_filter_firewall_rules, :rule => filter_rule,
        :internal_address => filter_rule.ip_pair.private_ip,
        :firewall => firewall
      )
      raise "Insertion failed: #{result[:out]}" if result[:status] != 0
    end
    filter_rule.update_attribute(:status, :done)
  end
  def insert_dhcp_entry(vm)
    vm.zone.dhcps.in_parallel do |dhcp_server|
      result = dhcp_server.synchronize
      raise "DHCP failed: #{result[:out]}" if result[:status] != 0
    end
  end
 end
end
Manager




Ver1             Ver2
module Network
 class Ver2
  def insert_filter_rule(filter_rule)
    quantum = Openstack::QuantumClient::L2l3.new(NephelaeConfig[:quantum])
    quantum_response = quantum.filter_rule.create(
      filter_rule.filter_address,
      filter_rule.ip_pair.public_ip.to_s,
      filter_rule.filter_port,
      filter_rule.filter_protocol
    )
    filter_rule.update_attribute(:quantum_uuid, quantum_response["filter_rule"]["id"])
  end

 def insert_dhcp_entry(vm)
   quantum = Openstack::QuantumClient::L2l3.new(NephelaeConfig[:quantum])
   quantum_response = quantum.dhcp_entry.create(vm.public_ip.to_s, vm.mac, vm.name)
  end
end
Manager


"1.0"             "2.0"


Ver1              Ver2
module Network
 module Manager
  extend self

  def for(versioning_object)
   versioning_object.version == "2.0" ? Network::Ver2.new : Network::Ver1.new
  end
 end
end
module Network
 module Manager
  extend self

  def for(versioning_object)
   versioning_object.version.constantize.new
  end
 end
end



Network::Manager.for(pool).insert_filter_rule(virtual_machine)
Várias formas de
                        atacar o problema
           r bu llet
 os ilve
N
               Resumindo
    Su                              bene fício
      an
         ec              Cu sto X
            es
               sida
                   de
Perguntas?

Implementações paralelas