In Java, an enum is not a plain replacement for a number (like in C/C++), but a family of objects which can have properties. For instance
public enum Order {
NAME("Ordering by name"),
SURNAME("Ordering by surname");
private String comment;
private Order(String comment) {
this.comment = comment;
}
public String getComment() {
return this.comment;
}
}
And then, I could do:
System.out.println(Order.NAME.getComment());
Now, imagine I define an API like:
public interface MyApi {
public List<People> getAllPeople(Order order);
}
I can do several things in the implementation:
A switch with the enum, defining the ORDER BY clause as needed for each value.
Add a new parameter to the enum:
an extreme example would be, with SQL,
NAME("Ordering by Name", " ORDER BY peo_name")
1, and just doif (order != null) { sql += order.getOrderClause(); }
Using JPA, I would use the property and not the column name, so I could do `NAME("Ordering by Name", "name") 2 and do
if (order != null) {jpql += " ORDER BY p." + order.getOrderAttribute(); }
On the plus side, I find it as the most straightforward way of implementing the Open/Closed principle (if I add a new ordering criteria, I just need to add the respective enum instance). On the less positive way, I am exposing internal details of my server to the client (although the client is not able to "inject" a different value to profit from it).
What kind of problems can I expect from this breach of abstraction? Is it worth it the simplicity of coding? There is any -hopefully- simple3 way to improve this design (the JPA one)?
1 peo_name
being the name of the column in the DB.
2 name
would be an attribute of People
, that is, there exists a getName()
method in People
.
3 One alternative I can think of would be using a new enum, Order2
, as part of the API, and then link each instance of such enum to one instance of Order
, but I think it is complicated and somewhat breaks the open/closed principle (to add a sorting criteria I would need to modify both Order
and Order2
).