-1

Originally posted here, moved to code review, redirected from code review back here as there is no code to review. I think the question is enough abstract to be asked here.

I have a mono repo with multiple nano services integrated with Kafka. The system data vesel is JsonMessage. There Are multiple formats Of json messages. These Json messages аre exchanged via these nano services. Same keys are used as element in constructing a key accessing data carried by these messages in a Redis cache. A global dictionary of property Keys is created via enum that is included as dependency to all systems:

enum Key {
  EVENT_NAME,
  COMMAND_NAME,
  CLIENT_ID
  TRANSACTION_ID,
  ORG_NUMBER,
  INCOME_DOCUMENT
...................
30+ more enrties
}

These keys fall in three categories, keys originating from the integration framework. Technical keys described in our application. And functional keys like organization number, income document and so on.

I attempted to split this enum into two enums, to isolate the DATA related keys in a separate enum. Using a marker interface would allow for two enums with Key abstraction.

enum SystemKey implements Key {
      CLIENT_ID, TRANSACTION_ID /* ... more keys */;
}



enum DataKey implements Key {
     ORG_NUMBER,INCOME_DOCUMENT /* ... more keys */;
}

This was blocked in a code review with the argument that

"Key enum is describing all the Keys in the Kafka message, having two enums in place of one would diminish the value of having the enum Keys"

Each service is not interested in all Keys. What objective value is diminished by breaking this enum into two enums? For example:

  • What can we not do with two enums that we can do with one?

  • Or what code quality hazard do we create with two enums, but not with one?

  • What about the opposite statements ? What are the advantages of each service exposing its own keys or splitting the keys by their responsibiliy?

11
  • 1
    Please do not repost closed questions which you deleted. Jun 3, 2023 at 16:31
  • 1
    maybe try compiling you example java?
    – Ewan
    Jun 3, 2023 at 16:35
  • also, whats with all this "can you elaborate?" reads like a homework question
    – Ewan
    Jun 3, 2023 at 16:36
  • 1
    @joshp Deleted questions are visible to users with 10k rep; the OP deleted the original after it was closed via community vote. Jun 3, 2023 at 16:51
  • I was not able to uendelete it. Probably not enough reputation. I have 9K reputation on stackoverflow from answering questions. I am experienced developer and this is 100% not a homework question. Jun 3, 2023 at 16:55

1 Answer 1

4

If the single big enum is used as a key value in a single message property to allow readers to determine the expected message format and content, then there are some consequences to breaking it into two enums. For example...

  1. A single enum enforces uniqueness of key names in source code across all record types. Two enums can have key names that duplicate each other, and require monitoring or naming conventions to avoid duplicates. Are key names used in the json messages?

  2. Ordinal values of the two enums will overlap unless they are explicitly defined. If you ever use the ordinal values in a setting where you don't know which enum to reference, this is a problem.

  3. If you want to build a dictionary of all keys and their values a single enum allows you to easily do it with and array indexed by ordinal value or an EnumMap, which is an efficient structure for small, stable key domains. EnumMap implementations typically store values in an array indexed by ordinal value Reference: OpenJDK 8 Source, but you use it like a map in your code.

  4. If you have two enums and want to use both enums as keys for a single dictionary using an EnumMap, first you will hit warnings that you are mixing generic types when you try to put() values. If you get around those, easy enough to do, you will have keys from one enum that overwrite keys from the other, unless you explicitly put their ordinal values in different ranges.

EnumMap is a Java specific implementation detail, but it serves to demonstrate a general disadvantage in the inability to rely on ordinal values. If you use a structure keyed by String then the overlapping ordinals are not important, but the uniqueness of string names remains important.

Those Are Some Concrete Disadvantages - Can they be avoided?

Yes, but not for free.

If your team never uses ordinal values, or only uses them in places where the two enum types are separated, you can ignore overlapping ordinal values.

If you change the message structure to have two message keys, say an Event Type and a Message Type, and then make all the code that serializes, deserializes, evaluates, creates these messages understand which Message Type belongs with which Event Type, then you can still have uniqueness and the ability to use ordinal values for each Type.

But you have a more complex structure and set of rules to follow. If messages currently have just one key governed by one Enum type, it could be quite a bit of work to revise the code and test it all.

You would need a good justification or reward for it.

It could be a better design overall. That depends on your project's requirements. But it might not be worth switching late in the game.

Advice

Try to find objective advantages to the approach you prefer. Are they worth the cost? You're not crazy to look at a big enum and wonder if it's a maintenance problem. The answer to that depends on details of your project and team. To my eye, 30 to 60 values does not instantly seem like a problem. Having more enums representing more key domains could be more complex.

7
  • In project there is no iteration upon these keys unless there is some form of frontend validation and in general when a lookup is perform the party peforming the lookup is interested in a specific value. The combination of Event /Command/Data plus potentialy transaction ID identifies uniquely a particular message. Probably transaction ID even without the other two identify it , but with the other two you become aware of the precise context and data that it contains. I am not sure that in our case we have any real iteration. Except when validating and then it is on a limited set of values. Jun 3, 2023 at 18:44
  • Yes, the KEY names are used in the json messages. This is how the lookup is performed. Jun 3, 2023 at 18:47
  • I mean it is enum with string value and the string value matches the property in the json message. Jun 3, 2023 at 18:48
  • Sure. You know your project. Your team may not care about ordinal values. I sometimes care. Most teams I worked with would mainly care about the string uniqueness, and complexity, which can be a mater of opinion. There are lots of ok ways to do this.
    – joshp
    Jun 3, 2023 at 18:52
  • I think creating a dictionary named f.ex. Names does not exclude having 2 enums one named SystemKeys the other named DataKeys. These enums can refer to the dictionary enum when initializing their values? So I kind of don't see how having a dictionary excludes the creation of additional enums based on the property values. And if we are to iterate upon all keys we can use an interface ? Jun 3, 2023 at 19:16

Not the answer you're looking for? Browse other questions tagged or ask your own question.