What are the preferred practises when it comes to putting complex data types in messages?
This is a high point of contention within our office, with several senior developer expressing very different views on what data is appropriate for a message and what should be persisted at source and passed through with identifiers.
Is it better to persist data to a defined data structure prior to sending a message to other services like below. Allowing each service to retrieve the data necessary to perform the operation.
public class OrderEventA : IEvent
{
public int OrderID { get; set; }
}
Or is it better to simplify data storage and allow NServiceBus to take care of the serialisation and persist the data until all nodes have preformed the necessary operations they need.
public class OrderEventB : IEvent
{
public Order order { get; set; }
}
public class Order
{
public int id { get; set; }
public Customer customer { get; set; }
public List<Products> products { get; set; }
public decimal TotalPrice { get; set; }
}
public class Customer
{
public int id { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string AddressLine3 { get; set; }
}
public class Products
{
public int Id { get; set; }
public string ProductName { get; set; }
public decimal Price { get; set; }
}
- When the message makes use of identifiers, we can pivot our data model without affecting any of the existing messages in the queue, simplifying migrations and product releases. We also gain extended controls over the data access, without publishing possibly sensitive information on the bus. Messages are smaller and have a reduced footprint during processing. You can control data domain contexts and boundaries.
- When the message transfers complex types, handler has all the information it needs without querying database explicitly (webapi/database repositories), simpler code no unnecessary repositories or api clients, quicker to extend the functionality on existing messages, prevents cross data contamination by providing shared dto objects. Simplifies event sourcing. When debugging messages, you see the entire state of the data at the time of processing.
Any help or insight is greatly appreciated?