﻿# Requirements and design: use cases, class and database diagrams

> Milestone 1, without code: turn the specification into use cases and user stories with acceptance criteria, and design a model–view class diagram and a database diagram on the GitLab wiki.

Source: https://laszlonemes.com/university/software-technology/requirements-design · Author: László Nemes

Milestone 1 · Software Technology

Milestone 1, without code: turn the specification into use cases and user stories with acceptance criteria, and design a model–view class diagram and a database diagram on the GitLab wiki.

14 min read `Use cases and use-case diagrams` `«include» vs «extend»` `User stories and acceptance criteria` `Model–view class diagram` `Database diagram` `Rendering big maps`

The first milestone, in week 4, has no code in it at all. You read the specification, decide what the game does and who does it, and draw how the program will be built: use cases, a use-case diagram, a class diagram and a database diagram, written up on the GitLab wiki.

It can feel like paperwork when everyone wants to start programming. It isn't: three people can only work in parallel if they share one picture of the game, and the use cases you write now are the yardstick of the next two milestones – "30% of the use cases work" means nothing until the use cases exist.

After this session you can

- turn a specification into use cases with actors, main flows and alternative flows
- draw a use-case diagram and use «include» and «extend» correctly
- write user stories whose acceptance criteria include the error case
- design a class diagram with a separate model and view layer
- spot a rendering design that won't scale to a big map

## What milestone 1 asks for

Everything in M1 grows out of the use cases (Fig. 1). The deliverable is the wiki of your GitLab project – not a Word file, not a PDF.

> **Fig. 1** · One chain: specification → use cases → diagrams and stories → wiki. A gap early in the chain shows up in every later milestone.
>
> *Diagram:* The specification becomes use cases: who does what with the game. From those come the use-case diagram, user stories with acceptance criteria, and the class and database diagrams. All of them go on the GitLab wiki, which is the deliverable of the first milestone.

| Artifact | What it answers |
| --- | --- |
| Use cases (text) | What can each actor do with the game, step by step, including what goes wrong? |
| Use-case diagram | Which actors and use cases exist, and how do they relate – on one page? |
| User stories + acceptance criteria | What exactly does "done" mean for each feature? |
| Class diagram | Which classes exist, in which layer, and who knows about whom? |
| Database diagram | What does the game store – saves, high scores, settings – and in what structure? |

## Use cases

A **use case** (*használati eset*) is a goal an actor reaches through the system: "start a new game", "save the game", "build a road". An **actor** is a role outside the system – a player, a second player on the same keyboard, sometimes a timer or another system. Find them by reading the specification and underlining every "the player can …".

A use case written out has a fixed shape – the main flow, plus what happens when things go differently:

A use case description

```text
Use case:        Load game
Actor:           Player
Precondition:    the main menu is open; at least one save file exists
Main flow:       1. The player chooses "Load game".
                 2. The game lists the save files, newest first.
                 3. The player picks one.
                 4. The game validates the file and restores the board, the players and the score.
                 5. The game continues from the saved state.
Alternative:     4a. The file is corrupt → the game shows a message and stays in the menu.
Postcondition:   the running game is exactly the saved one
```

The **use-case diagram** is the one-page overview: actors outside the system boundary, use cases inside it, lines for "this actor does it" (Fig. 2).

> **Fig. 2** · Use cases sit inside the system boundary. «include» arrows point to the part that always runs; «extend» arrows point from the optional behaviour to the use case it extends.
>
> *Diagram:* A use-case diagram for a generic tile-based game. The actor Player is connected to five use cases inside the system boundary: start new game, move character, pause game, save game and load game. Start new game includes choose map, load game includes validate save file, and pick up item extends move character.

- **«include»** – The base use case always runs the included one. Load game always validates the save file. Use it to share a step between use cases.
- **«extend»** – The extension runs only under a condition. Moving onto an item extends Move character with Pick up item.
- **System boundary** – The box that separates the game from its actors. Everything inside is what you build.

Common mistake

**Use cases that are keystrokes or screens**

"Press W", "Click the OK button" and "Main menu" are not use cases – they are UI details of one. A use case is a goal the player would name: "move the character", "start a new game". Aim for roughly 10–20 use cases of similar size; if one is ten times bigger than the rest, split it, because the M2 and M3 percentages are counted on them.

## User stories and acceptance criteria

A **user story** is the same goal in one sentence – who, what, why – plus **acceptance criteria**: the checks that decide whether it is done. The criteria are the most useful part. They tell the developer when to stop, the reviewer what to try, and the tester what to automate (Fig. 3).

A story with its criteria

```text
Title:   Implement save/load
Story:   As a player, I want to save the game, so that I can continue later.

Acceptance criteria
- [ ] Save creates a file in the user's save folder
- [ ] Load restores the exact game state, including moving units
- [ ] Error case: loading a corrupt file shows a message and keeps the current game
```

> **Fig. 3** · Each acceptance criterion becomes a check. The error case is the one most often missing – and the one most often broken in the final demo.
>
> *Diagram:* A user story card: as a player, I want to save the game, so that I can continue later. Its three acceptance criteria – save creates a file, load restores the exact state, a corrupt file shows a message and keeps the game – each map to one unit test in the model, and the reviewer checks each by hand.

In your assignment

**Stories become your first issues**

At M2 every story becomes a GitLab issue created from the Feature template, which has exactly these sections: user story, acceptance criteria (with an error case line), design notes. Write the stories now so that copying them into issues later is mechanical. Give every story at least one error or edge case: an empty save folder, a full board, a move off the map.

## The class diagram: model and view

The course requires at least a **two-layer architecture**: a **model** that holds the rules and the state of the game, and a **view** that draws it and turns input into calls on the model. MVC – with a separate controller – is fine too. The rule that makes it work is one-way: **the view knows the model, the model never knows the view** (Fig. 4).

> **Fig. 4** · Every arrow between the layers points down, into the model. The model reaches the view only through an interface it defines itself – GameListener – which the view implements.
>
> *Diagram:* A class diagram in two layers. The view layer has GameWindow, BoardPanel and MenuPanel. The model layer has Game, Board, SaveService and the GameListener interface. BoardPanel uses Game and implements GameListener; Game notifies its listeners and owns a Board; SaveService reads and writes the Game. No model class refers to a view class.

The interface trick is the observer pattern: the model publishes "the board changed", and whoever listens repaints. The model can then be created, played and tested without a window – which is exactly what the unit tests of M3 need.

Game.java – the model notifies, it doesn't draw

```java
// model package – no javax.swing / java.awt import anywhere in it
public interface GameListener {
    void boardChanged();
    void gameOver(GameResult result);
}

public void step(Direction direction) {           // in Game
    if (state != State.RUNNING || !board.isFree(player.next(direction))) return;
    player.move(direction);
    listeners.forEach(GameListener::boardChanged);  // the view repaints itself
}
```

### Unity and other engines

The same separation is required in Unity. A `MonoBehaviour` is view and controller: it reads input and moves sprites. The rules – whose turn, what is free, what the score is – live in plain C# classes that never import `UnityEngine`. Those are the classes you can unit test in EditMode, quickly.

BoardView.cs – the engine calls the model

```csharp
// Unity: the MonoBehaviour is the view and controller; the rules live in plain C# classes
public class BoardView : MonoBehaviour
{
    private Game game;                      // model class – no "using UnityEngine" in it

    void Start()  { game = new Game(MapLoader.Load(levelFile.text)); game.BoardChanged += Redraw; }
    void Update() { if (Input.GetKeyDown(KeyCode.W)) game.Step(Direction.Up); }
    void Redraw() { /* move the sprites to the positions the model reports */ }
}
```

Common mistake

**A model that imports the UI**

If a class in the model imports Swing, WinForms, WPF or `UnityEngine`, the layers are mixed. The symptoms come later: you can't test it without a window, and changing the UI breaks the rules. Check the diagram: an arrow from a model class to a view class is the bug, before any code exists.

On the wiki, the class diagram can be text that GitLab renders, so it changes in the same review as the code:

Class diagram page on the wiki (PlantUML)

```md
```plantuml
@startuml
package model {
  interface GameListener {
    +boardChanged()
    +gameOver(result)
  }
  class Game {
    -board: Board
    +step(direction)
    +addListener(l: GameListener)
  }
  Game "1" *-- "1" Board
  Game --> GameListener : notifies
}
package view {
  class BoardPanel
}
BoardPanel ..|> GameListener
BoardPanel --> Game
@enduml
```
```

## The database diagram

The database diagram shows what the game stores and how the pieces relate: saved games, high scores, players, settings. Most teams store a save as one serialized blob (JSON) next to a few searchable columns, which is a perfectly good design (Fig. 5).

> **Fig. 5** · Three tables and two one-to-many relations. Draw keys explicitly – the arrows are only as good as the foreign keys behind them.
>
> *Diagram:* A database diagram with three tables. players has an id primary key, a name and a creation time. saved_games and high_scores each have their own id and a player_id foreign key pointing to players, so one player has many saved games and many high scores.

One table of the diagram, as SQL

```sql
CREATE TABLE saved_games (
    id         INTEGER   PRIMARY KEY,
    player_id  INTEGER   NOT NULL REFERENCES players(id),
    map_name   TEXT      NOT NULL,
    state      TEXT      NOT NULL,      -- the serialized game, e.g. JSON
    saved_at   TIMESTAMP NOT NULL
);
```

Good to know

**No database server in the game?**

A desktop game rarely needs a database server. If you store saves as files, the diagram still describes their structure – what is saved, what refers to what – and the same shape works with an embedded database such as SQLite later.

## Designing for big maps

Some designs don't scale, and the usual victim is rendering. A grid of buttons or a table with one cell per tile is quick to build and works for a 10 × 10 board. At 100 × 100 it means ten thousand components that the UI toolkit lays out and repaints, and the game stutters (Fig. 6).

> **Fig. 6** · A widget per tile scales with the map. A single canvas that draws only what is on screen scales with the window.
>
> *Diagram:* Two ways to draw a big map. Left: one UI component per tile – a 100 by 100 map means ten thousand widgets to lay out and repaint. Right: one canvas that draws only the tiles inside the visible area from the model, so the cost grows with the screen, not with the map.

The scalable version is one drawing surface – a `JPanel` with `paintComponent`, a canvas, a tilemap in an engine – that asks the model for the tiles inside the visible area and draws only those:

BoardPanel.java – draw only the visible tiles

```java
@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    int firstCol = Math.max(0, camera.x / TILE);
    int lastCol  = Math.min(board.width() - 1, (camera.x + getWidth()) / TILE);
    int firstRow = Math.max(0, camera.y / TILE);
    int lastRow  = Math.min(board.height() - 1, (camera.y + getHeight()) / TILE);
    for (int row = firstRow; row <= lastRow; row++)
        for (int col = firstCol; col <= lastCol; col++)
            drawTile(g, board.tileAt(col, row), col * TILE - camera.x, row * TILE - camera.y);
}
```

In your assignment

**Decide this in the design, not in week 9**

Look at the biggest map your specification allows and write one sentence on the wiki about how you will draw it. If the answer is "one component per tile", check it with a quick experiment before M2. Rewriting the view at M3 costs the time you need for tests.

## The wiki

The milestone's text goes on the project wiki, edited in the browser or cloned as a git repository. Keep the structure flat and predictable, so the instructor – and you, in week 12 – can find things:

A wiki structure that works

```text
Home                      ← one paragraph about the game + links to every page below
├── Specification         ← the task in your own words; what is core, which sub-tasks you chose
├── Use cases             ← the diagram + one description per use case
├── User stories          ← story + acceptance criteria; these become the M2 issues
├── Class diagram         ← model and view layers, with a few sentences on the key decisions
├── Database diagram      ← tables or the save-file structure
├── UI sketches           ← menu, game screen, dialogs (photos of paper sketches are fine)
└── Team                  ← who owns which area, how you split the work
```

GitLab renders PlantUML blocks on the wiki, so diagrams can be text: no exported images going stale, and a change to the design is a readable diff.

Use-case diagram on the wiki (PlantUML)

```md
```plantuml
@startuml
left to right direction
actor Player
rectangle Game {
  usecase "Start new game" as Start
  usecase "Choose map" as Map
  usecase "Load game" as Load
  usecase "Validate save file" as Validate
}
Player --> Start
Player --> Load
Start .> Map : <<include>>
Load .> Validate : <<include>>
@enduml
```
```

> The design is not frozen after week 4. When the code teaches you something, update the diagram – the team's Definition of Done includes "wiki updated if the design changed".

Next: [milestone 2](https://laszlonemes.com/university/software-technology/version-control) turns the stories into issues and the issues into branches.

## Summary

- M1 is design only: use cases, use-case diagram, class and database diagrams – on the GitLab wiki.
- A use case is a goal an actor names; write the alternative flows; keep them countable and of similar size.
- User stories carry acceptance criteria, including an error case; they become the M2 issues.
- At least two layers: the view knows the model, the model never knows the view – also in Unity.
- Plan rendering for the biggest map: draw only the visible tiles from the model.
