No description
- Java 100%
| .mvn/wrapper | ||
| src | ||
| .gitignore | ||
| mvnw | ||
| mvnw.cmd | ||
| pom.xml | ||
| README.md | ||
Hexagonal architecture with Javalin
The bowling kata, with a simple HTTP API on top
Notes about architecture and testing strategy
It's important that the *Request, *Response records declared in the
routes package are NOT public.
Any change in those classes would be a breaking API change :)
This is also why we use plain Map<String, Object> in the tests - that way
if the returned JSON changes, our tests break.
Future work
For now we just have a Game instance directly in the app data, because there's no
persistence at all.
You get one Game per Javalin app, which is enough for this kata.
In real life, you'd probably have something like:
public interface GameRepository {
/**
* Store a new game in the repo
*
* @return the newly created ID
*/
String createGame();
void saveGame(String id, Game game);
Game getGame(String id);
}
and then, in main
GameRepository gameRepository = new SQLGameRepository();
var app = Javalin.create(config -> {
config.appData(GAME_REPOSITORY_KEY, gameRepository);
});
and in the routes:
var id = "..."; // extracted from the request
var repo = context.appData(Application.GAME_REPOSITORY_KEY);
var game = repo.getGame(id);
// same code as before
That way you can either:
- inject the
SqlGameRepositoryin the end-to-end tests
or, if you want a different kind of tests:
- mock the
GameRepositoryin the end-to-end test and focus on testing the status codes and the shape of the json requests/response - but in that case, you're more or less writing contract tests (which are fine too!)