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

Question about the example code and intended use #229

Open
chriscoindeskindices opened this issue Aug 26, 2023 · 2 comments
Open

Question about the example code and intended use #229

chriscoindeskindices opened this issue Aug 26, 2023 · 2 comments

Comments

@chriscoindeskindices
Copy link

chriscoindeskindices commented Aug 26, 2023

The example code on the main page:

>>> def configure_for_testing(binder):
...     configuration = Configuration(':memory:')
...     binder.bind(Configuration, to=configuration, scope=singleton)

and

>>> injector = Injector([configure_for_testing, DatabaseModule()])
>>> handler = injector.get(RequestHandler)
>>> tuple(map(str, handler.get()[0]))  # py3/py2 compatibility hack
('hello', 'world')

etc etc.

In this example it looks like we use binding through a global function, we create a module, and we create a class with an @Inject annotation.

Was this simply to illustrate all the ways that are possible to use this package and not a realistic example? For me, I've done everything in a module so my classes being injected are decoupled from the injector package and annotations. I view the module almost like a docker container + factory + builder pattern where everything is encapsulated and I use it as a black box by just saying "give me object" and it does the rest.

To me this is preferable for my use case, but I just want to make sure I'm not missing something I should be doing. Thanks.

@jstasiak
Copy link
Collaborator

jstasiak commented Sep 5, 2023

Hey,

While I'm tempted to actually get rid of that example now or at least rewrite it I think it's reasonably realistic.

I feel I don't fully understand your question, however – do you maybe have an example that would illustrate what you're unsure about and what you're doing differently?

@chriscoindeskindices
Copy link
Author

chriscoindeskindices commented Oct 7, 2023

For my purposes, which may be very very simple, I am only extending Module. So my application looks something like this:

class MyModule(Module):
  @provider
  def foo():
    return Foo()

  @provider
  def bar():
    return Bar()
    
  @provider
  def FooBar(foo, bar):
    return FooBar(foo, bar)
    
if __name__ == "__main__":
  injector = Injector(MyModule())

  fb = injector.get(FooBar)
  fb.run()

So this fits my purpose and it's great because I can create a base version of MyModule and extend that class, override or add other provider functions to create different versions of FooBar or FooBar's descendants, of which there are many. I've written my code in a way so that I can create, configure, and inject all variations at the module level. It works great for unit testing as well if I need to stub out providers with a mock provider that, for example returns some hardcoded value instead of actually querying a database.

My project is probably pretty small where this makes sense. I suppose I like it in this manner, and not using @Inject in any class because then the only class coupled to a framework is MyModule. If I had to for whatever reason, I could duplicate what MyModule does with vanilla python, but it would look a bit messy.

Perhaps, I am missing some of the benefits of doing injection with the other methods.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants