Milestone 1 · Software Technology
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.
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.
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.
| 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
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 oneThe 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).
- «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.
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
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 gameThe 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).
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
// 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
// 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 */ }
}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)
```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).
One table of the diagram, as 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
);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).
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
@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);
}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
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 workGitLab 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)
```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 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.