What is an observable collection and how it is different than a enumerable collection?
An observable collection implements the famous "Observer" design pattern. It is one of the design patterns that are listed in the famous book of the GOF.
The basic idea is as follows - if several objects has some dependency on the same object, such that when some interesting things happen inside that object, all those dependent objects should be notified about the event immediately, then this pattern is used. Here we call the dependent objects as the "Observer", and the objects onto which they all are depending as "Subject". When some event happens inside the subject, it is the responsibility of the subject to notify all the observers about this event. To facilitate this sort of message passing, all the observers has to subscribe to the subject when they are created. Details can be found here.
Related
When building an event store, the typical approach is to serialize the event and then persist the type of the event, the body of the event (the serialized event itself), an identifier and the time it occurred.
When it comes to the event type, are there any best practises as to how these should be stored and referenced? Examples I see store the fully qualified path of the class ie.
com.company.project.package.XXXXEvent
What effort is then required though if you decide to refactor your project structure?
After years running event-sourced applications in production, we avoid using fully qualified class names or any other platform-specific identifiers for event types.
An event type is just a string that should allow any kind of reader to understand how the event should be deserialized. You are also absolutely right about the issue with refactoring the application structure that might lead to changes in the class name.
Therefore, we use a pre-configured map that allows resolving the object type to a string and to reverse the string to an event type. By doing so, we detach the event type meta from the actual class and get the freedom to read and write events using different languages and stacks, also being able to freely move classes around of needed.
What effort is then required though if you decide to refactor your project structure?
Not a lot of effort, but some discipline.
Events are messages, and long term viability of messages depend on having a schema, where the schema is deliberately designed to support forward and backward compatibility.
So something like "event type" would be a field name that can be any of an open set of identifiers which would each have an official spelling and semantics.
The spelling conventions that you use don't matter - you can use something that looks like a name in a hierarchical namespace, or you can use a URI, or even just a number like a surrogate key.
The identifiers, whatever convention you use, are coupled to the specification -- not to the class hierarchy that implements them.
In other words, there's no particular reason that org.example.events.Stopped necessarily implies the existence of a type org.example.events.Stopped.
Your "factories" are supposed to create instances of the correct classes/data structures from the messages, and while the naive mapping from schema identifier to class identifier works, then yes, they can take that shortcut. But when you decide to refactor your packages, you have to change the implementation of the factory such that the old identifiers from the message schema map to the new class implementations.
In other words, using something like Class.forName is a shortcut, which you abandon in favor of doing the translation explicitly when the short cut no longer works.
Since event sourcing is about storing Domain Events, we prefer to avoid package-names or other technical properties in the events. Especially when it comes to naming them, since the name should be part of ubiquitous language. Domain Experts and other people don't lean on package names when making conversation about the domain. Package names are a language construct that also ties the storage of the Domain Events with the use of them within your software, which is another reason to avoid this solution.
We sometimes use the short class name (such as Class.forName in Java) to make mapping to code simpler and more automatic, but the class names should in that case be carefully chosen to match the ubiquitous language so that it still is not too implementation-specific.
Additionally, adding a prefix opens upp the possibility to have multiple Event Types with the same name but using different prefixes. Domain Events are part of the context of the Aggregate they are emitted from and therefore the Aggregate type can be useful to embed in the event. It will scope your events so you don't have to make up synthetic prefixes.
If you store events from multiple bounded contexts in one store, BoundedContext.EventThatHappened. Past tense for events, and event names are unique for a bounded context. As your events will change implementation, there is no direct connection to a class name.
Following the Vaughn Vernon recommendation, to achieve a high level of decoupling and single responsibility, just one aggregate should be changed per transaction.
In the chapter 8 of the Red Book Vaughn Vernon demonstrated how two aggregates can "talk" to each other with domain events. In the chapter 13 how different aggregates in two different bounded context can "talk" to each other with notifications.
My question is, why should I deal with these situations differently once both of them happen in different transaction? If is it just one or multiple bounded contexts the possible problems wouldn't be the same?
For example, if the application crashes between two domain events in the same bounded context I'll end up with inconsistency as with two bounded contexts.
It seems that the safest way to deal with two aggregates "talking" to each other asynchronously is to have a transitional status in it, persist the events before send them (to avoid lose events), have idempotent operations when possible and deduplicate the event in the receiving side when it's not possible to execute the operation in an idempotent way.
I see two aspects to consider in your question:
The DDD aspect: Event types and what you do with them
A technical aspect: how to implement it reliably
Regarding the types of Events what I would say is that events that stay within the boundaries of a bounded context (often called Domain Events) normally carry a lot of information. Potentially a big part of the state of the Aggregate. If you use CQRS, they are used to create the Read Model. Events that cross the BC boundaries are sometimes called Integration Events and they should carry as little data as possible (potentially, only global IDs, like CustomerId, OrderId). The reason is that every extra property that you add is extra coupling between the publisher BC and the subscriber BCs, which is what you want to minimize.
I would say that it's this distinction between the types of Events which might lead to have different technical solutions, but I agree with you that it doesn't have to be this way if you find a solution that works well for both cases.
The solution you propose is correct. It looks very similar to the Outbox feature of NServiceBus, which basically takes care of all this for you.
Another approach that I've used, if your message broker supports it, is what Azure Service Bus calls Send Via. With this feature, you can publish events Via your own queue but the send will be committed transactionally with the removal of the incoming message from the queue. This means that if for some reason the message that you are processing is not deleted from the queue successfully (DB update exception, broker unavailable, etc) and therefore it will be retried, you know for sure that the events won't be sent and you can safely publish them again during the retry. This makes making idempotent operations simpler and avoids publishing ghost messages.
I'm trying to ensure an aggregate field is unique on creation. I'm trying to handle the eventually consistency of the projections by using the following flow:
Command creates a new aggregate
Aggregate issues creation event
Event handler attempts to materialize the projection and if there is a uniqueness violation, it emits a UniqueConstraintViolationEvent
Aggregate consumes this event and marks itself as deleted
I'm trying to use the AggregateTestFixture to test this, but it doesn't appear to allow you to preform any assertions without issuing a command (whenThenTimeElapses seems to allow assertions, but I get a NPE when asserting the aggregate has been deleted). Is there a way to use the test fixture for this case, or is it not designed to account for non-aggregate events. If not, is there another way to verify that the aggregate has been removed?
I'm not confident that this is actually the correct approach. I've also considered dispatching a command in (3) or using a saga to manage the interaction. If I dispatch a command instead of an event, it seems to simply force me to write more boilerplate to emit the UniqueConstraintViolationEvent from the aggregate. Likewise, if I use a saga to model this interaction, I'm unsure how to end the saga's lifecycle without having the projection materializer emit a success event that the saga consumes.
You are looking at a Set Based Validation scenario, which is a little more cumbersome when dealing with a CQRS system. This blog explains some of your options nicely I feel, thus I'd pick and choose from there.
As a form of guideline, note that the Aggregate guards it's own consistency boundary. Extending that boundary by asserting uniqueness among an entire set of Aggregate is thus not desirable. Simply put, not a single Aggregate instance's problem.
Hence, I would perform this uniqueness check prior to issuing the command, by consulting a lightweight query model containing the desired constraint.
I came across that Event Sourcing assumes total encapsulation. Aggregates dosen`t allow to access their internal state. State is internaly kept only to impose valid transions. As far as I grasp this aggregates (in terms of outside world) just emits events. And I cant get my head around that actualy. I refine my models to reflect my bussiness needs which leads to objects that publish some API. For example, I have two aggregate roots: cart and order. I would like to build my order using ActiveItems from cart:
$order->addItems($cart->getActvieItems)
But this violates ES assumtion about total encapsulation of aggregate state. How order should be fulfilled with ActiveItmes according to ES good practices? Should I use read model? I think this leads to knowleadge leak out of the model (aggregate). Thank you in advance!
Alexey is right in that the Event Sourcing is just a persistence mechanism. I think the confusion comes when thinking about Aggregates. Encapsulation is an important concept when thinking about Aggregates. The implication here is that they are not used for query or the UI. Hence the reason CQRS fits in so well.
But most applications need to query the data or display things on the UI. And that's where Read Models come in handy. Assuming you are using CQRS and Event Sourcing (which you don't have to when using Aggregates) it's a fairly easy thing to do. The idea is to subscribe to the events and update the Read Model as you go. This doesn't 'leak' anything because the functionality is in the Aggregate domain objects.
Why is this a good thing?
Have no or extremely limited dependencies makes the aggregate's much simpler to work with.
Read models can be highly optimised for reading from and therefore very fast.
Read models don't require complex queries and joins.
There is a clear separation of concerns
This approach offers huge scaling potential
It's easy to test
I'm sure there are more. If it helps I have a blog post outlining a typical CQRS and ES architecture. You may find it helpful. You can find it here: CQRS + Event Sourcing – A Step by Step Overview
Event Sourcing does not assume anything in addition to the fact that you save the state of your object as series of events. There is even no requirements to have an "aggregate" when doing Event Sourcing.
If you are talking about the DDD terms Aggregate and Aggregate Root, again, Event Sourcing is just a way to save the object as a stream of events instead of the last actual state. There are no additionally imposed "requirements" like "total encapsulation" and inaccessibility of the internal state. Of course aggregates (and other objects) have state.
What could be confusing is that if you also use CQRS, you can have your aggregate state not being used since all its data is transient to the read model. But this is something else and does not need to be blindly applied.
Again, Event Sourcing is just a persistence method, nothing more, and nothing less.
$order->addItems($cart->getActvieItems)
In addition to the comprehensive coverage of CQRS in the answers, I'd like to point out that in the message driven systems commands(messages) should be self-contained and have all information encapsulated necessary to perform the action.
In the above example, Order aggregate receives command AddItems with the list of Items Ids as a payload. The fact that AddItems command handler needs to get additional information to handle the command points to a problem. AddItems command has no sufficient payload so Cart and Order are semantically coupled. You would want to avoid that.
Message passing reasoning is the key here. Here are some abstractions
class AddItems : Command
{
List ItemIds {get; set;}
}
class Order
{
void AddItems(AddItems command){}
}
I have two objects. A Meeting object and an Action object (action raised in a meeting). An Action can also exist independent of a Meeting. I have two ways of linking the Action raised to the Meeting:
have a method on Meeting where I
pass in the Action object such as
"addToMeeting(Action action)".
WIthin the internals of Meeting
I then link the action to the
meeting. For this approach though the
Meeting object needs to know about
and use the methods on the Action
object so becomes coupled.
have a method on Meeting where I just pass
the action number to be linked such
as "addToMeeting(int actionID)".
Great now Meeting object does not
need to know anything about Action
but......now the code adding the
action to the meeting needs to know
how to get the action ID so has
turned from this
"meeting.addToMeeting(action)" to
this
"meeting.addToMeeting(action.getID())".
For good OO design, which approach should be used? Or is there a third way....
If the only think you ever plan on linking to Meeting instances are actions, then it would seem most appropriate to make Meeting aware of Action, rather than the other way around.
Having the Actions class manipulate the internals of Meeting breaks encapsulation and generally makes it harder to maintain such code. So, I would expose a method addAction(Action a) on Meeting in this case.
However, if there are other things that can be linked to a meeting, you may want to consider abstracting the concept of "meeting items".
Rather than have Meeting know about Action, or vice verse, you could define an interface such as IMeetingItem which exposes the necessary information that Meeting would need to link to such items. Action would then implement IMeetingItem, making it possible to do something like:
meeting.addItem( action ); // action treated as an IMeetingItem in this context
Note that in both approaches, it is the Meeting class that mediates the functionality of adding an item to itself, rather than having the item being added manipulate the internal representation of a meeting.
I would suggest that you create an interface "Identifiable" with the method getID() on it which is implemented by Action
Then you can do the following:
addToMeeting(Identifiable action);
and inside the method do
this.actionId = action.getID();
As long as meetings are associated with actions in any way, you'll have some coupling. However, you might consider a third approach, to build an "action factory" that generates action objects. ID would be a property on the Action object, once it's created (and maybe saved). All that meeting would do is tell the factory to generate an action, and be able to access the action's ID property.
I would go with option #1 -- coupling is not a bad thing, in your case, since there is a clear relation between objects. I would go with option #1. This gives you the option for a meeting to have a property of MeetingActions[] or something similar.