Monday, 14 February 2011

Agatha rrsl, WCF and Collection data types

The devil is in the details. Read the documentation of every library you use. Reason about your code.

I have been recently refactoring and reviewing code of a project in order to move it from WPF to Silverlight. (I will make a series of posts on the trouble and horror that I met during this exercise)

In this production LoB system we have chosen to work with Agatha, a request-response service layer sitting on top of WCF that simplifies communication with the back-end, greatly improves modularity and really helps with maintainability (you should definitely take a look in this project if you are serious about your service layer.) Building our messages (classes) for our layer I noticed that we have used interfaces where we needed collections i.e. IList, ICollection etc. It seemed a strange choice from the beginning and down the road but it actually proved terribly wrong.

Suggestion: Always read the documentation.

So the problem lies in the way WCF decides to serialize/deserialize a collection when we use interfaces instead of concrete types. And it's cleanly explained in a simple to read MSDN article. Here is what's really going on:
When you declare, for example, an IEnumerable on your message/class that is going to be sent through the wire then the serialization engine chooses a type that implements the declared interface. So in my case it was choosing the ReadOnlyCollection causing me serious troubles in updating the state of my application on the backend. In general I have serious issues with libraries or practices that make me loose control over my code so I immediately refactored the whole thing.

I later on noticed that the same guys who wrote the code had made another quite strange choice which made me understand how this mess was created. The were using interfaces everywhere (OMG!) even in method return types. Well I don't want to go into the details of basic OO theories like abstraction or polymorphism but I will make a note here: it's considered good practice to have your argument types as generic as possible, i.e. use interfaces and your return types as specific as possible. It's your problem if you tied the calling code to the specific return type instead of using an interface not the method's. Your implementation has a single unit of change, the method body, and your code can be refactored like a charm. The overuse of interfaces is a common misconception of a lot of programmers who just learned about code design...

No comments:

Post a Comment