0

I know that we usually inject the dependencies by instantiating them in the constructor of the class we are injecting to. However, in my own experience, I just pass the class of the dependency as a parameter and do not instantiate in the constructor like the code below(I am currently working in Ruby):

class A
  def initialize(dependency: AnotherClass)
    @dependency = dependency
  end

def main_operation # do something here @params = # do some stuff to get some params here result = some_operation_to_perform_on_the_dependency_class # do something with result then return end

private

attr_reader :dependency

def some_operation_to_perform_on_the_dependency_class denpendency.new(@params).do_some_operation end end

My point is it doesn't make sense to instantiate the dependency object in the constructor because I need to pass in params which I can't get at the beginning

Therefore, I would love to hear are there any better ways/practices to do this(in OOP general or specifically in Ruby)? Or this is the only way to do it?

Fatima
  • 209

2 Answers2

6

It is not very sensible to ask what one does "usually" - how to design this kind of injection should depend on the requirements within the system, not on some habit of the programmer.

When a certain dependency A can be created before the construction of a dependend object of type B, injecting an A-object through the constructor of B is often the most simple solution and hence preferable. If that's not possible, because, as you wrote by yourself, the construction of the dependency can only be done at a later point in time, one needs to implement a more complex solution. In strictly typed languages like Java, C# or C++, the idiomatic solution would be to inject an abstract factory object, so the factory can be used to create the required dependency when possible. A simplified variant of this pattern, which is often sufficient for many purposes, is to provide this factory in form of a "call back" (delegate, higher-order function, whatever it is called in the specific environment).

In a language with dynamic typing like Ruby, injecting the class type instead of an object is a functionally equivalent approach, as you demonstrated it, with the advantage of being very concise. So in case this approach is sufficient for your case, go ahead, there is no need to overthink it. If the approach demonstrates itself not to be sufficient any more (for example, because the construction process itself requires more dependencies), then will be the time for thinking about a different solution like a factory.

Doc Brown
  • 218,378
1

First let's get the terminology right.

we usually inject the dependencies by instantiating them in the constructor of the class we are injecting to

This is nonsense. You either inject, in which case the dependency object pre-exists, OR you create, in which case it is not injected because it does not exist yet.

The choice boils down to the scope of the dependency object.

  • If it is only meaningful within the instance of the class, make the class create it and let it own it as one of its private members. This makes for nice encapsulation, it keeps the noise inside.
  • If the object is meaningful in its own right and/or other classes may depend on it as well, keep it external to the class and inject it.
Martin Maat
  • 18,652