A software system’s architectural meta-model defines the concepts used in a model and the rules for how those concepts are applied. The meta-model is like a cognitive grammar for design. It constrains our thinking and creates the vocabulary we use to talk about the architecture.[11] The diagram summarizes these ideas.
Defining a meta-model makes it easier to describe the architecture, set expectations for our audience, and reason about the models we create. To create a meta-model, start by defining the concepts at play. These will be the elements and relations in the architecture. Once we’ve described the concepts, establish the rules for using those concepts.
Concept individuation is the cognitive process by which we recognize ideas as being distinct from one another. As we individuate new ideas in the architecture, we update our understanding of the world and the models that represent it.
You have individuated concepts naturally since birth. Imagine the first time you encountered a door as a toddler. By watching adults use doors, you surmised that you could open doors by turning knobs. You individuated the concept of a door as distinct from a wall because you figured out that doors have knobs. One day you turned a knob to open a door, and it didn’t budge. Through this discovery, you individuated the concept of a locked door as distinct from an unlocked door and updated your internal mental model of the world.
To individuate concepts, we follow a simple process called the curiosity cycle [Mug14]. This process applies when defining any model, whether it is a model of our world or a software system’s architecture.
Start the process by asking a question. This question forms the basis for a test. Through the test, we’ll either find the answer in our model or find a gap in our current understanding. If we find an answer, then we reinforce our existing model. When we find a gap, we must figure out how to change our model to fill it.
Here’s an example of the curiosity cycle in action. Say stakeholders have prioritized availability, but we also need to keep costs down. Under these circumstances, we might ask the following questions:
Question: Which components cost us the most if they are unavailable?
Test: I can’t answer this question with our current model. I see components, but I can’t discern their costs.
Individuate a new concept: Let’s introduce cost.
Build new model: We can use color in our meta-model to represent costs. White means no loss whereas a dark red box means we’re losing a lot of money. The darker the color, the greater the loss.
Test: Ah-ha! Now I can see that component Foo is going to cause the most if it is unavailable.
After updating the meta-model to include the concept of cost, we can now create a new model that lets us reason about the relationship between costs and other quality attributes.
It takes time to arrive at the ah-ha! moment. There is also a risk that we may not have the knowledge or experience necessary to individuate concepts required to design the right system. Starting with an existing meta-model, such as an architecture pattern, can reduce this risk.
As discussed in The Four Principles of Design Thinking, all design is redesign. Patterns are the ultimate example of the redesign rule in action. Architecture patterns describe a prepackaged meta-model relevant to a specific problem. Pick an appropriate pattern, and the meta-model is free.
We explore several popular patterns in Chapter 7, Create a Foundation with Patterns. Notice how each pattern describes the elements, relations, and rules. Each pattern’s meta-model is complete, consistent, but also flexible so that designers may use the pattern under varying circumstances.
Most architectures include one or two thematic patterns to seed the system’s design. Even with these thematic patterns, there are still many details to sort out. As we add new concepts to the meta-model, it is possible that could undermine the patterns in our architecture’s foundation.
Combining meta-models—for example, by merging patterns—may introduce inconsistencies in the combined meta-model. For example, two meta-models might define a worker element, but the responsibilities for the worker and rules for its use are radically different. Reconciling inconsistencies involves merging similar concepts and renaming different concepts with the same name so that they remain distinct. Rules may also need to be adjusted. Failure to resolve these inconsistencies can undermine our design efforts.
As we add new concepts to the meta-model, the rules for using those concepts should also be updated. Rules describe how elements and relations interact in the system. They must reflect reality. For example, many programming languages have strict type systems. If we implemented a pipe-and-filter system (introduced) using a language with strong types, then the meta-model should include rules about types. If the language we choose doesn’t enforce types, then we’ll need to define message descriptions or protocol headers.
Rules also describe conceptual constraints we choose to place on the architecture. Conceptual constraints allow us to promote specific quality attributes. For example, in the layers pattern (introduced), an element within a layer is only allowed to use other elements in the same layer or the layer directly below it. We created this rule to promote maintainability. Violate this rule, and we’ll end up with an unmaintainable bowl of spaghetti.
We create rules the same way as other concepts. Ask a question. Test the model. Update the model by amending or adding rules. Repeat until the model sufficiently answers your questions.
Naming things is hard. Naming things is also surprisingly important. Since naming is a design tool, many of the principles you already know from writing good code apply to architecture too.
In Good Naming Is a Process, Not a Single Step,[12] Arlo Belshee describes seven stages of naming. The names we choose reflect how well we understand what we’re designing. As our understanding improves, so too do the names we give the concepts. Here are Belshee’s 7 Stages of Naming applied to software architecture.
No name. We don’t know enough about the system or context to extract a named element.
Name has absolutely no meaning. We have identified a chunk of ideas as being somehow related.
The name describes at least one of the element’s responsibilities.
The name directly describes all of the element’s responsibilities.
The name reflects a conscious decision to evolve the element’s responsibility. This only happens as we gain more knowledge about the element’s role in the context of the architecture.
The name describes the element’s responsibility but also its purpose. Understanding purpose requires that we understand why the element exists in addition to what it does.
The name transcends individual elements to create a new abstraction. This is where new concepts for the meta-model are born.
Here’s an example of one naming progression. In this project, we were attempting to name a set of elements responsible for fetching data from a web service and transforming it.
Stage | Name |
---|---|
1. Missing | The thing that does the thing |
2. Nonsense | Cranberry |
3. Honest | Job Starter Process |
4. Honest and Complete | Data Fetcher, Checker, Transformer, and Job Starter |
5. Does the Right Thing | Data Transformation Job Runner |
6. Intent | Data Preparer |
7. Domain Abstraction | Data Preparation Agent |
The final name emerged from the realization that there are several Agents with similar responsibilities and interaction rules across the system. The concept of Agents was a powerful idea that let us create clean abstractions and an improved meta-model. Now the name Agent carries meaning and communicates intent for architectural elements bearing that name.
Use names as a litmus test to determine how well you understand the concepts in the architecture. If your names are nonsense or simply honest, then you may have more work until you understand the concepts you’re designing.
Conway’s Game of Life is a zero player simulation in which the universe consists of a two-dimensional grid of cells.[13] For any given iteration of the game, a cell may be either alive or dead. There are four rules that determine a cell’s state:
Individuate the concepts in a meta-model that might describe Conway’s Game of Life by making an Architecture Flipbook, described on Activity 12, Architecture Flipbook.
Here are some things to think about:
What are the nouns and verbs in the game’s description and rules?
Looking at the names you choose, where do they lie on Belshee’s 7 Stages of Naming?
What questions do you need to answer with your model?
What elements and relations are in your diagram’s legend?
3.14.131.180