Do enums violate open/closed principle Java? [closed]
Asked Answered
V

3

10

In java, If we are using an enum and eventually we want to add/remove an attribute to/from that enum, hence its usages, we are violating open/closed principle in solid principles.

If so, what is the better usage of enums?

Vanya answered 15/7, 2016 at 9:59 Comment(6)
Could you elaborate? How are we violating those principles?Silverpoint
Open/closed is a principle, not a dogma that needs to be followed at all times.Obtain
@MarkRotteveel But that makes life easy at most of the time right? specially one is trying to extending some others code?Vanya
No, thinking for yourself makes life easy, not following ideas of others without understanding or reflection.Obtain
@MarkRotteveel so what is your interpretation?Vanya
In the thread, Use of strings vs enums as parameter of factory method? Bob Martin gives an answer where he mentions enums violating the OCP. The accepted answer here is clearly inaccurate.Villeneuve
S
12

The answer is no as OCP doesn't apply (and cannot apply) to Enums. Enums should be complete (contain all possible values) and static (static = final, non-mutable). You can see them as a small, finite set of Value Objects.

If you want something that can be extended, you can always use a class or build your own "type-safe enumeration" that can be extended.

About the language. I choose to use the term apply rather than violate, as principles, as many good practices, have a context where it makes sense to apply them. A violation (for me) means that a situation calls to use a principle, but it's not used or it's not implemented properly. It doesn't apply means what it says on the tin, that the principle brings no use in the current context or that it cannot be applied, as otherwise would go against other principles which have stronger forces ... in the context :).

Edit

Another reason why I think Enums don't violate OCP (now I use the word violate :D), is because OCP doesn't mean that all of the classes and methods can be extended, but rather that a conscientious developer makes informed decisions about where to put those extension points. In the case of an Enum a developer understands that there's no need to extend the possible values and further that it would be damaging to add new values, as existing code wouldn't know what to do with the new value. So he/she decides to completely close the class and not provide extension points. The same applies to any other class that is final. A final class doesn't violate OCP, but rather (or ideally) a developer made a decision of not allowing to extend it.

This is similar to what I mentioned before, that Enums are like a small, finite set of Value Objects. VOs are immutable and closed, and as such they don't violate OCP.

And to add something more, I've seen some libraries not implementing OCP correctly (Tapestry 5) and making more than needed final, which made them a PITA to use. Or just not closing anything, which made some devs make mistakes because they didn't understand the finer details of the library, and messed up the invariants.

Shabbir answered 15/7, 2016 at 10:19 Comment(7)
if so, obviously no problem. :)Vanya
I don't fully understand your comment... but makes me wonder if my answer sounds patronizing. I hope it's not!!Shabbir
Since enums cannot be extended, they violate OCP. The point that enums should be complete and not require extension means it's OK for them to violate OCP; but they still violate it.Villeneuve
@Villeneuve maybe this is language thing. I would say that it doesn't apply rather than violates the principle. But again, it's language and as such imperfect.Shabbir
So if i use some ENUM as PAymentType and as of now it has "DEBIT_CARD,CREDIT_CARD" and later if i introduce a new payment type "CASH" ,now if I add this to ENUM, does it violate OCP as I modified enum?Duaneduarchy
Assumptions like "Enums should be complete (contain all possible values)" stand for less than 1% of the enums used in practiceShould
@PetruLutenco In software design: "all models are wrong, but some are useful". And in statistics: 70% of them are lies, 20% are unknowingly wrong and 50% might be correct :D.Shabbir
V
9

The answer is yes. All Java enums violate the Open/Closed Principle, because they cannot be extended without modification.

The "better usage of enums" in Java is to have them implement an interface, and have clients depend on that interface rather than the enum implementation, because the interface does not violate the Open/Closed Principle.


Don't jump to the conclusion that if enums violate the OCP, then we shouldn't be allowed to use them. I want to clarify this answer with a reminder that the OCP, by definition, applies only to client-facing code, i.e. code that is public/exposed. The OCP is not a restriction on implementation details.

A module is said to be closed if it is available for use by other modules... At the implementation level, closure for a module also implies that you may compile it, perhaps store it in a library, and make it available for others (its clients) to use.

--Bertrand Meyer, Object-Oriented Software Construction 2nd ed. page 57

So, utilizing enums as part of an application's internal API avoids the OCP altogether. It is only as part of the external API where enums should be abstracted through an interface.

Consider that since an enum is a concrete implementation, exposing it only though an interface serves as much to satisfy the Dependency Inversion Principle as it does the OCP. Even if you believe that directly exposing enums somehow sidesteps the OCP, it still creates a concrete dependency, which violates the DIP.


Also consider the comment from @MarkRotteveel, "Open/closed is a principle, not a dogma that needs to be followed at all times."

Villeneuve answered 15/7, 2016 at 14:34 Comment(2)
This was exactly my thought. :)Vanya
Question is how then store the list of values and the process it one by one?. For example enum Fruits {apple, pear, banana} switch(Fruits) (case apple: gnerateApple(); break, .....) In this way I always need to update Enum, and function with switch, plus add somewhere method to generate "something". Any patterns for that problem?Nada
R
1

Open/Closed as well as all SOLID principles were designed to make easy refactor and understand the code. You should use it based on the context.

As long as Enum Types must be a a well-known set of values, you shouldn't write something like this:

enum Fruits {apple, pear, banana}
enum Food extends Fruits {chicken}

For three reasons:

1) Java doesn't allow it.

2) By no means a chicken is a Fruit

3) Fruit is no more a well-known and complete set of values

If you use Enum to define, for example, the planets of the Solar System and a new planet is discovered or an old one loses its status (or is destroyed by aliens) it's Ok to modify your class to adjust the new requirements.

Robert answered 15/7, 2016 at 10:48 Comment(1)
This does not answer the question, "Do enums violate OCP?" Yes or No?Villeneuve

© 2022 - 2024 — McMap. All rights reserved.