V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lml12377
V2EX  ›  程序员

di 依赖注入实现的意义是什么?

  •  
  •   lml12377 · 2016-08-17 20:33:36 +08:00 · 3790 次点击
    这是一个创建于 3019 天前的主题,其中的信息可能已经有所发展或是发生改变。

    一般的 PHP 框架,一个应用 Application ,生命周期大概是这样的: Request > Router / Url > Dispatch > Controller/Action [ > Service] > Model > [ > View] > Response ,当然可能有些差别,多数无外乎这样。

    那引入 di 注入的意义是什么呢?是为了把应用流程涉及的对象设计成组件来实现解耦吗?比如 RequestInterface / HttpRequest / CliRequest , RouterInterface / SimpleRouter / RegexRouter / MapRouter 等等这样?

    但是一个普通的带视图带数据库操作的请求大致流程大家都一样啊( ROR / J2EE / PHP MVC ),即使是 restful 也是有 Router / Request / ControllerAction / Response 的,这解耦的意义是什么呢?解来解去,还得捞出来组个 MVC 流程。

    就好像 Router 妥妥的依赖 Request ,那就手工注入喽? Router 构造函数参数是 RequestInterface $request 喽?当前应用入口决定注入何种 Request 对象喽?难不成哪天 Router 还依赖个奇怪的玩意不成?

    难道说仅仅是为了 mock 方便?还是说为了不确定的将来?还是说有其它的原因。。。

    第 1 条附言  ·  2016-08-18 09:30:03 +08:00
    我发现不发新贴,直接 Append 很多时候根本没有人看,但还是不发新的了,防止被你们嘲讽。。。

    还是上面的问题:
    其实我是想问的是意义。。。 sf 上有人嘲讽说:“用个 MVC 就是解耦完成了?”,一个 网页 /rest 应用除了 mvc + dao 应该也剩不了什么了吧,分层已经稳定了这么多年(即使是变种也变化不大),各层之间的依赖也简单明了,即使不分层一股脑往下写也必须得先输入再处理后输出,这依赖还能怎么变呢,何必去解它的耦呢,解完了该怎么依赖还是怎么依赖,只是你不再关心手工注入罢了。。。即使解了依赖,表面上是不关心依赖了,那显示依赖还是得要对系统有理解才能知道绑定什么依赖啊?另外依赖自动注入是解了耦并且是不用人为去注入或者去 servicelocator 获取,但是隐式的完成依赖真的好么。。。

    说的可能有点冲啊,不知道是不是这个理:

    router 依赖 url / request 来 setController/setAction ,以前是在 router -> __construct 设置参数 UrlInterface $url, RequestInterface $request 来实现依赖接口不依赖实现,这样 http / cli 的 request 都能玩得转。

    现在无非是把 router / url / request 都扔到容器里,拿出来的时候它就已经用 \Closure/invoke 巴拉巴拉一堆帮你把 url / request 注入到 router 里面并且把这个 router 给你了,是不是这个意思?

    但是是个人都知道这 router 就得依赖 request 啊,这解耦解到这种程度是何必呢?难道不是为了 mock 方便?
    13 条回复    2016-08-18 11:10:11 +08:00
    sunsh217
        1
    sunsh217  
       2016-08-17 20:46:39 +08:00   ❤️ 1
    没有意义 ,装逼货。
    sunsh217
        2
    sunsh217  
       2016-08-17 20:47:52 +08:00   ❤️ 1
    把简单事情搞复杂,是装逼的必要条件 。 DI 依赖,就是这么个装逼货。
    kungfuchicken
        3
    kungfuchicken  
       2016-08-17 21:00:08 +08:00   ❤️ 1
    依赖注入和 MVC 没有直接关系,设计这个东西主体思想是解耦,服务化接口。

    比如说很多服务,数据库,缓存,日志,相关的业务模块服务化之后,你替换掉其中任意一个具体的实现类,是不影响依赖这个服务的对应的业务和逻辑

    引自维基百科:
    Class A 中用到了 Class B 的对象 b ,一般情况下,需要在 A 的代码中显式的 new 一个 B 的对象。

    采用依赖注入技术之后, A 的代码只需要定义一个私有的 B 对象,不需要直接 new 来获得这个对象,而是通过相关的容器控制程序来将 B 对象在外部 new 出来并注入到 A 类里的引用中。而具体获取的方法、对象被获取时的状态由配置文件(如 XML )来指定。

    ```
    class Human {
    ...
    protected $father;
    ...
    public _construct() {
    $this->father = new Father();
    }
    }
    ```
    仔细看这段代码我们会发现存在一些问题:
    (1). 如果现在要改变 father 生成方式,如需要用 new Father('name')初始化 father ,需要修改 Human 代码;
    (2). 如果想测试不同 Father 对象对 Human 的影响很困难,因为 father 的初始化被写死在了 Human 的构造函数中;
    (3). 如果 new Father()过程非常缓慢,单测时我们希望用已经初始化好的 father 对象 Mock 掉这个过程也很困难。
    levn
        4
    levn  
       2016-08-17 21:43:26 +08:00 via Android   ❤️ 1
    在一个地方维护对象之间在构建时的依赖关系
    neoblackcap
        5
    neoblackcap  
       2016-08-17 21:48:29 +08:00   ❤️ 1
    依赖注入是控制反转的一种实现方式,高层次的逻辑不用了解底层的实现方式,而且可以跟依赖解耦。
    而且依赖注入解决了一些比如循环引用的问题。
    至于你发现它不好用那是你的业务逻辑没达到它适用的程度,这个时候一般有两种做法,你适应它,或者抛弃它。
    当然依赖注入最好用的地方就是测试,因为你可以轻易 mock 掉依赖的对象。
    miao1007
        6
    miao1007  
       2016-08-17 22:14:59 +08:00   ❤️ 1
    多人编程时,实现解耦
    AbrahamGreyson
        7
    AbrahamGreyson  
       2016-08-17 22:30:58 +08:00   ❤️ 1
    这个和应用的执行流程关系不大的。

    主要就像楼上的高手说的, 1 , 方便替换具体实现, 2 ,依赖于能力,而不是身份, 3 , 方便测试, 4 ,稍微一丁点提高编码效率。

    你讲的是一个 app 常用的执行过程, 但是在一个中等规模的 app 中,这些流程只是基础设施, 你的业务代码会非常的多,对象之间的依赖会非常复杂,依赖注入能够让你开发速度更快, 修改具体实现的时候无需触碰业务代码。

    new Service() 也是一种依赖注入,只不过是你手写的,而且无法注入接口,依赖注入更加灵活。
    huijiewei
        8
    huijiewei  
       2016-08-17 23:19:39 +08:00   ❤️ 1
    为了可以确定的测试,和未来无关
    georgema1982
        9
    georgema1982  
       2016-08-18 03:53:31 +08:00   ❤️ 1
    @sunsh217 把自己不懂的东西说成裝逼,本身就是裝逼的行为
    coconne
        10
    coconne  
       2016-08-18 09:32:36 +08:00   ❤️ 1
    更方便的面对接口编程
    breeswish
        11
    breeswish  
       2016-08-18 09:52:58 +08:00   ❤️ 1
    个人观点:最重要的作用是可测试
    repus911
        12
    repus911  
       2016-08-18 09:54:41 +08:00   ❤️ 1
    @georgema1982 不要侮辱装逼
    julyclyde
        13
    julyclyde  
       2016-08-18 11:10:11 +08:00
    方便替换(也就方便了 mock )
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1026 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 19:23 · PVG 03:23 · LAX 11:23 · JFK 14:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.