google / dagger

A fast dependency injector for Android and Java.
https://dagger.dev
Apache License 2.0
17.45k stars 2.02k forks source link

Provide an example relevant to java/android instead of coffee brewing #262

Open Aditya94A opened 9 years ago

Aditya94A commented 9 years ago

The awkward coffee example is quite confusing and it's difficult to relate to anything we do in Java or Android. It makes it hard to understand dagger and doesn't clearly indicate the advantages of dependency injection.

Surely, we want dagger to be accessible to a larger audience. Maybe we can find an example that makes sense in a context beyond coffee brewing? Perhaps something like SharedPrefences or a clear comparison of accomplishing the same task with and without dagger to illustrate it's advantage.

ZakTaccardi commented 9 years ago

agreed! For as something as complicated as Dagger, good documentation is as important as the quality of the library itself.

I recommend that this example provide three things:

For testing, I find it particularly difficult to override the @Provides methods for subcomponents. If I normally inject something in onCreate(), I don't know how to access the instance of that activity/fragment before onCreate is called to change the injection behavior.

jbaginski commented 9 years ago

please :)

artem-zinnatullin commented 9 years ago

Instead of complaining you can submit a PR and community with maintainers will review and improve it. This how OSS works!

On Fri, Nov 13, 2015, 19:30 Janusz Bagiński notifications@github.com wrote:

please :)

— Reply to this email directly or view it on GitHub https://github.com/google/dagger/issues/262#issuecomment-156480360.

@artem_zin

konmik commented 9 years ago

Dagger is not for Android only, so your more Android specific examples can bring about more confusion than clarification.

ghost commented 9 years ago

I agree with @artem-zinnatullin there is no point complaining when you actually haven't made enough effort to learn it, dagger 2 has a great following and there are tones of materials online to learn from.

jbaginski commented 9 years ago

I'm not an expert in that matter :(

On Fri, Nov 13, 2015 at 4:37 PM, Artem Zinnatullin <notifications@github.com

wrote:

Instead of complaining you can submit a PR and community with maintainers will review and improve it. This how OSS works!

On Fri, Nov 13, 2015, 19:30 Janusz Bagiński notifications@github.com wrote:

please :)

— Reply to this email directly or view it on GitHub https://github.com/google/dagger/issues/262#issuecomment-156480360.

@artem_zin

— Reply to this email directly or view it on GitHub https://github.com/google/dagger/issues/262#issuecomment-156482024.

best regards, Janusz Bartosz Bagiński http://goo.gl/x3aQ9X http://goo.gl/I96hnC http://goo.gl/f4D3ZG UK+44 (0) 7445 934 298PL+48 (0) 662 117 269

dlew commented 9 years ago

How about https://github.com/JakeWharton/u2020?

konmik commented 9 years ago

@dlew are you kidding? People need to understand what injectection is and to play with Dagger no less than a month before reading all that high-level examples.

JakeWharton commented 9 years ago

No need to be hostile and combative. Perhaps you should go inject a thermosiphon into your coffee maker and have a nice latte and relax.

konmik commented 9 years ago

Sorry if I was "hostile" somehow, this was not my intention. I just want to say that people who didn't work with DI before, need to start from really simple things, like "what is DI?", "why do we need DI?", the simplest possible (and workable real-life) example, etc.

sameb commented 9 years ago

Here's a good video about why DI is useful: https://www.youtube.com/watch?v=hBVJbzAagfs

cgruber commented 9 years ago

We definitely wrote the early documentation for the context of people who did know that they wanted dependency injection, since there are lots of "what is dependency injection" talks related to Spring and Guice which cover the concepts. But we're working on a fairly strong documentation overhaul, and it will include at least some introduction to the concepts, or a very clear call-out for where to read if you need more theory about DI.

Now that we've finally gotten the codeline synced out, and as we start syncing out docs updates, we'll be in a better position to take pull requests and interact more. I would ask that people do keep a bit of a civil tone. We know our documentation is not the greatest at present. We're working on it. :)

littledot commented 9 years ago

@konmik well the coffee maker example only relates to developers with coffee related jobs, catering to a smaller population already.

dlew commented 9 years ago

@konmik The question is about a sample in the context of Android, which is (I thought) exactly what u2020 provides. Sorry.

konmik commented 9 years ago

@littledot I don't have coffee in my programs. I have UI, network, storage, multithreading, event processing, etc. So despite the fact that coffee brewers are real, this is not a real-life example.

@sameb Looks good, but it is for Guice, so if one wants to study Dagger he need to study Guice first. They have a good example with twitter client.

@dlew Don't need to sorry, this is a very good example, but it is for advanced usage. :)

Hey guys, I also think that Dagger is awesome and it can have a much better spreading over Java developers than it has now if we could only break that hard-to-study barrier!

I'm not a dagger developer and I'm also not a native english-speaker, so I can not pretend to write official articles myself. But I have https://github.com/konmik/konmik.github.io/wiki/Snorkeling-with-Dagger-2, some find it to be useful for beginning. The main article idea is to be easily catchable by newcomers - goals of Dagger are visible, all terms have definitions, it has an easy-to-complex studying sequence, conceptual schemas, some "how it works" info, and examples are from real life. Feel free to reuse its plot / any parts of it.

JakeWharton commented 9 years ago

No simple example will ever be a real life example. The power of the library cannot be conveyed in something trivial, and thus the trivial examples must be convoluted. The names in the coffee example might as well be Gizmo, Trinket, Widget, and Fizzbang as they're just showing a representative composition of how injection can be used rather than introducing you to DI or even to the library.

On Fri, Nov 13, 2015 at 3:27 PM Konstantin Mikheev notifications@github.com wrote:

@littledot https://github.com/littledot I don't have coffee in my programs. I have UI, network, storage, multithreading, event processing, etc. So despite the fact that coffee brewers are real, this is not a real-life example.

@sameb https://github.com/sameb Looks good, but it is for Guice, so if one wants to study Dagger he need to study Guice first. They have a good example with twitter client.

@dlew https://github.com/dlew Don't need to sorry, this is a very good example, but it is for advanced usage. :)

Hey guys, I also think that Dagger is awesome and it can have a much better spreading over Java developers than it has now if we could only break that hard-to-study barrier!

I'm not a dagger developer and I'm also not a native english-speaker, so I can not pretend to write official articles myself. But I have https://github.com/konmik/konmik.github.io/wiki/Snorkeling-with-Dagger-2, some find it to be useful for beginning. The main article idea is to be easily catchable by newcomers - goals of Dagger are visible, all terms have definitions, it has an easy-to-complex studying sequence, conceptual schemas, some "how it works" info, and examples are from real life. Feel free to reuse its plot / any parts of it.

— Reply to this email directly or view it on GitHub https://github.com/google/dagger/issues/262#issuecomment-156547878.

konmik commented 9 years ago

@JakeWharton When you teach someone by example, you give him an example and you expect that the person will extrapolate the tools application to a more general use case.

The opposite happens very rarely. Most of the times when people see an abstract example, they think "oh, it is too complex and I don't see how I can use it anyway" and leave.

This is why your U+2020 is so cool - it is a real life example that people can take as a pattern and extrapolate to their usage as they become more familiar with it. But most of us need a simpler real-life example, U+2020 is too complex for an average Java/Android developer.

JakeWharton commented 9 years ago

But that's the fundamental problem here. Not only is Dagger high-leverage, it's high-barrier of entry. This is especially compounded by the fact that most don't what dependency injection is as a pattern before they look to a library to solve the problem.

I'm not saying it's impossible, it's just that this example was never meant to be for beginners. Focusing on it is the wrong approach because it's actually a good example of all the features available. What this issue should be about is a set of new and incremental examples which introduce concepts instead of just showing them off.

On Fri, Nov 13, 2015, 3:47 PM Konstantin Mikheev notifications@github.com wrote:

@JakeWharton https://github.com/JakeWharton When you teach someone by example, you give him an example and you expect that the person will extrapolate the tools application to a more general use case.

The opposite happens very rarely. Most of the times when people see an abstract example, they think "oh, it is too complex and I don't see how I can use it anyway" and leave.

This is why your U+2020 is so cool - it is a real life example that people can take as a pattern and extrapolate to their usage as they become more familiar with it. But most of us need a simpler real-life example, U+2020 is too complex for an average Java/Android developer.

— Reply to this email directly or view it on GitHub https://github.com/google/dagger/issues/262#issuecomment-156552316.

konmik commented 9 years ago

@JakeWharton I absolutely agree that there should be small steps in studying. Smaller steps - more confidence. (Confidence + confidence) * confidence = knowledge.

What is wrong with the Twitter client example? If I remember properly, you also had it in some talks. I think it is real enough even for non-android users because it gives an idea about client-server communication most of us are familiar with.

cbeust commented 9 years ago

I wish more people understood that it's okay to complain, or report a bug, even if you're not in a position to fix that problem yourself. As long as the report is constructive (which I think the initial request here was), it's still better than not reporting anything.

I completely agree that the coffee example is confusing. It's not easy to explain the value of Dagger but I'm sure we can come up with better examples than that. And yes, ideally, not an Android-centric one.

I think both Android and back end engineers alike can relate to an application that needs to make network calls and store data in a persistent storage. Maybe we can come up with an example around these concepts?

artem-zinnatullin commented 9 years ago

I wish more people understood that it's okay to complain, or report a bug, even if you're not in a position to fix that problem yourself.

Well, since I wrote:

Instead of complaining you can submit a PR and community with maintainers will review and improve it. This how OSS works!

I had to describe why I did so. (I'm not a maintainer of this project, so my opinion may differ from theirs)

OSS users usually see maintainers as persons who obligated to help everyone who uses their project. Every day I see how people post pieces of code from their projects and try to use maintainers as bug fixers. OSS is free and maintainers get no$thing for it, that's why you can find "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND in the LICENSE.txt.

On StackOverflow it's okay to ask: "How to …? I tried this, this and this.". But if you ask "How to …? Please paste me working code" your question can be closed without an answer because, literally you're asking somebody to do your work. And that's why StackOverflow still works (and reputation, of course, everyone wants to be on the top of the rating).

After a couple of articles and videos about DI, awkward Coffee example becomes understandable and at the same time abstract enough, so you are not tied to concrete details like networking/db/etc libraries and other APIs!

Zhuinden commented 9 years ago

Considering the documentation of a library should include how to make it work at a basic level out of the box, I don't think this is a scenario similar to how the "how do I do XYZ" questions work on Stack Overflow - considering they tell you to google it, look it up, have a glance at the documentation and put it together yourself first.

Now, if the documentation is not that helpful as it only tells you vaguely how to build a coffee brewer factory maker, then there's obviously an issue.

The current documentation doesn't address:

@aashrairavooru there is a valid reason to complain if you specifically need to look at other resources beyond the official documentation to start out with the basic setup of a simple project using that library.

codebymikey commented 9 years ago

I would be remiss if I said initially picking up Dagger was easy.

On my first foray with the Coffee example, I personally wasn't able to relate to it at all, and actually had to search for what terms like Thermosiphon meant - this coming from a native English speaker. I fear for non-native speakers trying to pick up the example.

Difficulty with me being unable to fully understand the sample and lack of time led me to set the library aside for a couple of weeks until I could find a better example to wrap my head around. I had a vague understanding of the basic idea, the example just didn't click with me due to all the unfamiliar terminologies being thrown around. I was finally able to understand it by reading some blog posts with better easier to understand examples as well as looking into some open source libraries (u2020 and some other cool informative open source android apps).

Thinking back to my (and probably most of us') first introduction to OOP, I'm pretty sure most of us can still vividly remember the simple but clear abstract example; describing it using the idea of Shapes, inheriting and overriding Shape attributes as well as overriding its functions like draw() and name(). This what I think Dagger is missing and is the main cause of the initial hard barrier to entry.

I think having a more general use case example like building a complex Car object using dependency injection might be something a lot of people might find easier to wrap their heads around.

Like @JakeWharton said, there's really nothing wrong with adding more samples. I just think it would be nicer to have a more relatable sample first for people to get their front foot in the door so to speak. And then for more advanced developers yearning for more, they can look into the Coffee-brewing example.

henieek commented 9 years ago

There are couple of different issues raised here.

First is vocabulary. It could be better, without a doubt. Unless you're a coffee-hipster it's unlikely you've ever heard about a thermosiphon.

Second thing is that unless you already have some experience with different DI frameworks you'll have a hard time learning Dagger using its current documentation. DI can really look like a time waster if you don't understand the context. I did a quick overview of how other DI libraries handle this issue and I really liked the Guice's approach: https://github.com/google/guice/wiki/Motivation.

Idea is simple. They show you a problem, then they show you a non-DI solution and then a DI solution, which is much cleaner. I believe Dagger needs something similar. Still, I believe the complexity of a Guice's sample could still be lower.

I was thinking about it for a while and I have an idea of a LED banner system. Imagine a LED banner at the restaurant's entrance, greeting its guests with different messages, depending on a context (e.g. "Good Morning" in the mornings and "Good Evening" in the evenings). If you try to model it in an OOP-way you may get something like this:

class Banner {
  @Inject Banner() { }
  void display(String message) {
    // some fuzzy assembly here
  }
}
class Greeter {

  private final Banner banner;
  private final String message;

  @Inject Greeter(Banner banner, String message) {
    this.banner = banner;
    this.message = message;
  }

  void greet() {
    banner.display(message);
  }
}
class Application {
  public static void main(String[] args) {
    // Dagger stuff here
    greeter.greet();
  }
}

Think about it.

PS: I'm totally against putting some Android-specific stuff in samples. For someone who's not into Android, SharedPreferences is even more enigmatic than Thermosiphon.

ZakTaccardi commented 9 years ago

I'm totally against putting some Android-specific stuff in samples

The complexity of the Android application/activity lifecycle definitely needs to be taken into account. This is because the framework is in control of how activities/fragments/views are instantiated, which makes the process much more complicated. Android doesn't have to be the ONLY example, but definitely should be in there as an additional resource.

First is vocabulary. It could be better, without a doubt. Unless you're a coffee-hipster it's unlikely you've ever heard about a thermosiphon.

I think the car/engine example would be more universally understand. Jake's twitter example was good too.

3flex commented 9 years ago

This is loosely related, but the Android examples in /examples still contain a warning that they may not reflect recommended Dagger 2 patterns. An update was already requested in https://github.com/google/dagger/issues/176.

Vetting the examples then removing the warning, and slightly fleshing out one of those examples with an implementation of SharedPreferences or an SQLiteOpenHelper singleton, might go a small way to improving Android-related documentation. Indeed @cgruber left this comment // TODO(cgruber): Figure out a better example of something one might inject into the app in the android-activity-graphs example.

(Would also like to see a build.gradle added to the examples to help people understand where to source @Inject annotation as I understand there are multiple options, and many tutorials recommend org.glassfish:javax.annotation:10.0-b28 over javax.annotation:jsr250-api. I don't know enough to say why.)

JakeWharton commented 9 years ago

@Inject comes from jsr330 whose dependency comes transitively (and thus automatically) from dagger-runtime.

On Wed, Nov 18, 2015 at 5:21 PM Matthew Haughton notifications@github.com wrote:

This is loosely related, but the Android examples in /examples still contain a warning that they may not reflect recommended Dagger 2 patterns. An update was already requested in #176 https://github.com/google/dagger/issues/176.

Vetting the examples then removing the warning, and slightly fleshing out one of those examples with an implementation of SharedPreferences or an SQLiteOpenHelper singleton, might go a small way to improving Android-related documentation. Indeed @cgruber https://github.com/cgruber left this comment // TODO(cgruber): Figure out a better example of something one might inject into the app in the android-activity-graphs example.

(Would also like to see a build.gradle added to the examples to help people understand where to source @Inject annotation as I understand there are multiple options, and many tutorials recommend org.glassfish:javax.annotation:10.0-b28 over javax.annotation:jsr250-api. I don't know enough to say why.)

— Reply to this email directly or view it on GitHub https://github.com/google/dagger/issues/262#issuecomment-157883440.

3flex commented 9 years ago

OK thanks. But I come full circle because if I remove javax.annotation:jsr250-api from build.gradle I get error: cannot find symbol class Generated because of Dagger's @Generated annotation in the generated code.

Then I found https://github.com/google/dagger/issues/95#issuecomment-67360117 where you said you'll always need to add the Glassfish dependency org.glassfish:javax.annotation on Android because its API doesn't support the annotation, then someone asks "why not use javax.annotation:jsr250-api?"...

So back it goes into build.gradle. Which is fine, it would just be good if this were officially documented by the project, or mentioned in the example projects.

netdpb commented 8 years ago

We are working on better documentation, including for Android. And @gk5885 is working on better example applications.

ZakTaccardi commented 8 years ago

Excellent.

My biggest request is a recommendation on how to manage sub-scopes on Android. Dagger is a breeze to use when you just store a singleton component in your Application, but it gets more complicated as you get down into an activity/fragment/scope. And then testing it.

Thanks!

Zhuinden commented 8 years ago

@ZakTaccardi in that case you just have to do exactly what I wrote here on SO: http://stackoverflow.com/questions/34187828/why-is-dagger2-asking-me-to-provide-something-that-the-component-is-not-supposed/34188127#34188127

ZakTaccardi commented 8 years ago

@Zhuinden here's my problem.

Your activity calls onCreate(), which calls createComponent(). Then the activity lifecycle continues and data is loaded (likely within onStart() etc etc.

Because of the way Espresso works, once I call activityRule.launchActivity(), onCreate(), onStart() etc are all called. I have no easy way to swap out the component being used to load the data after the activity is launched but BEFORE onStart() is called. Once the activity has settled I can swap out the component, but the data has already been loaded by then.

tl;dr: I want to easily change the component that is provided by this method on a per test basis

protected StripeComponent createComponent(CustomApplication application) {
    return DaggerStripeComponent.builder()
            .applicationComponent(application.getApplicationComponent())
            .build();
}
kamikat commented 8 years ago

Here's my experimental and minimum example https://github.com/kirisetsz/another-dagger2-android-example which should be a nice explanation about how to implement a DI pattern with dagger2 on Android.

I think I have picked up the idea of DI, but have no idea about whether I have chosen an appropriate name for abstractions :laughing: welcome to discuss your idea about it. And If that's the right way using dagger2 on android, there should be a helper library do something similar like the example does.

gryphon2411 commented 6 years ago

Any news about this one? It's been a while

Aditya94A commented 6 years ago

Damn. Has it really been three years?

Any news about this one? It's been a while

OP here. My news is that I just had to suck it up and learn it the hard way 💪

Zhuinden commented 6 years ago

Damn. Has it really been three years?

That's how I feel every day :smile:

Jokes aside, they really did make the docs better since.