What is left of Microsoft “Oslo”? What now with SQL Server Modeling? (Early 2010)

Back in October 2008 Microsoft announced “Oslo” as a new and world-changing modeling platform. While it always consisted of a language, an editor and a repository the community seemed to be mostly interested in the language “M” and it’s grammar features for creating new domain specific languages.

The feedback could be summarized to:

Great! We love model-driven. We love DSLs. But why the heck SQL?

After that they got engaged with that community. Chris hosted the DSL Dev Con. And Doug released “M” under the Open Specification Promise and founded the “M” Specification Community. Mathew Wilson implemented M in JavaScript. Hugo Brunelier elaborated on the possibilities of bridging it with Eclipse Modeling.

Many wrote, spoke and blogged about it. The fellow hope was, that Microsoft could bring model-driven development to a broader audience and by that increase both productivity and quality in software development.

For that community the renaming of “Oslo” to SQL Server Modeling was a slap in the face. Many stated that they were disappointed by Microsoft’s decisions.

Let’s look into the reasoning and the real consequences of that rename.

Even though I think it was a wise decision business-wise both the timing and the messaging was really bad.

The Repository and “Quadrant” were closely tied to SQL right from the beginnings of “Oslo”. The schema, constraints and functions part of “M” had and mostly still has only one implementation: also SQL.

But the languages part of “M” also referenced to as “MGrammar” had nothing to do with SQL at all and it still doesn’t have much to do with it today either.

“M” should have been split out from “Oslo” before the rename and everybody would have been happy.

So where is this going now?

“M” and “Quadrant” today are still code names. The only thing that has a final name is the repository part of “Oslo” which is now named SQL Server Modeling Services. And I think we agree that that is a OK name.

Most probably “M” will not become SQL Server Modeling M and neither will “Quadrant” be named SQL Server Modeling Quadrant.

I think the final “M” will be as much SQL as Entity Framework and OData are SQL today. All those are developed within the same group and I expect it to merge anyway.

“Quadrant” will probably replace the part in SQL Server Management Studio that enables browsing and editing of SQL data – which is horrible today anyway. It also has the potential of replacing Access as a platform for Information Workers.

And maybe some day we’ll see ideas from “Quadrant” in Excel.

Future of DSL Development with Microsoft Tools

Visual: There was a hope, that “Quadrant” could be a better DSL Toolkit. Those teams didn’t talk to each other, but now they do. I think MS gave up on visual DSLs with “Quadrant”. Instead we’ll see the DSL Toolkit getting more attention. In some Demos at PDC we saw diagrams in Visual Studio working together with SQL Server Modeling. That were already DSL Tools operating on “M” models.

Textual: “M” is at maximum a third of the “Oslo” vision. And the languages part again is only a subset of “M”. Maybe that helps seeing the priorities in the big context.

But still the commitment is alive. The November CTP has some great new features. For example more powerful “M” projections for grammar rules or basic debugging support.  Probably some day this will merge with the DSL Tools and we’ll have both graphical and textual DSLs support right within Visual Studio. I think and hope that the connection to SQL will not be very strong in the future.

Model-driven Development

As often when Microsoft starts (mis)using existing terms they or at least many of their employees just don’t get it. At least not in the first place.

An application that uses “M” to define the M in MVC is not automatically model-driven. It’s just a normal application that operates on data as most applications do. If you want to argue like that, then every C# file and all SQL table rows are models.

In my perception model-driven is, when models become part of the implementation. The Workflow Foundation is a good example for what model-driven means. You model something that is the source of truth for your application – instead of C# code.

If tools help building things like the workflow foundation based on either visual or textual DSLs, using interpreters or code generation, then they truly support the vision of model-driven software development.

Updates on what Oslo is and Quadrant not is (September 2009)

It has been more quiet around “Oslo” the last month. Maybe just about everybody is on vacations. Or people feel that everything will change with the PDC in November and are afraid of publishing nonsense.

Nonetheless, I felt it’s time for an update on what I think, heard and read about “Oslo”.

I divided my post in two sections:

  • Information about “Oslo”
  • What I think about “Oslo” today

have fun!

Some Information about “Oslo”

For those who don’t know, “Oslo” is the current codename for Microsoft’s forthcoming modeling platform, which is available as CTP Download since back in October 2008.

If you want to read more about what Oslo is about, I recommend those Resources:

Well, since then Microsoft has released two more CTP releases (January and May), written a lot of documentation and posted quite some videos and samples. If you ask me, it’s yet too much for such a young and undone technology. Oslo’s modeling language “M” has and The "Oslo" Modeling Language Specification, which yet has been implemented in JavaScript by Mathew Wilson (jsmeta).

The community did also care a lot, and there are even companies investing in tools around “Oslo”. Telrik published two projects on their Labs Site. A tool for comparing and migrating M as well as LINQ to M. There are even trainings offered by Agilitrain and PluralSight.

Some recommended links:

What I think about Oslo today
(May CTP + Announcements)

First of all I want to say, that I’m happy Microsoft released Oslo in such an early state. I think they know the pros and cons of such an open process. The community can help with forming the product, and companies can start to invest early in what they think might be valuable for the future. But It also means more friction for any changes that are made.

I have used M for defining schemas and languages and also played around with the Repository and Quadrant. As Microsoft also states, it’s early Alpha. I stumbled over many bugs which I still plan to report and blog about. But that is OK, no one ever said it was production ready.

“M”

So far I like the schema part of M, also called MSchema. It has a very concise (compared to XSD) c-style syntax and covers a lot of what I want to express when modeling information structures. The M-graph (for values) syntax is also OK, while I don’t like the MGraph API. M-constraints let you restrict your types in a nice way. What I don’t like here, is the missing support for weak constraints. Named M-queries (similar to LINQ syntax), are a nice way to query M structures.

M-grammar is useful for DSLs. I think it could be more opinionated. I feel MS is striving for an expressiveness that let you describe all computer languages in the world using MGrammar. This makes it more complex than necessary for covering DSLs. At the same time it doesn’t support nesting of languages, which would be especially useful for DSLs, because you often need to talk to external models (e.g. pinvoke). The support for editor customizing (crucial language workbench feature) as it is today is not sufficient and too hard to configure.

Another feature I miss here is referencing between nodes and even across files (linking + scoping). For now all references are just values (ids), and the output of a DSL program will be a tree model, no graphs!

The Repository

The Repository basically offers some features on-top of SQL server as are row-level security, hierarchies, localization, versioning, additional constraints. All those features are plain SQL “libraries” in conjunction with M-models which also are compiled down to SQL. I don’t yet know what to think about the Repository.

Naming / Packaging

In the last couple of weeks the Oslo team published two posts that confirmed some of my speculations.

Let’s start with Doug’s Post: On “Oslo” at Douglas Purdy

In this post he basically makes two statements:

The only thing that I feel bad about is that we kept the “Oslo” name around so long (you will see that change at the next PDC), which has continued to be a confusing point for customers (“I thought Oslo was your new SOA platform”).

Douglas Purdy

I agree. It was confusing. Although people slowly start to accept “Oslo” as for “Modeling”.

Oslo and EF / Data Programmability

With this in mind, we made a decision to merge the Data Programmability team (EDM, EF, Astoria, XML, ADO.NET, and tools/designers) and the “Oslo” team (“Quadrant”, Repository, “M”) together.

Douglas Purdy

I don’t yet know what to think about this. “Oslo” is not and should not evolve to an O/R-Mapper. M’s type system is structural and doesn’t map well to strongly typed objects as used by EF. I can see this choice limiting the modeling capabilities of Oslo. But I guess we have to wait and see.

Quadrant. A graphical Editor?

The other post, confirming my fears about Quadrant was Model Citizen : What’s So Compelling about "Quadrant" Anyway?.

Back in November last year, when I wrote a sum-up post about “Oslo” I concluded Quadrant:

Yes. Quadrant lets you interact with models graphically. It’s highly generic, customizable and it looks great.

Lars Corneliussen, November 2008, What "Oslo" is and is not

I concluded this from the official statement about Oslo plus some videos and screenshots I had seen.

A tool that helps people define and interact with models in a rich and visual manner

Doulas Purdy, September 2008, What is Oslo?

But here is the smackdown:

Microsoft code name "Quadrant" is a ‘tool for viewing and editing SQL data,’ but… so what?

Michael Murray, July 2009, What’s So Compelling about "Quadrant" Anyway?

As I understand today, and as it shows up in the May CTP, it is not a graphical editor or graphical editing toolkit but rather a light WPF-version of Microsoft Office Access that understands Oslo Modeling concepts and relationships and builds up default editors in a generic manner. This is still useful (if it is free), but not far as useful as what I hoped Quadrant to be.

Please, Microsoft, make Quadrant a graphical editing toolkit with good support for configurable diagramming and any custom WPF editors. It should also have the plug-in model VS2010 offers for sharing any extensions.

The “Oslo” Story

Microsoft tries to sell “Oslo” as if it was all one story. It’s a lie.

There is tons of impedance mismatches that restrict you in many ways.

Modeling Structure

  • M in general uses structural typing (duck typing, supports mix-ins) and supports real graphs (including references)
  • MGrammar ASTs are hierarchal (tree structure) and for now only supporting nodes and strings.
  • Databases store flat relational data,
  • and objects in the .NET world are typed nominally (no multiple inheritance).

DSLs + Repository

There is no story for “DSLs and the repository”, and there is not yet a good story for any runtime support off the repository or DSL files. It’s basically what you had before. You can either access the database via ADO.NET or an O/R-Mapper or you run directly off the parsed MGraph-AST representing your DSL-Script, which feels like visiting xml documents. M has a nice LINQ-ish query language, but that doesn’t work in memory against a graph.

Querying

M has good support for complex data structures. As said there is no support for in-memory queries. But even the database implementation is limited by it’s relational backend. Even though queries can consult complex properties for sorting or filtering, it can only return rows with a list of scalar fields.

Constraints

Most constraints on types are only implemented in the SQL-Mapping. Also here there is no in-memory implementation that would validate your model against a schema. Basically the M-compiler generates a database schema including checks that would not let you insert invalid data into the database.

Data and schema evolution

There is this dream about capturing requirements in quite fuzzy ways and then piece for piece add details to them – until they have reached some formal state that might be executable. This sounds nice in theory, but there is no chance to implement this stuff. M is very easy to change, and it is easy to add constraints and refactor schema structures. But there is no story around how to let your data evolve together with your schemas using the Repository. So, besides nice theories, Oslo doesn’t help here.

More to come

There will be new content and Chris Sells also announced a fresh CTP around this years PDC in November.

So far, only one session has been scheduled, but watch this list for more sessions to come: Microsoft PDC09 – Modeling Sessions

Hope to see you in LA in November!

dotnetpro 07/2009 – Turmbau zu Babel – DSLs entwickeln mit Eclipse Xtext

Der zweite Artikel unserer DSL-Serie bei der dotnetpro ist raus. Warum der Artikel Turmbau zu Babel heißt weiß ich nicht 🙂

Bild 2

Abstract: Domänenspezifische Sprachen sind eines der vielen Mittel, um Software zu industrialisieren und vor allem zu automatisieren. Praxisnah zeigt dieser Artikel eine DSL für den Import von Mainframe-Exporten – zum Beispiel, um Daten von einem Mainframe zu importieren und dabei zu konvertieren. Eclipse Xtext leistet beim Erstellen einer passenden DSL hervorragende Dienste.

Autoren: Markus Völter und Lars Corneliussen

Microsoft “Oslo” May CTP available (Including Quadrant)

The "Oslo” team has released the third CTP of Microsoft’s forthcoming modeling platform.

Some of the  changes are:

For more detailed information check out the team announcement and the release notes.

New Installer

oslo setup

Empty Quadrant Workspace

empty quadrant

Intellipad Splitting

intellipad-multisplit And yes, I’ll be blogging about my web-layout DSL 🙂

kick it on DotNetKicks.com

Lang.NET and DSL DevCon (Seattle 2009)

I just got back from a good week in Seattle. My plan was to visit the DSL DevCon only, but it turned out that the cheapest option was to stay from Tue, 14th until Sun, 19th. I then had time to visit both Lang.NET and DSL DevCon as well as some friends in the area. Last time in Seattle (ALT.NET Conf) I was occupied with shopping only, but this time I also had a whole day for sightseeing. It was great!

Lang.NET (tweets, videos)

langnet Lang.NET was all about general-purpose languages. The talks were good and I met interesting people. This two tweets from Paul Vick (VB.NET compiler in person) and Amanda Laucher (F# MVP) pretty much sum up, what I felt most of the time:

vick paulvick: I hope someday to be as funny as Gilad or Erik Meijer.

 

panda-vick pandamonial: @paulvick Some day I hope to be as clever :) 

 

I left with a superficial (limited brain capacity) overview over F#, Tcl/tk (Eagle), CodeContracs, JVM internals, Axum and Links.

DSL DevCon (tweets, videos)

fill-your-head DSL DevCon (aka SellsCon) was initiated by Chris Sells. Both conferences were held in the Microsoft Research Building on their Campus in Redmond (close to Seattle).

I don’t yet know what to expect from the DSL hype. People have been doing DSLs for decades, as they did SOA. But who knows which story marketing starts telling about DSLs soon.

Still, I got my head filled up with lots of new useful information. Things I’ll have a closer look on will be Irony, F# and the Intentional Software. I’ll also follow up on all the good connections to super-interesting people. Was also nice to finally meet the Oslo guys Doug Purdy, Don Box, Chris Sells, Jeff Pinkston, Chris Anderson, Paul Vick and David Langworthy in person.

I’ll write follow-up posts about what I learned as soon as I have time for it.

What’s next?

I’m really tuned to see how our profession will evolve. I hope it will change dramatically. We need better processes, better integrated tools, closer communication of intentions and a significant productivity boost. I can’t believe that we will be able to create software so much faster. But, if our software wasn’t so closely tied to platforms and if it was written in a more flexible manner, so I hope, software could at least survive longer. Software is often dead born. That is, were our industry looses so much of it’s productivity.

dotnetpro: Kurzer Rede langer Sinn

Der erste Artikel der DSL-Trilogie bei dotnetpro ist raus 🙂

Titel: Kurze Rede langer Sinn –Domänenspezifische Sprachen in der Softwareentwicklung

Abstract: Mit wenigen Worten viel sagen; das ist das Ziel einer guten domänenspezifischen Sprache. Sie sind in Kundenprojekten
jüngst in Mode gekommen, um fachlichen und technischen Anforderungen besser begegnen zu können.

Ausgabe: dotnetpro 05/2009 (15. April 2009)

Autoren: Lars Corneliussen und Markus Völter

Ja, wirklich:

Bild 10

Microsoft “Oslo” MGraph – the next XML?

Microsoft’s upcoming “Oslo” modeling initiative is about tools and languages. MGraph is the piece within the language “M” that defines values, while MSchema is for schemas, functions and constraints and MGrammar is for textual DSLs. “Oslo” is still CTP and it will take some time until all concepts are available for production use.

By then, Microsoft plans to publish an open specification, such that everyone who wants to can implement the “M” language. Their ambition is to make it be as broad as XML is today.

Anyone can implement it. We want this approach wide spread on a variety of different platforms. We want it to be as broad as Xml is today.

Douglas Purdy, A Lap around “Oslo”

Today we have lots of XML on the wire. There’s also lots of JSON.

I want to see MGraph get there as well.

Jeff Pinkston alias Pinky:-), MGraph as a data rep

What is MGraph?

MGraph at it’s base is not a language. It is a simple contract for storing structured data in form of a labeled directed graph. This is a set of nodes where each node has an optional label and a set of successors, each of which may be a node or any other object.

The idea behind that is, that every structure can be exposed as a MGraph just by implementing the following interface, which is the core API behind MGraph.

I added some comments for easier understanding.

// Exposes whatever structure as an MGraph
public interface IGraphBuilder
{
  // Checks, if the object submitted is a value or a (custom) node.
  bool IsNode(object value);
  // Retrieves a comparer for the (custom) node objects.
  IEqualityComparer NodeComparer { get; }
  // Extracts the label from a (custom) node.
  object GetLabel(object node);
  // Extracts the successors from a (custom) node.
  IEnumerable GetSuccessors(object node);
  // Gets a (custom) node with a label.
  object DefineNode(object label);
  // Sets successors to a (custom) node.
  void DefineSuccessors(object protoNode, IEnumerable successors);
}

As you see, even the node is not specified by an interface or a base class. Both labels and successors are extracted by the visiting graph builder.

If you want, read more about the MGraph Api here.

MGraph as a language

What I do care more about is how MGraph’s textual notation looks like and how it compares to XML.

On MSDN you can find a language specification covering MSchema and MGrammar which both use parts of MGraph, but in a slightly different manner. Microsoft definitely plans to bring those pieces together

Today MGraph is used for values in MSchema extent initializers as well as for the AST (Abstract Syntax Tree) productions in MGrammar.

The basic syntax of MGraph very similar to JSON:

label { 
  otherLabel { "value" },
  "value",
},
"value"

As mentioned previously a successor can be either a node or a value. A value is just written directly, while a node is split into a label followed by its comma-separated successors within curly braces.

The same data as a XML-fragment would look like this:


  value
  value

value

One of the major differences is, that MGraph doesn’t distinguish attributes and elements. As XML is used today, anyone use attributes and elements according to their personal taste anyway.

Typed values

The next great difference is, that values are not just strings, but typed. Some of the intrinsic types are Text, Logical or Number.

mynode
{
  text { "some text" },
  number { 1234 }
  logical { true }
}

Find a list of the supported types in chapter 3.5 Intrinsic Types in the “Oslo” Modeling Language Specification.

Escaped Labels

While XML-elements and attributes are restricted to QName, a label in MGraph can be any object. They way how this is expressed in the textual syntax is not finished yet, but in MGrammar productions more complex strings are defined with an id-function.

id("some label xyz") 
{
  true, 
  id("another node") { "value" }
}

Ordered and unordered successors

In order to make a mapping to relational structures easier, successors are not sorted by default. In order to sort the successors, they have to be encapsulated in an integer-labeled node.

{
  0 { "value1" },
  1 { "value2" }
}

Which alternatively also can be expressed by brackets instead of braces. In the “M” jargon this is called a sequence.

[
  "value1",
  "value2"
]

Single successor nodes, or labeled values

A named value in MGraph is just a labeled node with a single value successor. The equals-sign is just some syntactic sugar for better read- and writability. In the “M” jargon this is called Entity, but this name is subject to change. Record structure might be a better name.

person
{
  name = "John Smith",
  age = 24
}

equals to

person
{
  name { "John Smith" },
  age { 24 }
}

Better than XML?

XML is great. Mostly because it can be read by almost every system, not because it has such a nice syntax. It was never meant for the purpose it is used for today either. It is a markup language for defining additional metadata onto text.

But what XML is broadly used for today, is configuration files, transport messages and even internal DSLs. For this kind of information, that has more structuring elements than data, XML is way to verbose.

Therefore I think MGraph with its tight syntax has the potential to become a great and broad alternative.

What do you think?

Comparing XML, JSON and MGraph

Continue reading

Fowler’s DSL example with MGrammar (Draft!)

I drafted Fowlers state-machine example with MGrammar. While doing so I found a few things I would like to see optimized or find better solutions for.

  • New line handling. I would like to express one required new line, when it is required, but then ignore all the others. Forum discussion.
    I could make new lines part of some tokens and then just interleave other tokens. But I don’t think this would be a nice solution. Any ideas?
  • The blocks events, resetEvents, commands and state+ have to be written in order. It is possible to describe a grammar where unordered blocks would be allowed, but it’s not trivial.
    Ordered and unordered “Lists” of syntaxes, separated somehow should IMHO be supported directly: forum discussion.
  • I wrote the Grammar using Intellipad and the three-pane input/grammar/AST view. It’s great! But I’d like to define the Semantic Model (using MSchema) along with the grammar and directly validate my AST against it: forum discussion.
  • References are not directly supported by MGrammar/MSchema. Forum discussion.
  • Xtext, which is quite comparable to MGrammar has a much more compact syntax. But I haven’t done a more deep comparison yet.
    Sven Efftinge’s Blog: Fowler’s DSL example with Xtext

Still missing:

  • A schema that represents the structure of the AST and validates it using constraints.
  • An adapter to Simple State Machine on CodePlex or a generating a state machine framework using T4.

Would love your feedback…

Grammar definition

module MGrammar.Net.Sample {

  // This is my first try, to parse the state machine
  // dsl syntax proposed by Martin Fowler
  language Statemachine 
  {
    interleave Ignore = " ";
    
    syntax Main = 
        NewLines? e:Block(Events, NameAndCode)
        NewLines+ r:Block(ResetEvents, Name)
        NewLines+ c:Block(Commands, NameAndCode)
        NewLines+ s:List(StateBlock)
        NewLines?
        => Statemachine 
        {
          Events { valuesof(e) },
          ResetEvents { valuesof(r) },
          Commands { valuesof(c) },
          valuesof(s)
        };
        
    // list of syntax "Item" separated by one or more
    // new lines
    syntax List(Item) = n:Item => {n}
        | list:List(Item) NewLines+ n:Item 
            => {valuesof(list), n};
    
    // lists of tokens separated by whitespaces 
    syntax TokenList(Item) = n:Item => {n}
        | list:List(Item) n:Item 
            => {valuesof(list), n};

    // a block consisting of a keyword, new-line-
    // separated "Item"s and end
    syntax Block(Keyword, Item) = Keyword 
            NewLines items:List(Item) 
            NewLines End => {valuesof(items)};
            
    // a word projected as a name
    // grouped into a separate successor
    // for extensibility reasons
    syntax Name = n:Word
        => { Name {n} };
        
    // a word plus a code, separated by spaces
    syntax NameAndCode = n:Word c:Word
        => {Name {n}, Code{c}};
    
    
    // special block and subsyntaxes for states
    syntax StateBlock = State n:Word 
            actions:(NewLines a:Actions => a)?
            NewLines+ items:List(Transition) 
            NewLines+ End 
            => State 
            {
                Name { n }, 
                actions, 
                Transitions { valuesof(items) } 
            };

    syntax Transition = e:Word "=>" s:Word
        => { Event {e}, ToState{s} };
        
    syntax Actions = tActions "{" l:TokenList(Word) "}" 
        => Actions [ valuesof(l) ];
    
    
    // keyword specification for strong formatting
    @{Classification["Keyword"]} final token Events = "events";
    @{Classification["Keyword"]} final token Commands = "commands";
    @{Classification["Keyword"]} final token ResetEvents = "resetEvents";
    @{Classification["Keyword"]} final token State = "state";
    @{Classification["Keyword"]} final token End = "end";
    @{Classification["Keyword"]} final token tActions = "actions";
    
    
    // Some whitespace characters
    token NewLineCharacter 
            = 'u000A'  // New Line
            | 'u000D'  // Carriage Return
            | 'u0085'  // Next Line
            | 'u2028'  // Line Separator
            | 'u2029'; // Paragraph Separator
            
    token NewLines = NewLineCharacter#2..;
         
    token Letter = 'a'..'z' | 'A'..'Z';
    token Digit = '0'..'9';
    token Word = (Letter (Letter | Digit)*);
  }
}

Input Text

events
  doorClosed  D1CL
  drawOpened  D2OP
  lightOn     L1ON
  doorOpened  D1OP
  panelClosed PNCL
end

resetEvents
  doorOpened
end

commands
  unlockPanel PNUL
  lockPanel   PNLK
  lockDoor    D1LK
  unlockDoor  D1UL 
end

state idle
  actions {unlockDoor lockPanel}
  doorClosed => active
end

state active
  drawOpened => waitingForLight
  lightOn    => waitingForDraw
end

state waitingForLight
  lightOn => unlockedPanel
end

state waitingForDraw
  drawOpened => unlockedPanel
end

state unlockedPanel
  actions {unlockPanel lockDoor}
  panelClosed => idle
end

Output AST

Statemachine{
  Events{
    {
      Name{"doorClosed"},
      Code{"D1CL"}
    },
    {
      Name{"drawOpened"},
      Code{"D2OP"}
    },
    {
      Name{"lightOn"},
      Code{"L1ON"}
    },
    {
      Name{"doorOpened"},
      Code{"D1OP"}
    },
    {
      Name{"panelClosed"},
      Code{"PNCL"}
    }
  },
  ResetEvents{
    {
      Name{"doorOpened"}
    }
  },
  Commands{
    {
      Name{"unlockPanel"},
      Code{"PNUL"}
    },
    {
      Name{"lockPanel"},
      Code{"PNLK"}
    },
    {
      Name{"lockDoor"},
      Code{"D1LK"}
    },
    {
      Name{"unlockDoor"},
      Code{"D1UL"}
    }
  },
  State{
    Name{"idle"},
    Actions[
      "unlockDoor",
      "lockPanel"
    ],
    Transitions{
      {
        Event{"doorClosed"},
        ToState{"active"}
      }
    }
  },
  State{
    Name{"active"},
    Transitions{
      {
        Event{"drawOpened"},
        ToState{"waitingForLight"}
      },
      {
        Event{"lightOn"},
        ToState{"waitingForDraw"}
      }
    }
  },
  State{
    Name{"waitingForLight"},
    Transitions{
      {
        Event{"lightOn"},
        ToState{"unlockedPanel"}
      }
    }
  },
  State{
    Name{"waitingForDraw"},
    Transitions{
      {
        Event{"drawOpened"},
        ToState{"unlockedPanel"}
      }
    }
  },
  State{
    Name{"unlockedPanel"},
    Actions[
      "unlockPanel",
      "lockDoor"
    ],
    Transitions{
      {
        Event{"panelClosed"},
        ToState{"idle"}
      }
    }
  }
}