Должны ли перечисляемые объекты быть без гражданства?

Поскольку по замыслу константа перечисления в java является одноэлементной, и ради одновременного использования я обычно создаю экземпляры перечисления без сохранения состояния и использую параметры метода для ввода данных по мере необходимости.

Пример:

В настоящее время я создаю службу REST с операциями (реализованными как перечисление с использованием варианта шаблона стратегии).

public enum Operation {

  DO_THIS() {
    public Result doSomething(Object theData) {
    }
  } ,
  // Other Operations go here
  ;

  public abstract Result doSomething(Object theData);

}

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

Я мог бы сохранить состояние извне при использовании экземпляра enum, но скорее кажется, что состояние должно быть сохранено в операции, поскольку операция должна содержать свое собственное состояние.

Теперь мой общий вопрос:

Является ли экземпляр перечисления с отслеживанием состояния (помимо проблем параллелизма) плохой схемой?


person Daniel Hiller    schedule 12.02.2009    source источник
comment
без вопросов, да.   -  person user924272    schedule 23.05.2017


Ответы (8)


Я думаю, что это нарушает принцип наименьшего удивления.

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

person mparaz    schedule 12.02.2009
comment
В отличие от этого члены перечисления действительно являются экземплярами объекта Java первого класса, поэтому они могут иметь методы и переменные. Так может быть, весь дизайн перечисления может быть ошибочным? - person Daniel Hiller; 12.02.2009
comment
Я думаю, что причина, по которой разработчики Java использовали классы для Enum, заключается в том, что они допускают уникальность ссылок (другими словами, == будет работать). Идеальным сценарием было бы использование чего-то вроде символов, но тогда им потребуется поддержка JVM, и это слишком большое изменение. - person mparaz; 12.02.2009
comment
@mparaz: нет, дизайнеры Java создали перечисления как классы, чтобы позволить им иметь поведение, и это единственная языковая функция Java, которой мне не хватает в C#. Перечисления с поведением потрясающие. - person cletus; 12.02.2009

Котенок умирает каждый раз, когда вы создаете изменяемое перечисление. Спасите котят!

person Alex Miller    schedule 12.02.2009
comment
Ответ неприемлем в текущей форме. Пожалуйста, предоставьте подтверждающие и эмпирические доказательства! - person user924272; 13.01.2016

Да. И под «да» я подразумеваю «Всегда».

Если вы хотите сопоставить статистику по количеству вызванных операций, реализуйте некоторую наблюдаемость.

person cletus    schedule 12.02.2009
comment
Я подумаю об этом. На данный момент моей идеей было бы добавить экземпляр StateContainer в сигнатуру метода... - person Daniel Hiller; 12.02.2009
comment
Подожди. Если вы добавите наблюдаемость в перечисление, вы только что сделали его с полным состоянием! - person Tom Hawtin - tackline; 12.02.2009

Любая форма изменяемой статики — это грех. (Ну, вам могут сойти с рук негерметичные кэши, ленивая инициализация и формы ведения журналов.)

person Tom Hawtin - tackline    schedule 12.02.2009

Перечисление с отслеживанием состояния — это оксюморон, даже антишаблон!

http://en.wikipedia.org/wiki/Enumeration

Перечисление — это набор элементов, представляющий собой полный упорядоченный список всех элементов в этом наборе. Этот термин обычно используется в математике и теоретической информатике для обозначения списка всех элементов набора. В статистике используется термин категориальная переменная, а не перечисление. Точные требования к перечислению (например, должно ли множество быть конечным или разрешено ли списку содержать повторения) зависят от раздела математики и контекста, в котором он работает.

Перечисления имеют конечное число значений, которые должны быть постоянными, чем они и являются.

Однако тот факт, что они являются "первоклассными" Java-объектами, полностью противоречит сути намерения или духа перечисления.

Если требуется какое-либо состояние, перечисление (как упоминалось ранее) должно содержать состояние в Аспекте, или вызывающее нарушение перечисление должно, по крайней мере, содержать ссылку на состояние хранения класса делегата. Понимание «разделения интересов» поможет.

person user924272    schedule 29.03.2014

Это похоже на плохое использование перечислений — почему бы просто не использовать базовый абстрактный класс с новым подклассом для каждой операции?

person Marc Novakowski    schedule 12.02.2009
comment
поскольку операция как таковая является исправлением, преобразование в тип операции и использование фабрики кажется мне слишком накладным... - person Daniel Hiller; 12.02.2009
comment
Я думаю, что вы, возможно, преждевременно оптимизируете - нет ничего плохого в использовании фабрики, и на самом деле ваш код будет намного проще тестировать. - person Marc Novakowski; 12.02.2009

Я полностью согласен с mparaz в том, что это нарушает принцип наименьшего удивления. Люди ожидают, что перечисления будут константами.

Вы почти наверняка можете обойти ведение журнала, например:

DO_THIS() {
  public Result doSomething(Object theData) {
    MyUtilClass.doSomething(Object theData);
  }
}

и поместите свой журнал в другой класс.

ОДНАКО, если вы не можете обойти это, принцип наименьшего удивления является ориентиром; вы можете нарушить его, ЕСЛИ вы даете пользователям этого класса достаточно предупреждений о том, что происходит. Убедитесь, что объявление Enum содержит БОЛЬШОЕ уведомление о том, что оно изменчиво, и точно описывает, что такое изменчивость. Enum все еще должен работать; он выполняет сравнение ссылок с одним экземпляром для проверки значений перечисления.

person DJClayworth    schedule 12.02.2009

Есть случай, который, вероятно, оправдал бы это. Перечисление может реализовывать интерфейс, обычно с учетом конкретного варианта использования, который позволяет вам создавать во время выполнения/открыто «некоторые другие типы класса перечисления» динамическим образом, чтобы как-то назвать его.

Это означает, что экземпляры enum "singleton" могут быть вынуждены реализовать некоторые изменяемые сигнатуры методов (как сеттеры), которые, конечно, вы все равно можете скрыть с помощью пустого кода или исключения NotSupportedException.

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

person Whimusical    schedule 02.12.2015