#enum order

1 messages · Page 1 of 1 (latest)

arctic vale
#
    enum SetupWizardStep {
        WORLD_CREATION("Please enter a world name for the island world");

        private final String instruction;

        SetupWizardStep(String instruction) {
            this.instruction = instruction;
        }

        public String getInstruction() {
            return instruction;
        }
    }


SetupWizardStep step = ...
int nextStep = step.ordinal() + 1;
if (nextStep < values.length) {
  this.step = values[nextStep];
}

i have an enum that represents steps in a wizard. i want to use values() and orindal to determine the next step, but this means the enum has to be in step order. is this code fragile? would it be better to explicitly define the order in the constructor or the next step?

lucid mesaBOT
#

<@&987246399047479336> please have a look, thanks.

thorn totem
#

yes its fragile, dont rely on that

#

instead each step could know the next step

#

like an implict linked list

arctic vale
#

just want to make sure i understand why it's fragile, is it fragile because adding or removing values affects ordinal? if i'm not storing the ordinal number in a datastore or data structure and comment saying order is important would that make it less fragile?

thorn totem
#

all it takes is someone clicking on "refactor -> sort fields in project alphabetically"

#

and then everything collapses and u dont even notice it directly

#

or someone not super familiar with the code to add a new enum entry in the middle

#

the linking should be explicit in a way that the code compilation itself can guarantee no mistakes with it

#

and not implicit by order of source code

#

its not like this would be a gigantic mistake - it would work after all. but its fragile indeed

arctic vale
#

i didn't think of that. i thought adding a comment might be enough to make it less fragile

thorn totem
#

if u really need to go with the enum order id at least add numbers to it

#
1_GETUP
2_BREAKFAST
3_WORK
...
#

but still

#

id probably approach it differently

#
Step current = new Step(Task.GETUP, this::doGetup, Task.BREAKFAST);
...
current = current.nextStep();
#

and then maybe having some form of lookup map

#

Step getupStep = taskToStep.get(Task.GETUP);

#

or sth like that

#

now u can also do more complex setups

#

like loops

#

or going a step that conditionally needs to go back to a previous one

#

🤷‍♂️

arctic vale
#

i think going with defining the next step in the constructor. i need to think about if i can verify if the enum is configured properly or not. like all steps are linked and no cycles

thorn totem
#

or u make a map

#
Map<Step, Step> stepToNext = Map.of(
  Step.GETUP, Step.BREAKFAST,
  Step.BREAKFAST, Step.WORK,
  Step.WORK, ...
  ...
);
#

Step next = stepToNext.get(Step.GETUP); // Breakfast

#

or a list with constant indexOf searching:

#
List<Step> steps = List.of(
  Step.GETUP,
  Step.BREKFAST,
  Step.WORK,
  ...
);
...
int i = steps.indexOf(Step.BREAKFAST);
Step next = steps.get(i + 1);
#

(the map would be preferable)

arctic vale
#

would something like this be worth validating in the constructor of the class where it's defined. all steps are linked and no cycles

Map<Step, Step> stepToNext = Map.of(
  Step.GETUP, Step.BREAKFAST,
  Step.BREAKFAST, Step.WORK,
  Step.WORK, ...
  ...
);
thorn totem
#

i dont think u need to validate it

#

u can, but i dont think its necessary

#

maybe for a unit test

#

if ur doing unit tests

arctic vale
#

i also feel validating might be a bit overkill. it's a mc plugin so i don't have unit tests

merry adder
thorn totem
merry adder
#

tbh any of the options are fine

#

just don’t serialise it as a number

wild hound
#

like doesn't go 1 -> 2 -> 3 -> 4

#

its fragile to that change

#

as with all "fragile" things though, if it doesn't actually ever change then it never breaks and its fine

#

if it does it is suddenly not fine

neon snow
#

A wizard is basically a DAG, a Directed Acyclic Graph, so you can choose to model it that way, or you can choose to model it linearly

#

But anything that has a defined order, should be stored in a List

#

(or array)

wild hound
#

(or array list)

neon snow
#

(yeah, I said List)

merry adder
#

it might be a good idea to manage the state directly as well

#

if it’s complex enough

prime rapids
#

You can have the an enum that takes any previous declared value in the constructor. This means your state transistions are laid out in reverse in the enum declaration. There is also no way to access static variable from inside a constructor so you can't assign an enum value to say a static list. You also can't call values() in an enum constructor. Best you can do is write some validation code in a static method to call before use of the enum. If enum had a method that could be overridden that gets called after it was done with construction...