Monday, January 24, 2005
« More on web services and DataSet objects... | Main | dasBlog upgrade and a trip to Chicago »

Sahil has some interesting thoughts on the web service/DataSet question as well.

 

He spends some time discussing whether “business objects” should be sent via a web service. His definition of “business object” doesn’t match mine, and is closer to Fowler’s data transfer object (DTO) I think.

 

It is important to remember that web services only move boring data. No semantic meaning is included. At best (assuming avoidance of xsd:any) you get some limited syntactic meaning along with the data.

 

When we talk about moving anything via a web service, we’re really just talking about data.

 

When talking about moving a “business object”, most people think of something that can be serialized by web services – meaning by the XmlSerializer. Due to the limitations of the XmlSerializer this means that the objects will have all their fields exposed as public fields or read-write properties.

 

What this means in short, is that the “business objects” can not follow good OO design principles. Basically, they are not “business objects”, but rather they are a way of defining the message schema for the web service. They are, at best, data transfer objects.

 

In my business objects books and framework I talk about moving actual business objects across the wire using remoting. Of course the reality here is that only the data moves – but the code must exist on both ends. The effective result is that the object is cloned across the network, and retains both its data and the semantic meaning (the business logic in the object).

 

You can do this with web services too, but not in a “web service friendly” way. Cloning an object implies that you get all the data in the object. And to do this while still allowing for encapsulation means that the serialization must get private, friend/internal and protected fields as well as public ones. This is accomplished via the BinaryFormatter. The BinaryFormatter generates and consumes streams, which can be thought of as byte arrays. Thus, you end up creating a web service that moves byte arrays around. Totally practical, but the data is not human-readable XML – it is Base64 encoded binary data. I discuss how to do this in CSLA .NET on my web site.

 

Now we are talking about moving business objects. Real live, OO designed business objects.

 

Of course this approach is purely for n-tier scenarios. It is totally antithetical to any service-oriented model!

 

For an SO model you need to have clearly defined schemas for your web service messages, and those should be independent from your internal implementation (business objects, DataSets or whatever). I discuss this in Chapter 10 of my business objects books.


Monday, January 24, 2005 11:34:21 AM (Central Standard Time, UTC-06:00)
Almost.

If you work with you "business objects" you need to load them from a database. When the object is loaded, then you can serialize it. You retrieve an Order (header and details), and send it over the wire. That works great with .net remoting. Then in the client side you write Order.Customer.Name. At that moment you probably need to retrieve the customer from the database. If you are in your middle tier server that works nice. If you are in your rich client app then you have a problem. Or you make your "business object" MarshalByRef and pay a high performance price, or you need to redesign your application to make it work in multiple tiers.

Peter
Monday, January 24, 2005 12:17:02 PM (Central Standard Time, UTC-06:00)
Peter, this is the type of scenario that is covered in my business objects books. You are right, extra infrastructure is required to make the process seamless. Often that infrastructure can be codified into a framework, allowing you to easily construct business objects that are largely location independent and can work on the smart client as well as the middle-tier server.
Monday, January 24, 2005 12:59:03 PM (Central Standard Time, UTC-06:00)
Rocky,

Thanks for your response. Can I see a one liner definition of business objects per you?

My definition is --
A class that encapsulates both the data, and it's validation logic - i.e. intelligent data. <-- That's a biz object. And I do advocate that model all around since that means my validations sits in my business object, not all the 60 layers it goes thru (alongwith other advantages).

And basically what I had been arguing that web services transferring boring intrinsic data need that api dll on the other end that includes not only metadata, but also the intelligence with it. So that rule has been broken long time back. (Because hey, everyone does that now :) ).

Anyway, I'm busier at work today than Michael Jackson at a daycare. But I'm gonna be readin' all the developments around this rather interesting discussion later tonight.

I suspect though - at the end of the day - we are both talking the same thing - just different perspectives.

Later :)

- SM
Monday, January 24, 2005 1:11:19 PM (Central Standard Time, UTC-06:00)
Allright, my curiousity piqued my interest, and I did read your words in not such a rush ---

And now I agree.

You are absolutely right in saying that moving true business objects using binaryformatter thus reading the internal privates and friendlies is breaking the webservice "philosophy" - which is what I mentioned in my blog - people have broken that philosophy long back. There has been sufficient discussion and advocation of using BinaryFormatter on webservices on the internet. As a matter of fact - .NET 2.0 actually has a remoting format = binary on a dataset - that I think will work even on a webservice - in a model you describe above (Non web service way).

It is for that reason that I feel people will continue to and more increasingly remote datasets/tables as 2.0 gets wider acceptance. And that they will do so - without incurring the negative bloat effects - and yeah they will break the web service philosophy - which they already broke in 1.1.

In that sense - I think we are talking about the same thing - except I don't write off datasets as completely unusable. I just say, they are not as good as a well written BO - but they are an acceptable solution in certain situations.

Though u just made me spend 50 bucks now ... I gotta buy ur book.
Monday, January 24, 2005 1:14:00 PM (Central Standard Time, UTC-06:00)
Sahil, I think our definitions match then. However, if you follow decent OO design you'll invariably end up with objects that can't be serialized with the limits of the XmlSerializer and thus can't be passed directly through web services.

If the intent is to do SO, they SHOULDN'T be passed directly anyway, because that would break encapsulation.

If the intent is to do n-tier then we have a problem. This is where manual use of the BinaryFormatter comes into play, allowing you to pass "real" business objects (with decent OO design) via a web service in the form of a byte array.
Monday, January 24, 2005 2:55:02 PM (Central Standard Time, UTC-06:00)
Ahh .. I see it now .. I think we were singing the same song .. just different octaves.

I'll blog about it later during the day !! :)

Thanks !!
Monday, January 24, 2005 10:32:11 PM (Central Standard Time, UTC-06:00)
Blogged 'bout it !! :)

http://dotnetjunkies.com/WebLog/sahilmalik/archive/2005/01/24/48186.aspx
Thursday, January 27, 2005 8:53:21 AM (Central Standard Time, UTC-06:00)
But why would you use the native xmlserializer? We can write our own serializer that will serialize private fields as well, can't we?

I think I'll order your book just to read chapter 10 ;-) I'd say that our 'clearly defined schema' would at the very least define all values that we need in our business object.
Ruurd Boeke
Thursday, January 27, 2005 11:49:16 AM (Central Standard Time, UTC-06:00)
Writing a serializer that can serialize object graphs is non-trivial.

Writing one to serialize a single object isn't hard, and you could do what you suggest using reflection quite easily. It might be slow, but it would work fine.

But handling an object graph, in particular one that includes circular references between various objects, is a pretty difficult endeavor. Again, it can be done using reflection to get at the private fields, but the hard part is to follow the graph without duplication of data or going into an endless loop. And of course you need to be able to reestablish the relationships when you deserialize the byte stream on the other end.

Obviously these problems can all be solved, as evidenced by the BinaryFormatter. But writing your own is a non-trivial undertaking. And doing it with reflection means that it will be on the slow side...
Thursday, January 27, 2005 1:20:43 PM (Central Standard Time, UTC-06:00)
Thank you. But it being non-trivial only means there is a market for a great serializing-tool, because it would solve many of the problems I'm facing writing a good n-tier + soa enterprise app.

I know of one OR-Mapper that claims to generate your business object + give the option to serialize to xml. I'll check that out.
Ruurd Boeke
Thursday, January 27, 2005 2:49:08 PM (Central Standard Time, UTC-06:00)
Ahh, if you enter into the realm of code-gen then matters are different. If you code-gen your complete class (or at least everything directly dealing with your fields) then the code-gen can spit out code comparable to what I had in my VB6 business objects books.

There's still the potential issue of serializing the object graph, but the reality is that most code-gen/ORM tools just don't gen stuff that is complex, so they dodge the issue. As long as your data model and business object model aren't too complex (and your objects can be defined along data-centric lines) then they can be quite helpful.
Friday, January 28, 2005 4:07:31 AM (Central Standard Time, UTC-06:00)
Okay, great. I hope indigo will help in this regard. ;-)
Ruurd Boeke
Friday, January 28, 2005 12:49:36 PM (Central Standard Time, UTC-06:00)
Two friands and I are in the planning stage of an open source project called NTransfer that will use reflection to de/serialize business/domain objects to and from xml (including private fields) and with the ability to handle cyclic references.

Since the domain model is a network data structure (the object graph you can get from following all references from a single root object may be very large) the most important aspect of suct a Document/Object Mapper is to be able to limit the way relationships should be traversed by the serializer.

Mapping configurations in separate xml files will allow you to define how to extract hierarcichal tree structures from your domain model and to define different such trees for different services.

/Mats
Friday, January 28, 2005 6:44:26 PM (Central Standard Time, UTC-06:00)
Very interesting Mats! I've been looking into how the soap formatter deals with graphs and have been contemplating building my own xmlFormatter. I was really wondering why nobody had already build one (it's hard, but the binary and soap formatter do pull it off).
I think it would be of enormous help.

Until then, I'll stick with writing a simple surrogate.
Ruurd Boeke
Saturday, January 29, 2005 9:59:48 AM (Central Standard Time, UTC-06:00)
Hi Ruurd,

Actually, Ntransform will have to be slightly more competent than even the Soap and Binary formatters. They share the aspect that they have to deal with cyclic references, but I wouldn't say that this is quite as tricky as Rocky alludes to in his comments. All that's needed is an ArrayList that you hold internally in your serializer. If you think of the serializer as a Visitor (using the Visito pattern, I mean) just create an internal ArrayList called "VisitedObjects" for keeping track of where you've been so you don't serialize the same object twice.

What requires a wee bit more sophistication from the serializer is to be able to define limitations to the object graph in an xml mapping file. The Soap and Binary formatters just serialize all the referenced objects they can find (but not serializing the same object twice, thanks to a VisitedObjects collection) rendering potentially very large graphs when trying to serialize a domain object that is part of a network data structure. Also, NTrasform will support property paths, meaning that an attribute of the order element called "CustomerName" could be mapping to Order.Customer.Name.

/Mats
Saturday, January 29, 2005 10:17:35 PM (Central Standard Time, UTC-06:00)
Mats, I will be interested to see your results. In particular I am interested from the perspective of .NET CF, which doesn't support the BinaryFormatter and thus today has no way to serialize true object graphs. If your reflection-based solution works on CF as well as normal .NET it may offer a very realistic way to make CSLA .NET work (in substantial part) on CF.
Sunday, January 30, 2005 7:15:27 AM (Central Standard Time, UTC-06:00)
Rocky,

Interesting. I don't have much experience with CF so far and wasn't aware of this limitation (no Binary formatter). Given this, I'll do my best to see if NTransfer can't be made to run on CF. Thanks for the idea!

/Mats
Comments are closed.