sob., 20 lut 2021 o 03:10 Niall Douglas via Boost
On 19/02/2021 22:20, Krzysztof Jusiak via Boost wrote:
I hope that the examples and explanation helps a bit, but if not I'm also more than happy/available to have a follow-up (via zoom or similar) if that helps (feedback could be used to improve the documentation)?
Kris I speak from experience with Outcome that you're going to have to be much more hand holdy than that description you just gave. You'll need to explain things in small, baby steps, because DI is one of those things that nobody understands until the lightbulb switches on, and then they totally get it.
Given that Mr. Dimov and several others have indicated they don't understand the motivation behind DI, if you want to see DI get into Boost, you're going to have to write a lot of personalised responses to people and keep repeating yourself to each individual in turn until people twig what DI is and why it's useful. I did this for Outcome, and whilst it was laborious at the time, I think it paid off in the end for everybody here.
Yes. My recollection of the adventure with Outcome is similar. I guess it takes time and energy to explain one's idea to others. I imagine it is frustrating too. One writes a library, makes an effort to share it with the people, and the only response back is, "do more work, convince us".
(Incidentally, I chose DI to review manage for a reason, I think this is the first vocabulary library we've seen presented here since Outcome. I am *very* much hoping its review isn't going to turn into thousands of emails ...)
Andrzej, I'll give you my description of DI (which is not that of Boost.DI). For certain kinds of problem solution, it can make sense to turn inside out the traditional design of a C++ program i.e. place the innards on the outside, and put what is normally outside into the innards. You thus get an "inverted design" program.
Normally that's a bad idea, because maintenance is harder, it's anti social to other engineers, and so on. Also, in C++, we typically use template techniques such as CRTP for DI, we don't typically use polymorphic techniques in this, but that's peculiar to C++ and not what most languages do because they don't have powerful enough compile time facilities.
For complex use cases, or where a fixed ABI is absolutely needed, template based techniques are too painful to use to do DI, and for this niche use case, a common runtime framework such as that of Boost.DI lets arbitrary pieces of DI based code interoperate with one another in a composable fashion.
This use case is probably even more niche than that for Outcome, which maybe 15% of C++ developers would ever need to consider using. For non-template DI, I would estimate less than 5% of C++ developers would ever need to consider using it.
*However*, for where you do actually need runtime polymorphic DI, there are very few good solutions to hand in C++, unlike in other major languages. I think proposed Boost.DI could really fill that empty gap, and for those few who need that gap filled, they _badly_ need it filled. A standardised solution in this space would be particularly valuable.
Just to be clear, I was talking about DI in general above, I don't know if Boost.DI is the correct, or sufficient, or best approach to solving non-template DI in C++. That's for the review here to decide.
So far, my understanding is the following. Please correct me, if I am mischaracterizing the situation. This library is not so much about Dependency Injection. Dependency Injection is just a style of programming. The DI-library is rather about managing the complexity that results from choosing to use Dependency Injection. Suppose I have a class like the following: ``` struct Point { int x; int y; }; struct Rect { Point lowerLeft; Point upperRight; }; class State { Rect area; Point location; // invariant: location is inside area; public: State(int left, int lo, int right, int hi, int x, int y) : area{{left, lo}, {right, hi}}, location{x, y} {} }; int main() { State s{0, 0, 2, 2, 1, 1}; } ``` I do not like that I have to pass so many parameters, that in this configuration can be easily confused. So, I want to apply the Dependency Injection philosophy. I get: class State { Rect area; Point location; // invariant: location is inside area; public: State(Rect a, Point loc) : area{a}, location{loc} {} }; int main() { State s{Rect{{0, 0}, {2, 2}}, Point{1, 1}}; } ``` Now, I choose to use the DI-library (this is where I have troubles with understanding: why would I want to do that?). I get the following result: ``` int main() { State s = di::make_injector().create<State>(0, 0, 2, 2, 1, 1); } ``` And now I get back to the situation where I am passing six ints and can easily confuse which int represents what. I am pretty sure I am now unfairly mischaracterizing the library. But this is what I get from the motivation and tutorial sections, and the explanations I have seen so far. You cannot see this behavior in the tutorial example that is using class `app`, because most of the types in there are default-constructed or constructed from values that were themselves (perhaps recursively) default-constructed. So it looks to me that in order to appreciate this library, I have to make most of my types default-constructible. At which point am I missing something? Regards, &rzej;
Niall
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost