DI - Dependency Injection

Library Submission

Note: you must be a logged in registered user in order to submit a library!
  • logo_linkweb_linkcomment 
    Add a row
Display Statistics
Reviews There are 0 reviews
There are 5 comments

Comment on This Page

  • Kris says:

    Thanks for your time, feedback and valid points. Will try to improve the doc using your suggestions.

  • Rob Stewart says:

    Your Motivation page has English problems, but I’ll focus on content.

    Would anyone write code such as your Spaghetti Code? I’d expect a std::unique_ptr<logger> data member, not a default constructor that calls an init() function with one. Even as written, I’d expect the data member so that run() can use the logger. Why wouldn’t one just put a logger instance in app? Why bother with creating a pointer? I’m left to think you have a solution in search of a problem. You need to explain why a logger data member is an issue for testing, for example, to justify allocating it on the free store. That also will justify passing the logger to the app constructor rather than hard coding the logger type (mocking). Obviously, you could make the concrete type of logger object be runtime selectable, through the use of a factory, for example. You also could justify a logger pointer by suggesting that you want to keep the dependency out of the class header. In that case, you’d rely on a forward declaration and have a std::unique_ptr to the base as a data member.

    You wrote, “If we want to support different types of logger we need to write a bit of boilerplate code over and over again,” and then showed this code as justification:

      auto text_logger_ = std::make_shared<text_logger>();
      auto ci_logger_ = std::make_shared<ci_logger>();
      auto file_logger_ = std::make_shared<file_logger>();
      ...

    Why would one write all of those statements?

    The bullets following those statements are apparently related to the “boilerplate” paragraph, but there’s no flow nor reason given for their appearance. I don’t understand the point you’re trying to make. My guess is that this whole page is supposed to illustrate a case in which one will use some mechanism to determine the kind of logger to use, shows different ways of implementing that sort of thing, and then show how your library purports to improve on those other approaches. You haven’t motivated the need for that from the start, and there’s no narrative helping the reader to understand the pieces being shown.

    After wading through many factory-type solutions, we come to the Enhanced Dependency Injection bullet. That shows code that, I presume, is supposed to show the benefits of using your library, but I don’t see it. You’ve eliminated the runtime selection. The code looks very much like the original, manual DI code. The problem is that the only code that would, apparently, benefit from the library is the line calling app::run(), yet you’ve coupled that with calling injector.create<app>(). You have fine print excusing that issue, but the whole point of a Motivation section of the documentation is to motivate users to want to read more. Instead, you’ve burdened them with too many unrelated details and failed to actually show the benefits of your library. Note: A Motivation section is not the place to warn readers away from undesirable usage.

    In the end, I learned nothing more about the benefits of your library, from reading the Motivation page, beyond what the Introduction page presented, which does not motivate me to learn anything more about your library. I still see no benefit to it. I’ve read numerous claims, but I’ve seen none of them made manifest in the code or discussion.

  • Rob Stewart says:

    The Introduction was not helpful for several reasons. It should briefly explain DI, with links to more thorough explanations; it should explain why the reader should care about DI; and it should explain why your library helps with DI. “Dependency injection is a programming practice providing required instances to an object” doesn’t come close to describing DI. I suggest something more like the following:

    Dependency Injection (DI) involves passing (injecting) one or more dependencies (or services) to a dependent object (or client) which become part of the client’s state. It is like the Strategy Pattern, except the strategy is set once, at construction. DI enables loosely coupled designs, which is easier to maintain and test.

    That will better introduce the idea of DI, while beginning to motivate its use.

    Your Introduction spends a lot of time trying to sell the library’s features without ever helping the user understand the benefits of DI. You should help the reader understand the value of DI after the above description. Creating a Why Dependency Injection? section will allow those already familiar with it to move ahead, while keeping the attention of those unfamiliar with the subject. That section should answer the question, “Why should I use DI?”

    The last section of the Introduction should focus on why your library helps with DI. Even here, you haven’t helped yourself. You claim that your library reduces boilerplate, yet your second code snippet is more verbose than the manual DI shown to its left, and fails to illustrate any of the other benefits you claim (maintenance or testing benefits, better control, better understanding). You’d be better off not showing the code if developing those points cannot be shown concisely. In that case, just treat those topics in detail in subsequent pages.

  • tommy80486 says:

    Please find below my observations I made while reading through
    the documentation and source:

    The motivation and purpose of the library was immediately clear
    to me in a few seconds. I am already familiar with the concept
    of dependency injection and have used other dependency injection
    frameworks in other languages.

    In my view, someone that wasn’t familiar with dependency injection
    would still be able to understand the motivation of the library
    in under a minute.

    You might include a link to a description of dependency injection from
    wikipedia or some other reference for someone that wasn’t familiar with
    the concept.

    I followed the instructions under Installation on the Overview page.

    It was great to see the instructions to retrieve the boost library
    dependencies were included for someone that was entirely new to boost.

    It took me almost 25 minutes to download everything to get it all setup before
    I built my first example. You might include a note that it can take
    a while to download everything if you do not have boost already installed.

    The library path in the overview page is listed as:

    boost/di/example

    I found it at:

    boost/libs/di/example

    I am new to boost and wasn’t familiar with bjam. I wasn’t able
    to build the examples. I simply scrolled through the source
    code.

    It would be nice to build it with CMake.

    Overall, the purpose of the library was immediately clear. It
    was nice that it was a header only library. It was
    easy to use, and despite the fact it took a while to setup, which
    wouldn’t be an issue if I was more familiar with boost, I was able
    to become familiar with it and start using it quickly.