auraphp / Aura.Di

Dependency Injection System
MIT License
349 stars 63 forks source link

[Discussion] ContainerInterface get method #139

Closed harikt closed 7 years ago

harikt commented 8 years ago

The ContainerInterface get method looks a bit problematic .

Text copied from https://github.com/container-interop/container-interop/blob/master/docs/ContainerInterface.md#11-basics

get takes one mandatory parameter: an entry identifier. It MUST be a string. A call to get can return anything (a mixed value), or throws an exception if the identifier is not known to the container. Two successive calls to get with the same identifier SHOULD return the same value. However, depending on the implementor design and/or user configuration, different values might be returned, so user SHOULD NOT rely on getting the same value on 2 successive calls. While ContainerInterface only defines one mandatory parameter in get(), implementations MAY accept additional optional parameters.

The Aura.Di get only returns single instance when it is called once / twice .. There is already a discussion regarding the same : https://github.com/container-interop/container-interop/issues/69 According to the discussion https://github.com/container-interop/container-interop/issues/69#issuecomment-251050021 mentions about the containers

  1. Pimple has a factory method to declare a service instantiated each time it is retrieved (but only one way to retrieve services)
  2. Laravel has App::bind and App::singleton
  3. Symfony 2 has the notion of scope and Symfony 3 has the notion of shared service that can be used to have the container act as a factory. Once more, there is only one get method, not several ones.

can produce different instances.

There is also a discussion https://github.com/container-interop/container-interop/issues/44 where @pmjones is part of.

So what will be the best way to produce new instances for the registered service and a shared instance accordingly?

In Aura.Di we register as

$di->set('database', $di->lazyNew('Database'));
$di->set('example', $di->lazyNew('Example'));
$di->set('example', $di->newInstance('Example'));

But the fact is regardless of what / how we register the service we only get one instance. Probably we need to make some way so that the behaviors are same for all Di containers in the wild.

Thoughts ?

pmjones commented 8 years ago

This is what happens when we bind a library to an external interface -- the semantics change, even when the interface itself does not. :-/

I say if you want two different service instances, then define two different services.

djmattyg007 commented 8 years ago

I would not want the semantics of Aura\Di\Container::get() to change to that of the intended meaning for the ContainerInterop interface. I get the impression that a lot of the containers that follow ContainerInterop strictly are service locators, not true dependency injection containers.

Some of these containers simply won't let you use more than one service with the same class at all because they will only use the name of the class as the service name. Aura.Di is more advanced than that, and it's a good thing.