VB_
VB_

Reputation: 45692

Architecture for status managment

What I have:

One-to-many relationship between A and B entities. Each of those entities have a status. There are a finit amount of statuses, about 7-12 for each.

I have to check if the transition (from one status to another) is possible. And make few additional tasks on transition, like store history and make logging.

Don't fall in delusion, status isn't equals to state. It isn't about State Pattern because my entities haven't any state-based logic.

How does it happen:

Entity arrives as a part of update request, and I compare if old version of entity has the same status as the new version. If not - the status has been changed. Status is just a string or enum.

What I want:

Of course, there are some rules, which impose restrictions on state transition. I want the next:

  1. Transition verification. Means I want to check if the entity CAN be moved to the asked state. Example: A-entity can be moved to Y-state only if it is in X-state and all related B-entities are in Z-state.
  2. Automatical transition (not in all cases). Means the state of A-entity should always be consistent related to all linked B-entities. Example: If I move B-entity to X-state than related A-entity should be moved to 'Y-state'.
  3. Store history. Means which entity and when was moved to the state.

What a problem:

The simples solution is to write a transition-matrix, where matrix[i][j] == 1 if transition is possible and 0 otherwise. But there are some problems:

  1. What about situation when the transition is depend not only on the state of updated entity? Matrix doesn't solve this problem.
  2. What about history and loging?
  3. How to avoid a lot of if-statements?

Question

I'm looking for Pattern/Common Practice suitable for this situation. What is a patter/best practice of solving the task?

Upvotes: 2

Views: 134

Answers (3)

Alexander Petrov
Alexander Petrov

Reputation: 9492

Here something simple I wrote based on Enums :) It was originaly written as art of this post.How to implement status transitions for an Entity in java? Its purpose is to express state through Hibernate.

public enum State {
    STATE1,STATE2(STATE1),STATE3(STATE1,STATE2);

    private State[] previousStates;

    private State(){

    }
    private State(State ...state) {
        this.previousStates =state;
    }

    public State transition(State state) throws Exception {
        for(State tmp: state.previousStates) {
            if (this == tmp) {
                return state;
            }
        }
        throw new Exception("Illegal state");

    }

}

Upvotes: 0

Anders Johansen
Anders Johansen

Reputation: 10455

The A- and B-items should probably implement the same interface, such as

boolean canMove(State newState); // A-items know which B-items to check
void performMove(State newState, HistoryAndLog historyAndLog); // A-items and B-items will record history and log as appropriate. A-item will change related B-items as appropriate

In this case we are using composite (A-items check if related B-items can change state as desired) and delegation (have A- and B-items update the log and store history as they see fit). This removes the need for a lot of the if-statements.

The underlying design of the A- and B-items should probably be "state pattern", perhaps combined with Flyweight so you can use an underlying transition matrix to implement part of the logic.

EDIT: Expanding on Flyweight... For an N x M transition matrix, storing just a yes/no value takes one bit. If instead you have to store an object pr. cell, that would cost a LOT more (internal representaiton of object). Instead it's cheaper to create a temporary object on request from a factory class. Often by a factor of 100 or more pr. object.

Basically you are trading computation in the situation (create the object on demand) for storage (avoid storing N x M objects).

One could imagine something like this

class Factory {

  private boolean canTransitionItemA(final int n, final int m) {
    // Look up in matrix
  }

  public ItemType makeItemAFromCoordinates(final int n, final int m) {
    return new ItemA() {
      public boolean canTransition(<blabla>) {
        return canTransitionItemA(n, m) && canTransitionRelatedBItems(n, m);
      }
      <bla bla bla>
    }
  }
}

Upvotes: 1

John Deters
John Deters

Reputation: 4391

You are insistent that it's not a state pattern, but your description is exactly that of a finite state machine. You have a finite set of statuses. You have transition events where the status is changed. Those transition events need to have guards to ensure the transition is valid. You have exit and/or entry actions (logging). That's all classic state machine behavior.

Check out http://smc.sourceforge.net/ . It's a project that will take a .sm file you create and generate a state machine for you in your choice of 14 languages.

One reason to use a tool like this is that a code generator produces already working code. You don't have to test the mechanics of the state machine it produces, you just have to test your transitions and validations.

Upvotes: 2

Related Questions