The *Specified anti-pattern

I’ve spent far too much energy on this already. But it needs to be said to a broader audience. When your svc code creates *Specified properties for struct properties you’re doing more harm than good.

WCF allows you to define certain output elements as optional. This means that they won’t be sent in the message body. When the message is deserialize the message object will contain a property for that element but somehow there must be an indication that the element wasn’t received. If the type is nullable (like a string), no problem. But if the type is a struct, which aren’t nullable by definition, then how do you indicate the lack of a value? Welcome the *Specified boolean property.

So if our message has a DateTime element that has been marked as optional on transmission, and there is no data, that element won’t be included in the message. When WCF deserializes that message into the object, the property for the element isn’t nullable so it has to put a value into it. In the case of DateTime it will put in DateTime.MinValue which is an actual valid date. So for you to know that there wasn’t an value (or element for that matter) you will have to check the correlated *Specified property. Now the consumer of the WCF service has to write if…else statements in their code to translate the lack of value into something meaningful; like a Nullable<DateTime>.

As soon as you see if…else statements like this you can be assured that you have a leaky abstraction. The consumer of the WCF service has too much knowledge of the WCF service’s implementation details. The consumer shouldn’t care to have to look at one value to know if another value should be empty or not. It should just look at the value and be able to say “Oh, this is empty”. That’s why we have nullable types. In a lot of situations having no value is a valid state for an object or property. Worded another way, the absence of data is data in itself.

If we have to deal with checking the *Specified properties we’ve just introduced a piece of conditional logic into our application for every pair of properties that use this pattern. Conditional logic implementation are some of the easiest code to get wrong. In this case you may get your true and false if…else condition reversed. You may simply forget to do the conditional check. The use of a pattern that requires the implementation of conditional logic immediately makes your code more brittle and error prone.

On top of that, patterns like the *Specified one are not normally seen in the wild. The inexperience that people have with it means that they will make mistakes, like forgetting to check the *Specified property before working with its partner property. Again, we see the pattern introducing possible points of failure.

All of these problems could be alleviated if we adhered to two ideas: good encapsulation and null data being valid data. Until then, avoid the *Specified pattern like the plague.

Posted By: Donald Belcham

Published at

Originally posted at

Comments

No comments posted yet.