TL;DR
Assuming an enumeration used to map domains defined in the business rules of a system, it does not need to be constant, but must respect the business rules and, if necessary, change along with them.
Because we use enumeration
The enumeration is used mainly for two reasons:
- Make life easier for the developer who doesn’t need to consult the system manual at all times to remember what values a field can assume and the meaning of those values.
- Reinforce the validity of constants at compile time. This avoids literals spread across the code that inevitably may lag behind the actual values used in the system.
We should change an enumeration?
When we use enumerations to map database values, we must ensure that they track values in the database.
These values usually come from a domain defined in the system documentation. The precaution of not changing them will be the analyst’s and not the developer’s.
If at a given time the responsible analyst decides that the code 7
no more shall be the equivalent of Parcela Paga
and now should be Parcela em Atraso
, he shall bear the consequences of the decision:
- In the database (update in tables, procedures, triggers, views, queries)
- Change in us
Enum
s and refactoring of the impacted code
- Updating descriptions and fields on screens
- Etcetera, etcetera, etcetera.
The advantage of using an enumeration provided by the programming language is that if you change the description of it, you can easily find the affected points because they will no longer compile.
In addition, several Ides allow you to locate all points where a certain value is used not only by its name, but by analyzing the code semantics.
Techniques to deal with increasing enumerations
Polymorphism
Enumerations replace very simple constants. However, if the developer stops using features that the language offers and uses Enum
as if they were constant, filling the code with IF
s, the growth of the set values will be more prone to errors.
In Java, for example, instead of simply grouping IF
s like this:
if (TipoFuncionario.Celetista == functionario.getTipo()) {
//validar celetista
} else if (TipoFuncionario.QuadroPermanente == functionario.getTipo()) {
//validar quadro permanente
} else ....
We could add a parameter to the constructor of Enum
to force the developer to declare a validator for each added value.
public enum TipoFuncionario {
Celetista(new CeletistaValidator()),
QuadroPermanente(new QuadroPermanenteValidator()),
Surfista(new SurfistaValidator());
private FuncionarioValidator validator;
private TipoFuncionario(FuncionarioValidator validator) {
this.validator = validator;
}
public FuncionarioValidator getValidator() {
return validator;
}
}
So the whole place could just call the validation that:
funcionario.getTipo().getValidator().validate(funcionario);
Note that to add new values it is not necessary to change the existing code.
Note: This example was extracted from another answer from me here in the OR.
Define individual values for each constant
The Java language has a serious problem with Enum
s: it is not possible to define a value for each constant as quoted in the question.
You can even get an integer based on the order of the constant, but relying on the order of the constants declaration does not seem to me anything consistent.
So instead of doing something like:
public enum MeuEnum { valor1, valor2, valor3}
We should always associate value with a constant to map values of a domain:
public enum MeuEnum {
valor1("V1"), valor2("V2"), valor3("V3");
String id;
private MeuEnum(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
In the example above, we can map values of text or number domains, without worrying about the order or the name used for each element of the Enum
.
Cases where we shouldn’t use enumerations
There is a rule (Rule of Thumb) sort of like this:
If you’re gonna change, parametrize!
If a domain is constantly changing, perhaps an enumeration is not the most appropriate response.
It would probably be better to create a table in the database and allow the configuration of some features of each element.
This is much better than refactoring and recompiling code frequently.
Final considerations
Change is inevitable.
If very frequent, a more generic solution than Enum
s may be recommended.
Otherwise, the ideal is to use an OO approach according to the language used to reinforce the due treatment of each element at compile time.
And finally, we must bear in mind that the change of a Enum
is usually the result of change in business, which must be properly analyzed to cause the least impact on the system.
Some analysts have the habit of never delete an element from a domain, just depress it and add a new option to be used in new versions of the system. I believe that it is not always possible, but it is a good approach to be able to maintain historical data.
As there are those who do not understand the reasons for closure, I need to explain that the question is essentially one. Despite having clearly 5 parts, they are related and in the background are helping to clarify the doubt. You can answer relatively briefly. And it doesn’t even need to be answered separately.
– Maniero
Clarify this last paragraph: guarantee what? That the enumeration does not change from one version of the program to another? (nonsense, only if the implementation was in hardware...) or you refer to something else?
– mgibsonbr
It was more of a tease, so it’s not even in the question. It could be a check on the project if it had before a way, could not move anymore. It would not be a guarantee indeed. Just an indicator that it couldn’t be done. A field
private
is said to be guaranteed that it cannot be accessed externally to a class. But in practice this is possible. The compiler ensures that you cannot access it by accident. It would be the same, a guarantee that no accidents are made. I have ideas how to do this but I admit that I would not implement in a language. It would be very complicated.– Maniero
I get it. In fact, absolute guarantees do not exist (after all software was made to be changed - hence the "soft"), but I miss the computer programs being more "self-aware". Not only does "this code come out and enter this newer one", but the realization that the system already existed in an older version, and a certain insight into its structure to help establish the implications of the change. To what extent this is feasible, I can’t say, but it doesn’t hurt to push the boundaries a little until you see where it goes... :)
– mgibsonbr
I know that if we sat down to discuss some ideas, we would go days without sleep :)
– Maniero