Loading ...
Sorry, an error occurred while loading the content.
 

Re: [domaindrivendesign] Re: Event Sourcing and CQRS

Expand Messages
  • Greg Young
    I prefer using convention than either of these methods. Why map when you don t have to? Cheers, Greg ... -- Les erreurs de grammaire et de syntaxe ont été
    Message 1 of 59 , Nov 2, 2009
      I prefer using convention than either of these methods. Why map when you don't have to?

      Cheers,

      Greg

      On Mon, Nov 2, 2009 at 10:30 PM, Jérémie <Jeremie.Chassaing@...> wrote:
       

      I tried with delegates. It worked, but I found the name Apply(event, e => Apply(e)) not really convincing...
      Perhaps just Play(event, e => Apply(e)) since the other method is called Replay ?
      Or in the current Fluent fashion :
      Play(event).With(Apply) ?



      jeremie / thinkbeforecoding

      --- In domaindrivendesign@yahoogroups.com, Mark Nijhof <Mark.Nijhof@...> wrote:
      >
      > I think that in my example I got rid of the reflection by providing a action
      > delegate (forgot the name of the person suggesting that). Btw if you have an
      > event that has no corresponding overload then you have an exception being
      > thrown, so then you need an overload even if the AR isn't doing anything
      > with the event. I am not sure there are cases that you don't want to call
      > apply on an event, there might be cases that nothing happens, this way you
      > ensure that you cannot forget calling apply on an event where it was needed.
      >
      > Just checked and yes it is checked-in:
      > http://github.com/MarkNijhof/Fohjin/blob/master/Fohjin.DDD/Fohjin.DDD.Domain/BaseAggregateRoot.cs
      >
      > Sure using email is probably bad, but I didn't suggest that :) I suggested
      > using an event to notify which would then result in an e-mail being send
      > (SomethingHappened and a event handler that will send the email using a
      > service). I was only reacting to the if statement, which you probably have
      > in two places now, which looks like domain logic.
      >
      > -Mark
      >
      >
      >
      > On Mon, Nov 2, 2009 at 6:07 PM, Jérémie <Jeremie.Chassaing@...>wrote:

      >
      > >
      > >
      > > Yes, here, using dynamic, the dispatch must be made from the class itself,
      > > because the base class cannot access child class members.
      > > This is a choice to avoid code loaded with reflection and such low level
      > > stuff.
      > >
      > > If you use refelection, you have more code, but you can bypass private, so
      > > you can provide a Replay method in the AggregateRoot class that will
      > > dispatch events, and do the same kind of things with Append that will also
      > > dispatch the event to the correct Apply method.
      > >
      > > The problem with this approach is that Apply methods are then always called
      > > by reflection and Resharper will report them as Not Used.
      > > It makes the code a bit less compile time checked, since you won't notice I
      > > an Apply method is never called, or if you try to Apply and Append an event
      > > that has no corresponding implementation.
      > >
      > > The remark on the BookReturned / BookReturnedTooLate notification is then a
      > > matter of chosing how you want to split you events, depending on you
      > > language and use cases. Your proposition it totaly valid. Still I would not
      > > use the word Email in the event name because the email could be easily
      > > replaced with a SMS or a tweet.
      > >
      > >
      > > jeremie / thinkbeforecoding
      > >
      > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>,
      > > Mark Nijhof <Mark.Nijhof@> wrote:
      > > >
      > > > Hi a few quick notes after a quick look:
      > > >
      > > > There could be more logic with respect to storing and applying events in
      > > the
      > > > base class, also I saw that you would append and apply manually why not
      > > just
      > > > do append which would apply as well so you can do just apply or do
      > > append.
      > > >
      > > > I don't really like the overloads for apply aldo I do understand why you
      > > did
      > > > it this way I think it makes it less readable, but that is personal taste
      > > I
      > > > guess. Also keep in mind that not all events need to be doing something
      > > in
      > > > the domain AR it self, some are only used to notify something outside of
      > > the
      > > > domain. I would use an event to f.ex. notify that an e-mail should be
      > > send
      > > > as well.
      > > >
      > > > private void Apply(BookRegistered @event)
      > > >
      > > > {
      > > >
      > > > title = @...;
      > > >
      > > > isbn = @...;
      > > >
      > > > }
      > > >
      > > >
      > > >
      > > > private void Apply(BookLent @event)
      > > >
      > > > {
      > > >
      > > > borrower = @...;
      > > >
      > > > date = @...;
      > > >
      > > > expectedDuration = @...;
      > > >
      > > > }
      > > >
      > > >
      > > >
      > > > private void Apply(BookReturned @event)
      > > >
      > > > {
      > > >
      > > > borrower = null;
      > > >
      > > > }
      > > >
      > > >
      > > > This here, the decision has already been made that the book was late in
      > > the
      > > > domain, so why not be explicite about that and have a BookReturnedLate
      > > event
      > > > and a BookReturned event with different event handlers.
      > > >
      > > > class LateReturnNotifier :
      > > >
      > > > Handles<BookReturned>
      > > >
      > > > {
      > > >
      > > > public void Handle(BookReturned @event)
      > > >
      > > > {
      > > >
      > > > if (@...)
      > > >
      > > > {
      > > >
      > > > Console.WriteLine("{0} was late", @...);
      > > >
      > > > }
      > > >
      > > > }
      > > >
      > > > }
      > > >
      > > > -Mark
      > > >
      > > >
      > > > On Mon, Nov 2, 2009 at 3:53 PM, Jérémie <Jeremie.Chassaing@>wrote:
      > >
      > > >
      > > > >
      > > > >
      > > > > The second part of the series :
      > > > >
      > > > >
      > > http://thinkbeforecoding.com/post/2009/11/02/Event-Sourcing-and-CQRS-Lets-use-it
      > > > >
      > > > > here, we use use EventSourcing and CQRS to build a (very very basic)
      > > > > personal library management.
      > > > >
      > > > > Let me know your opinion/objections.
      > > > >
      > > > > Cheers
      > > > >
      > > > > jeremie / thinkbeforecoding
      > > > >
      > > > >
      > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
      > > <domaindrivendesign%40yahoogroups.com>,
      > >
      > > > > Jérémie <Jeremie.Chassaing@> wrote:
      > > > > >
      > > > > > I've not seen your code yet (but I will !),
      > > > > > and I'm following bjarte's blog, good stuff.
      > > > > >
      > > > > > Sure, there is no *need* to use dynamic, you can do all this with a
      > > bit
      > > > > of Generics and Reflection (this is what I do at work), but the code
      > > would
      > > > > have been way longer, and less explicit, especially for event dispatch
      > > (for
      > > > > replay or for event publishing on the DomainEvents class). Let's have
      > > fun
      > > > > and use new language keyword !
      > > > > >
      > > > > > I made no perf benchmarks (the goal is to make the concept clear),
      > > but
      > > > > I'm not sure that using dynamic make it slower.
      > > > > >
      > > > > > Cheers,
      > > > > >
      > > > > > jeremie / thinkbeforecoding
      > > > > >
      > > > > >
      > > > > >
      > > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
      > > <domaindrivendesign%40yahoogroups.com>,
      > >
      > > > > Mark Nijhof <Mark.Nijhof@> wrote:
      > > > > > >
      > > > > > > Hi Jeremie,
      > > > > > >
      > > > > > > Cool to see some more examples, have you seen my code on GitHub?
      > > > > > > http://github.com/MarkNijhof/Fohjin
      > > > > > > Also see Bjarte's blog on this: http://bjarte.com/
      > > > > > >
      > > > > > > Not 100% sure about the need to use the dynamic keyword, will take
      > > a
      > > > > closer
      > > > > > > look at that.
      > > > > > >
      > > > > > > -Mark
      > > > > > >
      > > > > > >
      > > > > > >
      > > > > > > On Fri, Oct 30, 2009 at 4:08 PM, Jérémie <Jeremie.Chassaing@
      > > >wrote:
      > > > > > >
      > > > > > > >
      > > > > > > >
      > > > > > > > Since everybody want to see code for Event Sourcing and CQRS...
      > > > > > > >
      > > > > > > >
      > > > >
      > > http://thinkbeforecoding.com/post/2009/10/30/Event-Sourcing-and-CQRS-Now
      > > > > > > >
      > > > > > > > This is a very simplistic implementation for in memory,
      > > synchronous
      > > > > Event
      > > > > > > > Sourcing and CQRS, but I'll then show how you can implement
      > > events
      > > > > > > > persistence, use asynchronous messaging and the rest.
      > > > > > > >
      > > > > > > > Starting with a basic model with no external dependencies enables
      > > to
      > > > > grasp
      > > > > > > > the concept and go straight to the core.
      > > > > > > >
      > > > > > > > Feel free to give your opinion,
      > > > > > > >
      > > > > > > > jeremie / thinkbeforecoding
      > > > > > > >
      > > > > > > >
      > > > > > > >
      > > > > > >
      > > > > >
      > > > >
      > > > >
      > > > >
      > > >
      > >
      > >
      > >
      >




      --
      Les erreurs de grammaire et de syntaxe ont été incluses pour m'assurer de votre attention
    • Jérémie
      Actualy I will store a new schema per event version. So each event/version will have it s own id. This way a event data will reference the version of the event
      Message 59 of 59 , Nov 6, 2009
        Actualy I will store a new schema per event version.
        So each event/version will have it's own id. This way a event data will reference the version of the event that was used to serialize it. There is currently no way to find all versions for an event.

        It could be possible to add this information (to find all versions for a given event), and even propose rules to upgrade events from one version to the next... but I didn't thought about it yet, and it's not required for now.

        [it seems that we all agree but communication is a bit messy :-) ]


        jeremie / thinkbeforecoding







        --- In domaindrivendesign@yahoogroups.com, Mark Nijhof <Mark.Nijhof@...> wrote:
        >
        > The schema will contain all historical versions I assume? So how do you map
        > the type in the schema with what is in the event store (I believe I remember
        > you said you had a list with types each having their own Id) So would this
        > information be in the xsd as well?
        >
        > -Mark
        >
        > On Thu, Nov 5, 2009 at 3:43 PM, Greg Young <gregoryyoung1@...> wrote:
        >
        > >
        > >
        > > That will only work when everyone is .NET (not common in most organizations
        > > I have worked with).
        > >
        > > I generally share a schema (say xsd) where everyone can generate their own
        > > messages from it (and I generate my assembly from the schema).
        > >
        > > That said, if you are completely .NET then sharing the assembly may not be
        > > too big of a deal.
        > >
        > > Greg
        > >
        > > On Thu, Nov 5, 2009 at 4:33 PM, Mark Henke <gilligan128@...> wrote:
        > >
        > >>
        > >>
        > >> I see your point but I am curious on why something would want to be
        > >> looking at the events and not have access to the messages assembly (or
        > >> whatever schema contract you have) that contains the events.
        > >> I see the Messages assembly as the contract to the outside world. If
        > >> anything wants to communicate with the service then they need a version of
        > >> that assembly so they know the rules.
        > >>
        > >>
        > >> On Thu, Nov 5, 2009 at 9:13 AM, Jérémie <Jeremie.Chassaing@...>wrote:
        > >>
        > >>>
        > >>>
        > >>> You still have the separator, and you can read the data only if you know
        > >>> the event. So you need external knowledge.
        > >>> Not good if you want to make a framework.
        > >>>
        > >>>
        > >>> jeremie / thinkbeforecoding
        > >>>
        > >>> --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>,
        > >>> Mark Nijhof <Mark.Nijhof@> wrote:
        > >>> >
        > >>> > true, but I was thinking that you don't need the schema for each event
        > >>> if
        > >>> > your serialization process is going to be the same for everything.
        > >>> Meaning
        > >>> > once you have used an event you should not change the order of the
        > >>> > properties, then using a separator then you don't need to know the
        > >>> length
        > >>> > for each field and you don't need the schema. You just need to know
        > >>> which
        > >>> > type the actual event is. And of course it is stored as bytes as you
        > >>> pointed
        > >>> > out already.
        > >>> >
        > >>> > -Mark
        > >>> >
        > >>> >
        > >>> > On Thu, Nov 5, 2009 at 2:52 PM, Jérémie <Jeremie.Chassaing@
        > >>> ...>wrote:
        > >>>
        > >>> >
        > >>> > >
        > >>> > >
        > >>> > > Yes I simply have a table to store schemaId/schema.
        > >>> > >
        > >>> > > in the schema you'll have :
        > >>> > >
        > >>> > > MyNamespace.MyCustomEvent
        > >>> > > {
        > >>> > > Name : String,
        > >>> > > NumberOfItems : Int32,
        > >>> > > Price : Decimal
        > >>> > > }
        > >>> > >
        > >>> > > (actually its xml, but you can use any format of this kind : Xml,
        > >>> Json, M..
        > >>> > > or your own)
        > >>> > >
        > >>> > > I also have ways to indicates nullable or lists
        > >>> > > like :
        > >>> > > Phones : String*
        > >>> > > or
        > >>> > > Age : Int?
        > >>> > >
        > >>> > > Then the data can be serialized as pure binary (here a show a
        > >>> readable
        > >>> > > version):
        > >>> > > 6MyName43.14
        > >>> > > the deserializer expects a string, it starts with a compact int for
        > >>> length
        > >>> > > (if the size is > 128 it will be on 2 bytes, if > 32xxx 3 bytes etc)
        > >>> > > then read the 6 chars,
        > >>> > > then expect an int : 4 (compact again)
        > >>> > > the a decimal 3.14 (on 8bytes)
        > >>> > >
        > >>> > > The cool thing is that you can build a tool that will show you event
        > >>> data
        > >>> > > without any external knowledge.
        > >>> > >
        > >>> > > jeremie / thinkbeforecoding
        > >>> > >
        > >>> > >
        > >>> > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
        > >>> <domaindrivendesign%40yahoogroups.com>,
        > >>>
        > >>> > > Mark Nijhof <Mark.Nijhof@> wrote:
        > >>> > > >
        > >>> > > > Interesting indeed, Greg used something similar where types where
        > >>> > > > represented by numbers that where specified with the serializer /
        > >>> > > > deserializer then the data was stored in the order of the
        > >>> properties.
        > >>> > > Your
        > >>> > > > events would probably only contain base types anyway.
        > >>> > > >
        > >>> > > > 1 = MyCustomEvent
        > >>> > > > 2 = MyOtherCustomEvent
        > >>> > > >
        > >>> > > > So you could have
        > >>> > > > 1;string;123;123.45
        > >>> > > >
        > >>> > > > for
        > >>> > > >
        > >>> > > > public class MyCustomEvent
        > >>> > > > {
        > >>> > > > public string Name {get; set;}
        > >>> > > > public int NumberOfItem {get; set;}
        > >>> > > > public decimal Price {get; set;}
        > >>> > > > }
        > >>> > > >
        > >>> > > > -Mark
        > >>> > > >
        > >>> > > >
        > >>> > > > On Thu, Nov 5, 2009 at 2:09 PM, Jérémie <Jeremie.Chassaing@
        > >>> >wrote:
        > >>> > >
        > >>> > > >
        > >>> > > > >
        > >>> > > > >
        > >>> > > > > 4th part of the series :
        > >>> > > > >
        > >>> > > > >
        > >>> > >
        > >>> http://thinkbeforecoding.com/post/2009/11/05/Event-Sourcing-and-CQRS-Serialization
        > >>> > > > >
        > >>> > > > > An exploration on storage options, and a way to reduce
        > >>> efficiently
        > >>> > > storage
        > >>> > > > > size.
        > >>> > > > >
        > >>> > > > > I still want to ear your remarks, positive or negative !
        > >>> > > > >
        > >>> > > > >
        > >>> > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
        > >>> <domaindrivendesign%40yahoogroups.com>
        > >>> > > <domaindrivendesign%40yahoogroups.com>,
        > >>> > >
        > >>> > > > > Jérémie <Jeremie.Chassaing@> wrote:
        > >>> > > > > >
        > >>> > > > > > Added a 3rd installement to the Event Sourcing and CQRS series
        > >>> :
        > >>> > > > > >
        > >>> > > > >
        > >>> > >
        > >>> http://thinkbeforecoding.com/post/2009/11/03/Event-Sourcing-and-CQRS-Dispatch-options
        > >>> > > > > >
        > >>> > > > > > I propose implementations for the various dispatch options
        > >>> discussed
        > >>> > > here
        > >>> > > > > or on tweeter, with pros and cons.
        > >>> > > > > >
        > >>> > > > > >
        > >>> > > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
        > >>> <domaindrivendesign%40yahoogroups.com>
        > >>> > > <domaindrivendesign%40yahoogroups.com>,
        > >>> > >
        > >>> > > > > Jérémie <Jeremie.Chassaing@> wrote:
        > >>> > > > > > >
        > >>> > > > > > > It's the best way to know.
        > >>> > > > > > > That's why I published the sample.
        > >>> > > > > > >
        > >>> > > > > > > Understand 'question aggressively' on code, not on people who
        > >>> wrote
        > >>> > > it,
        > >>> > > > > of course.
        > >>> > > > > > >
        > >>> > > > > > > jeremie / thinkbeforecoding
        > >>> > > > > > >
        > >>> > > > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
        > >>> <domaindrivendesign%40yahoogroups.com>
        > >>> > > <domaindrivendesign%40yahoogroups.com>,
        > >>> > >
        > >>> > > > > Nuno Lopes <nbplopes@> wrote:
        > >>> > > > > > > >
        > >>> > > > > > > > It sounds that I'm arguing for the sake of arguing. So its
        > >>> time
        > >>> > > for
        > >>> > > > > me
        > >>> > > > > > > > to step back and provide an alternative (philosophical or
        > >>> not) to
        > >>> > > the
        > >>> > > > >
        > >>> > > > > > > > state change event design philosophy. Hopefully you guys
        > >>> will
        > >>> > > > > > > > understand what I'm talking about and question me
        > >>> aggressively as
        > >>> > > I
        > >>> > > > > do
        > >>> > > > > > > > to yours. That is the only way I know how to validate if
        > >>> > > something is
        > >>> > > > >
        > >>> > > > > > > > good for me, is to question it.
        > >>> > > > > > > >
        > >>> > > > > > > > Talk to you soon.
        > >>> > > > > > > >
        > >>> > > > > > > > Nuno
        > >>> > > > > > > >
        > >>> > > > > > >
        > >>> > > > > >
        > >>> > > > >
        > >>> > > > >
        > >>> > > > >
        > >>> > > >
        > >>> > >
        > >>> > >
        > >>> > >
        > >>> >
        > >>>
        > >>>
        > >>
        > >
        > >
        > > --
        > > Les erreurs de grammaire et de syntaxe ont été incluses pour m'assurer de
        > > votre attention
        > >
        > >
        >
      Your message has been successfully submitted and would be delivered to recipients shortly.