Search code examples
dependency-injectioncrystal-lang

Depedency injection in crystal language


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


Solution

  • 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: "[email protected]")
        @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.