boost-ext / di

C++14 Dependency Injection Library
https://boost-ext.github.io/di
1.16k stars 140 forks source link

Usage Question: Why is the API not like make_unique<type> ? #371

Closed a-teammate closed 5 years ago

a-teammate commented 5 years ago

Expected Behavior

The API to be similar like std::make_unique and friends:

   auto injector = di::make_injector(
        // the to be injected parameters but without defined ordering
    );
   auto q = di::make_injected<QInterface>( injector );

Actual Behavior

   auto injector = di::make_injector(
        // the to be injected parameters but without defined ordering
    );
    auto q = injector.create<QInterface>();

For me, the first would be more understandable, as it resembles the usual way to construct something: you pass parameters to it. But I'm not so sure between the consequences of the two designs. Maybe I am too new to boost DI and DI frameworks. Then forgive me and just tell me "read the basics" or w/e.

kanstantsin-chernik commented 5 years ago

I would say it is a matter of view point. The problem is kind of "milk the cow or decaw the milk". In my opinion, injector itself is a complex factory which creates objects and it is natural to "ask" factory to create an object rather than to have a static function which accepts factory as an argument.

Besides, DI container was not invented here. There are a lot of references Kris used to build it so that developers could intuitively switch over to Boost.DI.

In any case, you still can have this type of API by implementing your own extension. It is fairly easy to do so.

a-teammate commented 5 years ago

I totally agree that it is a matter of taste.

As this library is aiming towards becoming something standard for C++, it should mimic the C++ standard (to keep the standard's design decisions intact while keeping it concise). And therefore may rethink whether the way objects tend to be created in Java is as applicable here.

a-teammate commented 5 years ago

[..] and it is natural to "ask" factory to create an object [...]

Hint me to a point in the c++ standard this pattern was used like that and I immediately revise my concerns. It just appears to me, that the factory does not need to maintain state and does not create different kinds of objects (or does it?), so why would it be worthy enough to create a factory first (boilerplate code) to create an actual object in the next step.

kanstantsin-chernik commented 5 years ago

I see your point. But DI container preserves state (shared scope and instance scope). Also, it is Boost.DI: lets compare tuple for instance. STL has the only Yoda style accessor while boost has both.

Here are a couple of references I think can answer you question: abstract factory pattern google fruit c++ ninject di

In any case it is extensible Open Source project. If you think it will be valuable for you: you can extend it, if you believe it will be valuable for everyone: send a pull request.

krzysztof-jusiak commented 5 years ago

@a-teammate added support for both: member function call and free function call for create -> https://github.com/boost-experimental/di/pull/372/commits/77b9ceeffe159ea71e837bcfc1ab51de30549bb5. It would be great if C++ has universal call syntax but oh well, maybe in the future. Thanks, for your feedback and thanks, @kanstantsin-chernik for your valid points :+1:

a-teammate commented 5 years ago

Perfect, thank you very much! :)