4

我现在正在使用看起来像这样的代码

public String getName(User user) {
     user.setSth(...);
     return user.getName();
}

我认为更改作为参数传递的对象是不好的做法。是否有检测这种代码的工具?我查看了 findbugs、pmd 和 checkstyle,但找不到任何检查。

PS对不起不好的例子。

4

7 回答 7

3

我认为您已经走在正确的轨道上:检测此类代码的最佳工具几乎肯定是Findbugs。但是,您可能需要为此模式编写自己的检测器。 这是一个如何编写检测器的示例,尽管它并不完全是您正在寻找的检测器。

警告:我真的不同意具有副作用的吸气剂总是不好的风格。但是,如果您真的想找到那种东西,我会推荐 Findbugs。

于 2009-02-13T13:36:18.570 回答
2

您将找不到任何东西,因为从工具的角度来看,“getName”和“setSth”只是方法调用。人类会说“这是一个 getter”和“这是一个 setter”,但工具不会。事实上,getName() 不是一个 getter,因为 getter 不接受参数。

因此该工具看不到任何异常,因为方法一直在更改对象。

如果您想强制执行此规则,请查看扩展 findbugs 和 PMD。两者都允许您定义额外的约束。您正在寻找的可能是:

  • 如果方法名称以“get”开头
  • AND 方法体调用任何对象的方法作为参数传递

然后打印警告。这不应该花太长时间。运行此程序,您将看到有多少“误报”(有关实际可行的方法的警告)。这将帮助您确定是否值得进一步追求。另外,您将有一个新项目添加到您的简历中:)

于 2009-02-13T12:58:29.740 回答
2

您可以使其User不可变(声明它final,声明所有属性final并远程设置设置器。我知道这并非在任何地方都可行,但在许多地方都很好,并且将其传递给其他函数不会有任何问题)。

如果您必须“更改”某些内容,则可以实现newId该示例中的功能:

public final class User {
    private final String name;
    private final int id;

    User(String name, int id) {
        this.name = name;
        this.id = id;
    }

    public User newId(int newId) {
        return new User(this.name, newId);
    }

    //getters here;
}

内置的String, Integer, ... 类也可以做到这一点。

于 2009-02-13T13:33:50.667 回答
1

您可以创建一个名为 UserView 的仅包含“getter”的接口,让 User 实现它并使用新的 UserView 接口作为参数类型。

interface UserView{
 public String getName();
...

class User implements UserView...

public String getName(UserView user) {
     user.setSth(...); // Will not compile
     return user.getName();
}
于 2009-02-13T13:11:45.823 回答
1

实际上,这在 C++ 中通过const限定符很容易做到。您将定义一个参数,const并且对于该参数,您只能调用定义为的方法const- 通常是 getter。

在 Java 中,这是不存在的,坦率地说,我并不介意。如前所述,有可以检查此行为的源代码分析器,以及执行此操作的元编程方法。

就个人而言,我相信如果方法命名正确,将对象传递给它是没有问题的,以便对其进行修改。

于 2009-02-13T13:32:29.953 回答
0

有些工具可以在比编译器通常所做的更高级别上“推理”代码。例如,声明性元编程是一门学科,它允许编写程序来检查另一个程序是否符合某种设计,或者相反,可以挖掘代码异味和反模式。

一些链接:

http://prog.vub.ac.be/DMP/

http://www.cs.bris.ac.uk/Publications/pub_master.jsp?id=1000273

其余的

http://www.google.com/search?num=100&hl=en&q=声明式+元编程

于 2009-02-13T13:10:54.700 回答
0

您正在 C++ 中寻找类似“const”的东西,它将强制使参数值与传入的引用一样不可变。不可变对象保证,如果您可以使用它们。

您认为这是“不好的”,因为这样的副作用会让用户感到惊讶。这是有效的,但只有当它是一个不受欢迎的惊喜时才会有害。

于 2009-02-13T13:31:32.700 回答