douchun2158 2014-10-17 12:07
浏览 26
已采纳

依赖注入/ LoD

I understand the basic principles of dependency injection but would like some advice on how to handle classes instantiated within other classes methods; does this go against the dependency injection pattern?

Moreover, I would like to write the object (class) to a DB (mongo in object form) and so don't want it to be bloated with other dependencies.

To better explain what I mean here is an example:

Lets say we have a user class that gets injected with a server class -

class User{
    public $user_id
    public $user_name;

    public function __construct(server $server){
        $this->server = $server;
    }

    public function delete(){
        //...delete user code

        // Send mail to user
        $mailer = new mailer($this->server);
        $mailer->sendMail();
    }

}

So two things about this

  1. This means that the User class now gets bloated as it contains the server class also
  2. Does this break the Law of Demeter? As the User class doesn't actually need the Server class other than to pass it onto the Mailer class..

I understand a way around this would be to inject the mailer class into the delete function when called from an outside controller, meaning the User class never has to be injected with the server class:

$server = new server();
$mailer = new mailer($server);
$user = new User();
$user->delete($mailer);

class User{
    public $user_id
    public $user_name;

    public function __construct(){
        // other code
    }

    public function delete(mailer $mailer){
        //...delete user code

        // Send mail to user          
        $mailer->sendMail();
    }

}

But surely this means that you would need to know every class needed by methods within a class, if this nesting becomes a few levels deep surely this will be difficult to keep track of.

Also what happens if user->delete is a private method? You wouldn't be able to call it from an outside controller to pass in the mailer object in the first place.

So my question really is what's the best way of going about this?

  • 写回答

1条回答 默认 最新

  • dqp99585 2014-10-17 12:09
    关注

    For me it is a smell to take a dependency on an object, just so you can construct a different object.

    Instead take a dependency on the object that you want to construct instead. So in your case just pass a mailer to your Users constructor, then you don't need to create a mailer and you don't need to care about the server.

    Here your User has a dependency on the mailer (to do the mailing) and so this is the thing that should be injected.

    You objects should only be creating new instances of leaf objects/data holders/DTOs. Anything which provides any functionality (ie services) should be injected into the objects which need to make use of the functionality.

    EDIT

    I don't do PHP but I think your user class should look more like this:

    class User{
        public $user_id
        public $user_name;
    
        public function __construct(mailer $mailer){
            $this->mailer = $mailer;
        }
    
        public function delete(){
            //...delete user code
    
            // Send mail to user
            $this->mailer->sendMail();
        }    
    }
    

    As for injecting via the constructor vs passing in to the method, this comes down to whether it is reasonable to expect a user of your User to provider a mailer when they want to delete a user. To me it doesn't sound like it is, so I would pass it through the constructor.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 R语言Rstudio突然无法启动
  • ¥15 关于#matlab#的问题:提取2个图像的变量作为另外一个图像像元的移动量,计算新的位置创建新的图像并提取第二个图像的变量到新的图像
  • ¥15 改算法,照着压缩包里边,参考其他代码封装的格式 写到main函数里
  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值