Week 14, year 2025

  • I've been kidnapped by Robert Caro - I've always enjoyed reading, and for most of my life I've particularly enjoyed reading history. I've head many great things about Robert Caro's books, but was deterred by their size. Finally, with his first book newly available as an ebook, I decided to dip my toes in. The books are too good for me to escape. [Martin Fowler]
  • MediatR 12.5.0 Released - I pushed out MediatR 12.5 today: Release Notes NuGet This is mainly a regular minor release with a couple extra interesting features: Adding convenience method to register open behaviors Better cancellation token support (it's passed now everywhere including behaviors) And some other cleanup items as well. Enjoy! [Jimmy Bogard]
Permalink | From 31 March 2025 to 06 April 2025 | Last updated on: Tue, 1 Apr 2025 23:19:29 GMT

Week 13, year 2025

  • The role of developer skills in agentic coding - As agentic coding assistants get more capable, Birgitta Böckeler is trying them to change existing codebases. This has led to some impressive collaboration sessions, but she's needed to intervene, correct and steer all the time. In her latest post, she describes examples of these interventions, giving ideas of the types of skills we currently need to correct the tools' missteps. [Martin Fowler]
Permalink | From 24 March 2025 to 30 March 2025 | Last updated on: Tue, 25 Mar 2025 15:19:29 GMT

Week 11, year 2025

  • New Eventuate platform APIs that support Async API: part 1 - events - New Eventuate platform APIs that support Async API: part 1 - events I recently developed a plugin for SpringWolf that configures an Eventuate service to expose an /springwolf/docs endpoint that returns an Async API document describing the messages that the service sends and receives. While implementing the plugin, however, I discovered that the existing Eventuate APIs were not well suited to exposing Async API-style metadata. For example, the messages sent by the service — and the channels to which it sent them — were not explicitly defined; instead, these details were hidden within the code This realization prompted the creation of a new set of Eventuate APIs for sending and receiving messages. The old APIs still work but only limited metadata can be generated from them. In this article, I’ll describe the new APIs for publishing and subscribing to events. A later article will describe the new APIs for commands and sagas. Let’s first look at the changes to event publishing. Event publishing Let’s first look at the old way of publishing events. After that I describe the new approach. Original event publishing API Previously, domain logic simply used the DomainEventPublisher to publish events: publicclassCustomerService{privateDomainEventPublisherdomainEventPublisher;@TransactionalpublicCustomercreateCustomer(Stringname,MoneycreditLimit){...domainEventPublisher.publish(Customer.class,customer.getId(),customerWithEvents.events);returncustomer;} As a result, the channels and event types were not explicitly defined. New event publishing API The new approach consists of defining one or more DomainEventPublisherForAggregate@Beans. A DomainEventPublisherForAggregate publishes events for a specific aggregate. Although defining DomainEventPublisherForAggregates involves more code, it explicitly defines the channels and events. The Eventuate plugin for Spring Wolf uses the DomainEventPublisherForAggregate@Beans to generate an Async API document describing the published events and their channels. Here’s the definition of a DomainEventPublisherForAggregate for the Customer aggregate: publicinterfaceCustomerEventPublisherextendsDomainEventPublisherForAggregate<Customer,Long,CustomerEvent>{} It’s injected into the CustomerService: publicclassCustomerService{privatefinalCustomerEventPublishercustomerEventPublisher;publicvoidreserveCredit(longorderId,longcustomerId,MoneyorderTotal){CustomerCreditReservedEventcustomerCreditReservedEvent=newCustomerCreditReservedEvent(customerId,orderId);customerEventPublisher.publish(customer,customerCreditReservedEvent); Finally, here is the @Bean implementation of the CustomerEventPublisher: @ComponentpublicclassCustomerEventPublisherImplextendsAbstractDomainEventPublisherForAggregateImpl<Customer,Long,CustomerEvent>implementsCustomerEventPublisher{publicCustomerEventPublisherImpl(DomainEventPublisherdomainEventPublisher){super(Customer.class,Customer::getId,domainEventPublisher,CustomerEvent.class);}} Let’s now look at the new event handling API. Subscribing to events Let’s first look at the old way of subscribing to events. After that I describe the new approach. Original event handling API Previously, event handlers were configured by defining a class that constructed DomainEventHandlers: publicclassOrderEventConsumer{publicDomainEventHandlersdomainEventHandlers(){returnDomainEventHandlersBuilder.forAggregateType("io.eventuate.examples.tram.ordersandcustomers.orders.domain.Order").onEvent(OrderCreatedEvent.class,this::handleOrderCreatedEvent)....build();}publicvoidhandleOrderCreatedEvent(DomainEventEnvelope<OrderCreatedEvent>domainEventEnvelope){... The DomainEventHandlers was then passed to a DomainEventDispatcherFactory: publicclassCustomerConfiguration{@BeanpublicOrderEventConsumerorderEventConsumer(CustomerServicecustomerService){returnnewOrderEventConsumer(customerService);}@BeanpublicDomainEventDispatcherdomainEventDispatcher(OrderEventConsumerorderEventConsumer,DomainEventDispatcherFactorydomainEventDispatcherFactory){returndomainEventDispatcherFactory.make("orderServiceEvents",orderEventConsumer.domainEventHandlers());} The Eventuate plugin for Spring Wolf can use the DomainEventDispatcher@Beans to generate an Async API document describing the subscribed to events and their channels. However, there’s no obvious way to customize the Async API document by, for example, specifying additional documentation. New event handling API The new approach is to define beans that have methods annotated with @EventuateDomainEventHandler. The annotation specifies the event handler’s subscriber ID and the channel. The event type is obtained from the method parameter. @ComponentpublicclassOrderEventConsumer{privateLoggerlogger=LoggerFactory.getLogger(getClass());privateCustomerServicecustomerService;publicOrderEventConsumer(CustomerServicecustomerService){this.customerService=customerService;}@EventuateDomainEventHandler(subscriberId="OrderEventConsumer",channel="io.eventuate.examples.tram.ordersandcustomers.orders.domain.Order")publicvoidhandleOrderCreatedEvent(DomainEventEnvelope<OrderCreatedEvent>domainEventEnvelope){OrderCreatedEventevent=domainEventEnvelope.getEvent();customerService.reserveCredit(Long.parseLong(domainEventEnvelope.getAggregateId()),event.orderDetails().customerId(),event.orderDetails().orderTotal());} The Eventuate plugin for Spring Wolf can search the application context for @Beans that have methods annotated with @EventuateDomainEventHandler. Moreover, in the future, it will support additional annotations that allow you to customize the generated Async API document. Show me the code The Eventuate Spring Wolf repository contains some example Async API docs The development branch of the eventuate-tram-examples-customers-and-orders repository contains an example application that uses the new APIs. What’s next A later post will describe the new APIs for sagas and command handlers. [Eventuate, Inc]
Permalink | From 10 March 2025 to 16 March 2025 | Last updated on: Wed, 12 Mar 2025 07:19:36 GMT

Week 9, year 2025

  • GenAI Patterns: Fine Tuning - While RAG is the most common way to focus a foundation model on material outside its training set, Bharani Subramaniam and I now finish our current batch of patterns by examining our experience with Fine Tuning where we learned to prioritize curating high-quality data. [Martin Fowler]
  • Commenting on removing "X" on US passports - The new US administration has decided to eliminate the “X” option for gender/sex on passports. I have several non-binary friends, and I don’t see why they should have to select an option that makes no sense for them. I also don’t see how an “X” option on identity documents causes a material problem for anyone else. There’s not much I can do to object to this change, but one little thing is to add a comment on the Federal Register for such rule changes. There are three such pages: DS-11 new passport application: (deadline 3/17/25) https://www. federalregister. [Martin Fowler]
  • (Naive) Reuse Considered Harmful? - Reuse per boxes and lines is great if you have no operational needs... [The Architect Elevator]
Permalink | From 24 February 2025 to 02 March 2025 | Last updated on: Mon, 3 Mar 2025 23:19:41 GMT

Week 8, year 2025

  • What role does LLM reasoning play for software tasks? - Recent LLM models have provided “reasoning” capabilities. Birgitta Böckeler asks what role these play with coding tasks. She doesn't have an answer, but does have questions and thoughts - and has not found such capabilities worthwhile so far. [Martin Fowler]
  • GenAI Patterns: Guardrails and RAG overview - Gen AI systems are gullible, and can easily be tricked into responding in ways that are contrary to an enterprise's policies or leak confidential information. Bharani Subramaniam and I describe how we can counter this by adding guardrails at the boundaries of the request/response flow. We also conclude our discussion of RAG with an overview of how all the RAG component patterns fit together. [Martin Fowler]
  • AutoMapper 14.0 Released - I pushed out version 14.0 (!) of AutoMapper over the weekend: Release notes NuGet This release targets .NET 8 (up from .NET 6 from the previous release). It's mainly a bug fix release, with some quality-of-life improvements in configuration validation where we gather up all the possible validation [Jimmy Bogard]
Permalink | From 17 February 2025 to 23 February 2025 | Last updated on: Wed, 19 Feb 2025 15:19:33 GMT

Week 7, year 2025

  • GenAI Patterns: Query Rewriting - Users often have difficulty writing the most effective queries. Bharani Subramaniam and I explain Query Rewriting: getting an LLM to formulate alternative queries to send to a RAG's retriever. [Martin Fowler]
  • GenAI Patterns: Reranker - LLMs struggle with large amounts of context. Bharani Subramaniam and I explain how to mitigate this common RAG problem with a Reranker which takes the document fragments from the retriever, and ranks them according to their usefulness. [Martin Fowler]
Permalink | From 10 February 2025 to 16 February 2025 | Last updated on: Thu, 13 Feb 2025 15:19:31 GMT