如何用很多参数重构类的方法?

Posted

技术标签:

【中文标题】如何用很多参数重构类的方法?【英文标题】:How to refactor method of class with a lot of arguments? 【发布时间】:2011-03-03 21:53:12 【问题描述】:

大家我对 ASP.NET MVC 应用程序中的旧代码有疑问, 在这段代码中,业务逻辑层中有一个类 Service。此类具有带有 20 个参数的方法,此方法使用这 20 个参数创建对象实例。 如何重构这段代码,因为当创建的对象改变时,这是一个问题,需要改变方法中的参数。 该服务类用于控制器类和单元测试。 帮我重构这段代码 提前致谢。

编辑附加信息:

我可以显示方法的签名

public Qualification CreateQualification(string achievableCode, string achievableTitle,
        string accreditationRef, bool brandingPrefix, long brand, float guidedLearningHours, 
        int creditValue, long level, long type, long gradingType, long area, int subArea,
        DateTime accreditationStartDate, DateTime accreditationEndDate,
        DateTime lastCertDate, string nameOnCert, 
        long organisationId)

我认为需要应用 Kely 和 Chevex 方法,例如我可以提取一些类

一个来自参数:

 long area, int subArea

其他

bool brandingPrefix, long brand,

提取子类后,我可以使用我正确理解的 Introduce Parameter Object 吗?

【问题讨论】:

+1,但是 ASP.Net MVC 什么时候成为传统的 :) 也许他指的是遗产,就像 Michael Feathers 在他的书 Working Effectively with Legacy Code (see modern interpretations section) 中所做的那样。 我说的是遗留代码我的意思是该代码是很久以前由其他开发人员编写的,此代码在 ASP.NET MVC 应用程序中 【参考方案1】:

创建一个对象来保存这 20 个参数并将该对象传递给方法。

例如:

public void MyMethod(MyArguments args)

    // do stuff

编辑

虽然这种模式可能对一次性重构有用,但如果您发现自己在多个方法中使用相同的参数,请考虑Chevex's 答案。这是更好的方法。

【讨论】:

不,这被称为Introduce Parameter Object 重构。 这很愚蠢,因为你必须在一个单独的对象上设置 20 个参数。这是同一件事,只是抽象了一点,以便作品与原始作品不同。与其将它们捆绑在一起,不如考虑我的答案,即识别相关值并将它们分解出来。 IMO 这比将所有参数塞进一个参数对象要好。挑选出可能组合在一起的数据,并将这些数据单独分解到自己的对象中。 我同意雪佛兰。这是事件处理程序(例如EventArgs)所采用的模式。真正的封装是更好的方法。 @Chevex - 你是对的,这门课一开始可能做得太多了。但是当红/绿重构时,最简单的改变是将它们捆绑到一个对象中。完成这些测试后,请考虑将关注点分离为单个对象和单个参数。 是的,Serghei,随着您对正在从事的项目积累经验,请尝试确定哪些价值观可以结合在一起,并以单独对象的形式为它们提供自己的家。【参考方案2】:

您可能会尝试识别参数中的相关数据并将它们分解到它们自己的自定义对象中。例如,假设你有这个对象:

public class Person

    public Person(string firstName, string lastName, int age,
        string streetAddress, string city, string state, int zipCode)
    
        this.FirstName = firstName;
        this.LastName = lastName;
        this.Age = age;
        this.StreetAddress = streetAddress;
        this.City = city;
        this.State = state;
        this.ZipCode = zipCode;
    

    public string FirstName  get; set; 
    public string LastName  get; set; 
    public int Age  get; set; 
    public string StreetAddress  get; set; 
    public string City  get; set; 
    public string State  get; set; 
    public int ZipCode  get; set; 

尝试将其重构为两个类,将相关的地址信息提取到它自己的类中,然后将该对象添加为原始对象的属性:

public class Person

    public Person(string firstName, string lastName, int age, Address address)
    
        this.FirstName = firstName;
        this.LastName = lastName;
        this.Age = age;
        this.Address = address;
    

    public string FirstName  get; set; 
    public string LastName  get; set; 
    public int Age  get; set; 
    public Address Address  get; set; 


public class Address

    public Address(string streetAddress, string city, string state, int zipCode)
    
         this.StreetAddress = streetAddress;
         this.City = city;
         this.State = state;
         this.ZipCode = zipCode;
    

    public string StreetAddress  get; set; 
    public string City  get; set; 
    public string State  get; set; 
    public int ZipCode  get; set; 

如果没有更多信息,我会说这是您最好的方法。

【讨论】:

Chevex-谢谢,这是提取子类的好主意,但问题是我不知道如何准确地将不同类中的参数分组。 不客气。我想这将是您必须通过经验和与项目领域专家的沟通来回答的问题。【参考方案3】:

使用Builder 模式

QualificationBuilder builder = new QualificationBuilder();
builder.setAchievableCode(achievableCode)
       .setAchievableTitle(achievableTitle)...
Qualification = builder.build();

【讨论】:

这是一个很好的方法,但是从 20 个参数中,8 个是创建 Qualification 对象的必填字段。这个怎么用builder实现的?

以上是关于如何用很多参数重构类的方法?的主要内容,如果未能解决你的问题,请参考以下文章

PHP 多参数方法的重构

如何用 Java 编写 AWS Lambda 来使用查询字符串参数?

Python如何用列表向类传参?急!在线等!

在html页面中如何用js调用java类

java中,如何用POST方法将参数传递给第三方网站

在c++中如何用new生成一个构造函数带参数的类数组?