Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the right way to define constants when there is a huge number of constants?

I'm working on some code which has a large number of constants to be defined. It primarily deals with Marketplace constants (could be US, UK, INDIA, JAPAN) and associated MarketplaceMerchantMapping which basically maps a MerchantID with a MarketplaceID.

For example:

public enum Marketplace {

    US("US"),
    JP("JP"),
    UK("UK"),
    IN("IN"),
    NZ("NZ"),
    CA("CA"),
    FR("FR"),
    ... 
    ...

  // This could go up to some 400 marketplaces

    private final String stringValue;

    public boolean isWest() {
        return this == US || this == CA || this == UK;
    }

    public boolean isEast() {
        return this == IN || this == NZ || this == JP;
    }

}
public enum MarketplaceMerchantMapping {

    USMAP(MarketplaceID.US, MerchantID.US, Marketplace.US),
    JPMAP(MarketplaceID.JP, MerchantID.JP, Marketplace.JP),
    UKMAP(MarketplaceID.UK, MerchantID.UK, Marketplace.UK),
    NZMAP(MarketplaceID.NZ, MerchantID.NZ, Marketplace.NZ),
    INMAP(MarketplaceID.IN, MerchantID.IN, Marketplace.IN),
    CAMAP(MarketplaceID.CA, MerchantID.CA, Marketplace.CA),
    FRMAP(MarketplaceID.FR, MerchantID.FR, Marketplace.FR),
    ...
    ... 

   // THis can go up to 400 Marketplaces * Number of merchantIds in each marketplace.


}

There are other similar constants defined similarly as enums or static constants.

This really is not scalable because every time we add support for a new Marketplace and Merchants, we need to go and update a bunch of files and test them and these config changes themselves take up a lot of developer time.

Ideally, I would like to know if there some way to define these constants in some config file and read those files to create the constants. Is there a way to create such enum constants by reading and parsing some config file?

So that if I have a config file with the following entries:

ConfigFile.cfg:

WestMarketplaces = ("US", "AG", "MX", "CA", ...) // Expand this later as required
EastMarketplaces = ("IN", "AU", "SG", "JP", ...) // Expand this later as required
EUMarketplaces = ("UK", "FR", "SP", ...) // Expand this later as required

WestMerchantIds = ("WA", "WB", "WC", "WD", ...) // Expand this later as required
WestMerchantIds = ("EA", "EB", "EC", "WD", ...) // Expand this later as required
EUMerchantIds = ("EUA", "EUB", "EUC", "WDD", ...) // Expand this later as required

marketplaceMerchantMapping = {
  "US" = "WA";
  "CA" = "WB";
  "MX" = "WC";
  "AU" = "EA";
  "IN" = "EB";
  "JP" = "EC";
  "UK" = "EUA";
  "FR" = "EUB";
...
} // Expand this later as required

Then, can it read these constants from the config file and build the appropriate enums or static constants?

Is this possible to do?

like image 679
Sunil Kumar Avatar asked Jun 18 '19 08:06

Sunil Kumar


2 Answers

When using a database isn't possible, then a well maintained XLS sheet might be the next best option. Together with a well tested process of fetching the sheet data, to either generate code from it, or to be used as some kind of property configuration input.

As the OP figured himself: Java source code isn't ideal when such a large number of "key" properties need to be maintained, but more importantly, are subject to regular updates.

Of course, the key aspect here is: well maintained. There needs to be a well defined process everybody has to follow, and the whole "chain", from making changes to the XLS (ideally in a version controlled manner), to producing the artefacts required at build time should be simple and well tested.

like image 74
GhostCat Avatar answered Sep 29 '22 00:09

GhostCat


Enums must be "known" at compile time. So as long as you work with Enums (and I understand that you would like to work with them because of type safety, IDE support and so forth) you have to write them and this is indeed tedious if there are a lot of them with inter-connections.

Now what you're asking for (if I understand you right) is:

  • I would like to define a configuration file (json/yaml) whatever
  • Based on this file I need to create "something" to work with at runtime.

I suggest here a rather non-widespread approach (at least in my experience) but this is something that will definitely help to get the work done:

Idea 1: if its tedious, why not to automate it?

Idea 2 if you like to work with enums, why not to create enums?

So basically I suggest code generation (and generating enums is simple, because they don't have any actual logic to be done) in build time.

So you'll need to do a couple of things if you decide to follow this path:

  • Make sure that the code generation is done before the compilation of the actual classes, otherwise you won't be able to use the auto-generated code from within your classes.

  • Make sure that the code is generated properly. Now in the past it was pretty painful process, but now there is a nice little library called Java Poet that makes the code generation a pretty easy process.

  • Make sure that this approach integrates will with your build tools. For example, if you use maven, consider creating a maven plugin that will trigger the code generation process and save it in target/generated-sources. Then attach it to generated-sources phase (that obviously runs before compile phase) and the generated sources will be indistinguishable from the point of view of java compiler when it starts to compile your classes.

In order to give you an example I can refer you to something that I've done recently as a pet project for a pretty similar issue (I appologize if it sounds like a self-advertisement, I never "promote myself" in SO, I'm doing this because I really believe that technically this can help if you decide to follow this path, because technically it contains all the pieces glued together):

So my goal was to automate exception creation (which is arguably slightly more complicated than enums generation), just like you, I thought it would be a good idea to create some configuration yaml file, throw into it information about exceptions (traceIds, messages, params, etc.) and let the build process create the actual java code of exceptions.

The source code is available on Github in a project called Simplex (simple exceptions handling library). It has maven plugin for the reference, generator that uses Java Poet, etc.

like image 43
Mark Bramnik Avatar answered Sep 29 '22 00:09

Mark Bramnik