0

here is a small code:

class Mail
{
    public $subject;

    public function send()
    {
        DI::get('mailer')->send($this);
    }
}

class Mailer
{
    public function send(Mail $mail)
    {
        //
    }
}

its doensnt use DI, I mean Mailer is not passed to Mail via constructor, just taken out from a container. But when to use which?

John Smith
  • 6,129
  • 12
  • 68
  • 123
  • 1
    As an architectural point of view: If you are using `$mail` in most methods just pass it in the constructor. Although if it is not used in most methods then maybe you should split into other classes because you should respect the Single Responsibility Principle...so all in all better pass in constructor, define it's role. P.S: might be easier to test. EDIT: If you are using strategy design pattern then you can pass it I guess...depends on what you are doing, post full code maybe? – ka_lin Sep 05 '16 at 15:54

1 Answers1

2

Using an IoC container as a Service Locator is an Anti-Pattern.

You should prefer constructor injection over method injection or property injection:

If the class cannot do its job without the dependency, then add it to the constructor. The class needs the new dependency, so you want your change to break things. Also, creating a class that is not fully initialized ("two-step construction") is an anti-pattern (IMHO). If the class can work without the dependency, a setter is fine. - Source

Your IoC container should only be accessed one time for a given object tree. When I say accessed I mean invoking DI::get('X'). You objects should not invoke DI::get('X'). Your objects should not be aware of the existence of an IoC container.

The IoC container should only be accessed from the Composition Root of your object graph.

In a MVC web application the composition root is usually a controller factory. In a console application it can be found in main.

Community
  • 1
  • 1
Remo H. Jansen
  • 23,172
  • 11
  • 70
  • 93
  • 2
    +1 for "Your object should not be aware of the existence of an IoC container". If you manage to avoid that (and taking all dependencies as arguments, i.e. no `new`, no `x::y()` in your code), then you are heading for a testable architecture. – chelmertz Sep 06 '16 at 11:04