dongweihuan8610 2013-05-09 12:32
浏览 66
已采纳

什么时候依赖注入容器会变得太大,我该怎么办呢?

We all know the why Dependency Injection is awesome because it makes code less coupled, easier to test, and much nicer to read! And then some decide to use a Dependency Injection Container like pimple for PHP to assist with the Dependency Inversion principle in SOLID.

So when creating your DiC using pimple, passing it through to the controller, and having all your new objects created in closures that are actually only instantiated when the developer calls $container['object'], this is great!

But what happens when you have a very large set of classes in your application? Say 1000+, and you want these available in the container?

Development-wise, this is going to be a nightmare placing these all within one file. What would be the best way to separate them, or would an alternative suggestion be preferable?

On the separation side, how about:

  • Creating the container
  • Including several files with the classes grouped together depending on the application
  • Adding to the container incrementally until the end of the file includes

On the flip side, I know Symfony2 uses XML/YAML for the DiC configuration, but really this doesn't go into much talk about the architectural side of things when an application contains so many classes.

What can a developer do to when they have such a large codebase?

  • 写回答

3条回答 默认 最新

  • duanchu2607 2014-11-20 11:00
    关注

    I'd like to answer this myself now.

    Dependency Injection Containers do not contain every object in your application. The fact that they are labelled containers is the main problem here. "DiC's" like Symfony's Pimple are not dependency injectors. They are glorified associative arrays used to hold objects and primarily advocate the Service Locator anti-pattern.

    See $this->get('something') in your code, like in Symfony? That's a service locator. Use that and you are hiding class dependencies and making a liar of your object API. This includes your controllers!

    Object requirements should be readable from the constructor or method signatures of an object only, and a provided to this object via Dependency Injection providing Inversion of Control through your codebase helping testability, maintainability and flexibility with greatly simplified polymorphism being made available through it.

    Dependency injection containers should be renamed to injectors, because that is what they should be doing - injecting dependencies for you. You should not be pulling objects out of them when you require. How are you going to use DI and inversion of control if you just pull them out when you need them using a service locator?

    In real life you wouldn't build a house by transporting the entire hardware store (hopefully) to the construction site so you can access any parts you need. Instead, the foreman (__construct()) asks for the specific parts that will be needed (Door and Window) and goes about procuring them. Your objects should function in the same way; they should ask only for the specific dependencies required to do their jobs. Giving the House access to the entire hardware store is at best poor OOP style and at worst a maintainability nightmare. rdlowrey - auryn

    You could use reflection to read object requirements then instantiate and inject dependencies automatically. Auryn is a fantastic injector for this. You set it up in your bootstrap and controller resolver and then you can write SOLID code for conrete auto-injection based on object typehints throughout your codebase. Any abstract classes / interfaces? No problem, you alias concretes to these either directly in-code or by reading them from a config file (preferable) and aliasing them in a loop that way. Using a configuration file means you can have config-based polymorphism at your disposal - the ability to switch out one concrete implementation with another simply by creating the new object and changing one string in a config file is fantastic.

    In conclusion, Dependency Injection Containers never become "too big" unless you're doing it wrong and using them as a service locator or a glorified associative array of objects! You don't shove all your objects in there in order to pull them out when you need them. I don't care if they're lazy-loaded. Use an actual injector. And don't even mention Laravel or "facades".

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 file converter 转换格式失败 报错 Error marking filters as finished,如何解决?
  • ¥15 ubuntu系统下挂载磁盘上执行./提示权限不够
  • ¥15 Arcgis相交分析无法绘制一个或多个图形
  • ¥15 关于#r语言#的问题:差异分析前数据准备,报错Error in data[, sampleName1] : subscript out of bounds请问怎么解决呀以下是全部代码:
  • ¥15 seatunnel-web使用SQL组件时候后台报错,无法找到表格
  • ¥15 fpga自动售货机数码管(相关搜索:数字时钟)
  • ¥15 用前端向数据库插入数据,通过debug发现数据能走到后端,但是放行之后就会提示错误
  • ¥30 3天&7天&&15天&销量如何统计同一行
  • ¥30 帮我写一段可以读取LD2450数据并计算距离的Arduino代码
  • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型