依赖注入容器什么时候可以变得太大,我该怎么办? [英] When can Dependency Injection Containers become too big, and what can I do about it?

查看:82
本文介绍了依赖注入容器什么时候可以变得太大,我该怎么办?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们都知道为什么依赖注入很棒的原因,因为它使代码更少耦合,更易于测试并且更易于阅读!然后有人决定使用依赖注入容器(例如 pimple )来帮助PHP 依赖反转原理/SOLID_%28object-directional_design%29"rel =" noreferrer> SOLID .

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.

因此,当使用pimple创建DiC并将其传递给控制器​​,并在闭包中创建所有新对象时,实际上只有在开发人员调用$container['object']时才实例化它们,这太棒了!

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!

但是,如果您的应用程序中有很多大量的类,会发生什么?假设有1000多个,并且您希望这些在容器中可用?

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?

在分离方面,如何:

  • 创建容器
  • 包括几个文件,这些文件的类别取决于应用程序
  • 逐步添加到容器中,直到文件末尾包含

另一方面,我知道 Symfony2使用XML/YAML 对于DiC配置,但实际上,当应用程序包含如此多的类时,这并不会过多涉及事物的体系结构方面.

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?

推荐答案

我现在想亲自回答.

依赖注入容器包含应用程序中的每个对象.它们被标记为容器的事实是这里的主要问题.像Symfony的 Pimple 一样,"DiC"也不是依赖项注入器.它们是美化的用于容纳对象的关联数组,主要倡导服务定位器反模式.

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.

请参见代码中的$this->get('something'),就像在Symfony中一样?那是服务定位器.使用它,您将隐藏类依赖关系并欺骗对象API.这包括您的控制器!

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.

依赖项注入容器应重命名为 injectors ,因为这是它们应该执行的操作-为您注入依赖项.在需要时,您不应从中拉出物体.如果仅在需要时使用服务定位器将它们拉出,该如何使用DI和控制反转?

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?

在现实生活中,您不会将整个五金店(希望)运到 施工现场,以便您可以访问所需的任何零件.而是领班(__construct()) 询问需要的特定零件(DoorWindow)并进行采购. 您的对象应该以相同的方式起作用.他们应该只要求特定的依赖 需要做他们的工作.授予House访问整个硬件商店的权限充其量是最差的 OOP风格,最糟糕的是可维护性的噩梦. rdlowrey-auryn

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

您可以使用反射来读取对象需求,然后自动实例化并注入依赖项. Auryn 是一个出色的注入器.您可以在引导程序和控制器解析器中对其进行设置,然后可以基于整个代码库中的对象类型提示编写SOLID代码以进行具体的自动注入.任何抽象类/接口?没问题,您alias直接在代码中或通过从配置文件(首选)中读取它们并以循环方式对其进行别名来具体化它们.使用配置文件意味着您可以使用基于 config的多态性-只需通过创建新对象并更改配置文件中的一个字符串,就可以将一种具体实现与另一种实现互换.

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.

总而言之,除非您做错了事并且将它们用作服务定位器或美化的对象关联数组,否则依赖项注入容器永远不会变得太大".您无需将所有对象都推到那里以便在需要时将它们拉出.我不在乎它们是否是延迟加载的.使用实际注射器.而且甚至不要提及Laravel或门面".

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".

这篇关于依赖注入容器什么时候可以变得太大,我该怎么办?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆