Have fun learning about Test-Driven Development with JitterTed's TDD Game

Live Coding Journal - Apr 2, 2026

Reflections, Learnings, and Mistakes from live coding my JitterTicket Event Sourcing application


Notes from Today’s Live Coding Session

Consuming Only Desired Events

I finally started on a big optimization, mainly for Projectors that need to catch up on lots of events (because they’re new or changed), where Event Consumers only fetch/receive events that they’re interested in. For example, the AvailableConcerts projector only needs to know about events relating to availability of customers to buy tickets. There’s no point in it fetching or receiving events like TicketsSold or event CustomerRegistered, especially since the large majority of events would be about ticket sales. The question was: how do consumers “publicize” which events they want?

The options were:

  1. Have an interestedIn() method that all consumers must implement, returning a list of event classes they want.
  2. Register desired events when the consumer registers itself with the Event Store
  3. Like #1, but using a code generator to generate the method (and other boilerplate, like the switch block for handling the events)
  4. Similar to #1, but using Annotations
  5. Have the Event Consumer create handle() methods, overloaded for each desired event, which reflection can find.

I decided to go with #5, as it’s straightforward to do, and unlike #1/#3, does not repeat the same information, which could lead to forgetting to publicize a desired event. I didn’t like #2, because as above, it’s easy to forget to update the configuration when desired events change, especially since configuration is in a separate file. I generally don’t like annotations, but #4 suffers from the same problem as above: having to update the annotation to indicate desired events.

Using reflection also allows me to handle implementation problems such as methods that might be handle() methods, but perhaps were misspelled (e.g., handel(ConcertScheduled event)), or if no methods handle events at all. I also added in extra checks for the case where somehow the consumer is getting events that it wasn’t interested in, which would indicate a bug elsewhere.

Moving to selective event consuming also means dropping the generic type from the NewEventConsumer, which helps as I continue to move away from an aggregate-focused design.

Void vs. void

This was a (not) fun troubleshooting session, took a long time to figure out why I couldn’t use MethodHandle.lookup().findVirtual() for the handle methods that return void. It turns out, Void.class is not the same as void.class (yes, a class from the “primitive” void)! After struggling through the rest of reflection to get the methods and try out invoking them, I got the prototype to work. However, it was much more painful and frustrating than it should have been thanks to docs that aren’t great.

Background Thoughts on Projection Design

Over the weekend, I’ve been thinking about Projections and how I’m currently caching them in memory to make updating their state fast. I was reminded of earlier thoughts where some Projections could use the database to perform the summary calculations (e.g., the Sales Projection). This is another reason in favor of consolidating the Projection persistence into the Projection code itself instead of the current “wrapper” way that I’m currently doing in the ProjectionCoordinator. Not only that, the persisting of the projection might be different depending on how “risky” it is to have it catch up if the system crashes or needs to restart. On the other hand, I want to implement a deferred-write mechanism for persisting projections, so having a standard way to deal with deferred writes (after a timeout or deferred data exceeds a threshold) might be easier with a ProjectionCoordinator design.

Next Steps

With the NewEventConsumer completed, I’ll be working on converting the RegisteredCustomersProjector to use it. If time allows, I’ll also convert the AvailableConcertsProjector.

Join me on my next stream, which I usually do Monday through Thursday, starting at 19:00 UTC on Twitch: https://jitterted.stream.


Make Your Code More Testable™️

Don't miss out on ways to make your code more testable. Hear about new Refactoring techniques, improving the Test-Driven Development process, Hexagonal Architecture, and much more.

    We respect your privacy. Unsubscribe at any time.