Question

Let's have a simplified business logic like this:

public enum BusinessLogic {
   STAGE_ONE(true, false, false),
   STAGE_TWO(true, true, false),
   STAGE_THREE(false, false, true);

  private final Boolean canStartProcessing; 
  private final Boolean canDoStuff; 
  private final Boolean canFinish;

  private BusinessLogic(Boolean canStartProcessing, Boolean canDoStuff, Boolean canFinish){
     ... usual simple constructor
  }
  ... getters
}

And let's say it is mapped to my Business Object like this:

public class BusinessObject {
  ... constructors, fields, getters, setters, etc...

  private BusinessLogic logic

  @Enumerated(EnumType.STRING)
  @Column(name = "LOGIC")
  public BusinessLogic getLogic(){...usual getter...} 

  public BusinessLogic setLogic(){...usual setter...}
}

When the workflow arrives for example Stage two, the BusinessObject will be updated and LOGIC field should be set to BusinessLogic.STAGE_TWO, therefore you can use functions like "start process" and "do stuff", before that you can't "do stuff", altough when it reached stage three, you can't do anything else, but "finish" the process.

Does this kind of business logic structure has something to do against good practice?
I mean for example: maintainability, not fully represented in Database or anything else I didn't think of?

Was it helpful?

Solution

I use enums this way all the time. Enums are a great way to write immutable helper objects that you only need exactly one copy of; they help reduce the chance of memory leaks and easily group many related classes together in a clear way.

What I would not do is expose the control of which particular BusinessLogic you're using to external classes using a public getter and setter method; that is violating encapsulation.

It looks like your use case uses the State Pattern, which is a great use for enums in Java. However, by removing the state transition logic from the class, you can't guarantee that other code will change the state when you don't expect. Fix this by having the state transition code inside the BusinessObject class itself, or at least in a package private object that you inject into the BusinessObject class.

OTHER TIPS

It may be a good idea to encapsulate behavior into a Java enum (or C++ enum class) when you find yourself writing switch statements like the following, especially when the switch is repeated in different parts of the code.

MyEnum x = ...;
switch (x) {
  case A:
    // Do something
    break;
  case B:
    // Do something
    break;
  case C:
    // Do something
    break;
  default:
}

It may make sense to change it to the following:

public enum MyEnum {
  A {
    public void doAction() { ... }
  },
  B {
    public void doAction() { ... }
  },
  C {
    public void doAction() { ... }
  },
  public abstract void doAction();
}

Then instead of a switch, you do this:

MyEnum x = ...;
x.doAction();

Essentially, you are abstracting a switch statement using dynamic dispatch instead.

Note that this is a simple example, the enum method may take parameters and return a value. This is only the general structure.

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