Announcing coi v0.5.0

Hi fellow rustaceans! I'm proud to announce my very first crate, coi (repo, crate, docs).

It's a dependency injection crate that focuses on simplicity of use. It relies on a procedural macro to do a lot of the busy work, and also provides a declarative macro to help initialize containers. Resolving dependencies also relies on async (in order to handle cases like establishing a DB connection, which might rely on async). Both procedural macros and async support can be turned off through features to help with compile times and to just turn off what you're not using.

I plan on getting this crate to 1.0 and maintain it for a long time (that was my current issue with existing DI crates, they seemed not feature-complete and not-maintained), so please file issues on any documentation or crate issues, even for minor things like typos. I'll gladly take any feedback on API design as well. If you feel the crate should have something that it doesn't, please file an issue for that as well!

Thread in reddit

Any chance you can explain what dependency injection is? I haven't been able to figure it out based on a couple of minutes of looking through the docs.

Wikipedia: Dependency injection

Having read through the Wikipedia article, I don't see how dependency injection differs from generics.

I tried experimenting with generics early on, but the lack of GAT's (tracking issue here) makes it nearly impossible to do without a massive amount of type hacking. It's certainly not something I would recommend for a team that has a good amount of junior rust devs on it.

With DI, you can also do dynamic configuration at runtime. For example, on intialization, your code could read some config file, env vars, etc. and then use that information to determine which implementation to register for which key. That's not really possible with generics, though it is possible with trait objects.

The idea with the crate providing a framework is to make that easier to manage when you have a sufficiently large project. If you're building a large backend, dealing with routing all of your objects to their proper dependencies manually can be pretty complicated. DI frameworks let you trade off that complexity for a little bit of runtime cost and heap allocation.

It also helps with complicated integration testing. You can register mocks in the container, and then just resolve a single instance from the container with all of the mocks in the right place.

Here's a good article on it from the C# perspective: https://stackify.com/net-core-dependency-injection/
and here's an example of a similar library in the npm ecosystem: https://www.npmjs.com/package/awilix

1 Like