检测作为参数传递的对象的变化值

发布于 2024-07-14 00:55:36 字数 258 浏览 14 评论 0原文

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

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

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

PS 抱歉举了个不好的例子。

I'm now working with code that looks like this

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

I think it's bad practice to change objects passed as parameters. Is there a tool that detects that kind of code? I looked at findbugs, pmd and checkstyle, but could not find any check for this.

P.S. sorry for bad example.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

七七 2024-07-21 00:55:36

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

警告:我不太同意副作用吸气剂总是不好的风格。 然而,如果你真的想找到这类东西,我会推荐 Findbugs。

I think you are already on the right track: your best tool to detect this sort of code is almost certainly Findbugs. However, you will probably need to write your own detector for this pattern. Here is an example of how you would write a detector, though it isn't exactly the detector that you're looking for.

Caveat: I don't really agree that a side-effecting getter is always bad style. However, if you really want to find that sort of thing, I would recommend Findbugs.

空宴 2024-07-21 00:55:36

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

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

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

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

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

You won't find anything because, from a tool's point of view, "getName" and "setSth" are just method calls. Humans say "this is a getter" and "this is a setter" but tools don't. In fact, getName() is not a getter because getters don't accept arguments.

So the tool can't see anything unusual because methods change objects all the time.

If you want to enforce this rule, have a look at extending findbugs and PMD. Both allow you to define additional constraints. What you're looking for is probably:

  • If method name starts with "get"
  • AND method body calls method of any object passes as parameter

then print a warning. That shouldn't take too long. Run this and you will see how many "false positives" you get (warnings about methods which are actually OK). This will help you determine whether it's worth to pursue this further. Plus you'll have a new item to add to your CV :)

但可醉心 2024-07-21 00:55:36

您可以使 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、...课程也能做到这一点。

You could make User immutable (declare it final, declare all properties final and remote the setters. I know that isn't practible everywhere but in many places that is good and you will have no problems in passing that to other functions).

If you have to "change" something, you can implement functions like newId in that sample:

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;
}

The built in String, Integer, ... classes do that, too.

莫多说 2024-07-21 00:55:36

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

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

class User implements UserView...

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

You can create an interface called UserView containing only "getters", make User implement it and use the new UserView interface as the type of parameter.

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

class User implements UserView...

public String getName(UserView user) {
     user.setSth(...); // Will not compile
     return user.getName();
}
叹梦 2024-07-21 00:55:36

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

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

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

Actually this is something that in C++ was very easy to do via the const qualifier. You would define a parameter as const and for that parameter you could only call methods defined as const - usually, getters.

In Java this is absent and frankly, I don't really mind. As mentioned there are source code analyzers which can check this behavior, as well as meta-programming methods to do this as well.

Personally, I believe that if the method is named properly, there is no problem of passing an object to it so that is it modified.

爱你不解释 2024-07-21 00:55:36

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

一些链接:

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

There are tools that can "reason" about code on a higher level than compilers typically do. Declarative Metaprogramming for example is a discipline that allows writing programs to check if another program conforms to a certain design, or, conversely, to mine for code smells and anti-patterns.

Some links:

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

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

and for the rest

http://www.google.com/search?num=100&hl=en&q=Declarative+Metaprogramming

忆悲凉 2024-07-21 00:55:36

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

您认为这是“坏”的,因为这样的副作用可能会让用户感到惊讶。 这是有效的,但只有当它是一个不想要的惊喜时才有害。

You're looking for something like "const" in C++ that will enforce making the parameter value as immutable as the reference that's passed in. Immutable objects guarantee that, if you can live with them.

You're arguing that this is "bad" because side effects like this can surprise a user. That's valid, but it's only harmful if it's an unwanted surprise.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文