A state-machine event (signal/trigger) implementation question

18 Views Asked by At

I'm implementing a state machine in Java using Enums and some helper classes. And I have a small question.

I had a state machine designed for 5 different states a 5 actions and it was working. One of those 5 actions was CHANGE action which would cause the state machine to go into OUTDATED state. However I got a change request to add 3 additional states and 5 additional actions. 2 of those actions are:

  • CHANGE_specific_field_to_X
  • CHANGE_specific_field_to_Y

Those CHANGE_to_* actions cause machine go into not an OUTDATED state, but in their own state, let's call it SPECIFIC_FIELD_NOT_PROVIDED

Now, my machine accept a so called 'Project' entity on which I run guards alongside with action type. So an example input would be:

project: {
  name: Project1,
  createdAt: <long>,
  ...
  <specific_field> // which I mention above
},
action: CHANGE_specific_field_to_Y

Problem is - I already have a CHANGED action and I don't want to introduce new ones to complicate things for state machine users (fellow devs). I want to use my existing CHANGED action. However, I don't have a history inside Project to know whether specific field was changed or not. And depending on x->y or y->x it will be a different target state so a boolean flag is not an option.

I came up with the following - instead of sending a project as an entity to the state machine, I'll wrap it into a new entity called argument and add a list of changed fields to that argument, now the input will look like:

argument: {
    project: {
        name: Project1,
        createdAt: <long>,
        ...
        <specific_field> // which I mention above
    }
    specific_field_change_event: {
        old_value: x
        new_value: y
    },
    action: CHANGE
}

Now the problem is I have to send specific_field_change_event for other actions like RUN or FAIL which don't care about this change. I decided to create a builder class which would accept a project and action as required arguments and everything else as optional. CHANGED processor only would throw and error if specific_field_change_event is not provided.

Thing is - for some reason I don't like this design because I depend on users using the builder correctly and then they will know about issue only at runtime when they receive an error that they didn't provide specific_field_change_event to CHANGHED processor.

Are there any best practices here when some of the trigger processors need an additional input? Any way around this?

0

There are 0 best solutions below