Event sourcing vs Refactoring

374 views
Skip to first unread message

alexandr...@gmail.com

unread,
Apr 20, 2015, 2:21:00 AM4/20/15
to ddd...@googlegroups.com

Hello,

I would like to use event sourcing but what if I have to change my events? Let's say that I have to change my events in order to have a finer granularity (I want to split my events) I imagine that I will have to keep my old events' classes in order to deserialize them. Then I will convert them to my new events in order to rebuild my aggregate. I am afraid that the event sourcing is not so resiliant to changes and that any refactoring of events could make the code difficult to understand. Any idea on this?

Alexandre

João Bragança

unread,
Apr 20, 2015, 5:19:26 AM4/20/15
to ddd...@googlegroups.com
Keep your old event classes around forever. Your aggregates and event handlers need to understand the old events and the new ones.

--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--

Chris Sampson

unread,
Apr 20, 2015, 5:22:31 AM4/20/15
to ddd...@googlegroups.com
Or if its just new fields added and you use json serialisation, then the new classes will work but will have default values for the new bits. 

Also, I don't know whether it is good practice or not but I have performed an upgrade script on the serailised blob before (my event store is a sql backend) 

alexandr...@gmail.com

unread,
Apr 20, 2015, 5:59:55 AM4/20/15
to ddd...@googlegroups.com, joao...@braganca.name
Hi João,

Thank you for your answer. This is was my initial idea but I believe that after a while the code could be complex to understand. We will have deprecated events, deprecated handle methods, etc.

Regards,
Alexandre

Colin Yates

unread,
Apr 20, 2015, 6:19:20 AM4/20/15
to ddd...@googlegroups.com
I think it is important to distinguish _why_ it has changed. If the
business logic has changed and as a result new events are emitted then
I think the old events should be kept and handled in the code - your
event stream is a record of _what_ happened.

If the business logic is the same however, and you are simply changing
how that decision is recorded then I might consider refactoring the
existing events.

Just my 2p,

Peter Hageus

unread,
Apr 20, 2015, 6:50:18 AM4/20/15
to ddd...@googlegroups.com

I use the ObsoleteAttribute on .Net.

 

That way I can factor them out gradually, and even have the compiler warn me about usages…

alexandr...@gmail.com

unread,
Apr 20, 2015, 7:48:44 AM4/20/15
to ddd...@googlegroups.com
Hi,

@Sammo
We already serialize the events using JSON and we store them in Cassandra. Indeed adding fields won't be a problem. My concern is more about a real break down of the existing events.

@Sammo @Colin
Let's imagine the following example :

I have a Shipment aggregate
- Shipment id
- Items
- Consignee information (name, address, phone, email)

I have an event that states that the consignee has changed: 
ConsigneeChanged(shipment id, name, address, phone, email)

Now the business is asking me to send an email to the shipper if the delivery information (name, address, phone) of the consignee has been changed.

I have two ways to handle this :
- Keep the event has it is (ConsigneeChanged) and handle this logic in the event listener
  Pros : I don't have to change my event
  Cons : My event listener will always be called even if the delivery information has changed

- Split the ConsigneeChanged event
  - DeliveryInformationChanged(shipment id, name, address, phone) // The email is not needed by the shipper
  - ConsigneeEmailChanged(shipment id, email) 
  
  Pros : I can have a dedicated event listener that will listen to the DeliveryInformationChanged
  Cons : I've changed my event
  
My question is then more about the way to handle the granularity of my events. Today if I don't have business rules I will create coarse-grained events. Tomorrow based on the new business rules I will have to break the events down.

Sorry in advance if my question sounds obvious for some of you but I am completely new with this concept :)

Thank you for your help.

Regards,
Alexandre

Colin Yates

unread,
Apr 20, 2015, 8:07:16 AM4/20/15
to ddd...@googlegroups.com
I too am new, but I would ask the following questions guide the thought process:
- where is the value to the business in this?
- what do we do about all the historical non-emailed changes? email
them (surely not!) or record them as 'processed'

If emailing really is important then I wonder if there is a separate
'send email processor' lurking in another BC that listens to the
ChangedEvent which itself emits events...

Colin Yates

unread,
Apr 20, 2015, 8:11:34 AM4/20/15
to ddd...@googlegroups.com
(and get used to there being very few 'ah yes, do this' answers and
many more 'what, where, why, when etc.' questions here :).

There is a serious point, which is that these design patterns are
quite expensive and should avoid becoming a golden hammer. If there is
little value for the business then maybe it is the wrong tool to model
this process.

Having said all that, realise the source of the problem is a
non-process related coarse grained event. DetailsChanged aren't as
useful (in my _very_ limited experience) as a sequence of much finer
grained events.

In this scenario, if this was something the business cared about then
I would refactor a new event which was only now being admitted.
Alternatively handle it in the handler until you can prove the
performance of no-ops is too high.

Greg Young

unread,
Apr 20, 2015, 8:24:35 AM4/20/15
to ddd...@googlegroups.com
Two things here.

1) You don't "refactor in new requirements"
2) You are using types as schema. Whether or not you need to keep them
around entirely depends on your serialization decisions. What if you
used json?

Greg
> --
> You received this message because you are subscribed to the Google Groups
> "DDD/CQRS" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to dddcqrs+u...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.



--
Studying for the Turing test

akshay puradkar

unread,
Apr 20, 2015, 11:17:43 AM4/20/15
to ddd...@googlegroups.com
Greg,

By (1), do you mean only adding DeliveryLocationMoved without removing the ConsigneeChanged event?

And what do you mean by 'types as schema'?

Greg Young

unread,
Apr 20, 2015, 11:30:35 AM4/20/15
to ddd...@googlegroups.com
You are defining the schema of your events through types. There are
other ways of doing this as well (.proto files or .xsd as example)

By #1 I meant you don't "refactor" new features into software. By
definition a refactor does not change contracts.

alexandr...@gmail.com

unread,
Apr 21, 2015, 2:49:59 AM4/21/15
to ddd...@googlegroups.com
Hi Greg,

1) So as a new feature should not change my contract my aggregate will have to generate the old event (ConsigneeChanged) but also the new one (DeliveryInformationChanged) ?
If so, won't it be better to only generate coarse grained events from the aggregate and if the need comes to split them we could handle the split in a event listener that would break down the coarse grained event and publish fine-grained events one the bus?

2) If I understand correctly you recommend to generate the event classes. What would be the advantage of doing this? 

Thank you
Alexandre

Greg Young

unread,
Apr 21, 2015, 3:02:26 AM4/21/15
to ddd...@googlegroups.com
#1 just pointing out that you are not refactoring in your situation.
By definition you are changing your contracts and behaviour so its not
a refactor (its a change just not a refactor).

#2 you are talking about needing to keep old types around to be able
to deserialize events. The reason you need to keep old types around is
that you are using your types as schema. There are other ways of
representing schema than using types (like explicit schema such as
protofbufs) you would then not need to keep your types around any
more. You could also look at using weak/hybrid serialization such as
mapping json

alexandr...@gmail.com

unread,
Apr 21, 2015, 4:17:41 AM4/21/15
to ddd...@googlegroups.com
#1 Yes you are right. So I would propose to do the following :
- My Shipment aggregate will generate the ConsigneeChanged event but not the DeliveryInformationChanged event. Reason being is that DeliveryInformationChanged is not needed to restore the aggregate's state (ConsigneeChanged contains everything)
- I will create an event listener that handle the ConsigneeChanged event. It will check whether the delivery information have been changed and if so publish the DeliveryinformationChanged event. 

#2 We already use JSON to serialize the events but indeed it could interesting to use mappers.

Alex

Ben Kloosterman

unread,
Apr 21, 2015, 7:51:51 PM4/21/15
to ddd...@googlegroups.com
We have the same issue without event sourcing for messages /data from other nodes in the system  , which we cant upgrade and are on older schemas..  Storing your data the same way can often make it easier..

Also worth noting that in most cases its safe to add fields but just like an interface its breaking when you rename or remove. Xml can be more powerful here using default values.

Ben
Reply all
Reply to author
Forward
0 new messages