混合基于构造器和基于setter的注射是坏事吗? [英] Is mixing constructor-based and setter-based injections a bad thing?

查看:104
本文介绍了混合基于构造器和基于setter的注射是坏事吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个CSV文件操作产品导入类,需要大约7个参数。这是进口商绝对需要的信息。



所有这些参数都有相同的使用寿命。最后我们必须有一个不可变对象


$ b $我很害怕在构造函数中列出所有这些,因为它对可读性的影响,并决定将其中3个移动到setters注入。但是显然这不是一个优雅的解决方案。



问题:



1)混合构造函数和setter-基础注射是不好的做法?



2)这个特殊问题如何解决?



我在想应用Martin Fowler的引用参数对象重构,但是有一个问题。



4可以很容易地将参数移动到Parameter对象(customerId,projectId,languageId等等) - 所有整数。



其他3个参数是我注入的对象(这是Mock单元测试所需的)。

解决方案

混合构造函数注入和属性注入不一定是坏事,但可能并不常见。作为一个总体策略,避免物业注入,因为要更正确地实施这个难点(这可能听起来很直观,但是这是真的)。​​



了解什么时候使用每个模式。




  • 构造函数注入应该是您的默认注入模式。实现它非常简单,可以保证不变量:将其分配给只读字段以确保消费者的不变量。

  • 当您拥有良好的本地时,可以使用属性注入默认实现,但您要遵循开放/封闭原则,并允许高级用户通过提供替代实现来扩展课程。



由于构造器化妆品,您不应该应用属性注入。

当您需要太多的依赖关系时,这可能表示您可能违反了单一责任原则 - 课堂只是一次尝试太多。



而不是引入参数对象(否则是一个好的建议),一个更好的选择是封装两个或更多的依赖nices转换为聚合服务,以协调这些依赖关系的交互。



想象一下,您的初始构造函数如下所示:

  public MyClass(IDep1 dep1,IDep2 dep2,IDep3 dep3,IDep4,dep4,IDep5 dep5)
pre>

在应用了一点分析之后,您会发现在这种情况下, IDep1,IDep3和IDep4将以特定方式一起使用。这将允许您引入一个封装这样的聚合服务:

  public class AggService:IAggService 
{
public AggService(IDep1 dep1,IDep3 dep3,IDep4 dep4)
{
// ...
}

// ...
}

现在可以将原始构造函数重写为:

  public MyClass(IAggService aggSrvc,IDep2 dep2,IDep5 dep5)

等等...



这是非常常见的总体服务是自己的一个正确的概念,突然你比开始时有更丰富的API。


I have a class for products import from CSV file operation which requires about 7 parameters. This is an info which is definitely needed for importer.

All of this parameters have the same life time. In the end we must have an Immutable Object.

I was too scared to list all of them in constructor because of its affect to readability and decided to move 3 of them to setters injection. But obviously it's not an elegant solution.

Questions:

1) Is mixing constructor-based and setter-based injections a bad practice?

2) How this particular problem can be solved?

I was thinking about applying "Introduce Parameter Object" refactoring by Martin Fowler, but there is a problem with this.

4 Parameters can be moved to Parameter object quite easily (customerId, projectId, languageId etc.) - all integers.

Other 3 parameters are an object I inject(it is required for Mock unit-tests).

解决方案

It's not necessarily a bad thing to mix Constructor Injection and Property Injection, but it may not be that common. As an overall strategy, avoid Property Injection since it's much more difficult to implement correctly (this may sound counter-intuitive, but it's true).

It's important to understand when to use each pattern.

  • Constructor Injection should be your default injection pattern. It's super-easy to implement and can guarantee invariants: assign it to a read-only field to ensure the consumer's invariants.
  • Property Injection can be used when you have a good Local Default implementation, but you want to follow the Open/Closed Principle and allow advanced users to extend the class by providing an alternative implementation.

You should never apply Property Injection because of constructor cosmetics.

When you require too many dependencies, it's a sign that you may be violating the Single Responsibility Principle - the class is simply trying to do too much at once.

Instead of introducing a Parameter Object (otherwise a good suggestion), a better option is to encapsulate two or more of the dependencies into an aggregating service that orchestrates the interaction of these dependencies.

Imagine that your initial constructor looks like this:

public MyClass(IDep1 dep1, IDep2 dep2, IDep3 dep3, IDep4, dep4, IDep5 dep5)

After applying a bit of analysis, you figure out that in this case IDep1, IDep3 and IDep4 will be used together in a particular way. This will allow you to introduce an aggregation service that encapsulated these like this:

public class AggService : IAggService
{
    public AggService(IDep1 dep1, IDep3 dep3, IDep4 dep4)
    {
        // ...
    }

    // ...
}

You can now rewrite the original constructor to this:

public MyClass(IAggService aggSrvc, IDep2 dep2, IDep5 dep5)

and so forth...

It is very common that the aggregate service turns out to be a proper concept in it's own right, and suddenly you have a richer API than when you started.

这篇关于混合基于构造器和基于setter的注射是坏事吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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