Messages, data and types

One concern I receive quite a bit from folks new to messaging, especially those coming from SOAP and WCF land, is how to preserve the convenience of proxy classes and data contracts that can be shared amongst multiple clients. The problem comes in when looking at coupling, especially around changes in the contract and how to upgrade clients. Clemens Vasters details many of these issues in his screencast on data/contract coupling in messaging.

One thing that grounds all of this is what we consider the message as developers, and what our transport and messaging system considers to be the message. For example, the Azure REST services expose contracts as XML. XML, by itself, and JSON make for great transport formats because the underlying technology provides a fairly universally acceptable common type system. Although your language might need to bridge from your format to theirs, people standardize on ISO formats for standard primitives to maximize interoperability (and minimize serialization mistakes).

Dealing with such large XML documents from a client API can be a pain, however. XML is notoriously finicky with respect to case sensitivity, and I can’t count how many times I’ve been bitten by this when dealing with raw XML and REST APIs. We would need to assume that documentation exists, and until forms become common in REST APIs, it’s difficult to say that HATEOAS will simply solve all these problems of self-describing APIs.

Instead, we often see REST and other messaging clients, out of convenience, build DTOs as a means of representing the message. But first – what is a message? A message is just data. It’s defined by a header and body, where the header is used by the transport/messaging system and the body is ignored (picture courtesy http://www.eaipatterns.com):

However, messages aren’t types. But what about sharing something like this?

[DataContract]
public class PurchaseOrder
{
	private int poId_value;
	
	// Apply the DataMemberAttribute to the property.
	[DataMember]
	public int PurchaseOrderId
	{
	
	    get { return poId_value; }
	    set { poId_value = value; }
	}
}

That’s still not terrible, because underneath the covers our message is still just XML or JSON. We use this type as a description or blueprint of our message, because it’s simpler to describe our message in C# terms instead of a looser type like XML or JSON, which are more difficult to describe and use in C#. I’m ignoring dynamic types in .NET – those to me are a bit of a hack in this case. In WCF, proxy classes get generated on the client side, so we’re still not taking an assembly dependency. This isn’t available in REST or other messaging technologies, leaving clients reliant on documentation to “Get it right” – assuming that they don’t make mistakes translating raw XML or JSON into code building raw XML or JSON on the client side.

So what typically happens in a homogenous environment is that data contract assemblies are shared:

image

Both client and server share a contracts assembly, and use the contracts assembly as a description for how to construct and consume the raw messages.

We introduce coupling on the client side with a raw type shared across the server boundary, but it’s up to those building the system to determine if this sort of coupling introduces any potential risks. When we look at coupling, we must always balance risk. If coupling introduces low risk, it might be acceptable (assuming we’re more or less prescient in our future system’s design).

From my experience, as long as the messaging infrastructure doesn’t assume that the message is built from a type and therefore leak those concerns, this sort of model can be a nice compromise in ecosystems where types as blueprints for messages ensures safety in our message construction and consumption. It’s similar to building MVC applications around View Models – they’re a blueprint for building forms, and a means of accepting raw form POSTs. Side note – I found it hilarious that the Rails folks ran into that mass assignment security problem – it’s a problem I’ve never, ever had in MVC.

But that’s the real kicker – our messaging infrastructure can’t assume types, as the message is not the type. We might use a type as a convenience to build and consume, as we do in MVC, but ultimately, our messaging infrastructure can’t assume a type. MVC handles this quite well, with model metadata and its ModelState objects. The original request is always preserved in its raw form (dictionary of strings), but the model provided to the controller action is an approximation of that request.

It’s only when we assume that we’ve literally shared types that we’re going to slip into real type coupling, and everything that SOAP failed to deliver comes back again.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in Messaging, SOA. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://twitter.com/DatawindAakash3 DatawindAakash3

    This is an amazing post , i really like this. You people really wrote very well , keep posting like this , i will appriciate you for ths great post, thank you so much for this article.
    Best Pc Tablets

  • Pingback: Messages, data and types | CodingScoop | Scoop.it

  • Steve

    If you are using types as a blueprint for your messages that works great for the producer side of the equation. But what about the consumer? Won’t you have to include some metadata on the message to give the consumer a hint as to how to interpret the message? I assume from the above that you would consider metadata regarding the type to be too leaky.

    It seems that many .NET frameworks use the type not only for serialization at the producer and consumer, but for routing of the messages to the appropriate handler within a consumer (IHandle or similar). It seems you wouldn’t be able to do this type of routing w/o passing/sharing a hint as to the type that was encoded in the message?

  • http://twitter.com/raykolbe Raymond

    @f974887ff60274e84f0cd039f051650a:disqus I use meta data “type” on my external events. Clients have to know the context of the information. How else would clients be able to process information correctly in their context?

  • Dale Anderson

    I’m currently looking at using pure interfaces as message types. NServiceBus supports interfaces as messages, and JSON.NET combined with ImpromptuInterface works really well for wrapping interfaces around JSON. It allows you to compose your message schemas from many simple structures.

    Requires a bit more exploration, but on the surface it seems like a really good compromise between the implicit / dynamic nature of JSON and the explicit nature of the CLR.

  • http://www.kizi-2.net/ kizi2

    very good article, the message is personal matter and I want them to be safe.

  • http://www.nx8.name/ nx8

    Great stuff here. The information and the detail were just
    perfect.