Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Confused by specificity injector #2

Open
garyrob opened this issue May 3, 2020 · 4 comments
Open

Confused by specificity injector #2

garyrob opened this issue May 3, 2020 · 4 comments
Assignees
Labels
documentation Improvements or additions to documentation enhancement New feature or request

Comments

@garyrob
Copy link

garyrob commented May 3, 2020

First I want to say that I'm new to dependency injection in general, but in the last week have experimented with the dependency-injector library, which seemed much more cumbersome to use than the injector library (which I also tried), which in turn seems much more cumbersome to use than autocontainer. So at this point I have to say that I'm very impressed with autocontainer and look forward to trying to use it in an upcoming project where I think dependency injection could be very helpful.

But, I'm confused by the Specifity Injector functionality described in an example on your main page. In the example, class D inherits from class A; class A does not inherit from class D. But the object retrieved with container.get(A) apparently inherits from both A and D, based on the results of the isinstance() asserts. This doesn't make sense to me. Why is that happening? Why would I even want it to happen?

It seems like it could be a good idea for the documentation to explain this.

@omranjamal
Copy link
Member

Hey, I'll surely update the documentation as soon as possible but as I don't want to keep you waiting, I'll explain here.

When you do container.get(A) the returned object is an instance of class D not A. As D inherits from A, it is also effectively an instance of A hence both asserts to be true.

As for why we would ever want this to happen there are three ways to answer this.

  1. The Abstract: Each time you extend a class you usually make the child class more feature rich and more useful or 'smart' or efficient but always make sure to keep the original functionality intact so when a function is hinted to need any instance of a base class it is (in some people's opinion) smart to inject the class farthest down the hierarchy.

  2. The common sense: When I create an abstract class Fruit to represent fruit and I have a function makeFruitSalad(fruit: Fruit) that makes a fruit salad, it makes sense that I would want an instance of Mango instead of a bare-bones Fruit class.

  3. The real world: More of then than not this is very useful for testing, when I have a large application and I have a class MagicClass I want to stub it and gather data about another function or class that communicates with MagicClass in that case I can just extend MagicClass and created FakeMagicClass and give it to the container so that I don't have to change my actual code being tested which is a sigh of relief.

I recognize that there are better and many more examples to explain this I hope this will do.

Please let me know if I can help you with anything else, I'll get started on a new and improved documentation ASAP.

@omranjamal omranjamal self-assigned this May 3, 2020
@omranjamal omranjamal added documentation Improvements or additions to documentation enhancement New feature or request labels May 3, 2020
@garyrob
Copy link
Author

garyrob commented May 3, 2020 via email

@omranjamal
Copy link
Member

omranjamal commented May 3, 2020

That's a great and sensible idea, I might implement that in the next major version! I wont argue at all against what you said up there the only reason I coded this behavior is because I wanted to emulate the type hint by interface and abstract class like in Java but in Python. Now that I think of it, it is in fact possible to achieve this in other ways.

Even though I might not implement deep_get() and get() as separate methods (that would really mess up the "auto" part). I'll probably decide based on explicitness. If you explicitly register A and B where B happens to extend A, the container will inject B if B is hinted and A if A is hinted.

In the case if A is not explicitly registered and only B is registered, the container will inject B if A is hinted. How does that sound?

Thanks for the moment of induced epiphany btw!

@garyrob
Copy link
Author

garyrob commented May 3, 2020 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants