REFERENCE · Architecture & package map · Blackjack Ensemble course
Reference card — print me
One page that tells you where everything lives and which way the arrows point. Ted's blackjack-ensemble-blue is a hexagonal (ports & adapters) Spring Boot app. Keep this next to the shortcut card.
adapters ──▶ application ──▶ domain
(in / out) (use cases, (pure rules,
ports) no framework)
domain depends on NOTHING.
arrows only ever point inward.
| Package | Role | Landmark classes |
|---|---|---|
| domain | Pure game rules & state. No imports of Spring/web. | Game, Hand, Card, Rank, Deck, Shoe, PlayerAccount, Wallet, Bet |
| application | Use-case orchestration (“services”). Drives the domain. | GameService, GameCommand |
| application.port | Interfaces the app needs — the “sockets”. | GameRepository, GameMonitor, Shuffler, PlayerAccountRepository |
| adapter.in.web | Driving adapter: Spring MVC controllers + view models. | BlackjackController, WelcomeController |
| adapter.in.console | Driving adapter: text UI. | ConsoleGame, ConsoleCard, ConsoleHand |
| adapter.out.repository | Driven adapter: persistence (CSV, in-memory event store). | CsvGameRepository, *Dto |
| adapter.out.* | Driven adapters: shuffler, game monitor. | RandomShuffler, HttpGameMonitor |
| (root) | Spring Boot startup & console entry point. | BlackjackGameApplication, Blackjack |
HexArchTest exists but is entirely commented out — the layering rules are documented there as intent, not enforced by CI right now. Re-enabling it could be a great ensemble task. Until then, the arrow is a discipline the team keeps by hand.
| Driving (in) | Driven (out) |
|---|---|
Calls into the app. The web/console uses GameService. | The app calls out through a port; an adapter implements it (DB, HTTP, RNG). |
| adapter.in.web → application | application.port ← adapter.out.repository |
| Style | Class | How state changes |
|---|---|---|
| Plain object | Wallet | Mutates a field directly (balance += amount). |
| Event-sourced | PlayerAccount | Records an event (MoneyDeposited), then apply() folds it into state. Rebuilt by replaying events via reconstitute(). |
The event vocabulary is a Java sealed interface PlayerAccountEvent permitting PlayerRegistered, MoneyDeposited, MoneyBet, PlayerWonGame, PlayerLostGame. apply() uses a switch with record patterns (a preview feature — that's the --enable-preview flag in pom.xml).
Glossary.md)| Term | Meaning |
|---|---|
| Blackjack / Natural | Ace + 10-value card in exactly 2 cards → immediate win (unless dealer also has it → Push). |
| Standing player | Didn't bust, no Blackjack; waits for the dealer to resolve the outcome. |
| Busted player | Hit and went over 21 → lost immediately. |
| Turn | A decision point: Hit or Stand. Turn complete = standing, bust, or Blackjack. |
| Push | A tie with the dealer. |
./mvnw verify # compile + run all tests (needs JDK 25)
./mvnw package # build the jar
java -jar target/blackjack-1.0.0.jar # play in a real terminal
pom.xml sets <java.version>25</java.version>, so Spring compiles with --release 25. Your machine's terminal and IntelliJ Project SDK must both be Temurin 25 (already installed at ~/.jdks/temurin-25).
Confused about where a class lives or which layer may call it? Ask me — I'll trace the call path in the real code.