Rockford Lhotka's Blog

Home | Lhotka.net | CSLA .NET

 Monday, May 31, 2004

A few weeks ago I posted an entry about a solution to today's problem with serializing objects that declare events. It was pointed out that there's a better way to handle the list of delegates, and so here's a better version of the code.

  _
  Private mNonSerializable As EventHandler
  Private mSerializable As EventHandler

  Public Custom Event NameChanged As System.ComponentModel.EventHandler
    AddHandler(ByVal value As System.ComponentModel.EventHandler)
      If value.Target.GetType.IsSerializable Then
        mSerializable = CType([Delegate].Combine(mSerializable, value), EventHandler)

      Else
        mNonSerializable = CType([Delegate].Combine(mNonSerializable, value), EventHandler)
      End If
    End AddHandler

    RemoveHandler(ByVal value As System.ComponentModel.EventHandler)
      If value.Target.GetType.IsSerializable Then
        mSerializable = CType([Delegate].Remove(mSerializable, value), EventHandler)

      Else
        mNonSerializable = CType([Delegate].Remove(mNonSerializable, value), EventHandler)
      End If
    End RemoveHandler

    RaiseEvent(ByVal sender As Object, ByVal e As System.ComponentModel.EventArgs)
      If mNonSerializable IsNot Nothing Then mNonSerializable(sender, e)
      If mSerializable IsNot Nothing Then mSerializable(sender, e)
    End RaiseEvent
  End Event

Monday, May 31, 2004 9:37:08 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
 Saturday, May 29, 2004

This week at Tech Ed in San Diego I got an opportunity to talk to David Chappell and trade some thoughts about SOA, Biztalk and Web services. I always enjoy getting an opportunity to talk to David, as he is an incredibly intelligent and thoughtful person. Better still, he always brings a fresh perspective to topics that I appreciate greatly.

 

In this case we got to talking about his Biztalk presentation, which he delivered at Tech Ed. Unfortunately I missed the talk due to other commitments, but I did get some of the salient bits from our conversation.

 

David put forth that the SOA world is divided into three things: services, objects and data. Services interact with each other following SOA principles of loose coupling and message-based communication. Services are typically composed of objects. Objects interact with data – typically stored in databases.

 

All of this makes sense to me, and meshes well with my view of how services fit into the world at large. Unfortunately we had to cut the conversation short, as I had a Cabana session to deliver with Ted Neward, Chris Kinsman and Keith Pleas. Interestingly enough, Ted and I got into some great discussions with the attendees of the session about SOA, the role of objects and where (or if) object-relational mapping has any value.

 

But back to my SOA conversation with David. David’s terminology scheme is nice, because it avoids the use of the word ‘application’. Trying to apply this word to an SOA world is problematic because it becomes rapidly overloaded. Let’s explore that a bit based on my observations regarding the use of the word ‘application’.

 

Applications expose services, thus implying that applications are “service hosts”, or that services are a type of interface to an application. This makes sense to most people.

 

However, we are now talking about creating SOA applications. These are applications that exist only because they call services and aggregate data and functionality from those services. Such applications may or may not host services in and of themselves.

 

If that wasn’t enough, there’s the idea being that tiers within an application should expose services for use by other tiers in the application. It is often postulated that these tier-level services should be public for use by other applications as well as the ‘hosting’ application.

 

So now things are very complex. An application is a service. An application hosts services. An application is composed of services. An application can contain services that may be exposed to other parts of itself and to others. Oy!

 

Thus, the idea of avoiding the word ‘application’ strikes me as being a Good Thing™.

The use of the trademark symbol for this phrase flows, as far as I know, from J. Michael Straczynski (jms). It may be a bit of Babylon 5 insider trivia, but every time I use the phrase, the ™ goes through my head...

Later in the conference, David and I met up again and talked further. In the meantime I’d been thinking that something was missing from David’s model. Specifically, it is the people. Not only users, but other people that might interact with the overall SOA system at large. David put forth that there’s a couple other things in the mix – specifically user interfaces and workflow processes, and that this is where the people fit in.

 

However, I think there’s a bit more to it than this. I think that for an SOA model to be complete, the people need to truly fit into the model itself. In other words, they must become active participants in the model in the same way that services, objects and data are active participants. Rather than saying that a user interface is another element of the model, I propose that the human become another element of the model.

 

As an aside, I realize that there’s something a bit odd or even scary about treating human beings as just another part of a system model, but I think there’s some value in this exercise. This is no different than what business process analysts do when they are looking at manufacturing processes. Humans are put at the same level as machines that are part of the process and are assigned run rates, costs, overhead and so forth. From that perspective, applying this same view to software seems quite valid to me.

 

So, the question then becomes whether a human is a new entity in the model, or is a sub-type of service, object or data. The way to solve this is to see if a human can fit the role of one of the three pre-existing model concepts.

 

My first instinct was to view a human as a service. After all, services interact with other services, and the human interacts with our system and visa versa. However, services interact using loose coupled, message-based communication. Typically our systems interact with users through a Windows or Web interface. This is not message-based, but rather is really quite tightly coupled. We give the user specific, discrete bits of data and we get back specific, discrete bits of data.

 

Certainly there are examples of message-based interaction with humans. For instance, some systems send humans an email or a fax, and the human later responds in some fashion. Even in this case, however, the human’s response is typically tightly coupled rather than message-based.

 

Ultimately, then, I don’t think we can view a human as a type of service due to the violation of SOA communication requirements.

 

How about having a human be an object? Other than the obvious puns about objectification of humans (women, men or otherwise), this falls apart pretty quickly. Objects live inside of services and interact with other objects within that service. While it is certainly true that objects use tightly coupled communication, and so do humans, I think it is hard to argue that a human is contained within a given service.

 

Only one left. Are humans data? Data is used by objects within a service. More generally, data is an external resource that our system uses by calling a service, which uses its objects to interact with this external resource. Typically this is done by calling stored procedures, where we send the resource a set of discrete data or parameters, and the resource returns a set of discrete data.

 

This sounds terribly similar to how our system interacts with humans. If we turn the idea of a user interface on its head, we could view our system as the actor, and the human as a resource. In such a case, when we display data on a screen, we are basically providing discrete data parameters to a resource (the human) in much the same way we provide parameters to a database via a stored procedure call. The human then responds to our system by providing a set of results in the form of discrete data. This could easily be viewed as equivalent to the results of a stored procedure call.

 

Following this train of thought, a human really can be viewed as a resource very much like a data source. Any user interfaces we implement are really nothing more than a fancy data access layer within a service. A bit more complex than ADO.NET perhaps, but still the same basic concept. Our system needs to retrieve or alter data and we’re calling out to an external resource to get it.

 

I put this idea forward to David, who thought it sounded interesting, but didn’t see where it helped anything. I can’t say that I’m convinced that it helps anything either, but intuitively I think there’s value here.

 

I think the value may lie in how we describe our overall system. And this is important, because SOA is all about the overall systems in our organizations.

 

Nothing makes this more evident than Biztalk 2004 and its orchestration engine. This tool is really all about orchestrating services together into some meaningful process to get work done. However, people are part of almost any real business process, which implies that somewhere in most Biztalk diagrams there should be people. But there aren’t. Maybe that’s because people aren’t services, so Biztalk can’t interact with them directly. Instead, Biztalk needs to interact with services that in turn interact with the people as a resource – asking for them to provide data, or to perform some external action and report the result (which is again, just data).

 

Then again, maybe my thought processes are just totally randomized after being on the road for four weeks straight and this last week being Tech Ed, which is just a wee bit busy (day and night)… I guess only time will tell. When we start seeing humans show up in our system diagrams we’ll get a better idea how and where we, as a species, fit into this new SOA world order.

Saturday, May 29, 2004 8:53:54 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
 Saturday, May 15, 2004

In .NET 1.x there's a problem serializing objects that raise events when those events are handled by a non-serializable object (like a Windows Form). In .NET 2.0 there's at least one workaround in the form of Event Accessors.

The issue in question is as follows.

I have a serializable object, say Customer. It raises an event, say NameChanged. A Windows Form handles that event, which means that behind the scenes there's a delegate reference from the Customer object to the Form. This delegate that is behind the event is called a backing field. It is the field that backs up the event and actually makes it work.

When you try to serialize the Customer object using the BinaryFormatter or SoapFormatter, the serialization automatically attempts to serialize any objects referenced by Customer - including the Windows Form. Of course Windows Form objects are not serializable, so serialization fails and throws a runtime exception.

Normal variables can be marked with the NonSerialized attribute to tell the serializer to ignore that variable during serialization. Unfortunately, an event is not a normal variable. We don't actually want to prevent the event from being serialized, we want to prevent the target of the event delegate (the Windows Form in this example) from being serialized. The NonSerialized attribute can't be applied to targets of delegates, and so we have a problem.

In C# it is possible to use the field: target on an attribute to tell the compiler to apply the attribute to the backing field rather than the actual variable. This means we can use [field: NonSerialized()] to declare an event, which will cause the backing delegate field to be marked with the NonSerialized attribute. This is a bit of a hack, but does provide a solution to the problem. Unfortunately VB.NET doesn't support the field: target for attributes, so VB.NET doesn't have a solution to the problem in .NET 1.x.

Though there is a solution in C#, the solution is not an elegant solution, so in both VB.NET and C# we really need a better answer. I have spent a lot of time talking with the folks in charge of the VB compiler, and hope they come up with an elegant solution for VB 2005. In the meantime, here’s an answer that will work in either language in .NET 2.0.

In VB 2005 we’ll have the ability to declare an event using a “long form” using a concept called an Event Accessor. Rather than declaring an event using one of the normal options like:

Public Event NameChanged()

or

Public Event NameChanged As EventHandler

where the backing field is managed automatically, you’ll be able to declare an event in a way that you manage the backing field:

  Public Custom Event NameChanged As EventHandler

    AddHandler(ByVal value As EventHandler)

    End AddHandler

    RemoveHandler(ByVal value As EventHandler)

    End RemoveHandler

    RaiseEvent(ByVal sender As Object, ByVal e As EventArgs)

    End RaiseEvent

  End Event

In this model we have direct control over management of each event target. When some code wants to handle our event, the AddHandler block is invoked. When they detach from our event the RemoveHandler block is invoked. When we raise the event (using the normal RaiseEvent keyword), the RaiseEvent block is invoked.

This means we can declare our backing field to be NonSerialized if we so desire. Better yet, we can have two backing fields – one for targets that can be serialized, and another for targets that can’t be serialized:

  _

  Private mNonSerializableHandlers As New Generic.List(Of EventHandler)

  Private mSerializableHandlers As New Generic.List(Of EventHandler)

Then we can look at the type of the target (the object handling our event) and see if it is serializable or not, and put it in the appropriate list:

  Public Custom Event NameChanged As EventHandler

    AddHandler(ByVal value As EventHandler)

      If value.Target.GetType.IsSerializable Then

        mSerializableHandlers.Add(value)

      Else

        If mNonSerializableHandlers Is Nothing Then

          mNonSerializableHandlers = _

            New Generic.List(Of EventHandler)()

        End If

        mNonSerializableHandlers.Add(value)

      End If

    End AddHandler

    RemoveHandler(ByVal value As EventHandler)

      If value.Target.GetType.IsSerializable Then

        mSerializableHandlers.Remove(value)

      Else

        mNonSerializableHandlers.Remove(value)

      End If

    End RemoveHandler

    RaiseEvent(ByVal sender As Object, ByVal e As EventArgs)

      For Each item As EventHandler In mNonSerializableHandlers

        item.Invoke(sender, e)

      Next

      For Each item As EventHandler In mSerializableHandlers

        item.Invoke(sender, e)

      Next

    End RaiseEvent

  End Event

The end result is that we have declared an event that doesn’t cause problems with serialization, even if the target of the event isn’t serializable.

This is better than today’s C# solution with the field: target on the attribute, because we maintain events for serializable target objects, and only block serialization of target objects that can’t be serialized.

Saturday, May 15, 2004 10:52:16 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
On this page....
Search
Archives
Feed your aggregator (RSS 2.0)
July, 2014 (2)
June, 2014 (4)
May, 2014 (2)
April, 2014 (6)
March, 2014 (4)
February, 2014 (4)
January, 2014 (2)
December, 2013 (3)
October, 2013 (3)
August, 2013 (5)
July, 2013 (2)
May, 2013 (3)
April, 2013 (2)
March, 2013 (3)
February, 2013 (7)
January, 2013 (4)
December, 2012 (3)
November, 2012 (3)
October, 2012 (7)
September, 2012 (1)
August, 2012 (4)
July, 2012 (3)
June, 2012 (5)
May, 2012 (4)
April, 2012 (6)
March, 2012 (10)
February, 2012 (2)
January, 2012 (2)
December, 2011 (4)
November, 2011 (6)
October, 2011 (14)
September, 2011 (5)
August, 2011 (3)
June, 2011 (2)
May, 2011 (1)
April, 2011 (3)
March, 2011 (6)
February, 2011 (3)
January, 2011 (6)
December, 2010 (3)
November, 2010 (8)
October, 2010 (6)
September, 2010 (6)
August, 2010 (7)
July, 2010 (8)
June, 2010 (6)
May, 2010 (8)
April, 2010 (13)
March, 2010 (7)
February, 2010 (5)
January, 2010 (9)
December, 2009 (6)
November, 2009 (8)
October, 2009 (11)
September, 2009 (5)
August, 2009 (5)
July, 2009 (10)
June, 2009 (5)
May, 2009 (7)
April, 2009 (7)
March, 2009 (11)
February, 2009 (6)
January, 2009 (9)
December, 2008 (5)
November, 2008 (4)
October, 2008 (7)
September, 2008 (8)
August, 2008 (11)
July, 2008 (11)
June, 2008 (10)
May, 2008 (6)
April, 2008 (8)
March, 2008 (9)
February, 2008 (6)
January, 2008 (6)
December, 2007 (6)
November, 2007 (9)
October, 2007 (7)
September, 2007 (5)
August, 2007 (8)
July, 2007 (6)
June, 2007 (8)
May, 2007 (7)
April, 2007 (9)
March, 2007 (8)
February, 2007 (5)
January, 2007 (9)
December, 2006 (4)
November, 2006 (3)
October, 2006 (4)
September, 2006 (9)
August, 2006 (4)
July, 2006 (9)
June, 2006 (4)
May, 2006 (10)
April, 2006 (4)
March, 2006 (11)
February, 2006 (3)
January, 2006 (13)
December, 2005 (6)
November, 2005 (7)
October, 2005 (4)
September, 2005 (9)
August, 2005 (6)
July, 2005 (7)
June, 2005 (5)
May, 2005 (4)
April, 2005 (7)
March, 2005 (16)
February, 2005 (17)
January, 2005 (17)
December, 2004 (13)
November, 2004 (7)
October, 2004 (14)
September, 2004 (11)
August, 2004 (7)
July, 2004 (3)
June, 2004 (6)
May, 2004 (3)
April, 2004 (2)
March, 2004 (1)
February, 2004 (5)
Categories
About

Powered by: newtelligence dasBlog 2.0.7226.0

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2014, Marimer LLC

Send mail to the author(s) E-mail



Sign In