I believe that every good developer should be familiar with the idea of leaky abstractions, after all we live in a time when many of our computing concepts involve higher and higher levels of abstraction in our coding model. I might go so far as to say that Joel characterizing this notion of Leaky Abstractions is a noteworthy contribution to the field of software development. I like to know what's going on behind the scenes of any tool that I'm using, in case the abstraction breaks and I am forced to pull out my pipe wrench and fix some plumbing. Perhaps this makes me a "Computer Science Elitist" or a Dinosaur who still has a "close to the metal" mindset in an age of abstraction. I like to know what's under the hood.
XML Web Services in .NET is a big abstraction. This abstraction tells me that I don't need to worry much about XML. This abstraction tells me that if I put [WebMethod] on a method, it will handle the plumbing of SOAP endpoints and my clients can interact with this code via discoverable types and I don't need to worry about how things are serialized. There are many cases where these great (and they are great) XML Web Services are leaky abstractions. Some of the more well known ones involve DateTime parsing and Serialization and such. I'll share a new one today to illustrate Leaky Abstractions.
I return Messages from my web services. One of the types inside my message is an enumeration, defined like so:
[Flags]
public enum PullOption
{
None = 0,
PullChangesOnly = 2,
PushChanges = 4,
EmptyTableAfterPush = 8,
StoredProcedure = 16
}
The system handles enums well enough. Note also that I have used the [Flags] attribute. Whenver I see [Flags] I have to do a double take to make sure I'm not writing code that is hard to read or maintain; often times, especially when dealing with the Win32 API, there are so many different options to deal with that [Flags] really is the best way to go about it. This code works fine on the server. Now, on my client, I notice that the results I get are not quite what I expected. The whole abstraction of XML Web Services and WSDL.exe in .NET is broken, and I have to start looking under the hood. My OperationDescription for this enum field looks something like:
<PullOption> None or PullChangesOnly or PushChanges or EmptyTableAfterPush or StoredProcedure</PullOption>
and the WSDL looks something like:
- <s:simpleType name="PullOption">
- <s:restriction base="s:string">
<s:enumeration value="None" />
<s:enumeration value="PullChangesOnly" />
<s:enumeration value="PushChanges" />
....etc. Clearly this abstraction leaks when you want to treat an Enum as Flags. I did not see a special SOAP attribute that would tell the Serializer to handle my Enum as an int, but I didn't spend all day on it either.
I changed the field to an int and now I can write bitwise and/or code on my client. The downside is that this enum must be duplicated to the client via code or assembly sharing now.
Beware leaky abstractions. A good developer uses abstractions and tools to become more productive. A good developer can look under the hood at the internals of an abstractiono, too.