【问题标题】:Which one is better, writing another method or adding one more parameter to an existing method?哪个更好,编写另一种方法或向现有方法添加一个更多参数?
【发布时间】:2019-01-16 04:28:24
【问题描述】:

我有一个方法:

public Question createQuestion(String text, Project project, User createdUser, Date createdDate)

控制器正在使用此方法创建问题。现在参数中没有标签了。我想实现一个向问题添加标签的功能。

要添加标签,我需要将标签集传递给它,当用户在创建问题时未向问题添加标签时,该标签集也可以为空。那么,我应该再向它传递一个参数,然后在将其添加到问题对象之前放置一个if 条件,还是应该编写一个单独的方法?

public Question createQuestionWithTags(String text, Project project, User createdUser, Date createdDate,Set<Tag> questionTagSet)

将调用createQuestion,然后在上述createQuestion() 方法返回的对象中设置questionTagSet。如果我编写另一种方法,则将在控制器中检查空标签,如果没有,则该检查条件将在实用程序中。 哪种方法更好?

另外,在相同的上下文中重载方法怎么样?

【问题讨论】:

  • 当然可以。可惜我没有早点回复。但是在阅读了您的解释后,我选择不去超载。谢谢:)

标签: java model-view-controller methods controller


【解决方案1】:

这个问题可能有很多很好的答案,根据您的具体用例,请记住设计模式(有时反模式是合理的)、最佳实践等,这将使您的代码更好。


也就是说,Question 应该有添加新标签的方法,因为它是具有 tags 属性的类(不是吗?)。你实现它的方式取决于你。可能是这样的:

public class Question {
  // ...
  public void addTags(Set<Tag> questionTagSet) {
    this.tags.addAll(questionTagSet);
  //...
  }
}

这样,无论您有Question 类型的对象,您都可以添加这样的标签:

//...
Set<Tag> tags = new HashSet<>();
Question q = new Question();
q.addTags(tags);
//...

从这一点来看,我认为没有“最佳”选项,而是“适合您的用例的最佳选项”。因此,一种选择是重载(请参阅下面的方法重载了解详细说明),另一种选择是新方法(当然具有不同的签名)。


方法重载:一种方法接收所有参数,另一种方法接收除questionTagSet 之外的所有参数,在那个方法中,您只需通过提供默认值来调用接收所有参数的方法:@987654327 @。现在,在接收questionTagSet 参数的方法中,如果questionTagSet 参数不是null,您将调用Question#addTags 方法。这将允许您使用相同的方法签名,但使用来自控制器的不同参数。因此,您不必检查每个控制器(可能很多),因为您只将检查移动到一个地方:createQuestionWithTags 方法。

类似这样的:

questionTagSet之外的所有参数的方法

public Question createQuestionWithTags(String text, Project project, User createdUser, Date createdDate) {
  return createQuestionWithTags(text, project, createdUser, createdDate, null);
}

带有所有参数的方法

public Question createQuestionWithTags(String text, Project project, User createdUser, Date createdDate,Set<Tag> questionTagSet) {
 Question q = new Question();
 //... some more additional logic here
 if (questionTagSet != null) { //<- logic for adding tags moved here
    q.addTags(questionTagSet);
 }
 return q;
}

如果您想使用 questionTagSet 参数进行一些检查,此实现可能会有所不同。

优点:

  • 您可以从不同的控制器以不同的方式调用方法createQuestionWithTags,而不必担心questionTagSet参数:

    1. utility.createQuestionWithTags("", new Project(), new User(), new Date(), new HashSet&lt;Tag&gt;())

    2. utility.createQuestionWithTags("", new Project(), new User(), new Date(), null)

    3. utility.createQuestionWithTags("", new Project(), new User(), new Date())

缺点

  • 重载有时会很棘手且令人困惑
  • 在进行单元测试时,您需要确定要测试的是哪种方法,因为签名几乎相同。

【讨论】:

  • 我已经在 Question 中有 addTag 方法,我是否应该以另一种方式重载它,比如从带有 questionTagSet 的方法中调用没有 questionTagSet 的方法?
  • @shelholmes221 如果我错了,请纠正我,但是,在没有参数的情况下调用方法 addTags 有什么意义?您是否尝试将Question 中的 tags 属性设置为空集?如果是这样,为什么不默认创建它呢?
  • addtags' 仅当questionTagSet 存在时才会从createQuestion 调用。如果questionTagSet 不存在,则不会调用addTags 。这就是为什么我问我应该在controller(调用实用程序方法)还是utilitycreateQuestion 是)中检查tags
  • @shelholmes221 看到我的答案更新了。此外,如果您认为这变得复杂,并且您有一个 GitHub 存储库供我查看,请告诉我 :)
  • 听起来不错,我想我会创建另一个方法而不是重载,并且只有在标签存在时才会调用新方法,并将 if 条件放在控制器而不是实用程序中,这将使我的单元测试也很容易,因为我只需要测试新方法而不是修改其他方法的现有单元测试。
【解决方案2】:

老实说,考虑到重载的复杂程度(JLS wise),我很难接受它。我的意思是看功能接口和重载(甚至在这个网站上搜索相关问题,看看人们有时是如何拉扯他们的头发的——包括我在内)。但这不仅仅与 lambdas 相关,重载被一些人认为过于复杂且很少需要,例如 this

您对这些方法的重命名是实现您所拥有的任务的最简洁的方法(除非您认为可能是构建器模式)。

【讨论】:

    【解决方案3】:

    这是Builder Pattern 的理想人选。在Question 中声明一个构建器,使用Fluent Interface Pattern 设置参数,最后调用build() 以实例化适当构造的具体Question 实例。它看起来像:

    Question.builder().withText(text).withProject(project).build();
    

    需要指定一组标签的事件将在调用build()之前为上述代码提供后缀,并调用withTags(tags)

    【讨论】:

      猜你喜欢
      • 2017-03-01
      • 2012-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-05
      • 2012-02-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多