如果单子是坏的,那么为什么服务容器是好的?[英] If Singletons are bad then why is a Service Container good?

本文是小编为大家收集整理的关于如果单子是坏的,那么为什么服务容器是好的?的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我们都知道坏单例是因为它们隐藏了依赖性,并且其他原因.

但是,在一个框架中,可能只需要实例化一次,并从无处不在(logger,db等).

要解决这个问题,我被告知使用所谓的"对象管理器"(或服务容器像Symfony一样),内部存储对服务(Logger等)的每个引用.

但是,为什么服务提供商不像纯粹的单身人士那样糟糕?

服务提供商也隐藏了依赖性,它们只是包裹了第一istance的创建.因此,我真的很努力地理解为什么我们应该使用服务提供商而不是单人.

ps.我知道,要不要隐藏依赖关系,我应该使用di(如Misko所述)

添加

我会补充:如今,单例不是邪恶的,Phpunit的创造者在这里解释了:

  • http:///sebastian-bergmann.de/Archives/882测试代码 - uses-singletons.html

di + singleton解决了问题:

<?php
class Client {

    public function doSomething(Singleton $singleton = NULL){

        if ($singleton === NULL) {
            $singleton = Singleton::getInstance();
        }

        // ...
    }
}
?>

即使这根本无法解决所有问题,这也很明智.

除了DI和Service容器外,是否有任何可接受的解决方案可以访问此辅助对象?

可以说,

推荐答案

服务定位器只是两个邪恶中的较小者. "较少"归结为这四个区别(至少我现在想不出其他任何其他区别):):

单一责任原则

服务容器不像Singleton那样违反单一责任原则. Singletons混合对象创建和业务逻辑,而服务容器严格负责管理应用程序的对象生命周期.在这方面,服务容器更好.

耦合

由于静态方法调用,通常将单单套件用于您的应用程序,该调用导致紧密的耦合且难以模拟依赖项在您的代码中.另一方面,SL只是一个类,可以注入.因此,尽管您的所有分类都取决于它,但至少它是一个松散的依赖性.因此,除非您将服务定位器作为单身人士本身实现,否则这会更好,也更易于测试.

但是,使用服务序列者的所有类都将依赖于服务序列,这也是一种耦合形式.可以通过为服务启动器使用接口来缓解这种情况,因此您不受混凝土服务器的实现的束缚,但是您的类将取决于某种定位器的存在,而所有类型的定位器都不使用ServiceLocator,从而大大增加了重用.

>

.

隐藏依赖项

隐藏依赖性的问题很大.当您只是将定位器注入消费课程时,您将不会知道任何依赖性.但是与单身人士相反,SL通常会实例化幕后所需的所有依赖关系.因此,当您获得服务时,您最终不会像 misko Hevery ">在信用卡示例中,例如您不必手动实例化依赖的所有依赖.

从实例中获取依赖项也违反了 demeter的法律不应该挖掘合作者.一个实例只能与其直接合作者交谈.这是Singleton和ServiceLocator的问题.

全球状态

全局状态的问题也有所缓解,因为当您在测试之间实例化新的服务定位器时,所有先前创建的实例也会删除(除非您犯了错误并将其保存在SL中的静态属性中).当然.

另请参阅服务位置位置位置位置上的依赖性点数 - 深度讨论.


塞巴斯蒂安·伯格曼(Sebastian Bergmann)对使用单例的测试代码:塞巴斯蒂安(Sebastian)绝不建议提出的解决方法使使用单子更少的问题.这只是制作代码的一种方法,否则将无法测试更具测试.但这仍然是有问题的代码.实际上,他明确指出:"仅仅是因为您可以,并不意味着您应该应该".

其他推荐答案

服务定位器模式是反图案.它不能解决暴露依赖关系的问题(您无法从班级的定义看出它的依赖性是什么,因为它们没有被注射,而是从服务定位器中撤出).

那么,您的问题是:为什么服务定位器很好?我的答案是:他们不是.

避免,避免,避免.

其他推荐答案

服务容器隐藏依赖性如单顿模式.您可能需要建议使用依赖性注入容器,因为它具有服务容器的所有优点,但据我所知(据我所知)服务容器所具有的缺点.

据我所知,两者之间的唯一区别是,在服务容器中,服务容器是要注入的对象(因此隐藏依赖关系),当您使用DIC时,DIC会为您注入适当的依赖项.由DIC管理的课程完全忽略了由DIC管理的事实,因此您的耦合,明确的依赖性和快乐的单位测试.

这是一个很好的问题,可以解释这两者的差异:依赖注入和服务定位器模式有什么区别?

本文地址:https://www.itbaoku.cn/post/627531.html

问题描述

We all know how bad Singletons are because they hide dependencies and for other reasons.

But in a framework, there could be many objects that need to be instantiated only once and called from everywhere (logger, db etc).

To solve this problem I have been told to use a so called "Objects Manager" (or Service Container like symfony) that internally stores every reference to Services (logger etc).

But why isn't a Service Provider as bad as a pure Singleton?

Service provider hides dependencies too and they just wrap out the creation of the first istance. So I am really struggling to understand why we should use a service provider instead of singletons.

PS. I know that to not hide dependencies I should use DI (as stated by Misko)

Add

I would add: These days singletons aren't that evil, the creator of PHPUnit explained it here:

DI + Singleton solves the problem:

<?php
class Client {

    public function doSomething(Singleton $singleton = NULL){

        if ($singleton === NULL) {
            $singleton = Singleton::getInstance();
        }

        // ...
    }
}
?>

that's pretty smart even if this doesn't solve at all every problems.

Other than DI and Service Container are there any good acceptable solution to access this helper objects?

推荐答案

Service Locator is just the lesser of two evils so to say. The "lesser" boiling down to these four differences (at least I can't think of any others right now):

Single Responsibility Principle

Service Container does not violate Single Responsibility Principle like Singleton does. Singletons mix object creation and business logic, while the Service Container is strictly responsible for managing the object lifecycles of your application. In that regard Service Container is better.

Coupling

Singletons are usually hardcoded into your application due to the static method calls, which leads to tight coupled and hard to mock dependencies in your code. The SL on the other hand is just one class and it can be injected. So while all your classed will depend on it, at least it is a loosely coupled dependency. So unless you implemented the ServiceLocator as a Singleton itself, that's somewhat better and also easier to test.

However, all classes using the ServiceLocator will now depend on the ServiceLocator, which is a form of coupling, too. This can be mitigated by using an interface for the ServiceLocator so you are not bound to a concrete ServiceLocator implementation but your classes will depend on the existence of some sort of Locator whereas not using a ServiceLocator at all increases reuse dramatically.

Hidden Dependencies

The problem of hiding dependencies very much exists forth though. When you just inject the locator to your consuming classes, you wont know any dependencies. But in contrast to the Singleton, the SL will usually instantiate all the dependencies needed behind the scenes. So when you fetch a Service, you dont end up like Misko Hevery in the CreditCard example, e.g. you dont have to instantiate all the depedencies of the dependencies by hand.

Fetching the dependencies from inside the instance is also violating Law of Demeter, which states that you should not dig into collaborators. An instance should only talk to its immediate collaborators. This is a problem with both Singleton and ServiceLocator.

Global State

The problem of Global State is also somewhat mitigated because when you instantiate a new Service Locator between tests all the previously created instances are deleted as well (unless you made the mistake and saved them in static attributes in the SL). That doesnt hold true for any global state in classes managed by the SL, of course.

Also see Fowler on Service Locator vs Dependency Injection for a much more in-depth discussion.


A note on your update and the linked article by Sebastian Bergmann on testing code that uses Singletons : Sebastian does, in no way, suggest that the proposed workaround makes using Singleons less of a problem. It is just one way to make code that otherwise would be impossible to test more testable. But it's still problematic code. In fact, he explicitly notes: "Just Because You Can, Does Not Mean You Should".

其他推荐答案

The service locator pattern is an anti-pattern. It doesn't solve the problem of exposing dependencies (you can't tell from looking at the definition of a class what its dependencies are because they aren't being injected, instead they are being yanked out of the service locator).

So, your question is: why are service locators good? My answer is: they are not.

Avoid, avoid, avoid.

其他推荐答案

Service container hides dependencies as Singleton pattern do. You might want to suggest using dependency injection containers instead, as it has all the advantages of service container yet no (as far as I know) disadvantages that service container has.

As far as I understand it, the only difference between the two is that in service container, the service container is the object being injected (thus hiding dependencies), when you use DIC, the DIC injects the appropriate dependencies for you. The class being managed by the DIC is completely oblivious to the fact that it is managed by a DIC, thus you have less coupling, clear dependencies and happy unit tests.

This is a good question at SO explaining the difference of both: What's the difference between the Dependency Injection and Service Locator patterns?