检测作为参数传递的对象的更改值

时间:2009-02-13 12:46:03

标签: java findbugs checkstyle pmd

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

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

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

P.S。抱歉的坏例子。

7 个答案:

答案 0 :(得分:2)

你找不到任何东西,因为从工具的角度来看,“getName”和“setSth”只是方法调用。人类说“这是一个吸气剂”和“这是一个制定者”,但工具却没有。实际上,getName()不是getter,因为getter不接受参数。

因此,该工具无法看到任何异常,因为方法始终会更改对象。

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

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

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

答案 1 :(得分: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;
}

内置的StringInteger,...类也可以这样做。

答案 2 :(得分:2)

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

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

答案 3 :(得分:1)

您可以创建一个名为UserView的界面,仅包含“getters”,让用户实现它并使用新的UserView界面作为参数类型。

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

class User implements UserView...

public String getName(UserView user) {
     user.setSth(...); // Will not compile
     return user.getName();
}

答案 4 :(得分:1)

实际上,这是通过const限定符在C ++中很容易实现的。您可以将参数定义为const,对于该参数,您只能调用定义为const的方法 - 通常是getters。

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

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

答案 5 :(得分: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=Declarative+Metaprogramming

答案 6 :(得分:0)

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

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