The docs had drifted from the code and described things that never existed. - architecture.md documented a QuitCommand class (quit/exit are aliases on MenuCommand) and a GameIO interface of read()/write(String); the real one is readLine() plus print(StyledText) with presentation hooks. Both corrected, along with the package diagram and the game-loop sketch. - conventions.md listed a package tree missing save, menu, io.text and command.impl. Updated, including why MapLayout lives in game. - data-structures.md claimed LinkedList was deliberately avoided (Pathfinder uses one for O(1) addFirst during path reconstruction), named the wrong queue for the Swing bridge, and listed an input history that was never built. - Removed enhancement-ideas.md and implementation-status.md: a backlog and a phase tracker, neither of which documents the delivered project. Also stop tracking the built jars. They still ship in the submission, but a 22 MB binary that changes on every build does not belong in git history.
3.8 KiB
Konventionen
Sprache, IDs, Package-Struktur, Naming.
Sprache
- Code: Englisch — Klassen, Methoden, Felder, Enums, Package-Namen, Javadoc.
- YAML: Englisch — Keys, IDs, alle Texte (descriptions, dialogue, readText, etc.).
- Doku-Prose (
docs/*.md): Deutsch — Diskussion mit dem Entwickler, keine Spec für Korrektoren.
IDs
Slugs, keine UUIDs. Begründung in item-model.md und yaml-schemas.md.
| Regel | Beispiel | Gegenbeispiel |
|---|---|---|
| nur kleinbuchstaben | kitchen, letter |
Kitchen, LETTER |
| ASCII, keine Umlaute | cellar, kueche schlecht |
keller gut, küche schlecht |
| Mehrwortig: snake_case | oil_lamp, old_man |
oilLamp, old-man, oil lamp |
| keine führende Ziffer | key1 |
1key |
nur [a-z0-9_] |
key2 |
key#2, key@2 |
Regex zur Validierung im WorldValidator:
^[a-z][a-z0-9_]*$
Geltungsbereich: id ist eindeutig innerhalb seiner Entitätsart. Ein Item und ein NPC dürfen lamp heißen (nicht empfohlen, aber technisch erlaubt).
Package-Struktur
thb.jeanluc.adventure
├── App, AppGui <- Entry Points (Konsole / Swing)
├── model
│ ├── Direction, Room, Player, Npc
│ ├── Quest, QuestStage, Ending, Combination, Condition, Effect, …
│ └── item <- eigener Subpackage wegen Hierarchie
│ ├── Item (abstract)
│ ├── ReadableItem
│ ├── SwitchableItem
│ └── PlainItem
├── io <- ConsoleIO, SwingIO, GameIO, Music*, MapPanel, QuestPanel
│ └── text <- StyledText, Style, Span, Hud, *View (15 Klassen)
├── command <- Command, CommandParser, CommandRegistry, ParsedCommand
│ └── impl <- die 15 konkreten Kommandos
├── game <- Game-Loop, Engines (Quest, Ending, Escort), Light,
│ Pathfinder, MapLayout, GameState/Session/Context
├── loader
│ └── dto <- die YAML-Records
├── save <- SaveService, SaveCodec, SaveData, Settings*
└── menu <- MainMenu, SettingsMenu, MenuAction
Wann ein Subpackage: wenn eine Klassenfamilie ≥ 3 Klassen umfasst und eine eigene Abstraktion bildet. Erfüllt von item (4), command.impl (15), io.text (15), loader.dto (16), save (7), menu (3). Sonst flach lassen — MapLayout liegt deshalb in game neben Pathfinder und nicht in einem eigenen map-Package (eine Klasse reicht nicht).
Naming
Java-Standard:
- Klassen:
UpperCamelCase - Methoden, Felder, Parameter:
lowerCamelCase - Konstanten:
UPPER_SNAKE_CASE - Packages:
lowercase, ohne Underscores wenn möglich
YAML:
- Keys:
lowerCamelCase(startRoom,readText,initialState) — passt zu Jackson-Default-Mapping auf Java-Felder - IDs: siehe oben
Javadoc
Pflicht laut Aufgabenstellung an Klassen, Methoden, und Instanzvariablen. Auch bei Lombok-Feldern wenn sie @Getter-exposed sind.
Keep it sachlich — was tut die Klasse/Methode, nicht wie. Keine Geschichten erzählen.
Tests
- Unit-Tests pro Domain-Klasse:
RoomTest,PlayerTest,ItemTestetc. - Integration-Tests für Loader:
WorldLoaderTestmitsrc/test/resources/world/-Fixtures - Naming:
methodName_condition_expectedResult— z.B.addExit_withNewDirection_storesNeighbour
Lombok-Cheatsheet
| Annotation | Wozu |
|---|---|
@Getter |
Getter für alle Felder |
@RequiredArgsConstructor |
Konstruktor nur für finals ohne Initializer |
@SuperBuilder |
Builder über Vererbung (statt @Builder) |
@Slf4j |
log-Field für SLF4J |
@ToString |
Nur wenn aussagekräftig — sonst weglassen |
Vermeiden: @Data (zu viel auf einmal, generiert equals/hashCode was bei Room/Player unerwünscht ist).