Red Riding Hood as UML diagrams
A gentle introduction to UML diagrams*
Little Red Riding Hood in the forest (image generated with ChatGPT/DALL-E, OpenAI, 2025).*
This article demonstrates how to translate a natural language story (the fairy tale of Little Red Riding Hood) into formal diagrams; specifically, UML diagrams. These are diagrams used to analyse a domain and/or design software systems (like applications). On the one hand this is rather ridiculous (or perhaps funny), as this fairy tale clearly does not need or implicate any software. On the other hand this fairy tale (story) is well known. And int this way can form a well known 'domain' for most readers. So this is a good introduction to (some) UML diagrams for non-technical people to get an understanding, or for beginning technical people (software engineering students).
We split the story into three parts to avoid the "One diagram to rule them all" antipattern (ODTRTA). A God diagram is an anti-pattern, just like a 'God object'. Splitting large diagrams up into several diagrams is a best practice to prevent 'cognitive load'. To still provide an overview, we create a separate high level diagram that shows the relationships between parts. This is similar to the C4 model method, which introduced different zoom levels. C4 is a method that followed UML, and the UML 'code' diagrams are the fourth C in C4.
This article first introduces the domain model: the "world" of the fairy tale with all characters and their relationships. Then we work out the story in three phases, each with a sequence diagram showing interactions between characters. Finally, the appendices contain a more detailed domain model (Fowler-style), the "God Diagram" as an anti-pattern example, and a use case view that connects the class and sequence perspectives.
Once upon a time...
Before we tell the story in sequence diagrams, we first define the "world" of the fairy tale in a class diagram. This is a simple domain model in the style of Larman (2004): only attributes, without data types or methods. This keeps the model readable and focuses on what exists in the fairy tale world, not yet how these concepts behave.
Glossary of entities
The table below describes each entity from the domain model:
| Entity | Description |
|---|---|
| LittleRedRidingHood | The main character, a young girl with a red hood |
| Mother | Little Red's mother, gives the task |
| Basket | Container with treats for grandmother |
| Wolf | The antagonist, hungry and cunning |
| Grandmother | Little Red's grandmother, sick |
| Huntsman | The hero who rescues |
| House | Grandmother's house |
| Stone | Punishment for the wolf |
In this beginner-friendly model, we show all entities at the same level of abstraction. In a more refined model, we would notice that LittleRedRidingHood and Grandmother are actually both instances of a shared superclass Person. Similarly, Wolf and possibly Huntsman are living beings with certain properties. This illustrates an important lesson in domain modeling: you can group entities under more abstract concepts.
For this story, we intentionally chose a flat structure because the narrative is more about who interacts with whom rather than their taxonomic classification. The detailed Fowler-style version in Appendix A goes deeper into this aspect.
Note about concrete examples: In a production environment, the Glossary would include concrete examples, such as LittleRedRidingHood { name: "Little Red", hasRedHood: true } or Basket { cookies: 12, wine: 1 }. This helps developers and domain experts understand the data format and possible values. For this educational example, we've omitted these details to focus on the relationships between entities.
(Of course, Grandmother's cabin in the original fairy tale predates modern addressing systems. In a contemporary retelling, we might add Grandmother { address: "Deep Forest Lane 7", postalCode: "12345-WOOD" } using the ZIP+4 format. The Wolf could then use Google Maps to plan a faster route through the forest, while Little Red Riding Hood gets stuck on the scenic path after exceeding her monthly mobile data limit - unable to check Waze for traffic updates.)
Why split up?
A large sequence diagram with all interactions quickly becomes confusing. Just like with code, the Single Responsibility Principle applies: each diagram describes one phase or scenario. This makes the diagrams:
- Readable - Each diagram fits on one screen
- Maintainable - Changes only affect the relevant part
- Testable - Each part can be verified separately
Quiz exercises
The quiz examples for this article are available as two separate pages:
Overview Diagram: The Three Phases
First, an activity diagram showing the main storyline:
We use an activity diagram for the overview because:
- It shows the sequence of phases (flow)
- Partitions clearly separate the three parts
- It's more abstract than a sequence diagram (no objects/methods)
For a behavioral bridge between this domain/class perspective and the sequence diagrams in phases A, B, and C, see Appendix C: Use Case Diagram.
Phase A: The journey to grandmother
Little Red Riding Hood receives the task to bring a basket to grandmother and meets the wolf on the way.
In this first phase we use strings as messages - the simplest way to show interactions between characters. This is how Alan Kay originally envisioned Object-Oriented Programming: objects that send messages to each other, without knowing the internal implementation of the receiver.
Explanation of phase A
In this diagram we see the setup of the story:
- Mother initiates the story by giving Little Red a task
- Little Red receives a basket (the message describes the content)
- Wolf gathers information and makes a plan
- The self-message ("I'll take the shortcut...") shows the Wolf's internal decision
Why strings as messages?
This notation with strings matches Alan Kay's original vision of message passing: objects communicate through messages, similar to how people talk to each other. This is fundamentally different from method calls (which we'll see in Phase B).
| Concept | Message passing | Method calls |
|---|---|---|
| Coupling | Loose: sender doesn't know implementation | Tight: sender knows the interface |
| Analogy | Event-driven architecture | RPC (Remote Procedure Call) |
| Flexibility | Receiver can interpret message | Contract is fixed |
In software we see message passing in event-driven systems (like message queues, publish-subscribe) and method calls in traditional OO (Java, C#, TypeScript).
Phase B: At grandmother's house
The wolf arrives first, eats grandmother, and disguises himself. Then Little Red arrives.
In this phase we switch from strings to method names. This is a step towards the formal UML notation used in software design. Method names are more specific: knock() is clearer than "knocks on the door".
Explanation of phase B
This diagram shows the climax of the story:
- destroy keyword shows that an actor "disappears" (eaten)
- The dialogue with
askAbout(eyes/ears/mouth)shows a repeating pattern - Self-calls (
disguise,getIntoBed) show internal actions of the Wolf
From messages to methods
Note the transition from Phase A to Phase B:
| Phase A (strings) | Phase B (methods) |
|---|---|
| "Good day, where are you going?" | askWhoIsThere() |
| "To grandmother's house..." | answer("...") |
This reflects how we work in software design: we start with informal descriptions (user stories, scenarios) and gradually formalize them into interfaces and method signatures.
Phase C: The rescue
The huntsman hears snoring, investigates the situation and rescues Little Red and grandmother.
In this phase we add even more detail: a StoneFactory that creates stones in a loop. This introduces two advanced UML concepts: the Factory design pattern and loop constructs in sequence diagrams.
Explanation of phase C
This diagram shows the resolution:
- create keyword shows that Little Red and Grandmother "return"
<<rescued>>is a stereotype indicating the type of interaction- The StoneFactory is a Factory (design pattern) that creates objects
- The loop construct shows that an action is repeated multiple times
Why a StoneFactory?
In software design we use Factories to create objects. The Factory pattern has several advantages:
- Encapsulation: the creation logic is in one place
- Flexibility: you can easily create different types of stones
- Testability: the factory can be mocked in tests
This is of course exaggerated for a fairy tale, but illustrates how you gradually add technical concepts to a model.
Note also that we show all three phases at different levels of detail:
- Phase A: strings (informal)
- Phase B: method names (semi-formal)
- Phase C: methods + loops + Factory (formal)
In real software development you would choose one level of detail for all parts. But for this tutorial we deliberately show the progression from informal to formal. It's a didactic choice to show how models can evolve.
Alternative: Overview as sequence diagram
As an alternative to the activity diagram, we can also create a high-level sequence diagram. This is more abstract and shows only the main interactions:
When to use which diagram?
| Diagram | Use case |
|---|---|
| Activity diagram | Shows flow and decisions, good for process steps |
| Sequence diagram | Shows interactions between objects/actors over time |
For the overview, the activity diagram works better because:
- It shows phases as blocks (partitions)
- It doesn't need objects at this abstraction level
- The sequence is visually clearer
Lesson: Avoid the "God Diagram"
Just like in software design we don't want a "God Object" that does everything. A diagram with 50+ interactions is:
- Unreadable - Too much to grasp at once
- Unmaintainable - Every change affects the entire diagram
- Unusable - For screen readers such a diagram cannot be made accessible
By splitting the story into A, B and C we get:
- Each diagram describes one phase
- Easy to understand and explain
- Better to translate into accessible descriptions
This principle also applies to software diagrams: split complex flows into sub-scenarios!
And they designed and documented happily ever after
We hope this example shows you that both natural language and formal diagrams have their place in software development. There is no "best" notation - it depends on:
The phase in the Software Development Life Cycle (SDLC)
| Phase | Preference | Why |
|---|---|---|
| Requirements | Natural language, User Stories | Communication with stakeholders |
| Analysis | Domain Stories, Use Cases | Understanding the problem domain |
| Design | UML diagrams, C4 | Precise specification for developers |
| Implementation | Code (the ultimate formal language) | Executable by machines |
| Documentation | Mix of both | Depends on the audience |
The audience
- Clients and end users - Natural language, possibly with Domain Stories
- Business Analysts - Use Cases, User Stories, acceptance criteria
- Developers - UML diagrams, API specifications, code
- Compilers and runtimes - Only formal code, no ambiguity allowed
Further reading
This insight is not new. Some classic sources:
- Patton (2014) described how to use User Stories to tell stories in Agile
- Fowler (2004) - UML Distilled - describes UML as a sketch tool for communication, not as a formal specification language
- Reeves (1992) wrote the groundbreaking article stating that code is the real design, not the diagrams
- Van der Wal (n.d.) provides practical explanation of domain modeling
See the References section at the bottom for full citations.
The lesson from Reeves
The article by Reeves (1992) is particularly relevant: he argues that high-level programming languages are just one step in a spectrum. The "real" code is machine code - everything above it is a form of design. This means:
- Diagrams are design at a high level of abstraction
- High-level code (Java, Python, TypeScript) is design at a lower level
- Machine code is the ultimate implementation
Therefore, it's essential to learn how to write high-level programming languages so they align with the design. The code must tell the story - just like this fairy tale of Little Red Riding Hood.
In conclusion
Just as Little Red Riding Hood eventually came home safely, we hope that after reading this example you:
- Understand when to use natural language and when to use formal diagrams
- Know how to split large stories into manageable parts
- Realize that code is also a form of storytelling
- Are ready to tell your own software stories - accessible to everyone
And then...
"They lived happily ever after" is a nice ending, but provides few starting points for a good story. What happens after "happily ever after"? In software terms: what happens after the first release?
Specifying and validating: the story continues
The goal of most software products is to make the user happy. But how do you know if your user is really happy? This is where specification and validation come in:
| Activity | Question | Method |
|---|---|---|
| Specifying | "What do we want to build?" | User Stories, Use Cases, Acceptance Criteria |
| Validating | "Did we build the right thing?" | User testing, A/B testing, feedback loops |
| Verifying | "Did we build it right?" | Unit tests, integration tests, code reviews |
Just like with Little Red Riding Hood: the story doesn't end at "happily ever after". Grandmother might have PTSD, the Wolf has family that wants revenge, and Little Red is considering a career as a hunter. The real work begins after the first version.
The technical term: Enshittification
Unfortunately, "happily ever after" is not always the reality. Doctorow (2023) introduced the (socio-)technical term enshittification to describe how many large social media platforms first create value for users, then for advertisers, and ultimately only for themselves.
Interestingly, economic research (Dubner, 2024) shows that many users would pay to make platforms like Facebook disappear. The "happily ever after" has become an illusion.
What does this mean for software development?
When designing software, ask yourself:
- Who are you optimizing for? The user, the company, or the shareholders?
- What is the long-term vision? Will the software continue to deliver value, or will it become an extraction machine?
- How do you measure "happy"? Engagement metrics are not the same as user satisfaction
This directly relates to the specification question: if you write User Stories from the user's perspective ("As a user I want..."), but the acceptance criteria optimize for advertisers, then you have a fundamental conflict.
About this article
This article was written by Bart van der Wal with Claude (Anthropic) as co-author. Claude helped structure the content, generate the PlantUML diagrams, and formulate the philosophical reflections.
Although I (Bart) am ultimately responsible for the content, feedback on any errors or unclear sections is very welcome. Report issues via GitHub or get in touch.
References
- Fowler, M. (2004). UML Distilled: A Brief Guide to the Standard Object Modeling Language (3rd ed.). Addison-Wesley. https://martinfowler.com/books/uml.html
- Doctorow, C. (2023, January 21). Tiktok's enshittification. Pluralistic. https://pluralistic.net/2023/01/21/potemkin-ai/
- Dubner, S. J. (Host). (2024, January 18). Are you caught in a social media trap? [Podcast episode]. In Freakonomics Radio. Freakonomics, LLC. https://freakonomics.com/podcast/are-you-caught-in-a-social-media-trap/
- Hoare, C. A. R. (1980). The emperor's old clothes. Communications of the ACM, 24(2), 75-83. https://doi.org/10.1145/358549.358561
- Patton, J. (2014). User story mapping: Discover the whole story, build the right product. O'Reilly Media.
- Reeves, J. W. (1992). What is software design? C++ Journal, 2(2). https://www.developerdotstar.com/mag/articles/reeves_design.html
- Van der Wal, B. (n.d.). Domeinmodellen [Domain models]. Minor DevOps. https://minordevops.nl/blok-2/domein-model.html
Appendices
Appendix A: Detailed Domain Model (Fowler-style)
For software developers who want to see a more formal domain model, we show below the Fowler-style version: with data types, visibility modifiers, and methods.
This modernized domain model illustrates an important point: design choices reflect values. By giving all FairyTaleCharacter instances access to Weapon, we model a world where Little Red and Grandmother have agency - they could defend themselves.
The Bechdel test asks whether a story features at least two women who talk to each other about something other than a man. Our original model implicitly failed this: Grandmother only exists to be eaten, Little Red only to be rescued by a man.
In software terms: your domain model encodes assumptions. If your e-commerce model has Customer and Admin where only Admin can issue refunds, you've encoded a power structure. Question your models!
Differences between Larman and Fowler style
| Aspect | Larman-style (simple) | Fowler-style (detailed) |
|---|---|---|
| Data types | No | Yes (String, boolean, etc.) |
| Methods | No | Yes (eatUp(), knock(), etc.) |
| Visibility | No | Yes (- private, + public) |
| Use case | Domain exploration, communication | Technical design, implementation |
The simple Larman-style model is better for communicating with stakeholders, while the Fowler-style model is better for developers who need to implement the system.
Appendix B: The "God Diagram" (anti-pattern)
The diagram below is an anti-pattern. We show it here explicitly to demonstrate why you should NOT do this. This is the diagram equivalent of the second situation that Hoare (1980) describes:
"There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies."
Creating a "God Diagram" is choosing the second option: so complex that you can no longer see the flaws.
Why is this an anti-pattern?
- Unreadable - Even with a relatively simple story like Little Red Riding Hood, the diagram is already overwhelming
- No focus - You can't see what it's about without studying the entire diagram
- Hard to maintain - Every change potentially affects the entire diagram
- Not accessible - A screen reader cannot generate a useful description of this
- Analysis paralysis - You drown in complexity
The solution: decomposition
The way to solve a large problem (or tell an extensive story) is to split it into sub-problems and solve each sub-problem separately. Not by creating one large solution at once, because then you drown in complexity.
The biggest challenge is often to ultimately validate the entire solution as a composition of your partial solutions. You have the additional problem that you must also make the partial solutions connect well to each other. You need an integration test or even an end-to-end test, in addition to unit tests for your components.
Software Engineering as Design Science
Software Engineering is a Design Science (DS). This anti-pattern illustrates the DS equivalent of the fact that a good/useful whole (system) is more than just the sum of its parts (elements). Splitting into parts is necessary, but the art is to design those parts so that together they form a coherent whole.
Or, as we stated in the introduction: just like with C4 diagrams, you use different zoom levels. You need an overview AND detailed views - but not everything in one diagram.
Appendix C: Use Case Diagram (linking class and sequence views)
This use case diagram provides a behavioral bridge between the class/domain model and the sequence diagrams above. The use cases describe what the actors try to achieve; the sequence diagrams show how those interactions unfold over time.