Visual Studio 2010 CTP 2 - A close encounter with Sequence Diagram - Willy-Peter Schaub's Cave of Chamomile Simplicity

Visual Studio 2010 CTP 2 - A close encounter with Sequence Diagram

In one of the Visual Studio 2010 CTP2 evaluation posts http://dotnet.org.za/willy/archive/2008/11/14/visual-studio-2010-ctp-2-5-7-reviewing-a-solution.aspx, I mentioned that we would have a closer look at the sequence diagram ... well, this it is q;-)

A very special THANK YOU to Suhail Dutta from Microsoft, for reviewing this post before it was published and sharing some really good news q;-)

101 - Sequence Diagram
101

What is it?

Without delving into UML Sequence diagrams, we can mention a hypothetical situation where a user needs someone to switch off a light. The sequence of events would be for person X to request a coordinator of all lights to switch off the light. The coordinator creates a committee to discuss the request and to ask the relevant administrator(s) to switch of the light. We thus have a "sequence" of events and lifetimes as shown:

image

For the UML exerts who cringe with the above loose and "humanoid" diagram, here is the UML Sequence Diagram equivalent:
image

A sequence diagram therefore visualises interaction of objects and the lifetime of involved objects, excelling in showing which objects communicate with which objects and what messages are triggered as part of the communication.

What is it NOT?

A sequence diagram is not good for showing complex procedural logic and "simplicity" should be rules 1-10 when creating sequence diagrams. The headaches start when you are trying to model and visualise scenarios such as complex branching (e.g. exceptions) or multiple threads.

Filtering capabilities, such as breaking up a complex diagram into multiple simpler diagrams brings some relief.image

What are some of the main artifacts?

Coordinator instance lifeline extract ...

Lifelines

A lifeline is a representation of a specific object within a sequence diagram, which typically has an object name. 

Messages
image

Messages, denoted as arrows, depict the communication between objects, which is typical synchronous or asynchronous.

image A solid arrow head depicts an implicit (synchronous) request and response. 
image A line arrowhead depicts an asynchronous message.
image A dashed line an asynchronous response.

Peeking into the new engine room (UML 2)
Shy Blue Man Inside a Bubble Clipart Illustration

Fragments

Fragments allow a degree of procedural logic to be sprinkled (i.e. if-else-then) to the sequence diagram, combining one or more processing sequences into one combined fragment. We will look at the various fragment types in a second, when looking at the Visual Studio 2010 CTP 2.

Gate

Another cool feature is a gate, which is essentially a connection point of a message within a fragment, to a message outside a fragment.  Gates can also act as off-page connectors, allowing us to break down complex sequence diagrams or re-usable sequences into separate sequence diagrams.

... right, let's see what Visual Studio 2010 CTP 2 can do for us ...

Visual Studio 2010 CTP2's view in sequence diagrams

What about reverse engineering code?
Colorful Circle Of Diverse People Holding Hands, Symbolizing Teamwork And Unity Clipart Illustration Graphic

I created a simple main program, contract class, base calculator class, division class and multiplication calculator class as follows to test the reverse engineering:

Main program
   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Text;
   5: using Calculator.Contracts;
   6: using Calculator;
   7:  
   8: namespace SD_Demonstration
   9: {
  10:     class Program
  11:     {
  12:         static void Main(string[] args)
  13:         {
  14:             #region DemoCode
  15:                 BaseCalculator calculator = new BaseCalculator();
  16:                 CalcRequest request = new CalcRequest(CalculationType.Add, 1, 2);
  17:  
  18:                 calculator.RequestCalculation(request);
  19:  
  20:                 Console.WriteLine("Calculation {0} {1} {2} = {3}",
  21:                                   request.ValueOne,
  22:                                   request.Type,
  23:                                   request.ValueTwo,
  24:                                   request.Result);
  25:  
  26:                 Console.ReadLine(); 
  27:             #endregion
  28:         }
  29:     }
  30: }
Contract Classes
   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Text;
   5:  
   6: namespace Calculator.Contracts
   7: {
   8:     public enum CalculationType { Add, Subtract, Divide, Multiply };
   9:  
  10:     public interface IBaseCalculator
  11:     {
  12:         int Add ( int valueOne, int valueTwo );
  13:         int Subtract ( int valueOne, int valueTwo );
  14:     }
  15:  
  16:     public interface ICalculator
  17:     {
  18:         void RequestCalculation ( CalcRequest request );
  19:     }
  20:  
  21:     public class CalcRequest
  22:     {
  23:         public CalcRequest(CalculationType type, int valueOne, int valueTwo)
  24:         {
  25:             this.Type = type;
  26:             this.ValueOne = valueOne;
  27:             this.ValueTwo = valueTwo;
  28:         }
  29:         
  30:         CalculationType type;
  31:  
  32:         public CalculationType Type
  33:         {
  34:             get { return type; }
  35:             set { type = value; }
  36:         }
  37:         
  38:         int valueOne;
  39:  
  40:         public int ValueOne
  41:         {
  42:             get { return valueOne; }
  43:             set { valueOne = value; }
  44:         }
  45:  
  46:         int valueTwo;
  47:  
  48:         public int ValueTwo
  49:         {
  50:             get { return valueTwo; }
  51:             set { valueTwo = value; }
  52:         }
  53:  
  54:         int result;
  55:  
  56:         public int Result
  57:         {
  58:             get { return result; }
  59:             set { result = value; }
  60:         }
  61:     }
  62: }
Base Calculator Class
   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Text;
   5: using Calculator;
   6: using Calculator.Contracts;
   7:  
   8: namespace Calculator
   9: {
  10:     public class BaseCalculator : IBaseCalculator, ICalculator
  11:     {
  12:  
  13:         #region IBaseCalculator Members
  14:  
  15:         public int Add(int valueOne, int valueTwo)
  16:         {
  17:             return valueOne + valueTwo;
  18:         }
  19:  
  20:         public int Subtract(int valueOne, int valueTwo)
  21:         {
  22:             return valueOne - valueTwo;
  23:         }
  24:  
  25:         #endregion
  26:  
  27:         #region ICalculator Members
  28:  
  29:         public void RequestCalculation(CalcRequest request)
  30:         {
  31:             ICalculator calculator;
  32:  
  33:             switch (request.Type)
  34:             {
  35:                 case CalculationType.Add:
  36:                     request.Result = this.Add(request.ValueOne, request.ValueTwo);
  37:                     break;
  38:                 case CalculationType.Subtract:
  39:                     request.Result = this.Subtract(request.ValueOne, request.ValueTwo); 
  40:                     break;
  41:                 case CalculationType.Divide:
  42:                     calculator = new DivisionCalculator();
  43:                     calculator.RequestCalculation(request);
  44:                     break;
  45:                 case CalculationType.Multiply:
  46:                     calculator = new MultiplicationCalculator();
  47:                     calculator.RequestCalculation(request); 
  48:                     break;
  49:                 default:
  50:                     throw new NotImplementedException();
  51:             }
  52:         }
  53:  
  54:         #endregion
  55:     }
  56: }
Division Class
   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Text;
   5: using Calculator.Contracts;
   6:  
   7: namespace Calculator
   8: {
   9:     public class DivisionCalculator : ICalculator
  10:     {
  11:         #region ICalculator Members
  12:  
  13:         public void RequestCalculation(CalcRequest request)
  14:         {
  15:             request.Result = request.ValueOne / request.ValueTwo;
  16:         }
  17:  
  18:         #endregion
  19:     }
  20: }
Multiplication Class
   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Text;
   5: using Calculator.Contracts;
   6:  
   7: namespace Calculator
   8: {
   9:     public class MultiplicationCalculator : ICalculator
  10:     {
  11:         #region ICalculator Members
  12:  
  13:         public void RequestCalculation(CalcRequest request)
  14:         {
  15:             request.Result = request.ValueOne * request.ValueTwo;
  16:         }
  17:  
  18:         #endregion
  19:     }
  20: }

Some Challenges ...

I encountered a few challenges with CTP2, which I reported to the product team. I will report on the feedback/resolution when available.

  1. Placing all classes in separate projects, resulted in the following error "VS1140:The integration tool encountered an error when it executed the command. For more information, see the inner exception message". I resolved it by placing all class source files into one main project.
  2. Using interface polymorphism resulted in a strange sequence diagram. In other words, the following code created some headaches:

public void RequestCalculation(CalcRequest request) {
    ICalculator calculator;

    switch (request.Type)  {
        ...
                case CalculationType.Divide:
                    calculator = new DivisionCalculator(); <<<<<<<<< reverse engineer fails with object not instantiated
                    calculator.RequestCalculation(request);
                    break;
         ...

   }

... whereas the following revised code worked A OK:

public void RequestCalculation(CalcRequest request) {
    switch (request.Type)     {
        ...
                case CalculationType.Divide:
                    DivisionCalculator calculator = new DivisionCalculator(); <<<<<<<<< implicit type instantiation worked OK
                    calculator.RequestCalculation(request);
                    break;
         ...

}

 Musical Blue Man Playing Jazz With a Saxophone Clipart Illustration GOOD NEWS: I have been informed that both issues have been filed as bugs and have been resolved since the release of the CTP2. Excellent response ... the VSTS product team is really "rocking" these days!

Creating the sequence diagram

image image
I right clicked in the ProgramMain,cs file inside the Main method and clicked Generate Sequence Diagram. The result was a comprehensive sequence diagram, which once the challenges described earlier were conquered, was correct and complete.

What about UML 2 features?

If we look at the UML Sequence Diagram carefully, we will notice two features, (1) the REF and (2) the ALT fragment.

image 
... sorry for the cut ... wish the modelling tools would allow a save as "JPEG" or "PNG" ...
image

The ALT fragment  models the switch, the if…then…else construct we coded in the BaseCalculator, stating that we will process the ADD, alternatively the SUBTRACT, alternatively the DIVIDE or alternatively the MULTIPLY. There is a limitation in the CTP2 for the eagle eyed readers ... again the team has already started work on this one ... 'cause you will notice that the diagram does not currently show the actual expression for the if then else on the fragment so it’s somewhat hard to figure out why each section is created.

The REF feature (official UML name is Interaction User) allows us to break logic in a sequence diagram into separate diagrams, reducing the noise and complexity in the main diagram. In the above sequence diagram we have extracted the "Create CalcRequest, the "DivisionCalculator" and the "MultiplicationCalculator" sequences, which are stored in separate sequence diagrams as below..

image image
As mentioned we can surround sequences with new fragment definitions:

image

The fragments supported in CTP deliver the following punch:

Alt Alternative fragment models if…then…else construct
Assert Assertion fragment models instances where sequences not shown as an operand of the assertion are regarded as invalid
Break Break fragment models an alternative sequence
Consider Consider fragment is the opposite of the ignore fragment and models that messages not included should be ignored
Critical Critical fragment models a critical section
Ignore Ignore fragment modes messages included in the current context to be "ignored"
Loop Loop fragment models a sequence of repeated messages
Negative Negative fragment models invalid messages
Option Option fragment models switch constructs
Parallel Parallel fragment models parallel (concurrent) sequences
Strict Sequencing Strict sequencing fragment models messages sequences which must be strictly processed in defined order
Weak Sequencing Weak sequencing fragment models messages sequences which must be processed, but in not necessarily in defined order

If you want more information, I suggest that you read the article "STRUCTURAL MODELING WITH UML2.0, Classes, Interactions and State Machines, by Øystein Haugen, Birger Møller-Pedersen, Thomas Weigert" at http://folk.uio.no/oysteinh/Haugen-MP-Weigert-UMLForReal.pdf.

Summary

Blue Man Holding a Pencil and Drawing a Circle on a Blueprint Clipart Illustration ... cannot wait for the go-live-license for Visual Studio 2010. These visualisation tools and modellers have been long overdue!!!

We are still working with a community technology preview (CTP) release and therefore some challenges and hiccups were expected. BUT, the diagram is far more comprehensive and usable than the diagrams generated by CTP1 ... we cannot wait for the next CTP and the final product.

My 'personal' rating, based on a 5 smiley (maximum) system ...

Sequence Diagrams The sequence diagram and UML 2 support is great. As we encountered some challenges and had to create a wish list, my rating is four smiley's.

Wish List

  1. More control when adding UML2 features and wizards to assist in the application of the fragments. If you are wondering what I mean, then have a look at http://oldresources.visual-paradigm.com/uml_diagrams/sequence_diagram/using_alternative_combined_fragments_in_sequence_diagram.html.
  2. Ability to save diagram as a graphics file (PNG,JPEG, GIF, ...) for documentation.
  3. Less memory usage and more performance ... it is a CTP and I did un in a Virtual machine, but performance could be better.

image ... sequence diagrams ... a small piece of the puzzle ...

Published Tuesday, November 18, 2008 11:32 AM by willy
Filed under: ,

Comments

# Pattern Editor oder Sequencer als benutzedefiniertes Steuerelement | hilpers

Pingback from  Pattern Editor oder Sequencer als benutzedefiniertes Steuerelement | hilpers

Leave a Comment

(required) 
(required) 
(optional)
(required) 

Enter the numbers above: