【发布时间】:2011-08-31 11:02:06
【问题描述】:
我们的域模型中有一些对象,您可笑地称之为 冒犯性 大型构造函数,如此之大以至于 IntelliSense 放弃了向您展示所有内容的尝试。 ..
用 50 个左右的参数提示一个类型,主要是值类型,一些引用类型:
public class MyLegacyType
{
public MyLegacyType(int a1, int a2, int a3, ... int a50) // etc
{
}
}
我现在就说,不,这种类型不能改变。类型本身在逻辑上代表一个实体,它恰好是重属性的。构造此类型的调用者提供来自多个来源的大部分参数,尽管有些是默认的。也许有一种模式可以将源提供给构造而不是结果。
但是,可以改变的是类型的创建方式。目前我们有部分代码存在以下问题:
- 类型缺少 IntelliSense。
- 丑陋且不可读的代码。
- 由于Connascence of Position合并的痛苦。
一个直接的答案是使用可选参数作为默认值和命名参数来帮助合并。我们在某种程度上对其他类型这样做,工作正常。
然而,感觉这似乎是完全重构的一半。
另一个明显的解决方案是使用容器类型来减少构造函数参数,这些容器类型具有过去是构造函数参数的属性。这很好地整理了构造函数,并允许您在容器中嵌入默认值,但本质上将问题转移到另一种类型上,并且可能与可选/命名参数用法相同。
还有 Fluent 构造函数的概念……基于每个属性(WithIntA、WithIntB)或容器类型(WithTheseInts(IntContainer c))。就个人而言,我喜欢调用方的这种方法,但是在大字体上它又会变得冗长,感觉好像我只是移动了一个问题而不是解决一个问题。
我的问题是:这些是解决问题的可行重构策略吗?请用一些相关的经验、陷阱或批评来充实任何答案。我倾向于使用 Fluent 的东西,因为我认为它看起来很酷,而且可读性强且易于合并。
我觉得我好像错过了构造函数重构的圣杯——所以我愿意接受建议。当然,这也可能是一个不幸且不可避免的副作用,即首先拥有具有这么多属性的类型...
【问题讨论】:
-
对于可选的构造函数参数,我会采用您的第二种方法(具有用于过去构造函数参数的属性的容器类型)。流利的接口很好,但如果你必须链接很多方法调用 IMO 会变得有点混乱
标签: c# c#-4.0 refactoring