tags:

views:

472

answers:

6

As by design an enum constant in java is a singleton, and for sake of concurrent usage I normally create stateless enum instances and use method parameters to inject the data as needed.

Example:

Currently I am creating a REST service which has Operations (implemented as an enum using a variant of the strategy pattern).

public enum Operation {

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

  public abstract Result doSomething(Object theData);

}

Now I want to collect data about how often an operation has been called and how often it succeeded and the like.

I could save the state externally when using the enum instance but it rather seems that the state should be saved in the Operation as the operation should contain it's own state.

Now my general question is:

Is a stateful enum instance (besides from concurrency issues) a bad design?

+10  A: 

I think it violates the Principle of Least Astonishment.

People expect the common usage of enums as they were originally designed - as constants or tokens, and not as general purpose classes with state.

mparaz
In contrast to that enum members are indeed first class java object instances, as such they can have methods and variables. So maybe the whole enum design may be flawed?
dhiller
I think the reason the Java designers used classes for Enums is because they allow reference uniqueness (in other words, == would work). The ideal scenario would be to use something like "symbols" but then they would need JVM support and are too big of a change.
mparaz
@mparaz: no the Java designers made enums like classes to allow them to have behaviour, which is about the only language feature from Java I miss in C#. Enums with behaviour are awesome.
cletus
+1  A: 

This seems like a bad use for enums - why not just go with a base abstract class with a new subclass for each operation?

Marc Novakowski
because the operation as such is fix, the conversion to an operation type and use of a factory seems too much overhead for me...
dhiller
I think you may be prematurely optimizing - there's nothing wrong with using a factory and in fact will make your code much easier to test.
Marc Novakowski
+4  A: 

Yes. And by 'yes' I mean 'Always'.

If you want to collate stats on the number of operations called, implement some observability.

cletus
I will think about that. At the moment my idea would be to add a StateContainer instance to the method signature...
dhiller
+1 to the observability part of the answer.
Chii
Hang on. If you add observability to the enum, you've just made it statefull!
Tom Hawtin - tackline
Not necessarily. AOP springs to mind.
cletus
+2  A: 

Any form of mutable static is a sin. (Well, you might get away with non-leaky caches, some lazy initialisation and forms of logging.)

Tom Hawtin - tackline
+1  A: 

I entirely agree with mparaz that it violates the Principle of Least Astonishment. People expect enums to be constants.

You can almost certainly work round the logging thing, by something like:

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

and put your logging in the other class.

HOWEVER if you can't work round this, the Principle of Least Astonishment is a guideline; you can violate it PROVIDED you give users of the class enough warnings about what is going on. Make sure the Enum declaration contains a BIG notice saying that it is mutable, and describing exactly what the mutability is. The Enum should still work; it's doing reference comparison against to single instance to test enum values.

DJClayworth
+3  A: 

A kitten dies every time you create a mutable enum. Save the kitties!

Alex Miller