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

Dependency Injection in Ruby

Dependency Injection in Ruby

Joshua Tompkins

February 07, 2017
Tweet

More Decks by Joshua Tompkins

Other Decks in Technology

Transcript

  1. Locator.register :logger { Logger.new } class SuperCoolApp def do_a_cool_thing logger

    = Locator.resolve(:logger) logger.info(‘log a cool thing’) end end
  2. class SuperCoolApp def initialize(logger) @logger = logger end def do_a_cool_thing!

    @logger.info(‘log a cool thing’) end end app = SuperCoolApp.new(Logger.new(STDOUT)) app.do_a_cool_thing!
  3. class Processor def initialize @repository = Repository.new @factory = Factory.new

    end def process(message) model = @factory.parse(message) @repository.save(model) end end
  4. class Processor def initialize(repository, factory) @repository = repository @factory =

    factory end def process(message) model = @factory.parse(message) @repository.save(model) end end Constructor Injection
  5. “…dependency injection has spread and been advocated as a cross-language

    best practice on trumped up benefits of flexibility and malleability. If your code never knows exactly who it's talking to, it can talk to anyone! …Hogwash.”
  6. class Processor def initialize @repository = Repository.new @factory = Factory.new

    end def process(message) model = @factory.parse(message) @repository.save(model) end end
  7. “…the ways [Ruby will] bend to extract the best of

    hard coding is truly impressive.” - A guy who’s wrong about stuff
  8. class Processor def initialize @repository = Repository.new @factory = Factory.new

    @billing_repo = BillingRepository.new end def process(message) @billing_repo.email_receipts model = @factory.parse(message) @repository.save(model) end end
  9. class Processor def initialize(repository, factory, billing_repo) @repository = repository @factory

    = factory @billing_repo = billing_repo end def process(message) @billing_repo.email_receipts model = @factory.parse(message) @repository.save(model) end end
  10. json_message = ‘’ # some JSON! processor = Processor.new( mock_repository,

    mock_factory, mock_billing_repository ) processor.process(json_message) Constructor Injection
  11. json_message = ‘’ # some JSON! processor = Processor.new processor.repository

    = mock_repository processor.factory = mock_factory processor.billing_repo = mock_billing_repo processor.process(json_message) Setter Injection
  12. class TimeFactoryProvider def resolve(type) if type == :now TimeFactory.new elsif

    # etc… end end end def publish!(provider) time = provider.resolve.now self.update published_at: time end
  13. db_connection = Sequel::Connection.new(‘mysql:…’) accessor = DbAccessor.new(db_connection) agent_repository = AgentRepository.new(accessor) usage_repository

    = UsageRepository.new(accessor) host_repository = HostRepository.new(accessor) factory = Factory.new processor = Processor.new( agent_repository, usage_repository, host_repository, factory ) decoder = Decoder.new(processor) decoder.run
  14. logger = Logger.new(STDOUT) db_connection = Sequel::Connection.new(‘mysql:…’) accessor = DbAccessor.new(db_connection) agent_repository

    = AgentRepository.new(accessor, logger) usage_repository = UsageRepository.new(accessor, logger) host_repository = HostRepository.new(accessor, logger) factory = Factory.new processor = Processor.new( agent_repository, usage_repository, host_repository, factory, logger ) decoder = Decoder.new(processor, logger) decoder.run
  15. class ClientsController < ApplicationController def index logger = Logger.new(STDOUT) dbAccessor

    = DbAccessor.new(CONN_STR, logger) client_repo = ClientRepository.new(dbAccessor, logger) client_repo.all end end
  16. client_repo.all end end class ClientsController < ApplicationController def index logger

    = Logger.new(STDOUT) dbAccessor = DbAccessor.new(CONN_STR, logger) client_repo = ClientRepository.new(dbAccessor, logger) client_repo.all end end class ClientsController < ApplicationController def index logger = Logger.new(STDOUT) dbAccessor = DbAccessor.new(CONN_STR, logger) client_repo = ClientRepository.new(dbAccessor, logger) client_repo.all end end class ClientsController < ApplicationController def index logger = Logger.new(STDOUT) dbAccessor = DbAccessor.new(CONN_STR, logger)
  17. Codependent::Manager.container :my_container do singleton :greeting from_value “Hello, World!” end end

    greeting = Codependent::Manager[:my_container] .resolve(:greeting) Codependent::Manager .reset_container!(:my_container)
  18. Simple DSL Manual configuration, no magic Circular dependencies (via setter

    injection) Instance & singleton dependencies Codependent Features