I just finished up some work for one of my clients building a metamodel and a DSL for services. I built the models and the DSL using eclipse (EMF, XText and GMF). While doing the models it struck me (again) how nice it is to build models with a flexible number of meta jumps (as described in Hofstadter) vs. the often more rigid models of standards (e.g., UML Profiles or the M3 model of OMG).
Since I often do similar tasks for my clients and sometimes have to introduce an architecture for metamodeling, I thought it might be a good idea to write a blog that explains some of the common architectures for building meta models. At least I can refer to this blog post when rather than having to write it up each time, right?
So What are Metamodels?
The simplest way to think of a metamodel is as a model of a modeling language (or perhaps a bit simplistic, a model of a model). That may be a bit tricky to absorb at first, but let me give you a real world example.
The world meta is Greek and means after or behind. We use the word meta to talk about the model that sits behind the language we're using. Say, for instance, that you are a software developer and you are building some banking software for your company in the programming language Java. Java allows you to build new constructs through classes, interfaces and methods. The users of the bank (say customers, bank clerks) are your users and you'll probably have to introduce them to your abstractions. You may also build a model using some kind of language out there to allow you to communicate your solution with other stakeholders. You would probably introduce abstractions such as Accounts, Transactions, etc.
Let's introduce you to Sally. Sally works for Oracle and she's building a parser and compiler for Java. Her models forms a language for your software. You are her customer. She may introduce you to a model that explains what's she is building for you. This model would describe your language (Java) and would introduce you to abstractions such as Class, Interface, Package, etc.
You may think of Sally as someone working on a metamodel. She's working on the model behind your language used to express models to your customers.
Now let me introduce you to Tom. Tom is creating tools for creating parsers and compilers. Sally is using Tom's tool to define the Java language. What would Tom's model be to Sally? What would Tom's model be to you?
During my 20+ years of teaching, I've found this to be one of the topics that seems to be hard for students to think about. One may say that Tom's model is a meta-model for Sally, but what is it to you? Here we often hear terms like 'meta-meta-model'.
Why Metamodels and Why Should I Care?
Usually, you don't care about Tom's model, but in my line of work, I often have to see both Sally and Tom's model… and often at the same time.
The reason I often need to deal with meta-meta-models is that I often have to relate a set of languages and I have to ensure that they can 'communicate'. Let' me not spend too much time justifying this, but I bet you can imagine how important it would be to have a meta-meta-model if you had to translate programs from Java to say Python… You'll have a great advantage if you can now express rules that state how concepts in Java maps to concepts in Python. To make this elegant, it is important that the two languages (Java and Python in this example) has a model defined in the same language… and often I have to define that language.
Fixed Level Metamodels
Most industry standards define a fixed number of meta-levels. In most cases they define 4 levels. These levels are often cleverly named with M#, where # is a number specifying which level of meta. M0 would be no meta, M1 is the model of the application, M2 is a the model of the modeling language for the application and M3 is a model of the modeling language for defining languages. In most cases the M3 language can be defined using itself, so there is usually no need for M4.
Let me illustrate using OMG.
- M0 to be instances (or the runtime objects).
- M1 is the application model defined in UML. So that would be the model you would build in the above example. It would contain Account, Transaction, etc. defined in say a UML class diagram.
- M2 would be the model for UML itself (let's call it the UML meta models). For you to define the UML class diagram, the UML language would have to expose Class, Association, Attribute, etc.
- M3 is a language called Meta Object Facilities (MOF). This language is used to create all UML based models.
UML goes on to blur the boundary a bit using so called UML Profiles that allows you to customize the UML model, but let's ignore this for now.
We could do the same with XML of course:
For most eager meta-meta… modelers, the fixed layer framework is usually more than sufficient. Most modelers never need to stride up and down the models. They typically work on level M(x) and only need to read level M(x+1) and their users produce level M(x-1). However, in my world as I said, that is not sufficient. I usually have to create models that represent level M(x+1), and sometimes level M(x+2) also. In addition I often have to create a model for that can be used to abstract level M(x-1).
This is when the fixed meta-level architecture tends to fall apart. I'll try to give you a simple example of why using the example of books and meta-books.
Let's describe a meta-book as a book that describes other books. Let's say we bought a book called "The best books of 2012". This book is all about recommended books published in 2012. Hence, it is a book about books, right?
This is true, but it is also a book. So a "The best books of 2012" is both a book and a meta-book… Confusing right? What if we had a book called "The best books about books of the 20th century"? One may argue that this is a meta-meta-book… as well as a meta-book… as well as a book. Makes your head spin doesn't it? Could you now conceive of a book of type meta-meta-meta-meta-meta-meta-meta-book? Would it be practical? I can conceive the concepts, but it would probably not be of much use, in my world, but perhaps in yours.
Also, why should we fix models to a specified level? When you built the bank model, you thought of Sally's Java model as a M2 level concept (you're defining M1). But what about Sally? Does she see herself working on M2? I could argue that she thinks of you working on M0 and her models being M1 (and Tom's models M2).
Golden Braid to the Rescue
I'm not sure if "Golden Braid" is the formally correct name for this concept, but I first learned about it reading Douglas Hofstadter's book called "Gödel, Escher, Bach: An Eternal Golden Braid". This book wrestles with the fundamental notion of "meaning" (although, you can read it as a nice book describing commonality between 3 geniuses in different fields. I believe Hofstadter's model of meta discussed and instantiated earlier than this book (e.g., it was implemented in LOOPS (Lips Object Oriented Programming System), but I've read other authors pointing back to Hofstadter as a source for this model, so I'll credit him.
His idea is very simple but also very elegant. It basically states two simple facts:
- Behind every object, there is another object that plays the role of a meta-object
- All meta-objects are objects
That was easy, right? But it is really powerful and flexible. EMF (the eclipse modeling framework) supports this idea (I'm not sure if it was accidental or deliberate, but the support is very good).
Many languages also supported the idea. Take Smalltalk as an example. If you inspected an object in a Smalltalk-80 debugger, you may be able to trace this as follows (this would be slightly different based on different Smalltalk implementations).
- We inspect the object 'account#1234' and we ask it, who is your meta-object, we get back and object and we ask it who are you?
- The object would say, I'm Account. We ask Account, who is your meta-object and again ask that meta-object, who are you?
- The object would say, I'm an Account class. We repeat the process.
- The 'next' object would say, I'm a Metaclass. We continue…
- The 'next object would say, I'm a Metaclass class. We continue…
- The 'next object would say, I'm a Metaclass.
Notice that we start to recurse in step 6. The "Metaclass class" defines "Metaclass" as its meta-object and "Metaclass" defines "Metaclass class" as its meta-object In Smalltalk-80, they decided that there were no reasons to have more flexibility to that (after all, we're now at meta-meta-meta-meta-book…).
In this blog entry I've tried to explain two different meta-modeling frameworks/architectures. The main purpose is to be able to point to this article in future work I do for my clients.
Most standards are built around a fixed-level meta-levels. Although this is probably sufficient for most problems, in my work, the "Golden Braid" approach to be more flexible.
I was originally planning to show some examples of why the "Golden Braid" approach seems to work better for most of my problems, but decided (wisely I think with respect to the length of this article already :)) to not make the argument here. Perhaps in a different blog-entry (or in some upcoming book), I'll show some examples of why the "Golden Braid" seems to work better.