looks nice but…
Luca | February 5, 2007A good design should follow (among the others) the Open-Closed Principle: you should be able to add new functionalities without amend the existing code.
In order to have a playground where we can continue this discussion
, let’s define a scenario: we have several strategies to validate a string(param1) and we use a factory method in order to obtain the correct strategy implementation from time to time.
A common implementation of the factory method in this scenario can be:
if (type.equals(MyTypes.BOOLEAN)) {
return new BooleanValidator(param1);
} else if (type.equals(MyTypes.NUMBER)) {
return new NumberValidator(param1);
} else if (type.equals(MyTypes.DATE)) {
return new DateValidator(param1);
}
Obviously the if with multiple branches smells to us like a three-days old sandwich in our lunch-bag
, and we are also breaking the OCP!!
If we are in JavaLand(but this is also valid for other languages such -for example- C#) reflection can help us: if we define that all the classes that implement a specific behaviour(in our example the validation of a string) stay in a defined package (let’s say P), the factory method can simply(?)� go through the classes in P and instantiate what we need thanksto the� reflection mechanism.
But..is that so simple ??
final Map validators = new HashMap();
[some code that through reflection populate the map with all the classes within the package P and assign the right key for each entry] [...]The latter solution from a technical point of view is smart and elegant, but sounds to me terribly unclear.
try {
Class theClass = validators.get(type);
Constructor constructor = theClass.getConstructor(new Class[]{CelonaDataTypes.class, String.class});
ValidatorInterface validator = (ValidatorInterface)constructor.newInstance(new Object[]{param1);
return validator;
} catch (InvocationTargetException e) {
throw new MyException(e.getMessage());
} catch (NoSuchMethodException e) {
throw new MyException(e.getMessage());
} catch (InstantiationException e) {
throw new MyException(e.getMessage());
} catch (IllegalAccessException e) {
throw new MyException(e.getMessage());
}
The (annoying) necessity of managing all the checked expections in JavaLand increase the white noise around the code. Furthermore the reflection APIs in Java are not so clear: if I find this code while I’m trying to learn a new code base a big WTF will appear over my head
!!
The former solution instead is surely a bit tacky, but is probably more readable (but, yes, I’m breaking the OCP and therefore I’m out of law). The second moreover looks a bit like a candy for my ego: my geek side will be really happy….but what about customers and the other team members ?
I’m not totally sure if my point of view is reasonable(any feedback is appreciated
) or if I’m simply scared by the increased complexity of my code.
But while I can agree that the first is nearly simplicistic, I’m not sure that the second is enough simple.
And if it’s not simple, I really don’t like it…





