Обнаружить изменение значения объекта, переданного в качестве параметра

StackOverflow https://stackoverflow.com/questions/545779

  •  23-08-2019
  •  | 
  •  

Вопрос

Сейчас я работаю с кодом, который выглядит так

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

Я считаю, что изменять объекты, передаваемые в качестве параметров, — плохая практика.Есть ли инструмент, который обнаруживает такой код?Я просмотрел findbugs, pmd и checkstyle, но не нашел никакой проверки.

P.S.извините за плохой пример.

Это было полезно?

Решение

Думаю, вы уже на правильном пути:ваш лучший инструмент для обнаружения такого рода кода почти наверняка Найти ошибки.Однако вам, вероятно, придется написать свой собственный детектор для этого паттерна. Вот пример о том, как написать детектор, хотя это не совсем тот детектор, который вам нужен.

Предостережение:Я не совсем согласен с тем, что геттер с побочным эффектом — это всегда плохой стиль.Однако, если вы действительно хотите найти что-то подобное, я бы порекомендовал Findbugs.

Другие советы

Вы ничего не найдете, потому что с точки зрения инструмента «getName» и «setSth» — это просто вызовы методов.Люди говорят «это геттер» и «это сеттер», но инструменты этого не делают.Фактически, getName() не является методом получения, поскольку методы получения не принимают аргументы.

Таким образом, инструмент не видит ничего необычного, поскольку методы постоянно меняют объекты.

Если вы хотите обеспечить соблюдение этого правила, взгляните на расширение findbugs и PMD.Оба позволяют вам определять дополнительные ограничения.Вероятно, вы ищете:

  • Если имя метода начинается с «get»
  • И тело метода вызывает метод любого объекта, передаваемого в качестве параметра

затем распечатайте предупреждение.Это не должно занять слишком много времени.Запустите это, и вы увидите, сколько «ложных срабатываний» вы получите (предупреждения о методах, которые на самом деле хороши).Это поможет вам определить, стоит ли заниматься этим дальше.Кроме того, у вас появится новая позиция в вашем резюме :)

Вы могли бы сделать 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, ...классы тоже так делают.

Вы можете создать интерфейс UserView, содержащий только «геттеры», заставить пользователя реализовать его и использовать новый интерфейс UserView в качестве типа параметра.

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

class User implements UserView...

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

На самом деле это то, что в C++ было очень легко сделать с помощью const квалификатор.Вы должны определить параметр как const и для этого параметра вы можете вызывать только методы, определенные как const - обычно, добытчики.

В Java этого нет и, честно говоря, я не особо против.Как уже упоминалось, существуют анализаторы исходного кода, которые могут проверить такое поведение, а также методы метапрограммирования, позволяющие сделать это.

Лично я верю, что если метод назван правильно, нет проблем с передачей ему объекта для его изменения.

Существуют инструменты, которые могут «размышлять» о коде на более высоком уровне, чем это обычно делают компиляторы.Например, декларативное метапрограммирование — это дисциплина, которая позволяет писать программы для проверки соответствия другой программы определенному дизайну или, наоборот, для поиска запахов кода и антишаблонов.

Некоторые ссылки:

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=Декларативное+Метапрограммирование

Вы ищете что-то вроде «const» в C++, которое обеспечит сделать значение параметра таким же неизменным, как и переданная ссылка.Неизменяемые объекты гарантируют это, если вы можете с ними жить.

Вы утверждаете, что это «плохо», потому что подобные побочные эффекты могут удивить пользователя.Это действительно так, но это вредно только в том случае, если это нежелательный сюрприз.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top