Platinum Partner
java,frameworks,wicket,code design

The Abuse of Utility Creational Methods

Sometimes I encounter code, which obviously the writer had good intentions in making the development easier and faster. However, in my opinion, it is not. It’s a kind of code that magically creates new instances and attaches one to another.

Usually it will be a static method in a utility class that accepts many parameters, probably Boolean flags among them. A method that in order to understand what exactly it is doing, you’ll need to drill down inside it and check what each parameter does. And to maintain the comments (if there are are any) of this API will probably be a nightmare.

I will show an example of what I mean using Apache Wicket. I’ve been developing an application with Wicket for more than a year now. Wicket resembles Java Swing in many aspects. The concept of a Page in Wicket resembles Java Swing’s JFrame. The concept of a Component that is added to another one is also similar. Below is a code of adding a TextField and a Label to a Form and attaching the Label to the TextField. We want to “attach” the label to the text field for error messages in a Feedback messages (among other things).

TextField patternTextField = new TextField("pattern");
patternTextField.setRequired(true);
patternTextField.setLabel(new ResourceModel("patternKey"));
add(patternTextField);

Below is the code that uses a utility method that does the same thing.

public static FormComponentLabel setFieldWithLabel(MarkupContainer container,String id,FormComponent formComponent,String labelKey,boolean setRequired) {
return setFieldWithLabel(container, id, formComponent, new ResourceModel(labelKey), setRequired);
}

Looking at that line, it’s not clear what exactly is done. In order to understand, below is the drill down of that method.

public static FormComponentLabel setFieldWithLabel(MarkupContainer container,String id,FormComponent formComponent,IModel labelKeyModel,boolean setRequired) {
formComponent.setLabel(labelKeyModel);
if (setRequired) {
formComponent.setRequired(true);
}
FormComponentLabel label = new CAFormComponentLabel(id, formComponent);
container.add(label);
container.add(formComponent);
return label;
}

 Take a look at another sequence of factory methods that do much more on the components.

public static void addFormLabelAndField(MarkupContainer container, String wicketID,String localizationID, boolean required,IValidator... validators) {
addFormLabelAndField(container, wicketID, localizationID, required, true,validators);
}

public static void addFormLabelAndField(MarkupContainer container, String wicketID,String localizationID, boolean required,boolean isVisable,IValidator... validators) {
addFormLabelAndField(container, wicketID, localizationID, required, isVisable, true,null, validators);
}

public static void addFormLabelAndField(MarkupContainer container, String wicketID,String localizationID, boolean required,boolean isVisable,boolean isEnable,AjaxEventBehavior behavior,IValidator... validators) {
addFormComponentsAndErrorFiels(container, new CATextField(wicketID), LabelType.CAFormComponentLabel, wicketID, localizationID, required, isVisable, isEnable, behavior, validators);
}

public static void addFormComponentsAndErrorFiels(MarkupContainer container,FormComponent firstComponent,LabelType labelType, String wicketID,String localizationID, boolean required,boolean isVisable,boolean isEnable,AjaxEventBehavior behavior,IValidator... validators) {
addFormComponentsAndErrorFiels(container, firstComponent, labelType, wicketID, localizationID, required, isVisable, isEnable, behavior,null, validators);
}

public static void addFormComponentsAndErrorFiels(MarkupContainer container,FormComponent firstComponent,LabelType labelType, String wicketID,String localizationID, boolean required,boolean isVisable,boolean isEnable,AjaxEventBehavior behavior,FormComponent labelComponent,IValidator... validators) {
for (IValidator validator : validators) {
firstComponent.add(validator);
}
if (behavior != null){
firstComponent.add(behavior);
}
firstComponent.setRequired(required);
firstComponent.setLabel(new ResourceModel(localizationID));
firstComponent.setEnabled(isEnable);
Component label = null;
switch (labelType) {
case CheckboxLabel:
label = new CheckboxLabel(wicketID+"Lbl", new ResourceModel(localizationID));
break;
case FormComponentLabel:
default:
label = new FormComponentLabel(wicketID+"Lbl", (labelComponent == null) ? firstComponent:labelComponent);
break;
}
label.setVisible(isVisable);
firstComponent.setVisible(isVisable);
container.add(label);
container.add(firstComponent);
}

It’s obvious that the original code is much clearer to read than the one with the utility method. On the other side, it looks as it is easier / faster to use the utility method. So which is better? Although there must be situations that the “utility way” is better, I strongly believe that the “normal way” should be preferred most of the times (after rereading, I strongly believe that it should be preferred ALL THE TIME).

Why? The answer is readability. I think that one of the reasons of writing “the utility way” code is that the developer “doesn’t think ahead”. What I mean by that is that instead of thinking how the code will be easy to understand in a few months from now (readability of code), the developer thinks how to make the programming “of now” faster (let’s write just one line instead of three).

Whenever I write code I keep in mind two things specifically:

  1. Make the code work and test it (which is obvious)
  2. “I write the code to someone else. A person whom I will never meet”

Let me elaborate about number 2. Here’s a quote from Martin Fowler’s Refactoring book: “Any fool can write code that a computer can understand. Good programmers write code that humans can understand.” I’m not saying that I’m a good (nor bad) programmer. All I am saying is that this phrase is in my mind whenever I write code. So, when I write code, I think about the person who will replace me some time in the future. A person that will probably be unfortunate to debug my code without me around to explain to him what’s going on.

So, looking back at the example, my opinion is that although the “utility way code” does what it is supposed to be doing, and may even helps to code faster without tedious repetitions, it is not better. I think that it is worse.

{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}