codeborne / klite

Kotlin async http server framework with coroutines and zero deps
MIT License
103 stars 16 forks source link

Dependency Injection docs #51

Open webleaf opened 6 months ago

webleaf commented 6 months ago

I would like more documentation (with examples) on Dependency Injection. In what cases and how to use it correctly. Explanation of all Registry interface methods is required. For example, I don’t understand in what cases the requireAll() method is needed in practice. In what cases should you use create(), and in what cases register()? Why is optional() needed? I also don’t understand the meaning of this test: https://github.com/codeborne/klite/blob/c85d582a646165e46d7c7c85cf9685fc3951dc4c/server/test/klite/DependencyInjectingRegistryTest.kt#L21-L30 In general, I need yet another small tutorial on DI. And more detailed documentation with real-life examples of your implementation.

angryziber commented 6 months ago

@webleaf thanks for feedback, I've made some small improvements in the docs, however IMHO all methods of Registry should be quite obvious if you have used a different DI framework before. Basically, it allows you to register class instances and get them back using require.

Also, you can look at SimpleRegistry implementation to make it totally clear what exactly do they do - it's only a few lines of code. DependencyInjectingRegistry would also auto-create instances using constructor parameters, so that you don't need to register instances manually if there is only one implementation.

As you can see from requireAll() test, it's needed to get all implementations of a particular interface from the registry, it's used by Klite itself internally as is intended for plugin-like functionaility.

create() was a more internal method, I've marked it as protected to avoid confusion. require() is create + register and is what you need in most cases.

angryziber commented 6 months ago

Regarding the use existing instance even for arguments with default values test: it does exactly what is written in the name: it provides registered instances to constructor arguments even if they have default values defined. I have changed the name a bit, but it is quite precise.

Does this answer your questions?

webleaf commented 5 months ago

@angryziber thanks for answer. It looks like I don't understand the purpose of a DI container at all. I still hope to see a good explanation in the documentation for some DI implementation. But I still can’t find an explanation why Constructor Injection is not enough? Apparently I haven’t had to write such a large project where this becomes insufficient.

Do I understand correctly that the DI container allows you to replace Constructor Injection by injecting a class directly into the body of a function and moving its configuration to a centralized storage (configuration file)?

angryziber commented 4 months ago

The Registry's here implement constructor injection. Of course, you can call constructors manually and create all the objects in the system, but the base Registry here is still useful for holding of these created objects, so that others can access them without having to know the details on how are they created (with which exactly constructor parameters).

Registry is basically a generic holder of singletons in the app.