我有一个采用30个参数的方法。我将参数放入一个类中,这样我就可以将一个参数(该类)传递给方法。在重构的情况下,传递封装了所有参数的对象(即使它包含了所有参数)是否完美?
我有一个采用30个参数的方法。我将参数放入一个类中,这样我就可以将一个参数(该类)传递给方法。在重构的情况下,传递封装了所有参数的对象(即使它包含了所有参数)是否完美?
Answers:
这是一个好主意。例如,通常是在WCF中完成数据合同的方式。
该模型的一个优点是,如果添加新参数,则该类的使用者不需要更改即可仅添加参数。
正如David Heffernan所提到的,它可以帮助自己编写代码:
FrobRequest frobRequest = new FrobRequest
{
FrobTarget = "Joe",
Url = new Uri("http://example.com"),
Count = 42,
};
FrobResult frobResult = Frob(frobRequest);
尽管这里的其他答案正确地指出,传递类的实例比传递30个参数更好,但是请注意,大量参数可能是潜在问题的征兆。
例如,很多时候静态方法的参数数量会增加,因为它们应该一直是实例方法,并且您传递了很多信息,这些信息可以更轻松地在该类的实例中维护。
或者,寻找将参数分组为更高抽象级别的对象的方法。IMO不得已将一堆不相关的参数转储到一个类中。
请参阅多少个参数太多?有关此的更多想法。
虽然重构为参数对象本身并不是一个坏主意,但不应将其用于隐藏这样的问题:需要从其他地方提供的30条数据的类仍然可能有点代码味道。引入参数对象重构应该被认为是更广泛的重构过程中的一个步骤,而不是该过程的结束。
不能真正解决的问题之一就是Feature Envy。通过参数对象传递的类对另一个类的数据如此感兴趣的事实,是否并不表示也许对该数据进行操作的方法应该移到数据所在的位置?最好识别属于同一类的方法和数据并将它们分组为类,从而增加封装并使代码更灵活。
在将行为及其所处理的数据分成单独的单元进行了几次迭代之后,您应该发现您不再拥有具有大量依赖关系的类,这总是一个更好的最终结果,因为它会使您的代码更加柔软。
这是一个绝妙的主意,也是解决该问题的非常普遍的解决方案。参数超过2或3的方法越来越难以理解。
将所有这些封装在一个类中可以使代码更加清晰。因为您的属性具有名称,所以您可以像下面这样编写自记录代码:
params.height = 42;
params.width = 666;
obj.doSomething(params);
自然,当您有很多参数时,基于位置标识的替代方法简直就是恐怖。
另一个好处是,可以在不强制所有呼叫站点进行更改的情况下,向接口协定中添加额外的参数。但是,这并不总是看起来那么琐碎。如果不同的呼叫站点需要不同的新参数值,那么与使用基于参数的方法相比,很难找到它们。在基于参数的方法中,添加新参数会强制每个调用站点进行更改以提供新参数,并且您可以让编译器完成查找所有参数的工作。
您也可以考虑使用结构而不是类。
但是,您要尝试做的事情很常见,也是个好主意!
无论您是否重构,使用Plain Old Data类都是合理的。我很好奇你为什么不这样认为。
这里有很多很棒的答案。我要加两分钱。
参数对象是一个好的开始。但是还有更多可以做的事情。考虑以下(红宝石示例):
/ 1 /而不是简单地对所有参数进行分组,而是查看是否可以对参数进行有意义的分组。您可能需要多个参数对象。
def display_line(startPoint, endPoint, option1, option2)
可能成为
def display_line(line, display_options)
/ 2 /参数对象的属性数量可能少于原始参数数量。
def double_click?(cursor_location1, control1, cursor_location2, control2)
可能成为
def double_click?(first_click_info, second_click_info)
# MouseClickInfo being the parameter object type
# having cursor_location and control_at_click as properties
这样的用法将帮助您发现向这些参数对象添加有意义的行为的可能性。您会发现他们可以更快地摆脱最初的Data Class气味,从而使您感到舒适。:-)