依赖注入框架会导致糟糕/懒惰的设计吗?

时间:2022-12-01 18:27:20

I'm fairly new to the DI concept, but I have been using it to some extent in my designs - mainly by 'injecting' interfaces into constructors and having factories create my concrete classes. Okay, it's not configuration-based - but it's never NEEDED to be.

我是DI概念的新手,但我在设计中已经在某种程度上使用它 - 主要是通过'注入'接口到构造函数并让工厂创建我的具体类。好的,它不是基于配置的 - 但它永远不需要。

I started to look at DI frameworks such as Spring.NET and Castle Windsor, and stumbled across this blog by Ayende.

我开始研究诸如Spring.NET和Castle Windsor之类的DI框架,并偶然发现了Ayende的博客。

What I got from this is

我从中得到的是

A) DI frameworks are awesome, but B) It means we don't have to worry about how our system is designed in terms of dependencies.

A)DI框架很棒,但B)这意味着我们不必担心我们的系统是如何根据依赖性设计的。

For me, I'm used to thinking hard about how to loosely-couple my system but at the same time have some sort of control over dependencies.

对我来说,我习惯于思考如何松散地耦合我的系统,但同时对依赖关系进行某种控制。

I'm a bit scared of losing this control, and it being just a free-for-all. ClassA needs ClassB = no problem, just ask and ye shall receive! Hmmm.

我有点害怕失去这种控制,它只是一个免费的。 ClassA需要ClassB =没问题,只要问,你就收到了!嗯。

Or is that just the point and this is the future and I should just go with it?

或者这就是重点,这就是未来,我应该选择它?

Thoughts?

8 个解决方案

#1


I wouldn't say that you don't have to think about dependencies, but using an IoC framework allows you to change the types which fulfill the dependencies with little or no hassle, since all the wiring is done in a central place.

我不会说你不必考虑依赖关系,但是使用IoC框架可以让你很少或没有麻烦地改变满足依赖关系的类型,因为所有的连线都是在一个中心位置完成的。

You still have to think about what interfaces you need and getting them right is not always a trivial matter.

你仍然需要考虑你需要什么样的接口,并且正确地使用它们并不总是一件小事。

I don't see how a loosely coupled system could be considered lazily designed. If you go through all the trouble of getting to know an IoC framework, you're certainly not taking the shortcut.

我不知道松散耦合的系统如何被认为是懒惰的设计。如果您经历了了解IoC框架的所有麻烦,那么您肯定不会采用这种捷径。

#2


One basic OO principle is that you want your code to depend on interfaces and not implementations, DI is how we do that. Historically, here is how it evolved:

一个基本的OO原则是您希望您的代码依赖于接口而不是实现,DI就是我们如何做到的。从历史上看,这是它的演变过程:

  1. People initially created classes they depended upon by "new'ing" them:

    人们最初通过“新”他们创造了他们依赖的课程:

    IMyClass myClass = new MyClass();

    IMyClass myClass = new MyClass();

  2. Then we wanted to remove instantiation so there were static methods to create them:

    然后我们想删除实例化,所以有静态方法来创建它们:

    IMyClass myClass = MyClass.Create();

    IMyClass myClass = MyClass.Create();

  3. Then we no longer depended on the lifecycle of the class, but still depended on it for instantiation, so then we used the factory:

    然后我们不再依赖于类的生命周期,但仍然依赖它进行实例化,所以我们使用了工厂:

    IMyClass myClass = MyClassFactory.Create();

    IMyClass myClass = MyClassFactory.Create();

  4. This moved the direct dependency from the consuming code to the factory, but we still had the dependency on MyClass indirectly, so we used the service locator pattern like this:

    这将直接依赖于消费代码转移到工厂,但我们仍然间接依赖MyClass,所以我们使用了这样的服务定位器模式:

    IMyClass myClass = (IMyClass)Context.Find("MyClass");

    IMyClass myClass =(IMyClass)Context.Find(“MyClass”);

  5. That way we were only dependent on an interface and a name of a class in our code. But it can be made better, why not depend simply on an interface in our code? We can with dependency injection. If you use property injection you would simply put a property setter for the interface you want in your code. You then configure what the actual dependency is outside of your code and the container manages the lifecycle of that class and your class.

    这样我们只依赖于代码中的接口和类的名称。但它可以做得更好,为什么不简单地依赖我们代码中的接口?我们可以依赖注入。如果使用属性注入,则只需在代码中为所需的接口添加属性设置器。然后,您可以配置代码之外的实际依赖项,容器管理该类和类的生命周期。

#3


I think that ideally, if you already have a loosley coupled system.., using a container will only move the place where you take the dependencies out of your code making them softer and let your system depend on the container building your object graph.

我认为理想情况下,如果你已经有一个loosley耦合系统..,使用容器只会移动你从代码中取出依赖关系的地方,使它们更柔和,让你的系统依赖于容器构建你的对象图。

In reality, attempting to use the the container will probably show you that your system is not as loosley coupled as you thought it was.. so in this way, it may help you to create a better design.

实际上,尝试使用容器可能会向您显示您的系统并不像您想象的那样松散耦合..所以这样,它可以帮助您创建更好的设计。

Well, i'm a newbie at this subjet.. so maybe i'm not that right.

好吧,我是这个子喷气机的新手..所以也许我不对。

Cheers.

#4


I must be high, because I thought the whole point of dependency injection is that the code that does stuff simply declares its dependencies so that someone who's creating it will know what to create with it for it to operate correctly.

我必须高,因为我认为依赖注入的全部意义在于,执行内容的代码只是声明其依赖关系,以便创建它的人知道要用它创建什么才能使其正常运行。

How dependency injection makes you lazy is maybe it forces someone else to deal with dependencies? That's the whole point! That someone else doesn't need to be really someone else; it just means the code you write doesn't need to be concerned with dependencies because it declares them upfront. And they can be managed because they are explicit.

依赖注入如何让你变得懒惰可能会迫使其他人处理依赖关系?这就是重点!别人不需要真正成为别人;它只是意味着你编写的代码不需要关心依赖项,因为它预先声明它们。它们可以被管理,因为它们是明确的。

Edit: Added the last sentence above.

编辑:添加上面的最后一句。

#5


Dependency injection can be a bit difficult to get used to - instead of a direct path through your code, you end up looking at seemingly unconnected objects, and a given action traces it's path through a series of these objects whose coupling seems, to be kind, abstract.

依赖注入可能有点难以习惯 - 而不是通过代码的直接路径,最终看到看似未连接的对象,并且给定的操作跟踪它通过一系列这些对象的路径,这些对象的耦合似乎是友好的,抽象。

It's a paradigm shift similar to getting used to OO. The intention is that your objects are written do have a focused and single responsibility, using the dependent objects as they're declared by the interface and handled by the framework.

这是一种类似于习惯OO的范式转变。目的是编写对象确实具有集中和单一的责任,使用依赖对象,因为它们由接口声明并由框架处理。

This not only makes loose coupling easier, it makes it almost unavoidable, or at least nearly so, which makes it much simpler to do things like run your object in a mock environment - The IOC container is taking the place of the run environment.

这不仅使松散耦合更容易,而且几乎不可避免,或者至少几乎如此,这使得在模拟环境中运行对象更简单 - IOC容器取代了运行环境。

#6


I would disagree and say they lead to better design in many cases. Too often devs create components that do too much and have too many dependencies. With IOC developers i find tend to migrate to a better way of thinking and produce smaller simpler components that can be assembled together into an app.s

我不同意并说它们在许多情况下会带来更好的设计。通常开发人员创建的组件过多且依赖性太大。对于IOC开发人员,我发现他们倾向于转向更好的思维方式,并生成更小的更简单的组件,这些组件可以组合到一个app.s中。

If they follow the spirit and do tests, they will further refine your components. Both exercises force you to write better testable components which fits very well with how IOC containers work.

如果他们遵循精神并进行测试,他们将进一步优化您的组件。这两个练习都迫使您编写更好的可测试组件,这些组件非常适合IOC容器的工作方式。

#7


You still have to worry. My team use Castle Windsor in our current project. It annoys me that it delays dependency lookup from compile time to runtime.

你还是要担心。我的团队在我们当前的项目中使用Castle Windsor。令我很生气的是,它将依赖查找从编译时延迟到运行时。

Without Castle Windsor, you write code and if you haven't sorted your dependencies out. Bang, the compiler will complain. With Castle Windsor you configure the dependencies in an xml file. They're still there, just separated out from the bulk of your code. The problem is, your code can compile fine if you make a mess of defining the dependencies. But, at runtime, Castle Windsor looks up a concrete classes to service requests for an interface by using reflection. If the dependency can't be found, you get an error at runtime.

如果没有Castle Windsor,您可以编写代码,如果您没有对依赖项进行排序。邦,编译器会抱怨。使用Castle Windsor,您可以在xml文件中配置依赖项。它们仍然存在,只是从大部分代码中分离出来。问题是,如果你弄清楚定义依赖项,你的代码可以正常编译。但是,在运行时,Castle Windsor通过使用反射查找具体的类来为接口提供服务请求。如果找不到依赖项,则在运行时会出现错误。

I think Castle Windsor does check the dependencies exist when its initialized so that it can throw an error pretty quick. But, it's still annoying when using a strongly typed language that this fuss can't be sorted out at runtime.

我认为Castle Windsor确实在初始化时检查依赖关系,以便它可以很快地抛出错误。但是,当使用强类型语言时,在运行时无法解决这个问题仍然很烦人。

So... anyway. Dependencies still seriously matter. You'll all most certainly pay more attention to them using DI than before.

所以无论如何。依赖性仍然严重。你们所有人都会比以前更加注意使用DI。

#8


We wrote custom DI framework, thought it took some time getting it right but it all worth the effort. We have divided the who systems into layers and the dependency injection in each layer is bound by rules. E.g. In the Log layer, CUD and BO interfaces cannot be injected.

我们编写了自定义DI框架,认为花了一些时间才能做到正确,但这一切都值得付出努力。我们将who系统划分为多个层,每个层中的依赖注入受规则约束。例如。在Log层中,不能注入CUD和BO接口。

We are still contemplating over the rules and some of these change every week while the others are remain the same.

我们仍在考虑规则,其中一些变化每周都有变化,而其他规则保持不变。

#1


I wouldn't say that you don't have to think about dependencies, but using an IoC framework allows you to change the types which fulfill the dependencies with little or no hassle, since all the wiring is done in a central place.

我不会说你不必考虑依赖关系,但是使用IoC框架可以让你很少或没有麻烦地改变满足依赖关系的类型,因为所有的连线都是在一个中心位置完成的。

You still have to think about what interfaces you need and getting them right is not always a trivial matter.

你仍然需要考虑你需要什么样的接口,并且正确地使用它们并不总是一件小事。

I don't see how a loosely coupled system could be considered lazily designed. If you go through all the trouble of getting to know an IoC framework, you're certainly not taking the shortcut.

我不知道松散耦合的系统如何被认为是懒惰的设计。如果您经历了了解IoC框架的所有麻烦,那么您肯定不会采用这种捷径。

#2


One basic OO principle is that you want your code to depend on interfaces and not implementations, DI is how we do that. Historically, here is how it evolved:

一个基本的OO原则是您希望您的代码依赖于接口而不是实现,DI就是我们如何做到的。从历史上看,这是它的演变过程:

  1. People initially created classes they depended upon by "new'ing" them:

    人们最初通过“新”他们创造了他们依赖的课程:

    IMyClass myClass = new MyClass();

    IMyClass myClass = new MyClass();

  2. Then we wanted to remove instantiation so there were static methods to create them:

    然后我们想删除实例化,所以有静态方法来创建它们:

    IMyClass myClass = MyClass.Create();

    IMyClass myClass = MyClass.Create();

  3. Then we no longer depended on the lifecycle of the class, but still depended on it for instantiation, so then we used the factory:

    然后我们不再依赖于类的生命周期,但仍然依赖它进行实例化,所以我们使用了工厂:

    IMyClass myClass = MyClassFactory.Create();

    IMyClass myClass = MyClassFactory.Create();

  4. This moved the direct dependency from the consuming code to the factory, but we still had the dependency on MyClass indirectly, so we used the service locator pattern like this:

    这将直接依赖于消费代码转移到工厂,但我们仍然间接依赖MyClass,所以我们使用了这样的服务定位器模式:

    IMyClass myClass = (IMyClass)Context.Find("MyClass");

    IMyClass myClass =(IMyClass)Context.Find(“MyClass”);

  5. That way we were only dependent on an interface and a name of a class in our code. But it can be made better, why not depend simply on an interface in our code? We can with dependency injection. If you use property injection you would simply put a property setter for the interface you want in your code. You then configure what the actual dependency is outside of your code and the container manages the lifecycle of that class and your class.

    这样我们只依赖于代码中的接口和类的名称。但它可以做得更好,为什么不简单地依赖我们代码中的接口?我们可以依赖注入。如果使用属性注入,则只需在代码中为所需的接口添加属性设置器。然后,您可以配置代码之外的实际依赖项,容器管理该类和类的生命周期。

#3


I think that ideally, if you already have a loosley coupled system.., using a container will only move the place where you take the dependencies out of your code making them softer and let your system depend on the container building your object graph.

我认为理想情况下,如果你已经有一个loosley耦合系统..,使用容器只会移动你从代码中取出依赖关系的地方,使它们更柔和,让你的系统依赖于容器构建你的对象图。

In reality, attempting to use the the container will probably show you that your system is not as loosley coupled as you thought it was.. so in this way, it may help you to create a better design.

实际上,尝试使用容器可能会向您显示您的系统并不像您想象的那样松散耦合..所以这样,它可以帮助您创建更好的设计。

Well, i'm a newbie at this subjet.. so maybe i'm not that right.

好吧,我是这个子喷气机的新手..所以也许我不对。

Cheers.

#4


I must be high, because I thought the whole point of dependency injection is that the code that does stuff simply declares its dependencies so that someone who's creating it will know what to create with it for it to operate correctly.

我必须高,因为我认为依赖注入的全部意义在于,执行内容的代码只是声明其依赖关系,以便创建它的人知道要用它创建什么才能使其正常运行。

How dependency injection makes you lazy is maybe it forces someone else to deal with dependencies? That's the whole point! That someone else doesn't need to be really someone else; it just means the code you write doesn't need to be concerned with dependencies because it declares them upfront. And they can be managed because they are explicit.

依赖注入如何让你变得懒惰可能会迫使其他人处理依赖关系?这就是重点!别人不需要真正成为别人;它只是意味着你编写的代码不需要关心依赖项,因为它预先声明它们。它们可以被管理,因为它们是明确的。

Edit: Added the last sentence above.

编辑:添加上面的最后一句。

#5


Dependency injection can be a bit difficult to get used to - instead of a direct path through your code, you end up looking at seemingly unconnected objects, and a given action traces it's path through a series of these objects whose coupling seems, to be kind, abstract.

依赖注入可能有点难以习惯 - 而不是通过代码的直接路径,最终看到看似未连接的对象,并且给定的操作跟踪它通过一系列这些对象的路径,这些对象的耦合似乎是友好的,抽象。

It's a paradigm shift similar to getting used to OO. The intention is that your objects are written do have a focused and single responsibility, using the dependent objects as they're declared by the interface and handled by the framework.

这是一种类似于习惯OO的范式转变。目的是编写对象确实具有集中和单一的责任,使用依赖对象,因为它们由接口声明并由框架处理。

This not only makes loose coupling easier, it makes it almost unavoidable, or at least nearly so, which makes it much simpler to do things like run your object in a mock environment - The IOC container is taking the place of the run environment.

这不仅使松散耦合更容易,而且几乎不可避免,或者至少几乎如此,这使得在模拟环境中运行对象更简单 - IOC容器取代了运行环境。

#6


I would disagree and say they lead to better design in many cases. Too often devs create components that do too much and have too many dependencies. With IOC developers i find tend to migrate to a better way of thinking and produce smaller simpler components that can be assembled together into an app.s

我不同意并说它们在许多情况下会带来更好的设计。通常开发人员创建的组件过多且依赖性太大。对于IOC开发人员,我发现他们倾向于转向更好的思维方式,并生成更小的更简单的组件,这些组件可以组合到一个app.s中。

If they follow the spirit and do tests, they will further refine your components. Both exercises force you to write better testable components which fits very well with how IOC containers work.

如果他们遵循精神并进行测试,他们将进一步优化您的组件。这两个练习都迫使您编写更好的可测试组件,这些组件非常适合IOC容器的工作方式。

#7


You still have to worry. My team use Castle Windsor in our current project. It annoys me that it delays dependency lookup from compile time to runtime.

你还是要担心。我的团队在我们当前的项目中使用Castle Windsor。令我很生气的是,它将依赖查找从编译时延迟到运行时。

Without Castle Windsor, you write code and if you haven't sorted your dependencies out. Bang, the compiler will complain. With Castle Windsor you configure the dependencies in an xml file. They're still there, just separated out from the bulk of your code. The problem is, your code can compile fine if you make a mess of defining the dependencies. But, at runtime, Castle Windsor looks up a concrete classes to service requests for an interface by using reflection. If the dependency can't be found, you get an error at runtime.

如果没有Castle Windsor,您可以编写代码,如果您没有对依赖项进行排序。邦,编译器会抱怨。使用Castle Windsor,您可以在xml文件中配置依赖项。它们仍然存在,只是从大部分代码中分离出来。问题是,如果你弄清楚定义依赖项,你的代码可以正常编译。但是,在运行时,Castle Windsor通过使用反射查找具体的类来为接口提供服务请求。如果找不到依赖项,则在运行时会出现错误。

I think Castle Windsor does check the dependencies exist when its initialized so that it can throw an error pretty quick. But, it's still annoying when using a strongly typed language that this fuss can't be sorted out at runtime.

我认为Castle Windsor确实在初始化时检查依赖关系,以便它可以很快地抛出错误。但是,当使用强类型语言时,在运行时无法解决这个问题仍然很烦人。

So... anyway. Dependencies still seriously matter. You'll all most certainly pay more attention to them using DI than before.

所以无论如何。依赖性仍然严重。你们所有人都会比以前更加注意使用DI。

#8


We wrote custom DI framework, thought it took some time getting it right but it all worth the effort. We have divided the who systems into layers and the dependency injection in each layer is bound by rules. E.g. In the Log layer, CUD and BO interfaces cannot be injected.

我们编写了自定义DI框架,认为花了一些时间才能做到正确,但这一切都值得付出努力。我们将who系统划分为多个层,每个层中的依赖注入受规则约束。例如。在Log层中,不能注入CUD和BO接口。

We are still contemplating over the rules and some of these change every week while the others are remain the same.

我们仍在考虑规则,其中一些变化每周都有变化,而其他规则保持不变。