By Peter Bell

Models, Meta Models and Meta-Meta Models, oh My!

When you first start to get involved with Domain Specific Modeling, some of the terminology can get confusing (especially when it isn't used consistently). One of the areas that seems to confuse many people is the difference between models, meta-models and meta-meta models. This posting shows examples of each and at the same time works up a usable meta-meta model for simple code generation.

A Basic Metamodel
Lets say I want to represent a user called Steve Kelly. The model in this case is Steve. But I need some structure for storing the information about users (whether that be a database schema, an XSD describing an XML schema, a grammar description in Extended-BNF or some other format). That would be my meta model.

In a database schema, it could be described with:

CREATE TABLE User (FirstName varchar(100), LastName varchar(100))
This creates a table into which users (models) like Steve Kelly could be placed.

An XSD might be:

<xs:complexType name="User">
<xs:sequence>
<xs:element name="FirstName" type="xs:string"/>
<xs:element name="FirstName" type="xs:string"/>
</xs:sequence>
</xs:complexType>

This would then allow me to create and validate XML documents containing users with a FirstName and LastName property - both of type: String.

You could also come up with some kind of abstract notation. Perhaps:

User
- FirstName: string
- LastName: string

But over time you're going to want to create many of these meta-models. You'll have one for users, another for products, another for views and another for controller actions. What we need is a meta-meta model for describing what a valid meta-model is.

A Basic Meta-Metamodel
Well for our use case to date, all we need is that a Class has 0.* Attributes - each of which have exactly one DataType (1.1). Using the same abstract notation, we could maybe write this as:

Class
- Name: string
- AttributeList: Attribute:0.*

Attribute
- Name
- DataType: DataType:1.1

DataType
- Name: String

Cool - so now we have a general way of talking about the structure of our metamodels. As you start to work with code generation this becomes really important as it allows you to work with arbitrary model structures in a consistent way.

Extending the Meta-Model
Well, that's fine, but what happens if I want to add addresses to my user? Now I need the concept of Relationships along with containment (is the related item composed within the parent or just associated to it - generally if you delete an item, any composed items will be deleted although associated ones won't be) and some constraints in terms of lower and upper bounds (0.1, 0.*, 1.1, 1.*, 2.5, etc.). So I might now describe something like:

User
- FirstName: string
- LastName: string
- AddressList: Address:0.*

Address
- Street: string
- City: string
- State: string
- ZIP: string

and my meta-metamodel now has:

Class
- Name: string
- AttributeList: Attribute:0.*

Attribute
- Name
- DataType: DataType:1.1

DataType
- Name: String

Reference
- name: String
- containment: boolean
- lowerBound: int
- upperBound: int

I've actually chosen to follow the ecore (EMF metamodel) from the Java/Eclipse world as if I *do* end up using third party tooling it'll probably be on a Java/Eclipse stack. Microsoft also has a meta-metamodel for their DSL tools. It also has the concepts of Classes, Relationships and Types, although they are described slightly differently, and its meta-metamodel also includes concrete syntactic information relating to the visual modeling tool - stuff like shapes and connectors. In fact, all modeling tools have some kind of meta-metamodel. Most of them are recognizably similar to the ecore (because there are only so many ways to really describe the structure of a meta-model), although MetaEdit+ has a superior but unusual meta-metamodel that allows relationships to be associated to multiple classes - not just two. It's a more powerful model, but it's possible to model most use cases without the extra sophistication of the MetaEdit+ approach.

So, we've looked at the structure of the meta-metamodel with some very basic constraints (lower and upper bounds for references). Next we might want to add support for inheritance.

Adding Inheritance

There are a number of ways we *could* add inheritance. In EMF ecore models, you simply add the concept of an eSuperType, where an eClass can have 0.* eSuperTypes (yep - multiple inheritance). So perhaps we could extend our concept of a class to reflect this:

Class
- Name: string
- AttributeList: Attribute:0.*
- eSuperType: Class:0.*

And now we have a fairly usable meta-metamodel. We're probably going to need to have a richer set of constraints than just basic data types and upper and lower bounds for relationships (is FirstName required? What are the maximum and minimum number of characters a FirstName can contain, etc), but lets treat that as a refinement. Firstly it's time to start to create some actual metamodels and then we can always extend the meta-metamodel as and when required.

So, our candidate metamodel (basically a subset of ecore):

Class
- Name: string
- AttributeList: Attribute:0.*
- eSuperType: Class:0.*

Attribute
- Name
- DataType: DataType:1.1

DataType
- Name: String

Reference
- name: String
- containment: boolean
- lowerBound: int
- upperBound: int

Comments
Very interesting Peter, thank you.

How would you define a constraint such as name must be between 5 and 50 characters long? I know you hinted at it, I'd be curious to see it.
# Posted By Baz | 6/24/09 12:26 PM
Hi Baz,

Good question. The answer of course is "it depends"! You could write your own constraint language, you culd use XSD (xschema) constraints, or you could pick constraints form some other existing project. I'm doing a "step by step rebuild" of this, so I'm going to start by getting the abstract grammar sans constraints in and working. Then I'll look at the EMF constraint language and implement the simplest subset that meets my needs. That way I'll be able to upgrade to all of the Eclipse based tools if I want, but I won't have to implement the entire ecore/EMF standard just to meet my use case that'll probably only require a subset of the capabilities.

Stay tuned for more information!
# Posted By Peter Bell | 6/24/09 12:32 PM
Hi Peter,

More normal would be to have:
- Steve Kelly as instance data (i.e. in the running system or database),
- Person in the model,
- Entity in the metamodel (e.g. Entity-Relationship diagrams), and
- Object in the meta-metamodel (if you're using MetaEdit+ or Microsoft DSL Tools; in Eclipse Ecore it would be EClass, in GME it could be Atom).

That gives you the four levels that are familiar from the OMG (M0 M1 M2 M3) and ISO's IRDS (http://users.jyu.fi/~jpt/ME2000/Me05/sld018.htm).

If you only have three levels, as in your example, there's no need to talk about meta-metamodels, which of course is good news as it makes things less complicated. You can shift everything down a level and have data, model and meta-model.

While it is possible to draw a model with "Steve Kelly" as one of the elements, e.g. a family tree, it's more normal in our industry to have models referring to roles people play rather than actual individuals. There might be a object "Blog Commenter" in your model, which would then be instantiated in various situations to "Steve", "Baz" or someone else. Only when you have three such instantiation steps do you need four meta-levels.

Mind you, if the stem cell research continues, "Steve Kelly" could well be considered a class. Currently that class would be a singleton, but if I clone myself we'd see the extra meta-level: Steve1 and Steve2 would be instances of "Steve Kelly" :-).
# Posted By Steven Kelly | 6/26/09 7:48 AM
Hi Steve,

Thanks for the comment. Of course, you're right. I have a meta-metamodel (based on ecore) with EClass, EAttribute, EReference and the like. Below that I have a metamodel for describing business objects which has concept like Object, Property, Relationship, Validation rule, and the like. That is used to create models of objects like Users, Products, Articles and Pages, and Steve would be but an instance of a User. I think I was getting confused by the fact that some of my models have instance data and some don't For instance I have a metamodel for describing controllers and their actions for websites. The models are then things like "Cart" and "Checkout" and "Form" and "PageDisplay", but there is no instance data - the models generate (or right now are interpreted) as is.

As for the rest of your comment, I'm torn. I've seen the blog posts talking about the evils of Singletons, but I don't think they were proposing an unlimited number of Kellys walking the streets of Jyväskylä :-)
# Posted By Peter Bell | 6/26/09 9:23 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.005.