Question

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 do

      if (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).

Was it helpful?

Solution

Abstraction leaks are a problem only to the degree that callers may rely on undocumented internals, and mysteriously break when you change those internals. For instance (since we're talking about ordering), if you return a list of things and it happens to always be sorted, callers might assume that this is part of the contract and break if you reimplement the method in a different way.

In this case, the leak is a problem to the degree that callers will come to expect the particular value that the additional method returns and depend on it. That seems unlikely to me, but you probably know your users better than we do, so it's your call. In general, I like utility methods in enums very much, precisely for the reasons you give.

Licensed under: CC-BY-SA with attribution
scroll top