Dependency Injection in Crystal?

I come from a C# background where Dependency Injection is an extremely common feature. it’s built into the ASP.NET web framework and provides a lot of behaviors in that world.

That being said, Dependency Injection does not seem to be common in Crystal from what I can find? Definitely doesn’t seem to be built into any of the existing web frameworks … and there also doesn’t appear to be a lot of libraries out there.

I’m just curious if this is intentional? Some language have features that make dependency injection less important. I’m not sure if Crystal has these? Or if there are other possibilities other than dependency injection?

Is it not necessary? Every time I see myself .new up instances of objects inside controllers a little piece of me wonders how I’m going to test those pieces with mocks or stubs.

Does anyone have any insights into Dependency Injection with Crystal?

Thanks so much.

Oh do I have something for you :star_struck:.

This feature is a core part of https://athenaframework.org, which utilizes the Dependency Injection component as a means of wiring services up used within the framework.

It’s heavily inspired by how DI is setup within Symfony, supporting most of the features Symfony does, with the main limitation being the compiled nature of Crystal. Because of that there aren’t really ways to modify the services while the container is being built.

The component can also be used independently (i.e. outside of the framework itself). Most of the documentation for it is on the module docs, and on Register - Athena.

I also wrote a blog post about this, although it’s a bit dated at this point and is more focused to the Dependency Injection component than standard DI in Crystal: https://dev.to/blacksmoke16/dependency-injection-in-crystal-2d66.

This is probably because DI is not real common in Ruby, where Crystal has kind of inherited the patterns and such from it. IMO it’s still an important design concept, even without the service container side of things. Having types be based on interfaces helps immensely when you go to test that type, or even want to have different implementations of something.

4 Likes

I have used dependency injection a lot with other langages and frameworks. However the nature of Crystal helps a lot to inject dependencies natively (via module, macro, annotation, monkey patching, hooks). So I don’t feel the lack. Otherwise it is affordable to create a DI lib or to implement a DI container. Like Athena supports it out of the box or you’ll find DI Shards too.