Retire the Tenets

John Heintz and I continue to be in mostly violent agreement. It’s kinda like me saying “You da architect! Look at my massive scale EAI Mashup!” and having him respond “No, you da architect! The SOA tenets drive me bonkers!” Makes you wonder what would happen after a few beers. What’s the architect version of Tastes Great, Less Filling? ^[Not that you would catch me drinking Miller Lite. Ever.]

Speaking of the tenets, John gives them a good shredding:

Tenet 1: Boundaries are Explicit
(Sure, but isn’t everything? Ok, so SQL based integration strategies don’t fall into this category. How do I build a good boundary? What will version better? What has a lower barrier to mashup/integration?)

Tenet 2: Services are Autonomous
(Right. This is a great goal, but provides no guidance or boundaries to achieve it.)

Tenet 3: Services share schema and contract, not class
(So do all of my OO programs with interface and classes. What is different from OO design that makes SOA something else?)

Tenet 4: Service compatibility is based upon policy
(This is a good start: the types and scope of policy can shape an architecture. The policies are the constraints in a system. There not really defined though, just a statement that they should be there.)

Ah, I feel better getting that out.

As John points out, the four tenets aren’t particularly useful as guidance. They’re too high level (like Mt. Rainier high) to be really actionable. They’re like knowing a pattern’s name but not understanding how and when to use the actual pattern. However, I don’t think the tenets were ever intended to be guidance. Instead, they were used to shift the conversation on how to build distributed applications just as Microsoft was introducing the new distributed application stack @ PDC03.

John’s response to the first tenet makes it sound like having explicit boundaries is obvious. And today, maybe it is. But back in 2003, mainstream platforms typically used a distributed object approach to building distributed apps. Distributed objects were widely implemented and fairly well understood. You created an object like normal, but the underlying platform would create the actual object on a remote machine. You’d call functions on your local proxy and the platform would marshal the call across the network to the real object. The network hop would still be there, but the platform abstracted away the mechanics of making it. Examples of distributed object platforms include CORBA via IOR, Java RMI, COM via DCOM and .NET Remoting.

The (now well documented and understood) problem with this approach is that distributed objects can’t be designed like other objects. For performance reasons, distributed objects have to have what Martin Fowler called a “coarse-grained interface”, a design which sacrifices flexibility and extensibility in return for minimizing the number of cross-network calls. Because the network overhead can’t be abstracted away, distributed objects are a very leaky abstraction.

So in 2003, Indigo folks came along and basically said “You know the distributed object paradigm? The one we’ve been shipping in our platform since 1996? Yeah, turns out we think that’s the wrong approach.” Go back and check out this interview with Don Box from early 2004. The interviewer asks Don if WCF will “declare the death of distributed objects”. Don hems and haws at first, saying “that’s probably too strong of a statement” but then later says that the “contract, protocol, messaging oriented style will win out” over distributed objects because of natural selection.

The tenets, IMHO, were really designed to help the Windows developer community wrap their heads around some of the implications of messaging and service orientation. These ideas weren’t really new – the four tenets apply to EDI, which has been around for decades. But for a generation of Windows developers who had cut their teeth on DCOM, MTS and VB, it was a significant paradigm shift.

These days, with the tenets going on four years old, the conversation has shifted. Platform vendors are falling over themselves to ship service/messaging stacks like WCF and most developers are looking to these stacks for the next systems they build. Did the tenets do that? In part, I think. Mainstream adoption of RSS was probably the single biggest driver of this paradigm shift, but the tenets certainly helped. Either way, now that service orientation is mainstream, I would say that the tenets’ job is done and it’s time to retire them. Once you accept the service-oriented paradigm, what further guidance do the tenets provide? Not much, if any.

Fantasy, Free Code and the SharePoint Model

It might sounds like a fantasy, but Nick Malik really wants free code. He started talking about it a few months ago when he was getting raked over the coals by debating Mort with the agile .NET community:

Rather than look at “making code maintainable,” what if we look at making code free.  Why do we need to maintain code?  Because code is expensive to write.  Therefore, it is currently cheaper to fix it than rewrite it.  On the other hand, what if code were cheap, or free?  What if it were cheaper to write it than maintain it?  Then we would never maintain it.  We’d write it from scratch every time.

Then about a week ago, he laid out the reasons why free code would be a good thing. At a high level (Nick’s blog has the details), those reasons are:

  1. Lower the cost of IT through reduced skill requirements.
  2. The speed of development goes up.
  3. Projects become more agile.
  4. Solution quality goes up.

Talking about the benefits of free code is sorta like talking about talking about the benefits of dating a movie star. The benefits are actually pretty obvious, but talking about them doesn’t really help you get there from here.

Actually, Nick isn’t suggesting that all code can be free. He’s focused on separating out business process modeling/development from the rest of software development. In essence, he’s describing a new class of developer (should we call the persona Nick as an homage?) who needs their own class of tools and for the IT department to “formally” allow them to “easily develop, test, and deploy [aka host] their processes.” For the most part, these BP developers wouldn’t be traditional developers. They’d be more like software analysts who do the work directly instead of writing specs for developers.

I call this separation of business and IT concerns the SharePoint Model. SharePoint, IMO, does an amazing job of separating the concerns and needs of business and IT users when it comes to running intranet web sites. Only the truly geeky stuff that requires specialized access, knowledge or equipment – installing the SharePoint farm in the first place, keeping it backed up, installing service packs, etc. – is done by IT. Everything else is done by the business folks. Need a new site? Provision it yourself. Need to give your v-team members access to it? Do it yourself. I see similarities in the free BP code approach Nick’s suggesting. I’d even argue that SharePoint is the natural “host” for such business processes. It already supports WF and can provide access to back-end enterprise data via the Business Data Catalog.

On the other hand, some of what Nick suggests seems fairly impractical. For example, he thinks IT should “formally and officially take control of managing the common enterprise information model and the business event ontology.” First off, who officially manages this today? Does such an official information model or event ontology even exist? I’m guessing not. That means you’ve got to start by getting the business people to agree on one. That’s usually a sucker’s bet. Nick also suggests we “reduce the leaky abstractions” in our services. To suggest this is even possible seems incredibly naive.

The good news is the things that will work (evolving BP into its own development discipline, building custom tools for BP development, getting IT into the BP hosting business) don’t depend in any way on the things that wont work (getting lots of folks to agree on anything, breaking the laws of physics, overcoming the law of leaky abstractions). I’m not sure it will result it truly free code, but it sure would bring the costs down dramatically. Thus, I think most of Nick’s free code vision is quite practical and not a fantasy at all.

As for dating a movie star, you’re on your own.

Another InitImportantThing Approach

I thought of another approach to the InitImportantThing problem that I blogged about yesterday. I think it’s a bit harder to code, but it’s certainly explicit and avoids the magic method that Jon dislikes so much.

The crux of the problem is that ServiceHostBase needs a valid ServiceDescription in order to operate. The WCF team chose to provide said description to ServiceHostBase via the abstract CreateDescription method. But as we saw, ServiceHostBase can’t call CreateDescription from it’s own constructor. So instead, derived classes are forced to call InitializeDescription in their own constructor. Since that call isn’t enforced by the compiler, it’s easy to forget to include it. Since the exception that gets thrown doesn’t really tell you what went wrong, it’s easy to spend hours trying to figure it out.

So here’s a better approach: since the ServiceHostBase needs a valid ServiceDescription in order to operate, why not pass it in as a constructor parameter?

ServiceHostBase has a protected constructor with no parameters. But since it needs you to call InitializeDescription in your derived class constructor, it really needs the ServiceDescription, a collection of ContractDescriptions (also returned from CreateDescription) and a collection of base addresses (passed into InitalizeDescription). If these were parameters on ServiceHostBase’s constructor, it could validate that information directly, without needing abstract or magic methods.

The one problem with this approach is that the creation of a ServiceDescription is non-trivial. ServiceHost’s implementation of CreateDescription generates the ServiceDescription by reflecting over the service type. You still need that code, but now you would call it from the base constructor initializer instead. That means it has to be a static method, but otherwise it would work just fine. Here’s yesterday’s code, updated for this approach:

public abstract class Base
{
    public Base(string importantThing)
    {
        if (string.IsNullOrEmpty(importantThing))
            throw new Exception();

        _importantThing = importantThing;

    }

    private string _importantThing;

    public string ImportantThing  
    {  
        get { return _importantThing; }  
    }
}

public class Derived : Base
{
    private object _data;

    public Derived(DateTime dt) : base(CreateImportantThing(dt))
    {
        _data = dt;
    }

    private static string CreateImportantThing(DateTime dt)
    {
        //this is obviously trivial, but could be much
        //more complicated if need be
        return dt.ToLongDateString();
    }
}

This seems like the best approach to me. You remove the un-obvious magic method call requirement when deriving your own service host while still enforcing the data consistency check in the base class during construction. Best of both worlds, right?

So I wonder why the WCF team didn’t do it this way?

Calling InitImportantThing

Jon Flanders throws a little vitriol at the WCF team fore their design of the abstract ServiceHostBase class, calling the current design “stupid”. Normally, I’m not one to take up for the WCF team. I’ve spent many an hour banging my head against WCF for different reasons but exactly how Jon describes. However, in this case, the WCF team looks caught between a rock and a hard place, where the rock is correct behavior and the hard place is the way CLR object construction works.

The crux of Jon’s beef is that if you build your own ServiceHost by inheriting from SeviceHostBase, it’s not enough just to override the abstract CreateDescription method. You also have to call the “magic” InitializeDescription method in your derived class constructor. If you don’t, CreateDescription never gets called. CreateDescription returns a ServiceDescription instance which is to route messages from the channel layer to the and service layer. Jon writes that “Creating a valid ServiceDescription and returning the list of implemented contracts is essential for making your ServiceHostBase-derived class work.” I.e. it’s really important. Yet, unless you remember to call InitializeDescription, this “essential” ServiceDescription doesn’t get configured correctly. Yep, I see how that might sound stupid.

But if this design is stupid, what would be a better design? After thinking about this specific problem a while, I’m don’t think there is a better design out there.

The question is, when is the right time to set up the service description? Jon called ServiceDescription “essential” to the operation of ServiceHostBase. That implies it should be configured during the construction of a new service host instance. It wouldn’t do to have ServiceDescription unconfigured for some period of time between construction and use. What if the ServiceDescription is invalid or the call to CreateDescription throws an exception? Then you’d be in a position where you could create what looks like a valid service host, but it would throw an exception when you tried to use it. You can see why the WCF team would want to avoid that scenario.

So if you want the service host to have a valid ServiceDescription by the end of construction, what choices do you have? Given that the ServiceDescription depends on derived class data, the only choice is to use a magic method! Here’s an example to demonstrate what I mean:

public abstract class Base
{
    public Base()
    {
    }

    private string _importantThing;
    protected abstract string CreateImportantThing();

    protected void InitImportantThing()
    {
        _importantThing = CreateImportantThing();
        if (_importantThing == null)
            throw new Exception();
    }

    public string ImportantThing  
    {  
        get { return _importantThing; }  
    }
}

public class Derived : Base
{
    private object _data;

    public Derived(DateTime dt)
    {
        _data = dt;
    }

    protected override string CreateImportantThing()
    {
        return _data.ToString();
    }
}

I’ve tried to distill out the relevant parts of ServiceHostBase. In the example, Base stores some important thing that gets created by the derived class based on data that’s passed into the derived class’s constructor. Remember, we want the class to be fully configured by the end of the constructor. If CreateImportantThing throws an exception or returns null, we want to know about it right away when the object is created.

In the code above, the magic method InitImportantThing never gets called and thus the _importantThing field never gets setup. This roughly corresponds to Jon’s scenario where he didn’t know to call InitalizeDescription. And like WCF, we can make this sample work by inserting a call to InitImportantThing at the end of Derived’s constructor.

You might be tempted to put the call to InitImportantThing in Base’s constructor. But that won’t work because Base’s constructor runs before Derived’s constructor does. Thus, Derived’s _data field will still be null and the call to CreateImportantThing throws a null reference exception.

The final option would be to place the a call to InitImportantThing in ImportantThing’s property get method, if _importantThing is null. This defers construction of _importantThing until the first time it’s used. By this time, the derived class constructor will have run and so the derived class data will be available for use. This eliminates the magic method call, but it means we don’t know if the instance is valid until we go to use it – i.e. the scenario we were expressly trying to avoid.

So basically, the looks like the WCF team had two choices:

  1. Err on the side of caution and require calling InitializeDescription in the ServiceHostBase derived class’s constructor.
  2. Err on the side of easy extensibility and call InitializeDescription the first time the ServiceDescription.

Put that way, what the WCF team ended up doing doesn’t seem so stupid. This is especially true when you consider that the vast majority of people aren’t creating their own service hosts anyway. It would have been possible to do both: explicitly call InitializeDescription in ServiceHost’s constructor but also have an implicit call in ServiceDescription property get if the field was null. But I’m not on the product team, so I don’t know what other tradeoffs that implies. Checking for a null reference seems like no big deal, but I don’t know how often this property gets called.

One other point: even though I don’t think this design is stupid, I agree 100% with Jon that the exception is misleading.The way it’s written, the immediate assumption is that your implementation of CreateDescription is bad, not that you forgot to call InitializeDescription. It turns out that ServiceHostBase is already tracking wether InitializeDescription has been called via the initializeDescriptionHasFinished field. So why can’t it throw an exception like “Dude, you forgot to call InitializeDescription” when that field is false? It wouldn’t make the design any cleaner, but it would have saved Jon hours of digging thru the implementation of ServiceHost and ServiceHostBase in Reflector.

Morning Coffee 109

  • I forgot to add a number to my last morning coffee post. However, after extensive research, I have determined that it was #108. So thing are continuing as usual today with #109. On the other hand, do you really want development and architecture opinions from a guy who can barely count? 😄
  • The finalists in the Dream-Build-Play contesthave been announced. I haven’t played any of them yet (some are available for download) but they several of them sure look good.
  • And speaking of gaming, MS announced an Xbox 360 price drop yesterday. So if you want to get in on some of the XNA action, here’s your chance (or you could just build for your PC – take your pick).
  • Finally on the gaming front, if you’re not busy Monday you can watch the first day of Gamefest 2007 online. Get the scoop on XNA 2.0 as well as the new XNA networking support. I, alas, am busy Monday so I’ll have to catch it on demand.
  • On to, you know, actual geek stuff things. Scott Guthrie seems to have retired his LINQ to SQL series and moved on to LINQ to XML. He shows how to build an RSS reader application with LINQ to XML. An oldie demo, but a goodie.
  • Wanna learn F#, there’s a whole site of samples up on CodePlex. (via Don Syme)
  • Jeff Atwood is annoyed at how many different products you have to install to get a current & complete setup of VS 2005. Of course, MS shipped two parts of that stack since VS05 shipped (TFS & DBPro), three service packs (VS05 SP1, SQL 05 SP2 and DBPro SR1) and a major OS upgrade (VS Vista update). Doesn’t the same thing happen with any shipping product after a few years? BTW, if this is such a huge hassle, I wonder why Jeff doesn’t create a slipstreamed VS installer?
  • Udi Dahan has a great post on estimation where he claims “Developers don’t know how to estimate.” No argument, but the way he phrases it sounds like it’s the developer’s fault they suck at estimation. It’s not. Developing – by definition – is building something you’ve never built before. Is it any surprise we suck at estimating how long it will take us to do something we’ve never done before?