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条)

报告相同问题?

悬赏问题

  • ¥30 求给定范围的全体素数p的(p-2)的连乘积
  • ¥15 VFP如何使用阿里TTS实现文字转语音?
  • ¥100 需要跳转番茄畅听app的adb命令
  • ¥50 寻找一位有逆向游戏盾sdk 应用程序经验的技术
  • ¥15 请问有用MZmine处理 “Waters SYNAPT G2-Si QTOF质谱仪在MSE模式下采集的非靶向数据” 的分析教程吗
  • ¥50 opencv4nodejs 如何安装
  • ¥15 adb push异常 adb: error: 1409-byte write failed: Invalid argument
  • ¥15 nginx反向代理获取ip,java获取真实ip
  • ¥15 eda:门禁系统设计
  • ¥50 如何使用js去调用vscode-js-debugger的方法去调试网页