Critical Development

Enterprise modeling, design, development, languages, and tools.

Multicasting with Silverlight 3 Local Messaging

Posted by Dan Vanderboom on April 29, 2009

[This article and the sample solution included were written with Silverlight 3 Beta.]

The very first thing I did to experiment with Silverlight 3’s new local messaging feature was to create an application with a listener name of “Everyone”, pop up multiple instances of the application, and try sending a message to all of the instances.  I got a nasty HRESULT E_FAIL exception message upon firing up the second instance.  I closed the application and restarted, only to find I got the same error message on the first instance as well (until I rebooted).

The problem was that a listener must have a unique name and I was violating that rule.  There are no groups, and multicasting to multiple receivers in the same group isn’t supported out of the box.  Because I didn’t dispose of the object, that name was never released.  This seems like a design flaw; when a Silverlight application instance ends, the Silverlight runtime should be able to detect that and release this name resource.

When I heard about this local message passing ability, my first thought was that it would create a neat opportunity, especially in out-of-browser applications, for multiple-window applications.  This would be great for those of us who use multiple monitors, as we could then slide panels around where we wanted them, taking full advantage of our workspace.

My sample application, which you can download here, consists of a TextBox, a Submit button that sends the content of that TextBox to all the other instances, and a TextBlock that displays important events.  The first time the application runs, it identifies itself as the master window.  All subsequent application runs identify themselves as child windows.  Here’s a screenshot of this application running out-of-browser:

Screenshot

To accomplish this, the master window will need to have a well known name.  I chose MyApp/Master to identify both the application and the window name.  Each of the child windows require a unique name, so I chose the format MyApp/{guid}.  Once an instance realizes there’s already a master window, it gives itself a child window GUID name and then registers that name with the master window.  When a child instance exits, it unregisters itself with the master instance.  And finally, when the master window exits, it informs all of the child windows (so they can shutdown, most likely).

I defined several static members in the App class itself, so they would be visible across pages, and also because I wanted to hook into Application_Exit and needed access from there.

public const string MasterWindowName = "MyApp/Master";
public static string WindowName;
public static Guid WindowID;
public static List<Guid> ChildWindows;

Hooking into the LocalMessageReceiver’s MessageReceived event, I looked for specific keywords in a protocol I quickly cooked up, and in most cases extracted a parameter by parsing the message string.  These commands are NewWindow, CloseWindow, MasterWindowClosed, and UpdateText.

void MessageReceiver_MessageReceived(object sender, MessageReceivedEventArgs e)
{
    if (e.Message.StartsWith("NewWindow:"))
    {
        if (App.ChildWindows == null)
            App.ChildWindows = new List<Guid>();

        Guid NewWindowID = new Guid(e.Message.Substring("NewWindow:".Length));

        App.ChildWindows.Add(NewWindowID);

        Log("New window detected, id = " + NewWindowID.ToString());

        return;
    }

    if (e.Message.StartsWith("CloseWindow:"))
    {
        var id = new Guid(e.Message.Substring("CloseWindow:".Length));

        if (App.WindowName == App.MasterWindowName)
            App.ChildWindows.Remove(id);

        Log("Closing window, id = " + id.ToString());

        return;
    }

    if (e.Message == "MasterWindowClosed" && App.WindowName != App.MasterWindowName)
    {
        Log("Master Window Closed");
        return;
    }

    if (e.Message.StartsWith("UpdateText"))
    {
        var text = e.Message.Substring("UpdateText:".Length);

        txtName.Text = text;

        // if this is the master window, then distribute to all child windows
        if (App.WindowName == "MyApp/Master")
            UpdateTextMulticast(text);

        return;
    }
}

As you can see, most of this is simple housekeeping code to track which application instances or windows are currently connected to the master window.  The UpdateText command calls the UpdateTextMulticast method, which looks like this:

private void UpdateTextMulticast(string Text)
{
    foreach (var id in App.ChildWindows)
    {
        var MessageSender = new LocalMessageSender("MyApp/" + id.ToString());
        MessageSender.SendAsync("UpdateText:" + txtName.Text);
    }
}

If the window is a child window, the Submit button sends a message to the master window; the master window, when clicking on Submit, calls the UpdateTextMulticast method.

private void btnSubmit_Click(object sender, RoutedEventArgs e)
{
    if (App.WindowName == "MyApp/Master")
    {
        UpdateTextMulticast(txtName.Text);
    }
    else
    {
        var MessageSender = new LocalMessageSender("MyApp/Master");
        MessageSender.SendAsync("UpdateText:" + txtName.Text);
    }
}

Finally, this is how a window alerts other windows that it’s closing (in App.xaml.cs):

private void Application_Exit(object sender, EventArgs e)
{
    if (WindowName != MasterWindowName)
    {
        var MessageSender = new LocalMessageSender(MasterWindowName);
        MessageSender.SendAsync("CloseWindow:" + WindowID);
    }
    else if (ChildWindows != null)
    {
        foreach (var id in ChildWindows)
        {
            var MessageSender = new LocalMessageSender("MyApp/" + id.ToString());
            MessageSender.SendAsync("MasterWindowClosed");
        }
    }
}

That’s about all there is to it.  Admittedly, having the same Silverlight application act as both master and child window might not be the best arrangement, and it certainly adds a little to the complexity of the code, but the sky is the limit as far as how the new local messaging feature of Silverlight 3 could be used.

What I’d really like to see is some kind of WCF customization that could define WCF services and host them specifically for consumption across this local messaging channel.  Doing so would eliminate the need for defining and parsing a protocol as I’ve done in this example, as WCF could handle the serialization and service method invocation.

Posted in Design Patterns, Distributed Architecture, Silverlight, User Interface Design | Leave a Comment »

Cloud Slam ‘09 Conference

Posted by Dan Vanderboom on April 14, 2009

If you’re interested in Cloud Computing, you should consider signing up for Cloud Slam, a very inexpensive four-day virtual conference.  You can attend from the comfort of your home (or local wine or coffee shop), and have access to about 100 hours of sessions for only $52.  It goes from April 20-24.

Speakers include such industry leaders as Stephen Herrod, CTO of VMWare, Simon Crosby, CTO of Citrix Systems, Werner Vogels, CTO of Amazon.com, and many more.

I can’t say I’ll see you there, but I’m definitely looking forward to it.  It should be a great source of information for what industry leaders are thinking and where cloud computing is headed.

Posted in Cloud Computing, Conferences | Leave a Comment »

Advanced Customization of a Silverlight ListBox

Posted by Dan Vanderboom on April 13, 2009

[This article and its solution are based on Silverlight 3 Beta and Blend 3 Beta.]

The more I work with Silverlight, the more impressed I am.  Though I do keep running into frustrating situations, I haven’t encountered nearly as many dead ends as I did writing Windows Forms applications.  But where I used to run into dead ends, I now find myself lost in a labyrinth of deeply-composed control hierarchies, dichotomized content controls, and numerous interrelated control and data templates.

But ultimately I can find a way to do what I set out to do.  That’s huge.  If the learning curve is treacherously steep and my solution to a problem is tricky and twisted, I can reassure myself of more fluent UI design in the future due to increased understanding.  The difficulty of solving these problems is due to complexity of the UI design itself, the immaturity of Silverlight and its APIs, and my own inexperience working with it.

You can download the finished solution here.

The Goal

When I set out to customize a list control, I didn’t start with the tools of Silverlight.  I sketched out a design that assumed anything would be possible, and decided to figure out later how to implement exactly that (in behavior and layout, not final visuals).  The mock-up below is similar to what I came up with, simplified to include only those elements I’m going to illustrate in this article.

image

The first thing you’ll notice is that the data template renders differently based on the data for that item.  I found a Code Project article by Anil Gupta on doing the same kind of thing.  This turns out to be the easy part.  (The space around and between items isn’t intended to be rendered as such, and was added only to emphasize the separate identities of the item templates.)

I also wanted each item in the list to be expandable to display more information and to host interactive controls like sliders (shown in the example) to manipulate the underlying data.  In noticing that this button and behavior, as well as the border, are common elements to each of the item templates, I decided that what I was looking at involved a ContentControl.  This new control would contain these common elements and a ContentPresenter which would be filled by the specific item type template (one for airplane, one for truck, one for boat).  That way, I could build a whole bunch of new templates for new item types and I wouldn’t have to worry about placing the button correctly or wiring up its behavior each time.

Though the illustration might suggest that the only difference among the templates is background color, I wanted to be able to completely differentiate them.  The only thing that would be standard would be a collapsed height of 32 to give a nice consistent vertical layout (and for this example, a standard expanded height of 64).  Inside, the controls and their layout could follow any design.

Unspecified at first, one of my presumptions was that the width of each item would fill all of the available space, which is the width of the ListBox minus borders, padding, and the vertical ScrollBar.  This would prove to be the most difficult challenge, and I found some discussion in the forums, but ultimately I would find my own way to solve it.

Finally, I wanted to do as much as possible in Blend.  XAML is fine for setting complex bindings and wiring up other things, but for drawing of graphics (editing templates), I wanted to leverage Blend as much as possible.

The Solution

First we need a data model, to know the shape of items that we’re binding to in our ListBox.  I used a simple example of a Vehicle base class and three derived types.  Elsewhere, I instantiate several of each type of vehicle and add them to the ListBox’s ItemsSource collection.

public abstract class Vehicle
{
    public string Manufacturer { get; set; }
    public string Model { get; set; }
    public double Price { get; set; }
}

public class Truck : Vehicle
{
    public bool HasFourWheelDrive { get; set; }
}

public class Boat : Vehicle
{
    public double HullWidth { get; set; }
}

public class Airplane : Vehicle
{
    public int MaxAltitude { get; set; }
}

I then created three UserControls, one for each vehicle type, and called them AirplaneTemplate, BoatTemplate, and TruckTemplate.  I gave each of them a DesignHeight of 64 to represent their expanded state, let their Width be Auto, and set HorizontalAlignment to Stretch.  I set the Height of each of the two Grid rows to 32, to ensure they wouldn’t stretch as the ContentControl hosting this content collapsed.

image

Selecting a Template Based on Item Data

There’s no way that I know of to write an expression in XAML that will bind to a different data template based on item data.  I also know of no way to write code behind a data template.  To get around these limitations, I created a data template called VehicleListDataTemplate that contains a single VehicleItemTemplate custom control which I could write code behind.  This control is a ContentControl, so it’s capable of drawing its own content as well drawing content passed into it.  The content that it supplies itself consists of the common UI elements: the border and the button to toggle the expansion or collapse of the item.

This control is mocked up like so, showing both collapsed and expanded states:

image

The control’s ContentPresenter, set with its Content property, would occupy the same space, although the button would be placed on top to ensure it was clickable.

This was my first custom Silverlight control (other than UserControls), so several things were new to me.  For one, defining a default control template in generic.xaml and writing a separate class file for behavior.  This is what the default template looks like:

<Style TargetType="local:VehicleItemTemplate">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:VehicleItemTemplate">

                <Grid x:Name="Core" Background="{TemplateBinding Background}"
                      d:DesignHeight="32" Height="{TemplateBinding Height}"
                      d:DesignWidth="312" Width="Auto"
                      VerticalAlignment="Stretch" HorizontalAlignment="Stretch">

                    <Border VerticalAlignment="Stretch" CornerRadius="5,5,5,5"
                            BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="2" />

                    <ContentPresenter
                        VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                        Content="{TemplateBinding Content}"
                        ContentTemplate="{TemplateBinding ContentTemplate}" Margin="0"/>

                    <Button x:Name="Expander" VerticalAlignment="Top" HorizontalAlignment="Right"
                            Margin="0,4,4,0" Width="28" Height="24"
                            BorderBrush="{TemplateBinding BorderBrush}"/>
                </Grid>

            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

And here it’s referenced by the data template:

<DataTemplate x:Key="VehicleListDataTemplate">
    <local:VehicleItemTemplate VerticalAlignment="Top" HorizontalAlignment="Left"
        Background="#0014145D" Margin="0,0,0,0" BorderBrush="#FF5063A5"
        d:DesignHeight="32" Height="32" d:DesignWidth="430"
        VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" />
</DataTemplate>

So far that’s not too bad.  We have a data template, which refers to VehicleItemTemplate (a ContentControl) that gives our common appearance and hosts a specific vehicle UserControl depending on the item data in question.  I count three layers so far, but unfortunately that isn’t enough.

Let’s take a look at how we set the content:

private void VehicleItemTemplate_Loaded(object sender, RoutedEventArgs e)
{
    var vehicle = DataContext as Vehicle;

    // vehicle will be null when this is executed in the designer
    if (vehicle == null)
        return;

    if (vehicle is Airplane)
        Content = new AirplaneTemplate();
    else if (vehicle is Truck)
        Content = new TruckTemplate();
    else if (vehicle is Boat)
        Content = new BoatTemplate();
}

Pretty simple: the DataContext is our item data object, we can inspect the type to figure out which one it is, and create a new vehicle UserControl of the appropriate matching type to set the Content.

To make it expand and collapse, we first need to get a reference to the button in our template, which is based on the parts I defined for the control.

[TemplatePart(Name = "Core", Type = typeof(FrameworkElement))]
[TemplatePart(Name = "Expander", Type = typeof(ButtonBase))]
public class VehicleItemTemplate : ContentControl

In the template, the Expander part must be some control that inherits from ButtonBase, and which therefore implements a Click event.  When the template is applied to the control at runtime, OnApplyTemplate is run, so we hook into that event there:

public override void OnApplyTemplate()
{
    base.OnApplyTemplate();
    ToggleButton = GetTemplateChild("Expander") as ButtonBase;
    ToggleButton.Click += new RoutedEventHandler(btnToggleSize_Click);
}

private void btnToggleSize_Click(object sender, RoutedEventArgs e)
{
    Duration duration = new Duration(TimeSpan.FromSeconds(0.2));

    Storyboard sb = new Storyboard();
    sb.Duration = duration;

    DoubleAnimation ani1 = new DoubleAnimation();
    ani1.Duration = duration;
    ani1.To = Height == 32 ? 64 : 32;
    Storyboard.SetTarget(ani1, this);
    Storyboard.SetTargetProperty(ani1, new PropertyPath("FrameworkElement.Height"));

    DoubleAnimation ani2 = new DoubleAnimation();
    ani2.Duration = duration;
    ani2.To = Height == 32 ? 64 : 32;
    Storyboard.SetTarget(ani2, Content as Control);
    Storyboard.SetTargetProperty(ani2, new PropertyPath("FrameworkElement.Height"));

    sb.Children.Add(ani1);
    sb.Children.Add(ani2);

    sb.Begin();
}

Now we have an animation that will smoothly expand or collapse our item and its content, and because I use the To property, we avoid jumping from one state to another.  Instead, if we click to expand and then click to collapse again, it will animate from its current position to the desired position.

Setting the Correct Width of ListBox Items

The biggest problem I had was in setting the correct width.  With all Widths set to Auto, each item in the list will take up only as much space as it needs.  They can be shorter or longer than the ListBox’s width, and each item could be rendered a different width (depending on the template).

The first thing I tried was to set the VehicleItemTemplate’s Width to the ActualWidth of the ListBox.  I didn’t have enough items in my list to see the vertical ScrollBar appear, but even without it, the borders of my item templates were being clipped by the right side of the ListBox, and I could see a gap of several pixels to the left as well as above and below each item.

image

With the default rendering of Silverlight being that nothing is drawn (border widths are zero, brushes are null, etc.), I find it odd that the ListBox assumes I want padding where I haven’t specified any.  After all, if I wanted this, couldn’t I add a Margin to my data template?

I removed the ListBox border, and finally added a ListBoxItem manually to the ListBox in Blend (thanks Brent).  Right-clicking on that ListBoxItem, I edited a copy of the control template, shown in the screenshot below:

image

This turns out to be different from the data template defined earlier.  This ListBoxItem template is itself a ContentControl, and its content is my VehicleListTemplate… (which is another ContentControl that hosts the specific vehicle UserControls…).  See how confusing this can get?  I feel like Alice in Wonderland sometimes, seeing how far the Silverlight hole really goes.  I also wonder why there doesn’t appear to be any way to edit this template without manually creating a ListBoxItem, when it clearly matters even when you’re defining a data template.

It’s also in this ListBoxItem template that you can render visual decorators to indicate various visual states: Normal, MouseOver, Pressed, and so on.  You might expect to handle that in your data template, but that doesn’t seem to be the case.

Anyway, within that ListBoxItem template was this ContentPresenter.

<ContentPresenter x:Name="contentPresenter"
                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                  Margin="{TemplateBinding Padding}" Content="{TemplateBinding Content}"
                  ContentTemplate="{TemplateBinding ContentTemplate}"/>

The third line shows a Margin being bound to the Padding property.  I removed this Margin altogether, and the gratuitous extra space around my items disappeared, making me happy.

Once you have this custom ListBoxItem template, you need to do two things:

  1. Delete the ListBoxItem you manually added in Blend.  Otherwise you’ll get an error when trying to set the ListBox’s ItemsSource property.
  2. Set the ItemContainerStyle property of the ListBox to point to this new template.  Note that this is different from the ItemTemplate property which sets the data template.

The ListBox XAML should now look something like this:

<ListBox x:Name="VehicleList" HorizontalAlignment="Stretch"
         Margin="20,20,20,20" Width="Auto"
         BorderThickness="2,2,2,2" BorderBrush="#FF99A712"
         ItemTemplate="{StaticResource VehicleListDataTemplate}"
         ItemContainerStyle="{StaticResource ListBoxItemStyle}">
    <ListBox.Background>
        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
            <GradientStop Color="#FF03021E"/>
            <GradientStop Color="#FF191651" Offset="1"/>
        </LinearGradientBrush>
    </ListBox.Background>
</ListBox>

Now we’re at a point where the item container itself isn’t adding any extra space, so if we go without borders or a vertical ScrollBar, everything fits just right… until the vertical ScrollBar appears.  This is close, but not good enough.  How can we take care of the space taken up by the vertical ScrollBar?

While I was digging through the ListBox template, I noticed that the ScrollViewer control had a property called ViewportWidth, and with some debugging saw that it was not quite as wide as the total ListBox width.  If only I had a reference to the ScrollViewer from within my VehicleItemTemplate ContentControl!  I looked for a while but found nothing.  You can call GetTemplateChild from within a control’s class but not from the outside because it’s a protected method.

I decided to cheat.  I created a new ListBox class that exposed the ScrollViewer as a property.  I felt it was safe to do so because ScrollViewer is a TemplatePart defined in the ListBox’s parts and states contract.

public class MyListBox : ListBox
{
    public MyListBox() : base() { }

    public ScrollViewer ScrollViewer
    {
        get { return GetTemplateChild("ScrollViewer") as ScrollViewer; }
    }
}

I also needed to be able to reference the MyListBox object from each VehicleItemTemplate, so I created a DependencyProperty to store that:

// store a reference to the MyListBox that contains this item
public static readonly DependencyProperty ParentListBoxProperty = DependencyProperty.Register(
    "ParentListBox", typeof(MyListBox), typeof(VehicleItemTemplate), new PropertyMetadata(null));

public MyListBox ParentListBox
{
    get { return GetValue(ParentListBoxProperty) as MyListBox; }
    set { SetValue(ParentListBoxProperty, value); }
}

Next, I set this new ParentListBox property from within the data template I defined earlier (using Element binding, which is new to Silverlight 3):

<DataTemplate x:Key="VehicleListDataTemplate">
    <local:VehicleItemTemplate VerticalAlignment="Top" HorizontalAlignment="Left"
        Background="#0014145D" Margin="0,0,0,0" BorderBrush="#FF5063A5"
        d:DesignHeight="32" Height="32" d:DesignWidth="430"
        VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch"
        ParentListBox="{Binding ElementName=VehicleList, Mode=OneWay}"/>
</DataTemplate>

Finally, I replaced the ListBox I was using with MyListBox, and in the VehicleItemTemplate_Loaded method, I added the following data binding in code:

// set up data binding:
// ViewportWidth of the ListBox's ScrollViewer tells us how much space we have available
//(ListBox.ActualWidth - borders - scrollbar)
WidthBinding = new Binding();
WidthBinding.Source = ParentListBox.ScrollViewer;
WidthBinding.Path = new PropertyPath("ViewportWidth");
SetBinding(WidthProperty, WidthBinding);

When there are more items than will fit in the ListBox, the vertical ScrollBar appears, and the width of all the item templates shrinks to accomodate it.  When the ListBox itself widens or shrinks, it adjusts.  This seems to produce the perfect fit for items.  If you download the sample source code, you’ll notice I set the page to auto size, so when you resize the browser, the ListBox will grow and shrink along with it, and you can easily test it.  Also, if you have the ListBox almost full and you expand one of the items with the expander button, you’ll see it adjust then as well.

Here is the final product:

image 

After all of that, we can finally rest assured that we’ll never see a horizontal ScrollBar in our ListBox.

Conclusion

There are several ListBox templates we didn’t take full advantage of: the ItemsPanel for the layout of items, the various embedded templates for parts such as ScrollBars, and the different states of the ListBoxItem template.  However, customization of these templates has been covered fairly well by other articles.

Being somewhat new to Silverlight, I’m curious to see how others would have accomplished the same things.  Is there an easier way to do some of this?  Are there some Silverlight API calls I could have used to reference the ListBox’s ScrollViewer, for example?

I spent many hours working out these details.  I hope I can spare some of you the trouble I encountered.  Happy Silverlight developing!

Posted in Custom Controls, Data Binding, Design Patterns, Expression Blend, Silverlight, User Interface Design | Leave a Comment »

ReMIX09 in Chicago

Posted by Dan Vanderboom on April 1, 2009

I’m taking the train with Mr. Payne down to Chicago for the first stop of the Mix It Up tour, hosted by the CD2 user group.  It starts at 6:30pm today (April 1st, no joke), at:

200 S. Wacker Dr., 15th Floor
Chicago, IL 60606

This is a Microsoft sponsored event to bring the MIX09 technology announcements to those of us who couldn’t make it to MIX.  If you weren’t able to go, you can still watch the recorded MIX session videos.

You can find more information about the Mix It Up tour dates and locations on Damon’s blog.

Posted in Conferences | Leave a Comment »

Windows Azure: Blobs and Blocks

Posted by Dan Vanderboom on February 21, 2009

I’ve been busy building a new cloud-based service for the past few weeks, using Windows Azure on the back end and Silverlight for the client.  One of the requirements of my service is to allow users to upload files to a highly scalable Internet storage system.  I’m experimenting with Azure’s blob storage for this, and I have a need to upload these blobs (Binary Large OBjects) in separate blocks.  There are two reasons I can tell why you’d want to do this:

  1. Although blobs can be as large as 2 GB in the current technical preview, the largest blob you can put in one operation is 4 MB.  If your file is larger, you have to store separate blocks, and then put a block list to assemble them together and commit them as a blob.
  2. If you want different users to upload different portions of a file, each user will have to upload individual blocks, and you’ll have to put the block list when all blocks are present.  This is something like a reverse BitTorrent or other P2P protocol.

My service needs to deal with separate blocks for the second reason, though the first is likely to be much more common.

Although there’s a good deal of information about blocks and blobs in the REST API for Azure Storage Services, piecing together code to make REST calls with all the appropriate headers (including authentication signatures) isn’t very fun.  Where is the .NET library to make it easy?

There is one, in fact.  If you’ve downloaded and installed the Azure SDK (Jan 2009), you’ll find a samples.zip file that needs to be unzipped, and the solutions built within it.  Particularly, you’ll need the StorageClient solution.  In it, you’ll find that you can save and load blobs (as well as use queues and table storage), but there’s nothing in the API that suggests it supports putting individual blocks, let alone putting block lists to combine all of those blocks into a blob.  The raw state of this API is unfortunate, but the Azure platform is in an early tech preview stage, so we can expect vast improvements in the future.

Until then, however, I dug into it and discovered that there actually was code to put blocks and commit block lists, but it wasn’t exposed in the API (in BlobContainerRest.PutLargeBlobImpl).  Rather, it was called only when the blob you try to put was over the 4 MB limit.  Taking this code and hacking it a bit, I extended the StorageClient library to provide this needed functionality.

First, add these abstract method definitions to the BlobContainer class (in BlobStorage.cs):

public abstract bool PutBlobBlockList(BlobProperties blobProperties,
    IEnumerable<string> BlockIDs, bool overwrite, string eTag);

public abstract bool PutBlobBlock(BlobProperties blobProperties, string BlockID,
    Stream stream, long BlockSize, bool overwrite, string eTag);

Next, you’ll need to add the implementations to the BlobContainerRest class (in RestBlobStorage.cs):

public override bool PutBlobBlock(BlobProperties blobProperties, string BlockID,
    Stream stream, long BlockSize, bool overwrite, string eTag)
{
    NameValueCollection nvc = new NameValueCollection();
    nvc.Add(QueryParams.QueryParamComp, CompConstants.Block);
    nvc.Add(QueryParams.QueryParamBlockId,
        Convert.ToBase64String(Encoding.Unicode.GetBytes(BlockID)));
    return UploadData(blobProperties, stream, BlockSize, overwrite, eTag, nvc);
}

public override bool PutBlobBlockList(BlobProperties blobProperties,
    IEnumerable<string> BlockIDs, bool overwrite, string eTag)
{
    bool retval = false;

    using (MemoryStream buffer = new MemoryStream())
    {
        XmlTextWriter writer = new XmlTextWriter(buffer, Encoding.UTF8);
        writer.WriteStartDocument();
        writer.WriteStartElement(XmlElementNames.BlockList);
        foreach (string id in BlockIDs)
        {
            writer.WriteElementString(XmlElementNames.Block,
                Convert.ToBase64String(Encoding.Unicode.GetBytes(id)));
        }
        writer.WriteEndElement();
        writer.WriteEndDocument();
        writer.Flush();
        buffer.Position = 0; //Rewind

        NameValueCollection nvc = new NameValueCollection();
        nvc.Add(QueryParams.QueryParamComp, CompConstants.BlockList);

        retval = UploadData(blobProperties, buffer, buffer.Length, overwrite, eTag, nvc);
    }

    return retval;
}

In order to test this, I added two buttons to an ASP.NET page, one to upload the blocks and put the block list, and a second to read the blob back to verify the write operations worked:

protected void btnUploadBlobBlocks_Click(object sender, EventArgs e)
{
    var account = new StorageAccountInfo(new Uri("http://127.0.0.1:10000/"), null, "devstoreaccount1",
        "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==");
    var storage = BlobStorage.Create(account);
    var container = storage.GetBlobContainer("testfiles");

    if (!container.DoesContainerExist())
        container.CreateContainer();

    var properties = new BlobProperties("TestBlob");

    // put block 0

    var ms = new MemoryStream();
    using (StreamWriter sw = new StreamWriter(ms))
    {
        sw.Write("This is block 0.");
        sw.Flush();
        ms.Position = 0;

        var PutBlock0Success = container.PutBlobBlock(properties, "block 0", ms, ms.Length, true, null);
    }

    // put block 1

    ms = new MemoryStream();
    using (StreamWriter sw = new StreamWriter(ms))
    {
        sw.WriteLine("... and this is block 1.");
        sw.Flush();
        ms.Position = 0;

        var PutBlock1Success = container.PutBlobBlock(properties, "block 1", ms, ms.Length, true, null);
    }

    // put block list

    List<string> BlockIDs = new List<string>();
    BlockIDs.Add("block 0");
    BlockIDs.Add("block 1");

    var PutBlockListSuccess = container.PutBlobBlockList(properties, BlockIDs, true, null);
}

protected void btnTestReadBlob_Click(object sender, EventArgs e)
{
    var account = new StorageAccountInfo(new Uri("http://127.0.0.1:10000/"), null, "devstoreaccount1",
        "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==");
    var storage = BlobStorage.Create(account);
    var container = storage.GetBlobContainer("testfiles");

    MemoryStream ms = new MemoryStream();
    BlobContents contents = new BlobContents(ms);
    container.GetBlob("TestBlob", contents, false);
    ms.Position = 0;

    using (var sr = new StreamReader(ms))
    {
        string x = sr.ReadToEnd();
        sr.Close();
    }
}

It’s nothing fancy, but if you put a breakpoint on the last sr.Close command, you’ll see that the value of x contains both blocks of data, equal to “This is block 0…. and this is block 1.”

Posted in Cloud Computing, Design Patterns, Windows Azure | 1 Comment »

Oslo: Misconceptions and Fallacies

Posted by Dan Vanderboom on February 1, 2009

In the many conversations and debates I’ve had about Oslo recently–in person, on the phone, through email, on blogs, and in the Oslo forum–I’ve encountered a good amount of resistance to the goals of Oslo.  Some of this is due to misconception and general confusion, some is due to an attachment to one’s current methodology, and some I believe is simply due to a fear of anything new and unknown.  In the course of these conversations, I’ve run across a common set of thoughts or themes which I have attempted to represent faithfully here.

My first article, Why Oslo is Important, attempted to elucidate the high-level collection of concepts, technologies, and tools flying under the Oslo banner as it exists today and how I imagine it evolving in the future.  Though I’ve received a lot of interest and appreciation, it also managed to spark some feedback from those who were still confused or concerned, leading me to believe that I had failed to deliver a fully satisfying explanation.

Understandably, Oslo and its target domain are too large to explain or digest in a single article, even a long one.  It’s also too early in the development cycle to be very specific.  So it’s reasonable to suggest that one can’t be totally satisfied until substantial examples and reference applications are built using the Oslo tools.  Fair enough.

This article isn’t going to provide that reference application.  It has the more modest goal of trying to dispel some of the common misconceptions and fallacies that I’ve encountered, and my responses to them.  In future articles, as I design and develop my newest software system, I’ll be documenting and publishing the how and why of my use of Oslo tools and technologies to provide more specific evidence of its usefulness.  I’ll also be providing references to much of the good work that is being done to provide solutions to various problems.

As always, I encourage you to participate and provide feedback: to me, and especially to the Oslo team.  The more brain power we can bring to bear on this problem in the community, the better off the Oslo team will be, and the faster Oslo will evolve to become precisely the set of tools we need to improve our overall development experience, and developer productivity in particular.

“Oslo doesn’t solve any problems that can’t already be solved with existing tools or technologies.”

When the first steam-powered tractors were sold to farmers in the 1860’s, traditional ox and horse farmers might have said the same thing.  “This tractor won’t do anything that my ox-plowing method can’t already do.”  This is true, but it’s not an effective argument against the use of the new technology, which was a much faster and more cost-effective method of farming.  The same farmer could harvest much more of his crop in the same amount of time, and as the new technology matured and gas-powered engines became available (in the 1880’s), so did the benefit increase.  The same goes for any high level language above assembly language, the use of a relational database over a loose collection of files, display of text on a CRT instead of punched tape to communicate with a user, or any other great technological leap forward that “doesn’t accomplish anything new”.

Then again, it all depends what kind of problems you’re talking about.  If you get specific enough, I’m sure you’ll find plenty in Oslo that’s new, even so early in its development, such as a shared repository for interoperable models and the ability to define new parsers that provide tooling support such as keyword colorization.  Sometimes it’s these little details that act as the glue to pull components together and create substantial value through the synergy that results.  Visual Studio and Intellisense weren’t strictly needed (you can still use Notepad and cs.exe), but it can quickly answer dozens of questions a day without having to jump out of context and spend a lot of time looking through disconnected documentation.

“We don’t need to know about Oslo or model-driven development because the applications I build are small and specific, or otherwise don’t need to be so general and flexible.”

This may or may not be true for you, but saying that the industry doesn’t need to advance because you don’t perceive a direct benefit to your own development isn’t valid.  The reason your applications are able to be so simple is because of the wealth of tools, languages, platforms, frameworks, and libraries that your applications leverage.  Standing on the shoulder of giants, you might say.

Many of these systems and components can benefit tremendously from a model-driven approach, and if it improves productivity for Microsoft and other third-party developers, that means they’ll be able to spend less time on plumbing and more time building the framework features you care about.  It’s also likely to make all of those APIs cleaner and more consistent, resulting in easier discoverability and fewer headaches for you, the API consumer.  As the .NET Framework and other frameworks and libraries grow ever larger, this will be critical to keeping things organized and under control.

“Oslo is going to force me to model all kinds of things that really aren’t needed in my software.”

The existence of Oslo will not force you to model any characteristics that you aren’t already modeling through other means.  What it will do is provide more options and tools for modeling your software more effectively and more productively.  It will also significantly ease the burden of creating more heavily model-driven software if you decide that’s right for your application or service.

For more information and a clearer definition of what a model is, see this article on the MSDN Oslo Development Center.

“Oslo will impose a workflow on me that doesn’t make sense for my methodology or business.”

Where Oslo fits into your specific workflow will be ultimately determined by you.  This isn’t any different from Entity Framework.  In v1 of EF, the tooling supports the reading of database structure and the generation of entity classes, but there is work being done to support a workflow going in the other direction: that of starting with classes and generating the database.  The Entity Framework itself doesn’t actually care in which direction you want to work; the issue is primarily one of tool support.  Other initiatives such as adding support for POCO indicate that the EF team is listening to feedback from the community and making the necessary changes to achieve broad support of their framework.  I would expect the same from the Oslo team.

Early releases of Oslo will have similar limitations; currently it seems that M can only be used to generate a database structure from MSchema, and that database structure can be read by Entity Framework to generate your entity classes.  Because Microsoft has such a broad audience to satisfy, other workflows will have to be accommodated, such as starting with class files and generating M files and database schemas.  In fact, I’ve submitted feedback to Microsoft’s Connect site to ensure this kind of multi-master synchronization of model representations is considered.

“Putting everything in a database is overkill for my application, so Oslo isn’t relevant to me.”

While the Repository is an important aspect of Oslo, it isn’t required.  Command line tools exist to transform textual input (specified as MGraph, or in your own custom-defined format using a Domain Specific Language) into MGraph output.  There is a separate step to convert this into SQL, or to optionally inject this data directly into the Oslo Repository.

If you don’t want to use the Repository, there are already multiple methods available for instantiating objects directly from this text data, whether it’s read from a file, embedded as a resource, or sent as data over a network.  Josh Williams (SpankyJ) has published an example showing how to convert DSL text into XAML, and instantiate the object graph using an MGraphXamlReader, and Torkel Ödegaard of Coding Instinct wrote an article demonstrating how to write a generic deserializer without using XAML.

Model formats such as CSDL, MSL, and SSDL for EF, or configuration data currently specified for WCF and WF, will all very likely be expressed in some DSL specified with M (there has been talk about these efforts already).  Since applications without database access will need these technologies, it will be impossible to force developers to read this model data from a SQL Server database.

“We already have XML, XSD, and XSLT, so there’s no benefit to having yet another language to specify the same things.”

XSD is used to define formats and languages (such as XAML), and XML is used as a poor man’s one-size-fits-all meta-format for specifying hierarchical data.  While XML is friendly enough to open in text editors, it’s designed more for tools than for human eyes.

Having different languages and formats to represent different kinds of data actually eases human comprehension and authoring ability.  As Chris Anderson said in his Oslo session at PDC, when you’re looking at XML in an editor, what stands out are not what’s important to your domain, but rather what’s important to XML: elements and attributes.

People are using XML to define their DSLs and formats, not because XML is the best representation, but because writing parsers for new formats and languages is just too hard.  Customers had been asking Microsoft for the ability to write these DSLs easily, so it was out of conversations and customer feedback that Microsoft decided to expose these services.

So it’s not a matter of absolutely needing M and the ability to define new languages because of some inability to get work done without them.  Rather, it’s about reducing the amount of mental work required to author our models and increasing our productivity as a result.  It’s also about having powerful transformational tools available to convert all formats and languages into a common representation so that the models can all interoperate despite their differences, in the same way that .NET languages all compile to a common CIL/MSIL language so that many different programming languages can interoperate.  Without this ability, we’d have a different community of developers for each language instead of one broad group of “.NET developers” who can all share and benefit from each other’s knowledge and libraries.  This has been recognized as such an important advantage that there are efforts underway to compile languages other than Java to JVM byte cote.

The larger the community, the larger our collective pool of knowledge, and the greater reuse we actually achieve.

“Oslo is too general and abstract to be useful to real developers building real systems.”

The idea that generalization can get out of control for a specific problem is valid, in the same way that a problem can be over-analyzed.  But that doesn’t mean that we should stigmatize all general-purpose software, or that we should ignore the growing trend for enterprise software systems to require greater flexibility, user customization support, extensibility, and so on.

The fact is that life on Earth evolves towards greater complexity, and as supporting hardware resources increase and business demands grow, so does software.  Taming that complexity will require rethinking how we approach every aspect of software design and development, including how to model it.

The software development industry is stratified into many layers, from platform development to one-off, command-line utilities.  Some organizations write software to support millions of users, while others deploy specialized applications in-house, but most of us fall somewhere in between.  Oslo seems to be most applicable to enterprise software offered to many customers, including cloud services, but there are subsets of Oslo that will have an impact on a great majority of .NET developers sooner or later.

There’s a lot of thought and work that goes on in our world (and billions of dollars spent) on “pure research” in the sciences (including computer science) that isn’t directly applicable to every John Doe, but without which we wouldn’t have things like nuclear power plants, microwaves, radio, television, satellite communication, or many pharmaceuticals.  The Nobel laureates of the world who have spent their lives studying something so abstract and remote from every day life have contributed massively to the technological progress of our world, and quite often contribute to a better, more sanitary, healthy, and productive society.  Despite the risks and dangers each technology enables, we somehow still make steady progress in terms of reducing chaos and violence.

Without abstract and general technology like general purpose language compilers, which can specify any logic we dream up for any type of application we care to build, we’d be back in the stone age.  The Internet itself is based on communication standards that are so general, they are applicable to any application protocol or service traffic we can devise.

So before dismissing software (or any technology) due to its abstract or general nature, think about where we’d be without them.  Someone has to approach the colossal, abstract, general problems with enough foresight to deliver solutions before they’re too desperately needed; and who better than a huge organization like Microsoft with deep pockets?

Ironically, our ability to define Domain Specific Languages with Oslo give us the converse power: the ability to define languages and formats that are extremely specific to our purposes and problem domains, and therefore enable us to write our specifications with less ceremony and noise that accompanies a general purpose language.  This allows us to specify our intentions more easily by saying only what we need to say to get the point across.  So the only reason Oslo must be so general is to provide that interoperability and translation layer across a set of specific formats that we define… without us having to work so hard for it.

For different reasons, it reminds me of generics, another general and abstract tool: it’s a complicated feature to implement in a language, but it provides great expressive power.  Generics also don’t provide anything we couldn’t manage to do before in other ways, but I certainly wouldn’t want to go back to programming without them!  In fact, you might say it’s an effective modeling tool.

Posted in Development Environment, Dynamic Programming, Language Innovation, Metaprogramming, Oslo, Problem Modeling | 5 Comments »

Twitter & the “Modeling Oslo” Microblog

Posted by Dan Vanderboom on January 29, 2009

I started using Twitter in December at the insistence of my colleagues at CarSpot, and I really didn’t get it at first.  Now that I’ve been “tweeting” for several weeks, and have my first few “followers”, I’m starting to see it as a useful communication tool (and apparently the fastest growing one on the Internet, according to podcast This Week In Tech).

I’ve been using it for a number of things, though I try (as on my blog) to stick with .NET programming topics.  What I find is that some of my thoughts and avenues of exploration crescendo to the point where I have to blog about it, but most pursuits are smaller and never cross the threshold.  Some of these small adventures in programming with new technologies are worth writing about, but I set such high expectations on myself for completeness of coverage, ability to reference reputable sources, providing adequately tested code samples, writing style including correct grammar and spelling, etc., that I put up a barrier to entry for each thought I might blog about.

Enter Twitter, the casual microblog.  With Twitter, I can share informal tidbits of knowledge, the status of progress on my projects, or just my confusion and frustration at the moment.  As I watch people watch each other on Twitter, I realize they’re learning from each other, and this provides not only as a channel of knowledge transfer, but also a sort of insider’s scoop, and an early look at larger things brewing (like a blog article, or a book).

I also occasionally make announcements as open invitations to meet somewhere fun, in case you happen to live in the Milwaukee area (or elsewhere when I travel).  So if you’re one of those that has caught the Twitter bug, or you’re just curious to see what I’m working on, feel free to listen in.

http://twitter.com/danvanderboom

Twitter Microblog on Microsoft Oslo

One of the things I’ve been studying intensely and starting to work with is Oslo.  I wrote an article to explain it, or at least to scratch the surface.  As I explore and experiment further, I decided that a Twitter account would be a perfect way to let people know what I’m doing with it.  I also plan to make important announcements about release schedules, suggest good articles and resources, point out key conversations (including some of my own) in the MSDN Oslo Forum and elsewhere, and share insights and fundamental concepts/definitions.

Whether you’re interested in Oslo and don’t know where to begin, are considering incorporating it next year, or you’ve decided to jump in and start using it now like me and simply want to compare notes with someone else in the trenches, feel free to tune in.

http://twitter.com/modelingoslo

The name refers to the fact that Oslo itself must be modeled, and that a discussion about modeling is meta-modeling.

I’m going off the beaten path with this one, so if you have any ideas for the type of content you’d like to see in an Oslo microblog, feel free to leave a comment and share your thoughts!

Posted in Oslo, Personal, Twitter | Leave a Comment »

Alienware M17: Ninja Laptop

Posted by Dan Vanderboom on January 27, 2009

My new laptop, an Alienware M17, arrived earlier this morning.  It’s almost fully loaded, sans dual video cards and dual hard drives (after changing my mind last minute).  First impressions?  In stunning matte black, with its ribbed Skull Cap cover design, a back-lit keyboard, and a soft fingerprint-proof and scratch-resistant surface, it’s absolutely gorgeous!  With the keys glowing red, it makes me want to do my programming in the dark.

See for yourself, though I have to say, it’s even sexier in person.

image image

The only thing that confused me was the pair of mouse buttons, which aren’t separated by any space or visual cue.  When I first saw it, I thought it was some kind of touch-sensitive slider bar.  Then I was afraid they’d given me some kind of Mac mouse, but once I figured out they were separate areas to press for left and right buttons, I was enormously relieved.

I’ve wanted an Alienware ever since I first saw their high-end configurations and sleek designs, and now that they’re owned by Dell, they have the same warranty options for hassle-free, next-day on-site service.  As many problems as I’ve had with Dell hardware, there’s nothing like the peace of mind of knowing that it’ll be taken care of immediately.

The shopping experience was almost perfect.  One minor flaw: their website shows order tracking before it gets shipped out, and after reaching a certain phase of the process (order confirmation, billing, pre-production, etc.), it kept going back to phase 1, Order Confirmation.  I watched it jump several times from being almost ready to ship, back to order confirmation, and had to call to confirm that it was their tracking system and not my order that was messed up.

It was shipped through FedEx, and I missed the delivery by twenty minutes.  On a Saturday.  For some reason, FedEx doesn’t deliver on Sunday or Monday, at least not to my house.  I called to see if I could meet the truck to pick it up, and the dispatcher promised to send the message out to the truck, but I never got a call back.  Not a big deal to wait a few extra days, but you can imagine by excitement, and then my frustration.  To make matters worse, FedEx’s online package tracking sucks.  It’s not real time.  By the time they tried delivering it, I had just seen it show up as leaving its previous stopping point (in another state).  I thought these carriers knew exactly where each package was at all times!  If so, this information does not make it to their website in a timely fashion.

At 3.06 GHz, with 4 GB of DDR3 1064 MHz RAM, and an ATI Mobility Radeon video card with 512 MB RAM (for a software engineer, not a gamer), this machine hit 5.6 on the Windows Vista performance index.  This is even better than the 5.3 that my Bad Ass Development Rig scored, although it’s not a fair comparison (and the Vista performance index isn’t a real measurement of performance anyway).

After building my desktop, I learned that it would cost me $200 or so to publish the results of the PCMark performance tests online.  So if you’re curious to know what my desktop or this laptop scored, feel free to leave a comment (and your email, which isn’t shared), and I’ll be happy to share that privately.

This machine seems to be all about the nice little touches, not unlike the subtle details of a luxury automobile: the soft black finish of the case, a plethora of ports (USB, Firewire, Coaxial, SATA, HDMI, etc.), a 2 megapixel camera built into the lid that can pivot to aim higher or lower, the touch sensitive media control bar at the top of the keyboard, the keyboard’s smooth feel, and so on.

I was expecting it to be extremely heavy, and by laptop standards I’m sure it is (with its 17 inch monitor), but as I hefted the package into the house, I was surprised by how light it felt, so it’s still extremely mobile.  The power brick, on the other hand, is truly a monster, but will be stuffed lovingly anyway into my backpack wherever I go.  It will have to go with me, since my expected battery life is only two hours.

So if you have $3,300 burning a hole in your pocket and need a blazing fast mobile monster of a machine, I highly recommend the Alienware M17.  If not, they do have cheaper configurations starting at around $1,800.

Posted in Development Environment, Hardware, Personal | 4 Comments »

Why Oslo is Important

Posted by Dan Vanderboom on January 17, 2009

imageContrary to common misunderstanding and speculation, the point of Oslo is not to put programming in the hands of business analysts who want to write their own business rules.  Do I think some of that will happen?  Architects and engineers will try everything they can imagine.  Some of them will succeed in specific niches or scenarios, but it won’t replace application or system design, and it will probably be very limited for the forseeable future.  Oslo is more about dramatically improving the productivity of designers and developers by generalizing common solution patterns and generating more adaptable tools.

PDC Keynote

Much of the confusion around Oslo occurs for two reasons:

  1. Oslo is designed at a higher level of abstraction than most systems today, so its scope is broad and it will have an impact on virtually every product, solution and service across Microsoft.  It’s difficult to get your head around something that big.
  2. Because of its abstract nature, core concepts are defined in terms that are heavily overloaded, like "Model", "Repository", and "Language".  Once you’ve picked up the lingo and can translate Oslo terminology into language you’re already familiar with, both the concept and magnitude of it will become obvious.

Oslo isn’t something completely new; in fact, Oslo borrows from a lot of previous research and even existing model-driven development tools.  Oslo focuses existing technologies and techniques into a coherent and mature vision of development, combining all parts into a more powerful whole, and promises to deliver a supremely adaptable and efficient platform to develop on.

What Is Oslo?

Oslo is a software factory for generating first-class, tool-supported languages out of your declarative specifications.

A factory is a highly organized production facility
that produces members of a product line
using standardized parts, tools and production processes.

-from a review of Software Factories

The product line is analogous to Oslo’s parsers, transform tools, and IDE plugins for new data models and languages (both textual and visual) that you define.  The standardized parts are Oslo’s library components; the tools are the M languages and the Quadrant/Intellipad application; and the processes are shaped by the flow of data through the Oslo tool chain (see the diagram near the end of this article).

With Oslo, you build the custom tools you need to rapidly build or generate software systems.  It’s all about using the right tool for the job, and having a say in how those tools are shaped to obtain the greatest leverage.

As stated at the home page of softwarefactories.com:

We see a capacity crisis looming. The industry continues to hand-stitch applications distributed over multiple platforms housed by multiple businesses located around the planet, automating business processes like health insurance claim processing and international currency arbitrage, using strings, integers and line by line conditional logic. Most developers build every application as though it is the first of its kind anywhere.

In other words, there’s already a huge shortage of experienced, highly-qualified professionals capable of ensuring the success of these increasingly complex systems, and with the need (and complexity) growing exponentially, our current development practices increasingly fall short of the total demand.

Books like Greenfield’s Software Factories have been advocating building at a higher level of abstraction for years, and my initial reaction was to see it as a natural, evolutionary milestone for a highly mature software system.  However, it’s an awful lot of focused development effort to attain such a level of maturity, and not many organizations are able to pull it off given the state of our current development platforms.

It’s therefore fortuitous that Microsoft teams have taken up the challenge of building these abilities into their .NET platform.  After all, that’s where it really belongs: in the framework.

Unexpected Awesomeness

Oslo of course contains a lot of expected awesomeness, but where it will probably have the most impact in terms of developer productivity is with new first-class languages and language tools.  Why?  It first helps to understand the world of data formats and languages.

We’ve had an explosion of data formats–these mini Domain Specific Languages, if you will (especially in the form of complex configuration files).  As systems evolve and scale, and the ways we can configure and compose our application’s behavior continues to grow, at what point do we perceive that configuration graph as the rich language that it becomes?  Or when our user interfaces evolve from Monolithic to Modular to Composite to Granular Composite (or User Composable), at what point does that persistent object graph become our UX DSL (as with XAML in WPF).

Sometimes we set our standards too low, or are slow to raise them when the time has come to do so.  With XML we get extensibility in defining languages and we think, "If we can parse it, then we can build a tool over it."  I don’t know about you, but I’d much rather work with rich client software–some kind of designer–over a textual data format any day.

But you know how things go: some company like Microsoft builds a whole bunch of cool stuff, driven off some XML configuration, or they unleash something like XAML on which WPF, WF, and more are built.  XAML is great for tools to read and write, and although XML and XAML are textual and not binary and therefore human readable in a text editor (the original intention behind that term), it’s simply not as easy to read as C# or VB.NET.  That’s why we aren’t all rushing to program everything in XAML.

Companies like Microsoft, building from the bottom up, release their platforms well in advance of the thick client user experiences that make them enjoyable to use and which encourages mass adoption.  Their models, frameworks, and applications are so large now that they’re released in massively differentiated stages, producing a technology adoption gap.

By giving that language a syntax other than XML, however, we can approach it in the same way we approach our program logic: in the most human readable and aesthetically-pleasant way we can devise, resembling our programming languages of choice.

Sometimes, the density of data and its structure in our model is such that a visual editor fails to represent that model well.  Source code is a case in point.  You could create a visual designer to visualize flow control, branching logic, and even complex expression building (like the iTunes Smart Playlist), but code in text format is more appropriate in this kind of scenario, and ends up being more efficient with the existing tooling available.  Especially with an IDE like Visual Studio, we’re working with human-millenia of effort that have gone into the great code editing tools we use today.  Oslo respects this need for choice by offering support for building both visual and textual DSLs, and recognizes the fluent definition of new formats and languages as the bridge to the next quantum leap in productivity.

If we had an easy way of defining languages in formats that we developers felt comfortable working with–as we’re comfortable with our general purpose languages and their rich tool support–then we’d be much more productive in the transition between a technology first being released and later having rich tool support over it.  WPF has taken quite a while to be adopted as much as it has, partly due to tool availability and maturity.  Before Expression Blend or Cider designers were released and hand-coding XAML was the only way, those who braved the angle brackets struggled with it.  As I play with Silverlight, I realize how much must still be done in XAML, and how we still struggle.  It’s simply not as nice to work with as my C# code.  Not as rich, and not as strongly tool-supported.

That’s one place Oslo provides value.  With the ability to define new textual and visual DSLs, rigorous verification and validation in a rich set of tools, the promise of Intellisense, colorization of keywords, operators, constants, and more, the Oslo architects recognize the ability to enhance our development experience in a language-agnostic way, raising the level of abstraction because, as they say, the way to solve any technical problem is to approach it at one higher level of indirection.  Unfortunately, this makes Oslo so generalized and abstract that it’s difficult to grasp and therefore to appreciate its immensity.  Once you can take a step back and see how it fits in holistically, you’ll see that it has the potential to dramatically transform the landscape of software development.

Currently, it’s a lot of work to implement all the language services in Visual Studio to give them as rich an experience as we’ve come to expect with C#, VB.NET, and others.  This is a serious impediment to doing this kind of work, so solving the problem at the level of Oslo drastically lowers the barrier to entry for implementing tool-supported languages.  The Oslo bits I’ve seen and played with are very early in the lifecycle for this massive scope of technology, but the more I think about its potential, the more impressed I am with the fundamental concept.  As Chris Anderson explained in his PDC session on MGrammar, MGrammar was an implementation detail, but sometime around June 2007, that feature team realized just how much customers wanted direct access to it and decided to release MGrammar to the world.

Modeling & The Repository

That’s all well and good for DSLs and language enthusiasts/geeks, but primarily perhaps, Oslo is about the creation, exploration, relation, and execution of models in an interoperable way.  In other words, all of the models that are currently used to describe a software system, or an entire IT environment, are either not encoded formally enough to verify or execute, or they’re encoded or stored in proprietary ways that don’t allow interoperability with other models.  A diagram in Visio or PowerPoint documenting network topology, for example, knows nothing about the component architecture or deployment model of the software systems installed and running on that network.

When people usually talk about models, they imagine high-level architecture documents, overviews used to visually summarize work that is much more granular in nature.  These models aren’t detailed, and they normally aren’t kept up to date and in sync with the current design as changes are made.  But modeling in Oslo is not an attempt to make these visual models contain all of the necessary detail, or to develop software with visual tools exclusively.  Oslo simply provides the tools, both graphical and textual, to define and relate many models.  It will be up to the development community to decide how all these tools are ultimately used, which parts of our systems will be specified in a mix of general purpose, domain specific, and visual languages.  Ultimately, Oslo will provide the material and glue to fill the gaps between the high and low level specifications, and unite them into a common, connected, and much more useful set of data.

To grasp what Oslo modeling is really all about requires that we expand our definition of "model", to see the models expressed in our configuration and XAML files, in our applications’ database schemas, in our entity classes, and so on.  As software grows in complexity and becomes more composable, we can use various languages to model its behavior, store that in the repository for runtime execution, inspection, or reuse by other systems.

This funny and clever Oslo video (reminiscent of The Hitchhiker’s Guide to the Galaxy) explains modeling in the broader sense alluded to here.

If we had some universal container for the storage of all different kinds of models, and a standardized way of relating entities across models, we’d be able to do things like impact analysis, where we could see the effect on software systems if someone were to alter the network it was running on; or powerful data mining on the IT execution environment of a business.

Many different tools, with different audiences, will be able to connect into this repository to manipulate aspects of the models that they understand and have access to.  This is just the tip of the iceberg.  We already model so much of what we do in the IT and software worlds, and as we begin adopting business process middleware and orchestration software like BizTalk, there’s a huge amount of value in those models converging and connecting.  That’s where the Oslo Repository comes in.

Oslo provides interoperability among models in the same way that SOA provides interoperability among services.  Not unlike the interoperability we have now among many different languages all sharing the same CLR specification.

Bridging data models across repositories or in shared repository is a major step forward.  With Windows Azure and Microsoft’s commitment to their online services platform (and considering the momentum of the SaaS movement with Amazon, Google, and others), shared storage and data sets are the future.  (Check out SQL Data Services if you haven’t already, and watch for some exciting announcements coming later this year!)

The Dichotomy of Data vs. Metadata

Jeff Pinkston from the Oslo team aptly reflects the attitude of the group when he scoffs at the categorical difference between data and metadata.  In terms of storing and querying it, serializing and communicating it, and everything else that matters in enterprise software, data is data and there’s no reason not to treat it the same when it comes to architecting a system.  We have our primary models and our secondary models, our shared models and our protected models, but they’re still just models that shape our software’s behavior, and they share all of the same characteristics when it comes to manipulation and access.  It’s their ultimate effect that differs.

It’s worth noting, I think, the line that’s been drawn between code and data in some programming languages and not in others (C# vs. LISP).  A division has been made for the sake of security rather than necessity.  Machine instruction codes are represented in the same sort of binary data and realized in the same digital circuitry as traditional user data.  It’s tempting to keep things locked down and divided, but as languages evolve to become more late bound and dynamic (and as the tools evolve to make this feasible), there will be more need for the manipulation of expression trees and ASTs.  I strongly suspect the lines will blur until they disappear.

Schema and Object Instance Languages

In order to define models, we need a tool.  In Oslo, this is a textual language called MShema and an editor called Intellipad.  I personally think it’s odd to talk people’s ears off about "model, model, model", and then to use the synonym "schema" to name the language, but all of these names could change before they’re shipped for all we know.

This is a simple example of an MSchema document:

module MyModel
{
    type Person
    {
        LastName : Text;
        FirstName : Text;
    }

    People : Person*;
}

By running this through the "M Compiler", a SQL script is generated that will create the appropriate database objects.  Intellipad is able to verify the correctness of your schema, and what’s really nice is that you don’t even have to specify data types when you start sketching out your model.  Defaults are assumed, and you can get more specific as your model evolves.

MGraph is a language for defining instances of objects, constrained by an MSchema and similar in format.  So MSchema is to MGraph what XSD is to XML.

In this article, Lars Corneliussen explains Microsoft’s vision to make MGraph as common as XML is today.  Take a look at his article to see a side-by-side comparison of the same object represented as XML (POX), JSON, and MGraph, and decide for yourself which you like best (or see below).

MSchema and MGraph are easier and more efficient to read and write than XML.  Their message format resembles typical structured programming languages, and developers are already familiar with these formats.  XML is a fine format for a tool; it’s human readable but not human-friendly.  A C-style language, on the other hand, is much more human-friendly than all of the angle brackets and the redundancy (and verbosity) of tag text.  That narrows down our choice to JSON and MGraph.

In JSON, the property/field/attribute names are delimited by quotation marks, suggesting that the whole structure is a dumb property bag.

{
    "LastName" : "Vanderboom",
    "FirstName" : "Dan"
}

MGraph has a very similar syntax, but its attribute property names are recognized and validated by the parser generated from MSchema, so the quotation marks are unnecessary.  It ends up looking more natural, and a little more concise.

{
    LastName : "Vanderboom",
    FirstName : "Dan"
}

Because MGraph is just a message format, and Microsoft’s service offerings already support multiple message formats (SOAP/POX/JSON/etc.), it wouldn’t disrupt any of their architecture to add an MGraph adapter, and I’ll be shocked if I don’t hear about one in their next release.

Meta-Languages and MGrammar

In the same way that Oslo includes a meta-model because it allows us to define models, it also includes a meta-language because it allows us to define languages (as YACC and ANTLR have done).  However, just as Pinkston doesn’t think data and metadata should be treated different, it makes sense to think of a language that defines languages as just another language.  There is something Zen about that, where the tools somehow seem to bend back upon themselves like one of Escher’s drawings.

DrawingHands

Here is an example language defined by MGrammar in a great article on MSDN called MGrammar in a Nutshell:

module SongSample
{
    language Song
    {
        // Notes
        token Rest = "-";
        token Note = "A".."G";
        token Sharp = "#";
        token Flat = "b";
        token RestOrNote = Rest | Note (Sharp | Flat)?;

        syntax Bar = RestOrNote RestOrNote RestOrNote RestOrNote;
        syntax List(element)
          = e:element => [e]
          | es:List(element) e:element => [valuesof(es), e];

        // One or more bars (recursive technique)
        syntax Bars = bs:List(Bar) => Bars[valuesof(bs)];
        syntax ASong = Music bs:Bars => Song[Bars[valuesof(bs)]];
        syntax Songs = ss:List(ASong) => Songs[valuesof(ss)];

        // Main rule
        syntax Main = Album ss:Songs => Album[ss];

        // Keywords
        syntax Music = "Music";
        syntax Album = "Album";

        // Ignore whitespace
        syntax LF = "\u000A";
        syntax CR = "\u000D";
        syntax Space = "\u0020";

        interleave Whitespace = LF | CR | Space;
    }
}

This is a pretty straight forward way to define a language and generate a parser.  Aside from the obvious keywords to define syntax rules and token patterns (with an alternative and more readable format for regular expressions), the => projection operator allows you to shape the MGraph output according to your needs.

I created two simple languages with MGrammar on the plane trip back to Milwaukee from the PDC in November.  The majority of my time was spent fussing with the editor, Intellipad, and for the last half hour I found it very easy to create a language on the fly, extending and changing it through experimentation quickly and easily.  Projections, which are functional expressions in MGrammar used to shape MGraph output, are the most challenging part.  There are a number of techniques that shape the output graph, so it will be good to see how this is approached in future reference examples.

Surreptitiously announced just before I wrote this, Mike Weinhardt at Microsoft indicated that a gallery of example grammars for MGrammar is being put together, to point to the sample grammars for various languages in addition to grammars that the community develops, and it should be available by the end of this month.  These examples demonstrating how to define languages and write sensible projections, coming from the developers who are putting MGrammar together, will be an invaluable tool for teaching you how to use common patterns (just as 101 LINQ Samples did for LINQ).

As Doug Purdy explained on .NET Rocks: "People who are building a domain specific language, and they don’t want to understand how to build a parser, or they’re not language designers.  Actually, they are language designers.  They design a language, but they actually don’t do the whole thing.  They don’t build a parser.  What they do, they just leverage the XML parser.  And what we’re trying to do is provide a toolset for folks where they don’t have to resort to XML in order to do DSLs."

From the same episode, Don Box said of the DSL session at PDC: "I’ve never seen a session with more geek porn in it."

Don: "It’s like crack for developers.  It’s kind of addictive; it takes over your life."

Doug: "If you want the power of Anders in your hand…"

The Tool Chain

Now that we have a better sense of what’s included in Oslo in terms of languages, editors, and the shared repository, we can look at the relationship among the other pieces, which are manifested in the CTP as a set of command-line tools.  In the future, these will integrate into an IDE, most likely Visual Studio.  (I’d expect Intellipad and Quadrant to merge with Visual Studio, but there’s no guaranty this will happen.)

When you create your model with MSchema, you’ll use m to validate that model and generate a SQL script to create a SQL Server 2008 database schema (yes, it only works right now with SQL Server 2008).  You’ll also use the m command to validate your object graph (written in MGraph) against your schema, and translate that into a set of SQL commands to perform inserts and updates against tables.

With enough models, there’ll be huge value in adding yours to the repository.  If you don’t mind writing MGraph or you generate it automatically with something like an MGraphSerializer class in your code, this may be all you need.

If, on the other hand, you decide you could really benefit by defining your own textual language to use instead of MGraph, you can use MGrammar to define a new language.  This language gets compiled by the mg compiler to create your parser, and the mgx command translates code in your new language into an MGraph, which can then be pulled into your database using m.

This diagram depicts the process:

image

Other than these command-line tools, Quadrant is the highly extensible visual tool for exploring models graphically, and Intellipad is a different face on the same shell for defining DSLs with MGrammar and writing DSL code, as well as writing and verifying MSchema and MGraph code.

We should see fairly soon the convergence of these three languages (MGraph, MSchema, and MGrammar) into a single M language.  This makes sense, since what you want to project in your DSL should be something within your model, verified by your schema.  This may ultimately make these projections much easier to write.

We’ll also see this tool chain absorbed into multiple development environments, eventually with rich binding across multiple representations of our model, although this will take longer in Visual Studio.

Languages and Nested Languages

I looked at some MService examples, and I can understand Damon’s concern that although it’s nice to have "operation" as a keyword in a service-oriented language, with more keywords giving you the ability to specify aspects of each endpoint and the communications patterns required, that enclosing the business logic within that service language is probably not a good idea.  I took this from Dennis van der Stelt’s blog:

service Service
{
  operation PhotoUpload(stream : Stream) : Text
  {
    .PostUriTemplate = "upload";

    index : Text = invoke DateTime.Now.Ticks.ToString();
    filename : Text = "d:\\demo\\photo\\" + index + ".jpg";
    invoke MService.ServiceHelper.StoreInFile(stream, filename);

    return index;
  }
}

Why not?  You’re defining a general purpose language within the curley braces, one capable of defining variables, assigning values, referencing .NET objects, and calling methods.  But why do you want to learn a new language to write services when the language you’re using right now is already supremely capable of that?  Don’t you already know a good syntax for invoking methods (other than "invoke %mehthod%")?  If instead you simply referenced an assembly, type, and method from an MService script, you could externally turn any .NET method with serializable parameters and return value into a service operation by feeding it this kind of file, without having to recompile, and without having to reinvent the wheel.

The possible exception would be if MGrammar adds the ability (as discussed by speakers at the PDC) of supporting multiple layers of enclosing languages within other languages.  In other words, you could use MService to define operations and their attributes using its own syntax, and within the curly braces that follow, use the C# or VB.NET parsers to process the logic with the comprehension of a separate language.  There are some neat possibilities here, but I expect the development community to be conservative and hesitent about mixing layers of semantics, as there is an awful lot of room for confusion and complexity.  It may be better to leave different language blocks in separate files or containers, and to allow them to reference each other as .NET assemblies and XML files reference each other today.

However, I wouldn’t get too hung up on the early versions of these new languages, or any one language specifically.  The useful, sensible ones that take real developer needs into account and provide the most value will be adopted, and many more will quickly fall into disuse.  But the overall pattern will be for the emergence of an amazing amount of leverage in terms of improving human comprehension and taking advantage of our ability to manipulate structured, symbolic object graphs to build and verify software systems.

Resources

After a few months of research and many hours of writing, I don’t feel like I’ve even scratched the surface.  But instead of giving you an absolutely comprehensive picture, I’m going to stop here and continue in future articles.  In the meantime, check out the following resources.

For an overview of the development paradigm, look for information on language-oriented programming, including an article I wrote that alludes to how "we will have to raise the level of abstraction to a point that may be hard for us to imagine with our existing tools and languages" due to the "precipitious growth of software complexity".  The "community of abstractions" is the model in Oslo-speak.

For Microsoft specific content: there were some great sessions at the PDC (watch the recorded videos).  It was covered (with much confusion) on the .NET Rocks! podcast (here and here) as well as on Software Engineering Radio; and there are lots of bloggers talking about their initial experiences with it, such as Shawn Wildermuth, Lars Corneliussen, and of course Chris Sells and Jeff Pinkston.  The most clear and coherent explanation I’ve heard was from an interview with Ron Jacobs and David Chappell (Ron gave the keynote at MSDN Dev Con, hosted the ARCast podcast for years).  MSDN has at least 29 videos on the Oslo Developer Center, where there’s a good amount of information. including a FAQ.  There’s also the online guide for MGrammar, MGrammar in a Nutshell, and the Oslo team blog.

If you’re interested in creating DSLs, make sure to keep a look out for details about the upcoming DSL Developers Conference, which is tentatively planned for April 16-17, immediately following the Lang.NET conference (on general purpose languages) on April 14-16.  I’m hoping to be at both this year.  And in case you haven’t heard, Microsoft is planning another PDC Conference for 2009, the first time ever these conferences have run for two consecutive years!  There will no doubt be much more Oslo news and conference material to cover it at the PDC in November.

Pluralsight, an instructor-led training company, now teaches a two-day "Oslo" Fundamentals course (and Don Box’s blog is hosted there).

The best way to learn about Oslo, however, is to dive in and use it.  That’s what I’m doing with my newest system, which needs to be modeled from scratch.  So if you haven’t done so already, download the Oslo SDK (link updated to January 2009 SDK) and introduce yourself to the future of modeling and development!

[Click here for the next article in this Oslo series, on common misconceptions and fallacies about Oslo.]

Posted in Data Structures, Development Environment, Distributed Architecture, Language Extensions, Language Innovation, Metaprogramming, Oslo, Problem Modeling, SQL Data Services, Service Oriented Architecture, Software Architecture, Visual Studio, Windows Azure | 31 Comments »

MSDN Developer Conference in Chicago

Posted by Dan Vanderboom on January 13, 2009

I just got home to Milwaukee from the MSDN Developer Conference in Chicago, about two hours drive.  I knew that it would be a rehash of the major technologies revealed at the PDC which I was at in November, so I wasn’t sure how much value I’d get out of it, but I had a bunch of questions about their new technologies (Azure, Oslo, Geneva, VS2010, .NET 4.0, new language stuff), and it just sounded like fun to go out to Fogo de Chao for dinner (a wonderful Brazilian steakhouse, with great company).

So despite my reservations, I’m glad I went.  I think it also helped that I’ve had since November to research and digest all of this new stuff, so that I could be ready with good questions to ask.  There’ve been so many new announcements, it’s been a little overwhelming.  I’m still picking up the basics of Silverlight/WPF and WCF/WF, which have been out for a while now.  But that’s part of the fun and the challenge of the software industry.

Sessions

With some last minute changes to my original plan, I ended up watching all four Azure sessions.  All of the speakers did a great job.  That being said, “A Lap Around Azure” was my least favorite content because it was so introductory and general.  But the opportunity to drill speakers for information, clarification, or hints of ship dates made it worth going.

I was wondering, for example, if the ADO.NET Data Services Client Library, which talks to a SQL Server back end, can also be used to point to a SQL Data Services endpoint in the cloud.  And I’m really excited knowing now that it can, because that means we can use real LINQ (not weird LINQ-like syntax in a URI).  And don’t forget Entities!

I also learned that though my Mesh account (which I love and use every day) is beta, there’s a CTP available for developers that includes new features like tracking of Mesh Applications.  I’ve been thinking about Mesh a lot, not only because I use it, but because I wanted to determine if I could use the synchronization abilities in the Mesh API to sync records in a database.

<speculation Mode=”RunOnSentence”>
If Microsoft is building this entire ecosystem of interoperable services, and one of them does data storage and querying (SQL Data Services), and another does synchronization and conflict resolution (Mesh Services)–and considering how Microsoft is making a point of borrowing and building on existing knowledge (REST/JSON/etc.) instead of creating a new proprietary stack–isn’t it at least conceivable that these two technologies would at some point converge in the future into a cloud data services replication technology?
</speculation>

I’m a little disappointed that Ori Amiga’s Mesh Mobile wasn’t mentioned.  It’s a very compelling use of the Mesh API.

The other concern I’ve had lately is the apparent immaturity of SQL Data Services.  As far as what’s there in the beta, it’s tables without enforceable schemas (so far), basic joins, no grouping, no aggregates, and a need to manually partition across virtual instances (and therefore to also deal with the consequences of that partitioning, which affects querying, storage, etc.).  How can I build a serious enterprise, Internet-scale system without grouping or aggregates in the database tier?  But as several folks suggested and speculated, Data Services will most likely have these things figured out by the time it’s released, which will probably be the second half of 2009 (sooner than I thought).

Unfortunately, if you’re using Mesh to synchronize a list of structured things, you don’t get the rich querying power of a relational data store; and if you use SQL Data Services, you don’t get the ability to easily and automatically synchronize data with other devices.  At some point, we’ll need to have both of these capabilities working together.

When you stand back and look at where things are going, you have to admit that the future of SQL Data Services looks amazing.  And I’m told this team is much further ahead than some of the other teams in terms of robustness and readiness to roll out.  In the future (post 2009), we should have analytics and reporting in the cloud, providing Internet-scale analogues to their SQL Analysis Server and SQL Reporting Services products, and then I think there’ll be no stopping it as a mass adopted cloud services building block.

Looking Forward

The thought that keeps repeating in my head is: after we evolve this technology to a point where rapid UX and service development is possible and limitless scaling is reached in terms of software architecture, network load balancing, and hardware virtualization, where does the development industry go from there?  If there are no more rungs of the scalability ladder we have to climb, what future milestones will we reach?  Will we have removed the ceiling of potential for software and what it can accomplish?  What kind of impact will that have on business?

Sometimes I suspect the questions are as valuable as the answers.

Posted in ADO.NET Data Services, Conferences, Distributed Architecture, LINQ, Mesh, Oslo, SQL Analysis Services, SQL Data Services, SQL Reporting Services, SQL Server, Service Oriented Architecture, Virtualization, Windows Azure | Leave a Comment »