有大量常量时定义常量的正确方法是什么?

时间:2019-06-18 08:52:50

标签: java enums config constants configuration-files

我正在处理一些具有大量要定义的常量的代码。它主要处理Marketplace常数(可以是美国,英国,印度,日本)和相关联的MarketplaceMerchantMapping,基本上将MerchantIDMarketplaceID映射。

例如:

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.


}

还有其他类似的常量,其定义与枚举或静态常量类似。

这确实不可扩展,因为每次我们添加对新市场和商家的支持时,我们都需要去更新一堆文件并进行测试,而这些配置更改本身会占用大量开发人员时间。

理想情况下,我想知道是否有某种方法可以在某些配置文件中定义这些常量并读取这些文件以创建常量。有没有一种方法可以通过读取和解析一些配置文件来创建此类枚举常量?

因此,如果我有一个包含以下条目的配置文件:

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

然后,它可以从配置文件中读取这些常量并构建适当的枚举或静态常量吗?

这可能吗?

3 个答案:

答案 0 :(得分:5)

如果无法使用数据库,则维护良好的XLS工作表可能是次佳的选择。结合经过良好测试的获取工作表数据的过程,以从中生成代码,或用作某种属性配置输入。

正如OP自己想像的那样:当需要维护如此大量的“关键”属性时,Java源代码并不理想,但更重要的是,需要定期进行更新。

当然,这里的方面是:维护良好。每个人都必须遵循一个明确定义的过程,并且整个“链”,从对XLS进行更改(理想情况下以版本控制的方式进行更改),到生成构建时所需的工件,都应该简单且经过良好测试。

答案 1 :(得分:4)

枚举必须在编译时是“已知的”。因此,只要您使用Enums(并且我了解由于类型安全,IDE支持等原因,您希望与他们一起使用) 您必须编写它们,如果其中有很多相互连接,这确实很乏味。

现在您要的是(如果我理解正确的话):

  • 无论如何我想定义一个配置文件(json / yaml)
  • 基于此文件,我需要在运行时创建“东西”以供使用。

我建议在这里使用一种不太广泛的方法(至少以我的经验),但这绝对有助于完成工作:

想法1 :如果乏味,为什么不使其自动化?

想法2 如果您想使用枚举,为什么不创建枚举?

所以基本上我建议在构建时生成代码(并且生成枚举很简单,因为它们没有任何实际的逻辑要完成)。

因此,如果您决定遵循此路径,则需要做几件事:

  • 确保在编译实际的类之前完成代码生成,否则您将无法在类中使用自动生成的代码。

  • 确保代码正确生成。过去,这是一个非常痛苦的过程,但是现在有了一个名为Java Poet的漂亮小图书馆,它使代码生成变得非常简单。

  • 确保此方法将与您的构建工具集成。例如,如果您使用maven,请考虑创建一个maven插件,该插件将触发代码生成过程并将其保存在target/generated-sources中。然后将其附加到generated-sources阶段(显然在compile阶段之前运行),并且从Java编译器开始编译类时,生成的源将是无法区分的。

    < / li>

为了给您一个例子,我可以向您介绍我最近作为一个宠物项目完成的一些类似问题(我很抱歉,如果这听起来像是在做自我广告,我从不会在《所以,我这样做是因为我真的相信,从技术上讲,如果您决定遵循此方法,这会有所帮助,因为从技术上讲,它包含粘合在一起的所有部分):

所以我的目标是自动化异常创建(可以说它比枚举生成稍微复杂一些),就像您一样,我认为创建一些配置yaml文件,并在其中添加有关异常的信息(traceIds)是个好主意。 ,消息,参数等),并让构建过程创建实际的异常Java代码。

Github上有一个名为Simplex的项目(简单的异常处理库)中提供了源代码。它具有供参考的Maven插件,使用Java Poet的生成器等。

答案 2 :(得分:0)

如果您只是想以一种更具可读性的方式编写枚举,则可以为其添加一个属性:

public enum Marketplace {
     US("US", false, true),
     JP("JP", true, false),
     UK("UK", false, true),
     IN("IN", true, false),
     NZ("NZ", true, false),
     CA("CA", false, true),
     FR("FR", false, false);

     // This could go uptp some 400 marketplaces

     private final String stringValue;

     /** Markers for the getters */
     private final boolean isWest, isEast;

     Marketplace(String stringValue, boolean isEast, boolean isWest) {
         this.stringValue = stringValue;
         this.isEast = isEast;
         this.isWest = isWest;
     }

     public boolean isWest() {
         return isWest;
     }

     public boolean isEast() {
         return isEast;
     }
}

从技术上讲,如果将其设置为枚举的属性,则可以轻松地将它们保存在数据库中。如果没有可用的数据存储,则必须在源代码中对其进行维护。