Solving for enum inheritance

I am working with a team to build a concept of website features which will provide answers to applications on whether something is turned on or off. Think of it as a table of preprocessed business questions with an on/off switch. It looks something like this:

KeyDescriptionYes/No
1Business rule #1Yes
2Business rule #2No
3Business rule #3Yes

You might be asking well, why would you do this? First, as systems grow, so doesn't debt unless it is managed and given some attention. Developers come and go, point in time decisions are made, and right or wrong the cost to fix existing systems is very costly. Secondly, there is a net request performance gain from housing all the answers in one table. Since there a crap ton of rules and data that needs to be gathered per feature, the performance cost even with async server side processing is not acceptable for rendering a page. One could argue, did we let things get to complicated with rules or even general architecture, maybe...

There is also cons to keep in mind. Will this concept explode where everything is just a feature and become unmanageable adding to existing technical debt? With discipline, strong control and a code review process hopefully it can be. Since each feature will be preprocessed, will the net performance gain out weight the cost of processing each record in batch? The other risk to keep in mind whenever you start creating ODS type tables there is an inherent risk of them being out of sync with operational data stores.

From an application consumer, the goal is provide an easy way to ask "Is this feature turned on". We can make one call to a Feature data access manager and then return all the features possibly in an EnumSet. It might look like:

EnumSet<Feature> features = featureDAO.getFeatures();
features.contains(Feature.SOME_FEATURE);

Throwing a wrench in the mix, there are different sub types of features, something like SubType1Feature or SubType2Feature. The next thought is, should we throw all the features in one Enum or apply inheritance to the various type Feature Enums. Unfortunately you cannot extend an enum and the core behavior of an Enum is that it is a well known set of values that only provides the non-subclassing variant. If you try to subclass or extend we would have confusing interactions with switch statements and other enum features. If you try to extend an enum in your favorite IDE you should get a compile time error.

Researching more, a nice write up of a extensible enum pattern was posted that highlights a few steps that provides a good alternative instead of string-based provider look ups. This pattern is called Mixin, which is a class that contains a combination of methods from other classes which encourages code reuse and avoid multiple layers of inheritance.

  1. Define an interface with needed functionality.
  2. Declare an enum implementing the interface where the enum constants represent the known values
  3. Include a factory method mapping from names to objects implementing the interface.

While this isn't perfect, it still allows us to provide an easy way for consumers to call. The only thing they will need to know is, what type of Feature enum they need to check. At a high level, here is what we ended up with:

interface WebFeature {   }

public enum SubType1Feature implements WebFeature {    
    //..
}

public enum SubType2Feature implements WebFeature {    
//..
}

Set<WebFeature> features = Sets.newHashSet();
features.add(SubType1Feature.SOME_WHATEVER);
features.add(SubType2Feature.SOME_WHATEVER_2);

if (features.contains(SubType1Feature.SOME_WHATEVER)) { 
    //true
}