5

I am working on a project based on the Java EE technology. First I'd like to tell you what I want to achieve, then what I already tried.

Task:

Imagine two types of configurations, which you want to choose and edit/define in the JEE application via GUI entries. Config A is for the communication with System A and Config B is for the communication with System B.

Config A got a few properties equal to Config B, but the properties itself differ in some way (example: enumerations). Additionally Config A and B each got more properties which they don't have in common. Now, if the application user enters one configuration(A or B) it should be possible to access in a general and easy way all given methods/properties of the configurations, without always asking which type of configuration was picked. How can one access especially the properties/methods that differ, in an easy and not redundant way?

Current setup:

Because I try to reduce redundant code I created an abstract class defining a general configuration, let's call it "GeneralConfiguration".

Config A and B each extend GeneralConfiguration. For each "shared" property GeneralConfiguration defines an interface. Each interface got implemented by different enums, which represent the possible entries for the general configuration depending on the config type (A or B).

I think my setup is not optimal. So what do you think, how to handle this kind of task?

  • What exactly do you think is not optimal ? – Spotted Aug 22 '16 at 9:41
3

I think the question is interesting. It isn't the problem itself. It's due to the misuse of inheritance. A very common misuse.

Why do I say so?

Because I try to reduce redundant code I created an abstract class defining a general configuration, let's call it "GeneralConfiguration".

That is one of the worse reason for using inheritance. The aim beneath abstract classes is way more sophisticated than save us from code duplication.

For each "shared" property GeneralConfiguration defines an interface

Here the implementation details have been transferred to something meant to be abstract. That kills what abstract classes do well, abstract us from the details.

The only thing in common between A and B is that, conceptually, both are configurations, but here end their similarities.

How is that?

Now, if the application user enters one configuration(A or B) it should be possible to access in a general and easy way all given methods/properties of the configurations.

By design both have turned into something different. Both have been designed as two different components, and now, we are trying to fix it with inheritance. Inheritance doesn't work in that way.

On the paper, both might have the very same meaning and purpose, but such feature has not been transferred to the design.

If we want to abstract ourselves from the "details" (A or B), the configuration should be totally agnostic to them.

Example:

public Configuration {
  Map<enum,Object> properties;

  public Configuration(){
        properties = new HashMap<enum,Object>();
  }

  public Object getProperty(enum propertyName){
         return properties.get(propertyName);
  }

  public void setProperty(enum propertyName, Object value){
        properties.put(propertyName, value);
  }
 }

Now, there's neither A nor B (and the inheritance becomes unnecessary).

How we implent A and B?

Now, we can implement "details" over the abstraction. For instance, implementing delegation pattern

public ConfigA {
    Configuration config;

  public ConfigA(Configuration config){
      this.config = config;
  }

 public String getA(){
       return (String)  config.getProperty(MyEnumA.A);
  }

  public void setA(String value){
      config.setProperty(MyEnumA.A,value);
  }
      ...
}

If we need "details" we use ConfigA/ConfigB. We use Configuration for the rest.

Note: When I do say abstraction I'm not referring only to abstract classes. I'm referring to the concept.

0

I think the Builder pattern may help you.

public class ConfigBuilder 
{
    public void SetPropertyA(string a)
    public void SetPropertyB(int b)
    public GeneralConfiguration Build()
}

The UI may interact with the methods exposed by the ConfigBuilder object. Once the user is OK, the Build method will be invoked to determine if ConfigA or ConfigB will be created base on the properties set in the ConfigBuilder object.

  • I think I will get into the same problem with the Builder Pattern. If I look at this example sourcemaking.com/design_patterns/builder/java/2 , the model Pizza is the same every time. But in my case it will have some same properties and some different. So this leads to the same problem of accessing the non-overlapping properties, doesn't it? – qecce Jul 22 '16 at 14:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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