Lately I stumble a lot upon code I wrote 4 or more years ago. In the light of introducing new features the code gets tested for its quality. One antipattern I’ve found which I had used in the past but which is really hard to extend is convenience constructors.
Lately I stumble a lot upon code I wrote 4 or more years ago. In the light of introducing new features the code gets tested for its quality. One antipattern I’ve found which I had used in the past but which is really hard to extend is convenience constructors. Take a constructor for a command object for example:
public SetProperty(String filename, String key, String value) {
this(filename, key, value, null);
}
public SetProperty(String filename,
String key, String value, String comment) {
this(filename, ReferenceTo.key(key), value, comment);
}
public SetProperty(String filename,
String sectionType, String sectionName,
String key, String value) {
this(filename, sectionType, sectionName, key, value, null);
}
public SetProperty(String filename,
String sectionType, String sectionName,
String key, String value, String comment) {
this(filename, ReferenceTo.sectionAndKey(sectionType, sectionName, key), value, comment);
}
public SetProperty(String filename,
AdvancedPropertyReference propertyReference,
String value, String comment) {
this(filename, propertyReference, value, comment);
}
public SetProperty(String filename,
AdvancedPropertyReference propertyReference,
String value, String comment) {
super(filename);
this.propertyReference = propertyReference;
this.value = value;
this.comment = comment;
}
We need to add a new feature which enables us to append properties not just set and replace them. One way could be to extend the class. But this is overkill. Just adding a new parameter flag should suffice. But this would blow up the number of constructors because you need to include a version with and without the new parameter for each (used) constructor. Here an old friend comes to the rescue: design patterns. Looking at the GoF book shows a good solution to the problem: the builder pattern.
public class SetPropertyBuilder {
private final String filename;
private String sectionType;
private String sectionName;
private String referenceKey;
private String value;
private String comment;
private boolean append;
public SetPropertyBuilder(String filename) {
super();
this.filename = filename;
}
public SetPropertyBuilder set(String key, String newValue) {
this.referenceKey = key;
this.value = newValue;
return this;
}
public SetPropertyBuilder append(String key, String additionalValue) {
set(key, additionalValue);
this.append = true;
return this;
}
public SetPropertyBuilder inSection(String type, String name) {
this.sectionType = type;
this.sectionName = name;
return this;
}
public SetProperty build() {
AdvancedPropertyReference reference = ReferenceTo.key(this.referenceKey);
if (this.sectionType != null && this.sectionName != null) {
reference = ReferenceTo.sectionAndKey(this.sectionType, this.sectionName, this.referenceKey);
}
return new SetProperty(this.filename, reference, this.value, this.comment, this.append);
}
}
Now we can eleminate all but one constructor from the SetProperty command. Adding a new property now yields one new method in the builder.