Nullables & A-Frame Architecture Livestream

In this weekly livestream series, which is currently ongoing, I pair up with Ted M. Young, aka jitterted. We look at Nullables and A-Frame Architecture as an alternative to Mocks, Spies, and Hexagonal Architecture. Each episode combines a healthy dose of architecture and design discussion with practical, hands-on coding.

Nullables Training

Apr
11
2023

Learn how to apply these ideas to your own code! I’m offering live online training for this material on April 11th and 12th. Register here.

To be notified about upcoming “Testing Without Mocks” training courses, send an email with the subject “Subscribe” to nullables-training+subscribe@googlegroups.com or join the mailing list here (requires Google login).

For private training, contact me directly.

Episodes

#1: Nullable Die Rolls

Screenshot of “Nullable Die Rolls” episode

In our first session, we introduce the codebase we’re working on: Ted’s yacht-tdd, which is a web-based Yahtzee-like dice game written in Java and using the Spring framework.

We introduce the core concepts of Nullables, and modify Ted’s DieRoller class to be nullable, in place of his existing stub-based approach. Along the way, we have a lot of great conversations about the similarities and differences between Hexagonal Architecture and A-Frame Architecture.

#2: Exploring Architecture

Screenshot of “Exploring Architecture” episode

We use the DiceRoller class to dig into the conceptual differences between Hexagonal Architecture and A-Frame Architecture, and think about at what belongs in the “logic,” “infrastructure,” and “application” layers. Ultimately, we’re able to eliminate the class entirely.

#3: Fetcher Nullability

Screenshot of “Fetcher Nullability” episode

We start our work on the HttpAverageScoreFetcher and HttpScoreCategoryNotifier classes. These adapters are part of Ted’s implementation of Hexagonal Architecture: they retrieve and store data from a separate “Yacht Tracker” service. We spend some time understanding how hexagonal architecture works, then make HttpAverageScoreFetcher nullable. Along the way, we demonstrate the plusses—and minuses!—of using an embedded stub.

#4: State-Based Notifier

Screenshot of “State-Based Notifier” episode

We look at how to make the HttpScoreCategoryNotifier class nullable. This adapter stores data to a separate “Yacht Tracker” service. We demonstrate how to make the adapter expose its state by creating a reusable OutputTracker class, then demonstrate how easy making an adapter Nullable can be.

#5: get() HttpClient

Screenshot of “get() HttpClient” episode

In the last few episodes, we made the adapters for Ted’s scoring service Nullable. These are the “out” or “secondary” adapters in the codebase’s Hexagonal architecture.

Now that the adapters are Nullable, we see an opportunity create a low-level HttpClient adapter that the scoring service adapters can use. This should simplify the Nullability logic in those adapters and open up new opportunities for testing. We start with the get() method and the Nullable’s configurable responses.

#6: Finish HttpClient

Screenshot of “Finish HttpClient” episode

We finish off our Nullable JsonHttpClient adapter by adding support for multiple responses per endpoint, output tracking, and the post() method. Now we’re ready to use it in the rest of our code. In the final few minutes of the episode, we demonstrate how it works by using it in HttpScoreCategoryNotifier.

#7: High-Level Adapters

Screenshot of “High-Level Adapters” episode

We take advantage of our new JsonHttpClient infrastructure to simplify our ScoreCategoryNotifier and AverageScoreFetcher adapters. Now they can be tested easily and no longer need clunky embedded stubs. Along the way, we have lots of conversations about design—test design, input validation, anti-corruption layers, and more.

#8: Nullable Application

Screenshot of “Nullable Application” episode

Now that we’ve finished making our adapters nullable, we’re ready to introduce them to our application code. We start by making GameService nullable, then clean up all the existing tests to use GameService.createNull() rather than creating and injecting dependencies manually. That leaves plenty of time for design discussion, and a start to our next feature: persistence! We design our database schema and decide how to tackle the problem.

#9: Database Dreams

Screenshot of “Database Dreams” episode

Databases! With our initial implementation of nullables complete, it’s time to add persistence. We start by reviewing Ted’s Spring Data JPA spike, then begin creating a GameDatabase infrastructure wrapper from scratch. The goal is to write low-level tests that give us total control over how the wrapper works. Most of our time is spent fighting with Spring Data, but by the end, we’ve got it figured out.

Nullables Training

Apr
11
2023

Learn how to apply these ideas to your own code! I’m offering live online training for this material on April 11th and 12th. Register here.

To be notified about upcoming “Testing Without Mocks” training courses, send an email with the subject “Subscribe” to nullables-training+subscribe@googlegroups.com or join the mailing list here (requires Google login).

For private training, contact me directly.