Sequence Diagram RE, LINQ, and Lambdas

The Sequence Diagram Reverse Engineering feature available in Visual Studio 2010 allows you to create a UML 2.1 “like” diagram that represents your source code. I say “like” in the previous sentence because we use all the notation prescribed by the UML standard, but there are a few instances where we add some notation that is not found in the standard. Support for LINQ and Lambda expressions are examples of where we have extended the Combined Fragment notation to include what we have dubbed a “Deferred Call”.

Here’s a simple console application that I’ll use to show what I mean.

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        class Customer
        {
            public string Name { get; set; }
            public string City { get; set; }
        }

        static void Main( string[] args )
        {
            var customers = new Customer[]{ 
                                new Customer{ 
                                    Name="Sally Smith",
                                    City="Dallas"
                                },
                                new Customer{
                                    Name="John Roberts",
                                    City="Denver"
                                },
                                new Customer{
                                    Name="Cameron Skinner",
                                    City="Redmond"
                                },
                                new Customer{
                                    Name="Betty Silas",
                                    City="Redmond"
                                }
                            };

            Func<Customer, string > test = ( x ) => { return string.Format( "Name={0}", x.Name );  };

            var customer = from x in customers
                      where x.City == "Redmond"
                      select x;

            foreach( var x in customer )
            {
                Console.WriteLine( x );
                Console.WriteLine( test( x ) );
            }
        }
    }
}

And here’s the resulting diagram created by right-clicking anywhere in the Main() method and selecting “Generate Sequence Diagram…”:

image

( NOTE: Ok, it’s not exactly. I’ve collapsed a couple of lifelines to reduce the amount of information displayed. Notice the LifelineGroup1 lifeline? Try it out for yourself by generating the sequence diagram, then select the four Program.Customer lifelines by Ctrl + Left click, then right click and select Collapse. Once you do that, you might want to relayout the diagram in order to fill the resulting blank space. Do that by right-click and select Rearrange Layout. )

Take note of the two Deferred Call combined fragments. Here’s one that represents the where clause in the LINQ expression:

image

And here’s the other one that represents the lambda:

image

 

We wanted to make it very explicit and indicate to you that a sequence of messages may actually not execute in the exact spot on the diagram as indicated if you were looking at the diagram relative to time passing as you move down the Y axis. We found this important in both LINQ expressions as well as lambdas, ‘cause LINQ expressions are not necessarily executed at the time you step over that line in the debugger. And when it comes to lambdas, we wanted to show the actually definition of the lambda when invoked, as UML doesn’t really have a way to show that otherwise.

This approach may seem strange at first, especially when trying to get your head around the diagrammatic representation of LINQ expressions. Deferred execution in LINQ is common place. One technique that helps drive a deeper understand of LINQ’s deferred execution strategy is to step through the Visual Studio debugger. Once you do, you’ll also understand the diagrammatic representation better.

For example, hit F11 to start stepping into this code. Keep hitting F11 until you get to the foreach statement:

image

( Notice how you stepped right over the LINQ expression to get to the foreach? )

Hit F11 again and customer will be highlighted. One more time and the in keyword will be highlighted. One more time and the highlighted statement to be executed next jumps to the where clause of the LINQ expression:

image

Hit F11 a few more times and the highlighted statement jumps back down to the foreach statement. This is “deferred execution” in action!

Hope that helps,

Cameron