2

Is there any way to do dependency injection in crystal, I only found it with some frameworks(like athena and shivneri) but not by itself

RonanDev
  • 23
  • 3

1 Answers1

4

Dependency injection is a generic technique and it is supported in Crystal, for instance, via constructor injection. The following example could have been written similar in almost any object oriented languages. It defines an interface (an abstract class), and passes it to the constructor. Later, you can choose what implementation you want to provide:

record Email, subject : String, to : String

abstract class EmailSender
  abstract def send(email)
end

class RealEmailSender < EmailSender
  def send(email)
    # some code to send an email
    # ...
  end
end

class StubEmailSender < EmailSender
  def send(email)
    # some test code to log the email without sending
    puts "STUB: sending email #{email}"
  end
end

class CheckoutService
  def initialize(@email_sender : EmailSender)
  end
  
  def process_order
    email = Email.new(subject: "Received order", to: "john.doe@abc.test")
    @email_sender.send(email)
  end
end

# inject the stub to skip sending a real email
email_service = StubEmailSender.new
checkout_service = CheckoutService.new(email_service)
checkout_service.process_order

Constructor injection demonstrates that dependency injection is possible. Another option would be to use generics. But perhaps you were not asking about manually arranging the services, but on how to use a dependency injection framework for the wiring?

To the best of my knowledge, no popular dependency injection framework exists for Crystal. It should be possible to write one, but it is not clear to me whether it is needed. Note that dependency frameworks see broad usage in some languages (like Java) but not in all. Ruby is one example where dependency frameworks exist but remain controversial.

Philipp Claßen
  • 41,306
  • 31
  • 146
  • 239