Can we Have Zen WET Code?

The DRY Principle says you Don’t Repeat Yourself when writing code. Encoding the same knowledge in two distinct locations means that if the information changes, we need to update both of them.

Failing to apply this principle leads to what is humorously called WET code. (“Write Everything Twice” or “We Enjoy Typing”, according to Wikipedia editors).

What does this mean in terms of zen levels?

There can be two reasons for repeating code (whether they are good or bad reasons is out of scope here):

  • To implement two similar but distinct features of a program, for instance two similar pages of a website
  • To implement two aspects or two representations of the same feature, for instance computing the url of the same page for two different links.

The two situations are different.

In the first case, they are an opportunity to factor common code. The two components drifting out of sync won’t cause bugs in the application (at worst some inconsistent behaviour). If each page of a website contains the same HTML code in the header, for instance, forgetting to update one of them to reflect a change in the website’s visual style will make the pages individually look okay, at the expense of consistency and professionalism.

In the second case we have the same piece of knowledge recorded in two or more locations. In database design this is called denormalisation. If those locations do not agree, the program will malfunction in some way, maybe by computing incorrect data or by crashing. In other words it is essential that those pieces be kept in sync, and therefore the gravity of that “WET code” is directly linked to its zen level.

It’s okay to repeat code as long as its synchronisation is guaranteed by a deep zen level.

Consider the following Java example:

List<String> allMyFriends = new ArrayList<String>();

Or wait, we have even worse: some classes need access to the Class object they’re parametrised with:

MyClass<String> myObject = new MyClass<String>(String.class);

This is clearly a redundancy of the second type here. We are saying three times that myObject deals with Strings, and if we change one of the three items the program is not going to work.

It may seem trivial here, because the three Strings are on the same line of code (in other words it is automatically Level Three), but it needs not be so. The type of myObject, and the type parameter of MyClass can be moved away from each other (assuming for the sake of argument that the type is passed through a method instead of by constructor. In a real situation, MyspecificClass would probably pass String.class itself, specifically in the name of DRY)

class MySpecificClass extends MyClass<String> {}

private MyClass<String> myObject;

void someMethod() {
  myObject = new MySpecificClass().setType(String.class);
}

But how bad is it, really?

As we are saying three times the same thing, what happens if we get one of them wrong?

MyClass<Tomato> myObject = new MyClass<String>(String.class);

Compilation error: MyClass<String> can’t be assigned to a MyClass<Tomato> vairiable.

MyClass<String> myObject = new MyClass<Tomato>(String.class);

Two compilation errors: MyClass<Tomato> can’t be assigned to a MyClass<String> object, AND the MyClass<Tomato> constructor expects a parameter of type Class<Tomato> but got a Class<String> instead.

MyClass<String> myObject = new MyClass<String>(Tomato.class);

Compilation error: the MyClass<String> constructor expects a parameter of type Class<String> but got a Class<Tomato> instead.

In other words that small piece of code does not follow DRY principles because it repeats three times the same piece of information. However it is zen Level One because failing to keep the components in sync immediately produces a compilation error.

Going back to our old definition of quality, quality code should be robust against future bugs (check), against bugs present in the initial version (check). It should be easy to understand (check: code with more redundancy is easier to understand). Finally it should not require lots of typing (fail: we’re typing more). In other words, failing to follow DRY does not lead to lower quality program. What really matters is the zen level of their synchronisation.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" cssfile="">