Lesson 1 - modelint/mbse-tutorials GitHub Wiki

Use your words

You cannot solve a problem, let alone specify a system, without an adequate and sufficiently precise vocabulary.

Consider the problem of computing the area and eccentricity of an ellipse. You may already know how to do this and, if not, you can surely google up the answer.

But humor me for a moment and pretend that you don't remember exactly how and you're at a cafe with a shitty internet connection.

You draw this picture and ponder for a moment...

images/lesson-01/10.png

Well, we know there must be a center, but that's not much to compute with.

Let's add in some ellipse semantics.

images/lesson-01/20.png

Now that we have an adequate vocabulary, we are in a position to solve the problem. In fact, once we discover the semantics we need, the problem practically solves itself.

Modeling a vocabulary

We model the vocabulary or, if you want to sound smart, "semantics" of our problem space with a class model. We use a class model rather than an ontology since we are interested in more than just compiling a network of related terms.

We're ultimately going to use our semantics to define executable behavior and computations. So we'll also need to capture the rules and constraints that apply to our terminology. A class model does this by allowing us to define precise relationships and constraints defined on multiplicity and attribute value ranges.

So that's what we're up to here—building a powerful semantic model that defines our subject matter and then using that as a foundation for defining executable behavior.

An example class model

Let's say that we are building an air traffic control system that, as one of its requirements, assigns aircraft to available runways for takeoff.

And, actually, that's an important point. We don't just start modeling vocabulary without purpose. We need three things to get us focused:

  1. Requirements
  2. Project scope
  3. Level of abstraction (subject matter definition)

The first two items are pretty straightforward. Requirements-wise, our system must assign any aircraft that wishes to take off to an available runway. And if multiple aircraft have been assigned to take off from the same runway, as is often the case, they need to take off in a prescribed order. Given some aircraft, we should be able to find out its take off order.

We'll assume that some air traffic controller assigns the runway, so the actual choosing of a runway is outside our scope. And we won't worry about landing any planes. So that's our scope more or less.

Level of abstraction is actually the most important thing when it comes to modeling, even though it may not be the most obvious. What do we mean by that? We need some way to decide what kinds of details we are modeling. For example, we need some way to pose the query: "What position is aircraft N1382RQ in for takeoff?" Is there a command line interface? Voice? Are we clicking on an aircraft icon? Let's focus on the aircraft domain and ignore the user interface. That's an example of choosing specific subject matter to model. We're going to ignore all user interface details. Of course, those will need to be handled in our system, but the rules of aircraft management stand on their own and can be paired with any manner of user interface. In fact, it can be argued, that it is best to understand the aircraft management rules first and then chose or design an appropriate user interface rather than the other way around.

We'll be covering these three ideas, requirements, scope, and subject matter definition in a lot of detail in coming lessons. This is just a heads up that you need to have these all squared away before you can model effectively. You will have no way of knowing if your model is covers the desired scope, requirements and delivers the right level of detail otherwise.

Now let's consider the terminology we need to solve the problem. Which things are of interest to us? Aircraft, obviously, though we should be more specific. We cannot assign a runway for takeoff to an aircraft that is in the airspace already. So we really mean Taxiing Aircraft. And we certainly care about Runways. For now, that seems good enough considering our ultra simple requirement.

Once we decide that a term is going to be modeled, we name it with initial caps. You could choose some other convention if you like, put them all in boldface or color them blue if you like. But initial caps works well and is readable when you are working with plain text. Plus, our community seems to be converging on that standard.

How do we tell them apart?

We need a way to tell one Taxiing Aircraft apart from another. Is there any characteristic of an aircraft that guarantees that no two instances are confused with one another? Yes, the tail number. This is a real world identification policy designed to distinguish one aircraft from another.

How about Runways? It turns out that the number printed on the runway 27 for example both establishes its heading (270 degrees) and is unique. If you have two parallel runways, you distinguish them by adding a letter to the name. So 27R and 27L refer to parallel runways oriented at 270 degrees on the left and right sides.

We call a characteristic, or combination of characteristics that distinguish instances an identifier. Tail number is the identifier of Taxiing Aircraft and Runway name is the identifier of Runway in our example.

Let's grab the specification of some airport, SFO is near me, and populate some example instances of our Runway class:

images/lesson-01/30.png

And let's just use the US tail number specification to generate a population of Taxing Aircraft instances:

images/lesson-01/40.png

What we have done so far is not only identify to semantic elements of interest, but we can also think of each as a set definition. We have the Runway set, which we can populate with any elements of interest as well as a Taxiing Aircraft set that can also be populated. We define an identifier for each set so that we can label the set elements.

We often refer to our set elements as instances. Thus, 28R is an instance of the Runway class.

Now at this point you might be thinking, "Hey, I know how to code already. Why are you telling me about classes?" While there are similarities, we are not talking about a class you might define in Java or C++. Those are for implementation. When we create a system specification everything is based on math and logic rather than any particular implementation concepts. This is why I am hammering home the concept of a set definition. Concepts like set definitions, logical predicates, mappings and such are based on mathematic definitions. And those are our modeling foundations.

So everything you know about object oriented programming... just take all that, put it in a box. Put that box in a drawer, shut the drawer, leave the room and turn the light off.

Relationships

Now let's say that we see that Taxiing Aircraft N99126B is assigned to take off from Runway 28R. We can visualize this as a mapping among set elements as shown:

images/lesson-01/50.png

But what is this relationship exactly and what are its rules?

From the perspective of any arbitrary instance of Taxiing Aircraft, it can be assigned to at most one runway for takeoff at any given time. Does that sound right?

From the perspective of any arbitrary instance of Runway, it can have zero, one or many Taxiing Aircraft assigned at any time. Do you agree?

Note that our relationship has two perspectives, each taken from the point of view of an arbitrary instance on one side or the other.

images/lesson-01/60.png

The above notation is read by starting with an instance on one side and reading the perspective on the other side.

For example: A Taxiing Aircraft is queued for takeoff from zero or one Runway

We can refer to the entire Relationship by its name. Here we have the R1 relationship.

Rules

We have captured a few rules in the process of defining this relationship. For example, we will not allow the same Taxiing Aircraft to be assigned two Runways to take off from at the same time. We do allow for the possibility that a Taxiing Aircraft is not always assigned to a Runway for takeoff, and so on. Student exercise: How many rules have we captured here?

Model vs. Data

Note that model we have drawn does not mention any specific aircraft or runway. The model captures systematic definitions, rules, and constraints that don't vary from instance to instance. So, no matter which Taxiing Aircraft you happen to be, there is no way you can be assigned more than one Runway for takeoff at a time. And, if that weren't true, we would need to change our model somehow to account for any special cases.

When we refer to data or instances, we are thinking about a particular scenario, use case, or just a snapshot in time. We need a way to gather together all instances that exist at a given point in time to verify that our model really works. It is super easy to fool ourselves and think we have a complete model otherwise.

In the previous figures of this lesson we drew set diagrams. That's a useful way to show that we are dealing with sets, but we need something a little easier to manage, especially when we are considering larger populations across multiple classes and relationships.

images/lesson-01/70.png

Like any visual representation, the table is a bit misleading in that it appears to suggest a vertical ordering. But we think of a class as a set definition. Two important things about sets: Elements are not ordered and there is no duplication. Keep this in mind when you look at any of our class tables.

It does bring up the question of how do we represent the order of planes line up for a given Runway. Hang on, we'll get to that soon.

First we need to ask our selves how to represent that blue line shown earlier between N99126B and 28R.

Here's one way to do it:

images/lesson-01/80.png

We call the title of each column an Attribute. We define an attribute such that it must always hold a meaningful value per instance at any given time. There are a lot of good reasons for this rule that we'll get into later. Spoiler alert, allowing non-values leads to massive headaches when it comes to modeling safe and reliable logic. It also encourages some pretty sloppy modeling. For now though, I'm just going to lay out the table rules with minimal justification.

Okay, how about doing it the other way around. We could add an attribute (column) to the Runway table. Ah, but according to our model a Runway at any given point in time might not have any assigned aircraft. So... same problem. What can we do?

We're going to need another table. Let's try this:

images/lesson-01/90.png

Wow! Isn't that satisfyingly minimal compared to our previous attempt? There was only one mapping to record and we did it with a single row. No need for any weird empty cells.

Each table we use represents a class population. This means that there must be a class missing from our model. Let's update it to include our new table.

images/lesson-01/100.png

We've updated our model to include an extra class. Notice how we named the new class by converting a verb-y perspective into a noun-y class name. This makes sense because an instance in the Takeoff Assignment class is the result of performing the action implied by the perspective.

To assign a Taxiing Aircraft to a Runway we create an instance of Takeoff Assignment. If we wanted to revoke an assignment we would simply delete an instance of Takeoff Assignment.

You may be wondering why the attributes aren't shown on the class diagram. Actually, they should be. I was just keeping the emphasis on the class and relationship up until now. And, when I create an informal presentation of a model, especially to a non-modeler audience, this simplification is useful. But you're going to be a modeler, so let's add those attributes in so that the model and tables match up.

images/lesson-01/110.png

The model seems to match the data in our simple scenario of a single aircraft being assigned for takeoff. Let's make the scenario more interesting and see how well the model holds up.

images/lesson-01/120.png

And let's fill in our tables with the new scenario:

images/lesson-01/130.png

Our tables show all of the assignments. Remember that set elements (our rows) are not ordered. So how to we capture the takeoff sequence for each runway?

There are two different ways that we can capture order in our class model. I'm going to show you the way I would model this particular situation given our tiny set of requirements. But the other method is quite useful as well and we'll, depending on our needs, and we'll get to that in a future example.

The technique we'll use here is to add an ordering (ordinal) attribute to our Takeoff Assignment table as shown:

images/lesson-01/140.png

Now let's update the class diagram to include that ordinal attribute and the implied ordinal relationship.

images/lesson-01/150.png