Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为了重构的目的,有一个只包含属性的类可以吗?_C#_Oop_Refactoring - Fatal编程技术网

C# 为了重构的目的,有一个只包含属性的类可以吗?

C# 为了重构的目的,有一个只包含属性的类可以吗?,c#,oop,refactoring,C#,Oop,Refactoring,我有一个需要30个参数的方法。我将参数放入一个类中,这样我就可以将一个参数(类)传递到方法中。在重构的情况下,传入一个封装了所有参数的对象,即使它只包含了所有参数,这也很好。这是一个好主意。例如,它通常是在WCF中执行数据契约的方式 此模型的一个优点是,如果您添加了一个新参数,则类的使用者不需要仅仅为了添加参数而进行更改 正如David Heffernan提到的,它可以帮助自己记录代码: FrobRequest frobRequest = new FrobRequest { FrobTa

我有一个需要30个参数的方法。我将参数放入一个类中,这样我就可以将一个参数(类)传递到方法中。在重构的情况下,传入一个封装了所有参数的对象,即使它只包含了所有参数,这也很好。

这是一个好主意。例如,它通常是在WCF中执行数据契约的方式

此模型的一个优点是,如果您添加了一个新参数,则类的使用者不需要仅仅为了添加参数而进行更改

正如David Heffernan提到的,它可以帮助自己记录代码:

FrobRequest frobRequest = new FrobRequest
{
    FrobTarget = "Joe",
    Url = new Uri("http://example.com"),
    Count = 42,
};
FrobResult frobResult = Frob(frobRequest);

这是一个很好的想法,也是解决这个问题的一个非常普遍的办法。超过2或3个参数的方法越来越难以理解

将所有这些封装在一个类中可以使代码更加清晰。由于属性具有名称,因此可以编写如下自文档代码:

params.height = 42;
params.width = 666;
obj.doSomething(params);
当然,当您有很多参数时,基于位置标识的替代方案非常可怕


另一个好处是,在接口契约中添加额外的参数可以在不强制所有调用站点进行更改的情况下完成。然而,这并不总是像它看起来那么琐碎。如果不同的调用站点需要不同的新参数值,那么与基于参数的方法相比,更难找到它们。在基于参数的方法中,添加一个新的参数迫使每个调用站点的一个改变来提供新的参数,并且可以让编译器执行找到它们的工作。

也可以考虑使用结构而不是类。


但是你所尝试的是一个非常普遍和伟大的想法

30个参数太乱了。我认为拥有一个具有属性的类更漂亮。您甚至可以为属于同一类别的参数组创建多个“参数类”。

这里的其他答案正确地指出,传递一个类的实例比传递30个参数要好,但请注意,大量参数可能是潜在问题的症状

例如,很多时候静态方法的参数数量都在增加,因为它们一直都应该是实例方法,并且您正在传递大量信息,这些信息可以更容易地在该类的实例中维护

或者,寻找将参数分组到更高抽象级别的对象中的方法。在IMO中,将一堆不相关的参数转储到单个类中是最后的手段


有关这方面的更多想法,请参阅。

马丁·福勒在其著作《重构》中称之为重构。有了这样的引用,很少有人会说这是一个坏主意。

虽然重构到参数对象本身并不是一个坏主意,但它不应该被用来隐藏一个问题,即一个需要从其他地方提供30条数据的类仍然可能是一种代码味道。引入参数对象重构可能应该被视为更广泛的重构过程中的一个步骤,而不是该过程的结束

它没有真正解决的一个问题是功能嫉妒。传递参数对象的类对另一个类的数据如此感兴趣,这一事实是否表明可能应该将对该数据进行操作的方法移动到数据所在的位置?识别属于一起的方法和数据的集群并将它们分组到类中,从而提高封装性并使代码更加灵活,这样做确实更好


在多次将行为和它所操作的数据分解为单独的单元之后,您应该发现,您不再有任何具有大量依赖项的类,这总是一个更好的最终结果,因为它将使您的代码更加灵活。

这是一个好的开始。但是现在你已经有了新的课程,考虑把你的代码翻出来。将该类作为参数的方法移动到新类中(当然,将原始类的实例作为参数传递)。现在你有了一个大的方法,单独在一个类中,把它分解成更小的、更易管理的、可测试的方法会更容易。其中一些方法可能会移回原始类,但相当一部分可能会留在新类中。你已经超越了过去


拥有一个包含30个参数的方法是一个非常明显的迹象,表明该方法太长、太复杂。太难调试,太难测试。因此,您应该对此采取一些措施,引入参数对象是一个很好的起点。

无论您是否正在重构,使用类都是合理的。我很好奇为什么您认为它可能不是。

也许C#4.0的可选和命名参数是一个很好的替代方案

无论如何,您描述的方法也可以很好地抽象程序的行为。例如,您可以在接口中使用一个标准的
SaveImage(ImageSaveParameters saveParams)
-函数,其中
ImageSaveParameters
也是一个接口,并且可以根据图像格式使用其他参数。例如,
JpegSaveParameters
具有
Quality
-属性,而
PngSaveParameters
具有
BitDepth
-属性


这就是Paint.NET中的“保存”对话框的工作方式,因此它是一个非常真实的示例

> P>正如前面所说:这是正确的步骤,但也要考虑以下几点:

    你的方法可能太复杂了(你应该考虑把它分成更多的方法,甚至把它变成一个单独的类)
  • 如果为参数创建类,请将其设置为
  • 如果许多参数可能为null或可能具有某些默认值,则可能希望对类使用

    • 这里有这么多很棒的答案。我想加上我的两分钱<
      def display_line(startPoint, endPoint, option1, option2)
      
      def display_line(line, display_options)
      
      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