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

CQRS à la Greg Example

Expand Messages
  • Mark Nijhof
    Hi, Since multiple people have been asking for this and I feel that the core is good enough to share I thought I would share the repository here already.
    Message 1 of 30 , Oct 26, 2009
      Hi,

      Since multiple people have been asking for this and I feel that the
      core is good enough to share I thought I would share the repository
      here already. Disclaimer: Now keep in mind that this has not been
      reviewed by Greg yet and that I am still working on it. I am also
      working on a complete detailed blog post (or several) to explain what
      is going on and why (with diagrams and all that fancy stuff). Once
      that is done it will be published here: http://blog.fohjin.com/ I am
      currently finishing my specifications for the GUI and will split the
      existing domain specifications a bit more per scenario, but I think
      you will like what you see there (hope at least).

      The most interesting scenario is a transfer from one account to an
      other account.

      Link: http://github.com/MarkNijhof/Fohjin

      Note on SQLite: Because I am developing on x64 I have the x64 version
      of SQLite referenced in the projects, except for the test project
      because TestDriven.Net executes everything in x86. Now if you are
      running on a x86 machine all you have to do is copy the x86
      System.Data.SQLite.* from /lib/sqlite/bin to /lib/sqlite/bin/x64 (this
      approach is tested). There are two different SQLite databases, one is
      the event store and the other is the reporting database. I haven't
      figured out yet how, but it is possible to load the SQLite databases
      in Visual Studio to inspect the content. Both databases are created on
      first use, and deleting them will give you a fresh start.

      I would like to hear your opinions, I am very enthusiastic about this
      architecture when there is a need for a domain.

      -Mark
    • Gustavo Melo
      Hello Mark, Nice to see some action about this ! What version of VS was build this application? VS2010? ... -- [] s Gustavo Melo
      Message 2 of 30 , Oct 26, 2009
        Hello Mark,

        Nice to see some action about this !

        What version of VS was build this application? VS2010?

        On Mon, Oct 26, 2009 at 12:32 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
         

        Hi,

        Since multiple people have been asking for this and I feel that the
        core is good enough to share I thought I would share the repository
        here already. Disclaimer: Now keep in mind that this has not been
        reviewed by Greg yet and that I am still working on it. I am also
        working on a complete detailed blog post (or several) to explain what
        is going on and why (with diagrams and all that fancy stuff). Once
        that is done it will be published here: http://blog.fohjin.com/ I am
        currently finishing my specifications for the GUI and will split the
        existing domain specifications a bit more per scenario, but I think
        you will like what you see there (hope at least).

        The most interesting scenario is a transfer from one account to an
        other account.

        Link: http://github.com/MarkNijhof/Fohjin

        Note on SQLite: Because I am developing on x64 I have the x64 version
        of SQLite referenced in the projects, except for the test project
        because TestDriven.Net executes everything in x86. Now if you are
        running on a x86 machine all you have to do is copy the x86
        System.Data.SQLite.* from /lib/sqlite/bin to /lib/sqlite/bin/x64 (this
        approach is tested). There are two different SQLite databases, one is
        the event store and the other is the reporting database. I haven't
        figured out yet how, but it is possible to load the SQLite databases
        in Visual Studio to inspect the content. Both databases are created on
        first use, and deleting them will give you a fresh start.

        I would like to hear your opinions, I am very enthusiastic about this
        architecture when there is a need for a domain.

        -Mark




        --
        []'s
        Gustavo Melo
      • James Crowley
        Opened fine for me in VS2008 ... Thanks Mark! James 2009/10/26 Gustavo Melo ... -- James Crowley Managing Director Developer Fusion -
        Message 3 of 30 , Oct 26, 2009
          Opened fine for me in VS2008 ... Thanks Mark!

          James

          2009/10/26 Gustavo Melo <pipocadr@...>
           

          Hello Mark,

          Nice to see some action about this !

          What version of VS was build this application? VS2010?



          On Mon, Oct 26, 2009 at 12:32 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
           

          Hi,

          Since multiple people have been asking for this and I feel that the
          core is good enough to share I thought I would share the repository
          here already. Disclaimer: Now keep in mind that this has not been
          reviewed by Greg yet and that I am still working on it. I am also
          working on a complete detailed blog post (or several) to explain what
          is going on and why (with diagrams and all that fancy stuff). Once
          that is done it will be published here: http://blog.fohjin.com/ I am
          currently finishing my specifications for the GUI and will split the
          existing domain specifications a bit more per scenario, but I think
          you will like what you see there (hope at least).

          The most interesting scenario is a transfer from one account to an
          other account.

          Link: http://github.com/MarkNijhof/Fohjin

          Note on SQLite: Because I am developing on x64 I have the x64 version
          of SQLite referenced in the projects, except for the test project
          because TestDriven.Net executes everything in x86. Now if you are
          running on a x86 machine all you have to do is copy the x86
          System.Data.SQLite.* from /lib/sqlite/bin to /lib/sqlite/bin/x64 (this
          approach is tested). There are two different SQLite databases, one is
          the event store and the other is the reporting database. I haven't
          figured out yet how, but it is possible to load the SQLite databases
          in Visual Studio to inspect the content. Both databases are created on
          first use, and deleting them will give you a fresh start.

          I would like to hear your opinions, I am very enthusiastic about this
          architecture when there is a need for a domain.

          -Mark




          --
          []'s
          Gustavo Melo




          --
          James Crowley
          Managing Director
          Developer Fusion - Connecting developers worldwide

          Developer Fusion Ltd | 58 Sandringham Close | Enfield, EN1 3JH
          mob: 07986 624128 web: http://www.developerfusion.com/
        • Mark Nijhof
          Version is 2008, I will at some point to go 2010 to try how that goes, but I ll wait untill R# works there :) also this is only changing version 11 back to 10
          Message 4 of 30 , Oct 26, 2009
            Version is 2008, I will at some point to go 2010 to try how that goes, but I'll wait untill R# works there :) also this is only changing version 11 back to 10 in the solution file.

            -Mark


            On Mon, Oct 26, 2009 at 6:03 PM, James Crowley <james.crowley@...> wrote:
             

            Opened fine for me in VS2008 ... Thanks Mark!


            James

            2009/10/26 Gustavo Melo <pipocadr@...>

             

            Hello Mark,

            Nice to see some action about this !

            What version of VS was build this application? VS2010?



            On Mon, Oct 26, 2009 at 12:32 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
             

            Hi,

            Since multiple people have been asking for this and I feel that the
            core is good enough to share I thought I would share the repository
            here already. Disclaimer: Now keep in mind that this has not been
            reviewed by Greg yet and that I am still working on it. I am also
            working on a complete detailed blog post (or several) to explain what
            is going on and why (with diagrams and all that fancy stuff). Once
            that is done it will be published here: http://blog.fohjin.com/ I am
            currently finishing my specifications for the GUI and will split the
            existing domain specifications a bit more per scenario, but I think
            you will like what you see there (hope at least).

            The most interesting scenario is a transfer from one account to an
            other account.

            Link: http://github.com/MarkNijhof/Fohjin

            Note on SQLite: Because I am developing on x64 I have the x64 version
            of SQLite referenced in the projects, except for the test project
            because TestDriven.Net executes everything in x86. Now if you are
            running on a x86 machine all you have to do is copy the x86
            System.Data.SQLite.* from /lib/sqlite/bin to /lib/sqlite/bin/x64 (this
            approach is tested). There are two different SQLite databases, one is
            the event store and the other is the reporting database. I haven't
            figured out yet how, but it is possible to load the SQLite databases
            in Visual Studio to inspect the content. Both databases are created on
            first use, and deleting them will give you a fresh start.

            I would like to hear your opinions, I am very enthusiastic about this
            architecture when there is a need for a domain.

            -Mark




            --
            []'s
            Gustavo Melo




            --
            James Crowley
            Managing Director
            Developer Fusion - Connecting developers worldwide

            Developer Fusion Ltd | 58 Sandringham Close | Enfield, EN1 3JH
            mob: 07986 624128 web: http://www.developerfusion.com/

          • James Crowley
            hey Mark, I m curious particularly around your decision to use the reporting layer in order to manage money transfers between accounts: private void
            Message 5 of 30 , Oct 26, 2009
              hey Mark,

              I'm curious particularly around your decision to use the reporting layer in order to manage money transfers between accounts:

                      private void MoneyTransferIsGoingToAnInternalAccount(MoneyTransfer moneyTransfer)
                      {
                          var account = _reportingRepository.GetByExample<AccountReport>(new { AccountNumber = moneyTransfer.TargetAccount }).First();
                          _commandBus.Publish(new ReceiveMoneyTransferCommand(account.Id, moneyTransfer.Ammount, moneyTransfer.SourceAccount));
                      }

              I posted a similar question to the list a few days ago with regards to fetching domain entities via a unique constraint that is not a Guid, as it didn't feel very nice to have to have to go to the eventually-consistent read layer in order to work out what the account guid is? What are your thoughts on this?

              Thanks!

              James

              2009/10/26 Mark Nijhof <Mark.Nijhof@...>
               

              Version is 2008, I will at some point to go 2010 to try how that goes, but I'll wait untill R# works there :) also this is only changing version 11 back to 10 in the solution file.

              -Mark


              On Mon, Oct 26, 2009 at 6:03 PM, James Crowley <james.crowley@...> wrote:
               

              Opened fine for me in VS2008 ... Thanks Mark!


              James

              2009/10/26 Gustavo Melo <pipocadr@...>

               

              Hello Mark,

              Nice to see some action about this !

              What version of VS was build this application? VS2010?



              On Mon, Oct 26, 2009 at 12:32 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
               

              Hi,

              Since multiple people have been asking for this and I feel that the
              core is good enough to share I thought I would share the repository
              here already. Disclaimer: Now keep in mind that this has not been
              reviewed by Greg yet and that I am still working on it. I am also
              working on a complete detailed blog post (or several) to explain what
              is going on and why (with diagrams and all that fancy stuff). Once
              that is done it will be published here: http://blog.fohjin.com/ I am
              currently finishing my specifications for the GUI and will split the
              existing domain specifications a bit more per scenario, but I think
              you will like what you see there (hope at least).

              The most interesting scenario is a transfer from one account to an
              other account.

              Link: http://github.com/MarkNijhof/Fohjin

              Note on SQLite: Because I am developing on x64 I have the x64 version
              of SQLite referenced in the projects, except for the test project
              because TestDriven.Net executes everything in x86. Now if you are
              running on a x86 machine all you have to do is copy the x86
              System.Data.SQLite.* from /lib/sqlite/bin to /lib/sqlite/bin/x64 (this
              approach is tested). There are two different SQLite databases, one is
              the event store and the other is the reporting database. I haven't
              figured out yet how, but it is possible to load the SQLite databases
              in Visual Studio to inspect the content. Both databases are created on
              first use, and deleting them will give you a fresh start.

              I would like to hear your opinions, I am very enthusiastic about this
              architecture when there is a need for a domain.

              -Mark




              --
              []'s
              Gustavo Melo




              --
              James Crowley
              Managing Director
              Developer Fusion - Connecting developers worldwide

              Developer Fusion Ltd | 58 Sandringham Close | Enfield, EN1 3JH
              mob: 07986 624128 web: http://www.developerfusion.com/




              --
              James Crowley
              Managing Director
              Developer Fusion - Connecting developers worldwide

              Developer Fusion Ltd | 58 Sandringham Close | Enfield, EN1 3JH
              mob: 07986 624128 web: http://www.developerfusion.com/
            • Mark Nijhof
              Hi James, In this example I get from an external source (in my example I am faking external as being myself as well) and the external source has no knowledge
              Message 6 of 30 , Oct 26, 2009
                Hi James,

                In this example I get from an external source (in my example I am faking external as being myself as well) and the external source has no knowledge of my AR Id's only a known account number (you could make this an AR Id as well I guess). So I have to get the Id of the AR to load from the event store, for this using the reporting database is a valid thing, because what I am really doing here is _querying_ for an account that has this account number, you could even choose to make one specific table only mapping the Id with the Account Number. The eventual consistency issue is not a very big one here I would say because these action will be dealt with very quickly, you could also create one specific queue that just deals with updating this special mapping table and not make that eventual consistent. All depends on your scenario.

                As you may have seen I am not using any queues yet, this will be added later to serve as an example, also there is no transaction spanning the event store and reporting db yet.

                Also note that I am not using the reporting layer to manage transactions between accounts. A domain event is being fired and two event handlers act on this. One to update the reporting database and one to transfer it further.

                -Mark


                On Mon, Oct 26, 2009 at 6:24 PM, James Crowley <james.crowley@...> wrote:
                 

                hey Mark,


                I'm curious particularly around your decision to use the reporting layer in order to manage money transfers between accounts:

                        private void MoneyTransferIsGoingToAnInternalAccount(MoneyTransfer moneyTransfer)
                        {
                            var account = _reportingRepository.GetByExample<AccountReport>(new { AccountNumber = moneyTransfer.TargetAccount }).First();
                            _commandBus.Publish(new ReceiveMoneyTransferCommand(account.Id, moneyTransfer.Ammount, moneyTransfer.SourceAccount));
                        }

                I posted a similar question to the list a few days ago with regards to fetching domain entities via a unique constraint that is not a Guid, as it didn't feel very nice to have to have to go to the eventually-consistent read layer in order to work out what the account guid is? What are your thoughts on this?

                Thanks!

                James

                2009/10/26 Mark Nijhof <Mark.Nijhof@...>

                 

                Version is 2008, I will at some point to go 2010 to try how that goes, but I'll wait untill R# works there :) also this is only changing version 11 back to 10 in the solution file.

                -Mark


                On Mon, Oct 26, 2009 at 6:03 PM, James Crowley <james.crowley@...> wrote:
                 

                Opened fine for me in VS2008 ... Thanks Mark!


                James

                2009/10/26 Gustavo Melo <pipocadr@...>

                 

                Hello Mark,

                Nice to see some action about this !

                What version of VS was build this application? VS2010?



                On Mon, Oct 26, 2009 at 12:32 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                 

                Hi,

                Since multiple people have been asking for this and I feel that the
                core is good enough to share I thought I would share the repository
                here already. Disclaimer: Now keep in mind that this has not been
                reviewed by Greg yet and that I am still working on it. I am also
                working on a complete detailed blog post (or several) to explain what
                is going on and why (with diagrams and all that fancy stuff). Once
                that is done it will be published here: http://blog.fohjin.com/ I am
                currently finishing my specifications for the GUI and will split the
                existing domain specifications a bit more per scenario, but I think
                you will like what you see there (hope at least).

                The most interesting scenario is a transfer from one account to an
                other account.

                Link: http://github.com/MarkNijhof/Fohjin

                Note on SQLite: Because I am developing on x64 I have the x64 version
                of SQLite referenced in the projects, except for the test project
                because TestDriven.Net executes everything in x86. Now if you are
                running on a x86 machine all you have to do is copy the x86
                System.Data.SQLite.* from /lib/sqlite/bin to /lib/sqlite/bin/x64 (this
                approach is tested). There are two different SQLite databases, one is
                the event store and the other is the reporting database. I haven't
                figured out yet how, but it is possible to load the SQLite databases
                in Visual Studio to inspect the content. Both databases are created on
                first use, and deleting them will give you a fresh start.

                I would like to hear your opinions, I am very enthusiastic about this
                architecture when there is a need for a domain.

                -Mark




                --
                []'s
                Gustavo Melo




                --
                James Crowley
                Managing Director
                Developer Fusion - Connecting developers worldwide

                Developer Fusion Ltd | 58 Sandringham Close | Enfield, EN1 3JH
                mob: 07986 624128 web: http://www.developerfusion.com/




                --
                James Crowley
                Managing Director
                Developer Fusion - Connecting developers worldwide

                Developer Fusion Ltd | 58 Sandringham Close | Enfield, EN1 3JH
                mob: 07986 624128 web: http://www.developerfusion.com/

              • Mark Nijhof
                Btw GitHub offers a download as well, so can be by-passed if needed :)
                Message 7 of 30 , Oct 26, 2009
                  Btw GitHub offers a download as well, so can be by-passed if needed :)

                  On Mon, Oct 26, 2009 at 6:38 PM, Mark Nijhof <mark.nijhof@...> wrote:
                  Hi James,

                  In this example I get from an external source (in my example I am faking external as being myself as well) and the external source has no knowledge of my AR Id's only a known account number (you could make this an AR Id as well I guess). So I have to get the Id of the AR to load from the event store, for this using the reporting database is a valid thing, because what I am really doing here is _querying_ for an account that has this account number, you could even choose to make one specific table only mapping the Id with the Account Number. The eventual consistency issue is not a very big one here I would say because these action will be dealt with very quickly, you could also create one specific queue that just deals with updating this special mapping table and not make that eventual consistent. All depends on your scenario.

                  As you may have seen I am not using any queues yet, this will be added later to serve as an example, also there is no transaction spanning the event store and reporting db yet.

                  Also note that I am not using the reporting layer to manage transactions between accounts. A domain event is being fired and two event handlers act on this. One to update the reporting database and one to transfer it further.

                  -Mark



                  On Mon, Oct 26, 2009 at 6:24 PM, James Crowley <james.crowley@...> wrote:
                   

                  hey Mark,


                  I'm curious particularly around your decision to use the reporting layer in order to manage money transfers between accounts:

                          private void MoneyTransferIsGoingToAnInternalAccount(MoneyTransfer moneyTransfer)
                          {
                              var account = _reportingRepository.GetByExample<AccountReport>(new { AccountNumber = moneyTransfer.TargetAccount }).First();
                              _commandBus.Publish(new ReceiveMoneyTransferCommand(account.Id, moneyTransfer.Ammount, moneyTransfer.SourceAccount));
                          }

                  I posted a similar question to the list a few days ago with regards to fetching domain entities via a unique constraint that is not a Guid, as it didn't feel very nice to have to have to go to the eventually-consistent read layer in order to work out what the account guid is? What are your thoughts on this?

                  Thanks!

                  James

                  2009/10/26 Mark Nijhof <Mark.Nijhof@...>

                   

                  Version is 2008, I will at some point to go 2010 to try how that goes, but I'll wait untill R# works there :) also this is only changing version 11 back to 10 in the solution file.

                  -Mark


                  On Mon, Oct 26, 2009 at 6:03 PM, James Crowley <james.crowley@...> wrote:
                   

                  Opened fine for me in VS2008 ... Thanks Mark!


                  James

                  2009/10/26 Gustavo Melo <pipocadr@...>

                   

                  Hello Mark,

                  Nice to see some action about this !

                  What version of VS was build this application? VS2010?



                  On Mon, Oct 26, 2009 at 12:32 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                   

                  Hi,

                  Since multiple people have been asking for this and I feel that the
                  core is good enough to share I thought I would share the repository
                  here already. Disclaimer: Now keep in mind that this has not been
                  reviewed by Greg yet and that I am still working on it. I am also
                  working on a complete detailed blog post (or several) to explain what
                  is going on and why (with diagrams and all that fancy stuff). Once
                  that is done it will be published here: http://blog.fohjin.com/ I am
                  currently finishing my specifications for the GUI and will split the
                  existing domain specifications a bit more per scenario, but I think
                  you will like what you see there (hope at least).

                  The most interesting scenario is a transfer from one account to an
                  other account.

                  Link: http://github.com/MarkNijhof/Fohjin

                  Note on SQLite: Because I am developing on x64 I have the x64 version
                  of SQLite referenced in the projects, except for the test project
                  because TestDriven.Net executes everything in x86. Now if you are
                  running on a x86 machine all you have to do is copy the x86
                  System.Data.SQLite.* from /lib/sqlite/bin to /lib/sqlite/bin/x64 (this
                  approach is tested). There are two different SQLite databases, one is
                  the event store and the other is the reporting database. I haven't
                  figured out yet how, but it is possible to load the SQLite databases
                  in Visual Studio to inspect the content. Both databases are created on
                  first use, and deleting them will give you a fresh start.

                  I would like to hear your opinions, I am very enthusiastic about this
                  architecture when there is a need for a domain.

                  -Mark




                  --
                  []'s
                  Gustavo Melo




                  --
                  James Crowley
                  Managing Director
                  Developer Fusion - Connecting developers worldwide

                  Developer Fusion Ltd | 58 Sandringham Close | Enfield, EN1 3JH
                  mob: 07986 624128 web: http://www.developerfusion.com/




                  --
                  James Crowley
                  Managing Director
                  Developer Fusion - Connecting developers worldwide

                  Developer Fusion Ltd | 58 Sandringham Close | Enfield, EN1 3JH
                  mob: 07986 624128 web: http://www.developerfusion.com/


                • Richard Dingwall
                  ... Thanks for this Mark. Having a peruse now :) -- Richard Dingwall http://richarddingwall.name
                  Message 8 of 30 , Oct 26, 2009
                    On Tue, Oct 27, 2009 at 3:32 AM, Mark Nijhof <Mark.Nijhof@...> wrote:
                    >
                    >
                    >
                    > Hi,
                    >
                    > Since multiple people have been asking for this and I feel that the
                    > core is good enough to share I thought I would share the repository
                    > here already. Disclaimer: Now keep in mind that this has not been
                    > reviewed by Greg yet and that I am still working on it. I am also
                    > working on a complete detailed blog post (or several) to explain what
                    > is going on and why (with diagrams and all that fancy stuff). Once
                    > that is done it will be published here: http://blog.fohjin.com/ I am
                    > currently finishing my specifications for the GUI and will split the
                    > existing domain specifications a bit more per scenario, but I think
                    > you will like what you see there (hope at least).
                    >
                    > The most interesting scenario is a transfer from one account to an
                    > other account.
                    >
                    > Link: http://github.com/MarkNijhof/Fohjin
                    >
                    > Note on SQLite: Because I am developing on x64 I have the x64 version
                    > of SQLite referenced in the projects, except for the test project
                    > because TestDriven.Net executes everything in x86. Now if you are
                    > running on a x86 machine all you have to do is copy the x86
                    > System.Data.SQLite.* from /lib/sqlite/bin to /lib/sqlite/bin/x64 (this
                    > approach is tested). There are two different SQLite databases, one is
                    > the event store and the other is the reporting database. I haven't
                    > figured out yet how, but it is possible to load the SQLite databases
                    > in Visual Studio to inspect the content. Both databases are created on
                    > first use, and deleting them will give you a fresh start.
                    >
                    > I would like to hear your opinions, I am very enthusiastic about this
                    > architecture when there is a need for a domain.
                    >
                    > -Mark

                    Thanks for this Mark. Having a peruse now :)

                    --
                    Richard Dingwall
                    http://richarddingwall.name
                  • Žilvinas Šaltys
                    Amazing work. Really interested to read your blog post to better understand what s happening. Thanks for sharing this.
                    Message 9 of 30 , Oct 26, 2009
                      Amazing work. Really interested to read your blog post to better understand what's happening.
                      Thanks for sharing this.

                      On Mon, Oct 26, 2009 at 2:32 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                      Hi,

                      Since multiple people have been asking for this and I feel that the
                      core is good enough to share I thought I would share the repository
                      here already. Disclaimer: Now keep in mind that this has not been
                      reviewed by Greg yet and that I am still working on it. I am also
                      working on a complete detailed blog post (or several) to explain what
                      is going on and why (with diagrams and all that fancy stuff). Once
                      that is done it will be published here: http://blog.fohjin.com/ I am
                      currently finishing my specifications for the GUI and will split the
                      existing domain specifications a bit more per scenario, but I think
                      you will like what you see there (hope at least).

                      The most interesting scenario is a transfer from one account to an
                      other account.

                      Link: http://github.com/MarkNijhof/Fohjin

                      Note on SQLite: Because I am developing on x64 I have the x64 version
                      of SQLite referenced in the projects, except for the test project
                      because TestDriven.Net executes everything in x86. Now if you are
                      running on a x86 machine all you have to do is copy the x86
                      System.Data.SQLite.* from /lib/sqlite/bin to /lib/sqlite/bin/x64 (this
                      approach is tested). There are two different SQLite databases, one is
                      the event store and the other is the reporting database. I haven't
                      figured out yet how, but it is possible to load the SQLite databases
                      in Visual Studio to inspect the content. Both databases are created on
                      first use, and deleting them will give you a fresh start.

                      I would like to hear your opinions, I am very enthusiastic about this
                      architecture when there is a need for a domain.

                      -Mark


                      ------------------------------------

                      Yahoo! Groups Links

                      <*> To visit your group on the web, go to:
                         http://groups.yahoo.com/group/domaindrivendesign/

                      <*> Your email settings:
                         Individual Email | Traditional

                      <*> To change settings online go to:
                         http://groups.yahoo.com/group/domaindrivendesign/join
                         (Yahoo! ID required)

                      <*> To change settings via email:
                         mailto:domaindrivendesign-digest@yahoogroups.com
                         mailto:domaindrivendesign-fullfeatured@yahoogroups.com

                      <*> To unsubscribe from this group, send an email to:
                         domaindrivendesign-unsubscribe@yahoogroups.com

                      <*> Your use of Yahoo! Groups is subject to:
                         http://docs.yahoo.com/info/terms/


                    • sebaszipp
                      Great job Mark, As many others I would have a more clear perspective of CQS at architecture level if I see how it s implemented in code. I ll be reading your
                      Message 10 of 30 , Oct 28, 2009
                        Great job Mark,

                        As many others I would have a more clear perspective of CQS at architecture level if I see how it's implemented in code.
                        I'll be reading your blog.

                        Thanks a LOT for taking the time to provide Greg's magic for us and those that can't assit to Greg conferences for any reason.

                        Cheers,
                        Sebastian.


                        --- In domaindrivendesign@yahoogroups.com, Mark Nijhof <Mark.Nijhof@...> wrote:
                        >
                        > Hi,
                        >
                        > Since multiple people have been asking for this and I feel that the
                        > core is good enough to share I thought I would share the repository
                        > here already. Disclaimer: Now keep in mind that this has not been
                        > reviewed by Greg yet and that I am still working on it. I am also
                        > working on a complete detailed blog post (or several) to explain what
                        > is going on and why (with diagrams and all that fancy stuff). Once
                        > that is done it will be published here: http://blog.fohjin.com/ I am
                        > currently finishing my specifications for the GUI and will split the
                        > existing domain specifications a bit more per scenario, but I think
                        > you will like what you see there (hope at least).
                        >
                        > The most interesting scenario is a transfer from one account to an
                        > other account.
                        >
                        > Link: http://github.com/MarkNijhof/Fohjin
                        >
                        > Note on SQLite: Because I am developing on x64 I have the x64 version
                        > of SQLite referenced in the projects, except for the test project
                        > because TestDriven.Net executes everything in x86. Now if you are
                        > running on a x86 machine all you have to do is copy the x86
                        > System.Data.SQLite.* from /lib/sqlite/bin to /lib/sqlite/bin/x64 (this
                        > approach is tested). There are two different SQLite databases, one is
                        > the event store and the other is the reporting database. I haven't
                        > figured out yet how, but it is possible to load the SQLite databases
                        > in Visual Studio to inspect the content. Both databases are created on
                        > first use, and deleting them will give you a fresh start.
                        >
                        > I would like to hear your opinions, I am very enthusiastic about this
                        > architecture when there is a need for a domain.
                        >
                        > -Mark
                        >
                      • David Perfors
                        Hi Mark, Thanks a lot for this example. I was looking into the code and looked ad the implementations of IBus and saw that it is using reflection for the
                        Message 11 of 30 , Oct 28, 2009
                          Hi Mark,

                          Thanks a lot for this example. I was looking into the code and looked ad the implementations of IBus and saw that it is using reflection for the PublishMultiple method. Can you tell me (us) more about why you are doing that instead of just calling the Publish method?

                          Looking forward to the blogposts :)

                          David.

                          2009/10/26 Mark Nijhof <Mark.Nijhof@...>
                          Hi,

                          Since multiple people have been asking for this and I feel that the
                          core is good enough to share I thought I would share the repository
                          here already. Disclaimer: Now keep in mind that this has not been
                          reviewed by Greg yet and that I am still working on it. I am also
                          working on a complete detailed blog post (or several) to explain what
                          is going on and why (with diagrams and all that fancy stuff). Once
                          that is done it will be published here: http://blog.fohjin.com/ I am
                          currently finishing my specifications for the GUI and will split the
                          existing domain specifications a bit more per scenario, but I think
                          you will like what you see there (hope at least).

                          The most interesting scenario is a transfer from one account to an
                          other account.

                          Link: http://github.com/MarkNijhof/Fohjin

                          Note on SQLite: Because I am developing on x64 I have the x64 version
                          of SQLite referenced in the projects, except for the test project
                          because TestDriven.Net executes everything in x86. Now if you are
                          running on a x86 machine all you have to do is copy the x86
                          System.Data.SQLite.* from /lib/sqlite/bin to /lib/sqlite/bin/x64 (this
                          approach is tested). There are two different SQLite databases, one is
                          the event store and the other is the reporting database. I haven't
                          figured out yet how, but it is possible to load the SQLite databases
                          in Visual Studio to inspect the content. Both databases are created on
                          first use, and deleting them will give you a fresh start.

                          I would like to hear your opinions, I am very enthusiastic about this
                          architecture when there is a need for a domain.

                          -Mark


                          ------------------------------------

                          Yahoo! Groups Links

                          <*> To visit your group on the web, go to:
                             http://groups.yahoo.com/group/domaindrivendesign/

                          <*> Your email settings:
                             Individual Email | Traditional

                          <*> To change settings online go to:
                             http://groups.yahoo.com/group/domaindrivendesign/join
                             (Yahoo! ID required)

                          <*> To change settings via email:
                             mailto:domaindrivendesign-digest@yahoogroups.com
                             mailto:domaindrivendesign-fullfeatured@yahoogroups.com

                          <*> To unsubscribe from this group, send an email to:
                             domaindrivendesign-unsubscribe@yahoogroups.com

                          <*> Your use of Yahoo! Groups is subject to:
                             http://docs.yahoo.com/info/terms/


                        • Mark Nijhof
                          Hi, Because that is a nasty home made implementation of a bus :) The Publish method needs to know the exact type of the command/event that gets passed in
                          Message 12 of 30 , Oct 28, 2009
                            Hi,

                            Because that is a nasty home made implementation of a bus :) The Publish method needs to know the exact type of the command/event that gets passed in because that is used to get the correct xxxHandlers from the IoC container. I cannot use an Generic in the PublishMultiple because these commands/events are 99% of the time not of the same type. I will probably change it into something like this: http://codebetter.com/blogs/gregyoung/archive/2009/10/03/delegate-mapper.aspx

                            Also one thing I like to highlight is that in this first version I am not using anything complex because I explicitly wanted to show that the core of this is actually very simple, if I started with NServiceBus and NHibernate than that would have taken away from the simplicity of this type of architecture. That is why I have implemented my own very simple ORM (one has to do that once in their career anyway right) and my own bus. I plan on continuing on this example by introducing these types of options as well, all do the event store will remain custom SQL, actually I will also implement one using SQL Server and that one will use a stored procedure ;)

                            -Mark


                            On Wed, Oct 28, 2009 at 8:16 PM, David Perfors <dnperfors@...> wrote:
                             

                            Hi Mark,

                            Thanks a lot for this example. I was looking into the code and looked ad the implementations of IBus and saw that it is using reflection for the PublishMultiple method. Can you tell me (us) more about why you are doing that instead of just calling the Publish method?

                            Looking forward to the blogposts :)

                            David.

                            2009/10/26 Mark Nijhof <Mark.Nijhof@...>
                            Hi,

                            Since multiple people have been asking for this and I feel that the
                            core is good enough to share I thought I would share the repository
                            here already. Disclaimer: Now keep in mind that this has not been
                            reviewed by Greg yet and that I am still working on it. I am also
                            working on a complete detailed blog post (or several) to explain what
                            is going on and why (with diagrams and all that fancy stuff). Once
                            that is done it will be published here: http://blog.fohjin.com/ I am
                            currently finishing my specifications for the GUI and will split the
                            existing domain specifications a bit more per scenario, but I think
                            you will like what you see there (hope at least).

                            The most interesting scenario is a transfer from one account to an
                            other account.

                            Link: http://github.com/MarkNijhof/Fohjin

                            Note on SQLite: Because I am developing on x64 I have the x64 version
                            of SQLite referenced in the projects, except for the test project
                            because TestDriven.Net executes everything in x86. Now if you are
                            running on a x86 machine all you have to do is copy the x86
                            System.Data.SQLite.* from /lib/sqlite/bin to /lib/sqlite/bin/x64 (this
                            approach is tested). There are two different SQLite databases, one is
                            the event store and the other is the reporting database. I haven't
                            figured out yet how, but it is possible to load the SQLite databases
                            in Visual Studio to inspect the content. Both databases are created on
                            first use, and deleting them will give you a fresh start.

                            I would like to hear your opinions, I am very enthusiastic about this
                            architecture when there is a need for a domain.

                            -Mark


                            ------------------------------------

                            Yahoo! Groups Links

                            <*> To visit your group on the web, go to:
                               http://groups.yahoo.com/group/domaindrivendesign/

                            <*> Your email settings:
                               Individual Email | Traditional

                            <*> To change settings online go to:
                               http://groups.yahoo.com/group/domaindrivendesign/join
                               (Yahoo! ID required)

                            <*> To change settings via email:
                               mailto:domaindrivendesign-digest@yahoogroups.com
                               mailto:domaindrivendesign-fullfeatured@yahoogroups.com

                            <*> To unsubscribe from this group, send an email to:
                               domaindrivendesign-unsubscribe@yahoogroups.com

                            <*> Your use of Yahoo! Groups is subject to:
                               http://docs.yahoo.com/info/terms/



                          • Mark Nijhof
                            Hi, I finally got the first blog post about this published, it is long! Not so much code, more the explanation behind it (as I understand it). Link:
                            Message 13 of 30 , Nov 11, 2009
                              Hi,

                              I finally got the first blog post about this published, it is long! Not so much code, more the explanation behind it (as I understand it).

                              Link: http://blog.fohjin.com/blog/2009/11/12/CQRS_a_la_Greg_Young

                              -Mark


                              On Thu, Oct 29, 2009 at 1:09 AM, Mark Nijhof <mark.nijhof@...> wrote:
                              Hi,

                              Because that is a nasty home made implementation of a bus :) The Publish method needs to know the exact type of the command/event that gets passed in because that is used to get the correct xxxHandlers from the IoC container. I cannot use an Generic in the PublishMultiple because these commands/events are 99% of the time not of the same type. I will probably change it into something like this: http://codebetter.com/blogs/gregyoung/archive/2009/10/03/delegate-mapper.aspx

                              Also one thing I like to highlight is that in this first version I am not using anything complex because I explicitly wanted to show that the core of this is actually very simple, if I started with NServiceBus and NHibernate than that would have taken away from the simplicity of this type of architecture. That is why I have implemented my own very simple ORM (one has to do that once in their career anyway right) and my own bus. I plan on continuing on this example by introducing these types of options as well, all do the event store will remain custom SQL, actually I will also implement one using SQL Server and that one will use a stored procedure ;)

                              -Mark



                              On Wed, Oct 28, 2009 at 8:16 PM, David Perfors <dnperfors@...> wrote:
                               

                              Hi Mark,

                              Thanks a lot for this example. I was looking into the code and looked ad the implementations of IBus and saw that it is using reflection for the PublishMultiple method. Can you tell me (us) more about why you are doing that instead of just calling the Publish method?

                              Looking forward to the blogposts :)

                              David.

                              2009/10/26 Mark Nijhof <Mark.Nijhof@...>
                              Hi,

                              Since multiple people have been asking for this and I feel that the
                              core is good enough to share I thought I would share the repository
                              here already. Disclaimer: Now keep in mind that this has not been
                              reviewed by Greg yet and that I am still working on it. I am also
                              working on a complete detailed blog post (or several) to explain what
                              is going on and why (with diagrams and all that fancy stuff). Once
                              that is done it will be published here: http://blog.fohjin.com/ I am
                              currently finishing my specifications for the GUI and will split the
                              existing domain specifications a bit more per scenario, but I think
                              you will like what you see there (hope at least).

                              The most interesting scenario is a transfer from one account to an
                              other account.

                              Link: http://github.com/MarkNijhof/Fohjin

                              Note on SQLite: Because I am developing on x64 I have the x64 version
                              of SQLite referenced in the projects, except for the test project
                              because TestDriven.Net executes everything in x86. Now if you are
                              running on a x86 machine all you have to do is copy the x86
                              System.Data.SQLite.* from /lib/sqlite/bin to /lib/sqlite/bin/x64 (this
                              approach is tested). There are two different SQLite databases, one is
                              the event store and the other is the reporting database. I haven't
                              figured out yet how, but it is possible to load the SQLite databases
                              in Visual Studio to inspect the content. Both databases are created on
                              first use, and deleting them will give you a fresh start.

                              I would like to hear your opinions, I am very enthusiastic about this
                              architecture when there is a need for a domain.

                              -Mark


                              ------------------------------------

                              Yahoo! Groups Links

                              <*> To visit your group on the web, go to:
                                 http://groups.yahoo.com/group/domaindrivendesign/

                              <*> Your email settings:
                                 Individual Email | Traditional

                              <*> To change settings online go to:
                                 http://groups.yahoo.com/group/domaindrivendesign/join
                                 (Yahoo! ID required)

                              <*> To change settings via email:
                                 mailto:domaindrivendesign-digest@yahoogroups.com
                                 mailto:domaindrivendesign-fullfeatured@yahoogroups.com

                              <*> To unsubscribe from this group, send an email to:
                                 domaindrivendesign-unsubscribe@yahoogroups.com

                              <*> Your use of Yahoo! Groups is subject to:
                                 http://docs.yahoo.com/info/terms/




                            • sebaszipp
                              Hi Mark, Great blog. Thanks for clarifying in detail things about CQRS. Still a grey zone I d like to get better is about AR load performance when the event
                              Message 14 of 30 , Nov 12, 2009
                                Hi Mark,

                                Great blog. Thanks for clarifying in detail things about CQRS.

                                Still a grey zone I'd like to get better is about AR load performance when the event storage is large enough to kill performance.
                                I know rolling snapshots takes care of this field, but by rolling snapthost I might get an incomplete AR?
                                Could you please explain this?

                                Thanks.


                                --- In domaindrivendesign@yahoogroups.com, Mark Nijhof <Mark.Nijhof@...> wrote:
                                >
                                > Hi,
                                >
                                > I finally got the first blog post about this published, it is long! Not so
                                > much code, more the explanation behind it (as I understand it).
                                >
                                > Link: http://blog.fohjin.com/blog/2009/11/12/CQRS_a_la_Greg_Young
                                >
                                > -Mark
                                >
                                >
                                > On Thu, Oct 29, 2009 at 1:09 AM, Mark Nijhof <mark.nijhof@...> wrote:
                                >
                                > > Hi,
                                > >
                                > > Because that is a nasty home made implementation of a bus :) The Publish
                                > > method needs to know the exact type of the command/event that gets passed in
                                > > because that is used to get the correct xxxHandlers from the IoC container.
                                > > I cannot use an Generic in the PublishMultiple because these commands/events
                                > > are 99% of the time not of the same type. I will probably change it into
                                > > something like this:
                                > > http://codebetter.com/blogs/gregyoung/archive/2009/10/03/delegate-mapper.aspx
                                > >
                                > > Also one thing I like to highlight is that in this first version I am not
                                > > using anything complex because I explicitly wanted to show that the core of
                                > > this is actually very simple, if I started with NServiceBus and NHibernate
                                > > than that would have taken away from the simplicity of this type of
                                > > architecture. That is why I have implemented my own very simple ORM (one has
                                > > to do that once in their career anyway right) and my own bus. I plan on
                                > > continuing on this example by introducing these types of options as well,
                                > > all do the event store will remain custom SQL, actually I will also
                                > > implement one using SQL Server and that one will use a stored procedure ;)
                                > >
                                > > -Mark
                                > >
                                > >
                                > >
                                > > On Wed, Oct 28, 2009 at 8:16 PM, David Perfors <dnperfors@...>wrote:
                                > >
                                > >>
                                > >>
                                > >> Hi Mark,
                                > >>
                                > >> Thanks a lot for this example. I was looking into the code and looked ad
                                > >> the implementations of IBus and saw that it is using reflection for the
                                > >> PublishMultiple method. Can you tell me (us) more about why you are doing
                                > >> that instead of just calling the Publish method?
                                > >>
                                > >> Looking forward to the blogposts :)
                                > >>
                                > >> David.
                                > >>
                                > >> 2009/10/26 Mark Nijhof <Mark.Nijhof@...>
                                > >>
                                > >>> Hi,
                                > >>>
                                > >>> Since multiple people have been asking for this and I feel that the
                                > >>> core is good enough to share I thought I would share the repository
                                > >>> here already. Disclaimer: Now keep in mind that this has not been
                                > >>> reviewed by Greg yet and that I am still working on it. I am also
                                > >>> working on a complete detailed blog post (or several) to explain what
                                > >>> is going on and why (with diagrams and all that fancy stuff). Once
                                > >>> that is done it will be published here: http://blog.fohjin.com/ I am
                                > >>> currently finishing my specifications for the GUI and will split the
                                > >>> existing domain specifications a bit more per scenario, but I think
                                > >>> you will like what you see there (hope at least).
                                > >>>
                                > >>> The most interesting scenario is a transfer from one account to an
                                > >>> other account.
                                > >>>
                                > >>> Link: http://github.com/MarkNijhof/Fohjin
                                > >>>
                                > >>> Note on SQLite: Because I am developing on x64 I have the x64 version
                                > >>> of SQLite referenced in the projects, except for the test project
                                > >>> because TestDriven.Net executes everything in x86. Now if you are
                                > >>> running on a x86 machine all you have to do is copy the x86
                                > >>> System.Data.SQLite.* from /lib/sqlite/bin to /lib/sqlite/bin/x64 (this
                                > >>> approach is tested). There are two different SQLite databases, one is
                                > >>> the event store and the other is the reporting database. I haven't
                                > >>> figured out yet how, but it is possible to load the SQLite databases
                                > >>> in Visual Studio to inspect the content. Both databases are created on
                                > >>> first use, and deleting them will give you a fresh start.
                                > >>>
                                > >>> I would like to hear your opinions, I am very enthusiastic about this
                                > >>> architecture when there is a need for a domain.
                                > >>>
                                > >>> -Mark
                                > >>>
                                > >>>
                                > >>> ------------------------------------
                                > >>>
                                > >>> Yahoo! Groups Links
                                > >>>
                                > >>>
                                > >>>
                                > >>>
                                > >>
                                > >>
                                > >
                                > >
                                >
                              • Mark Henke
                                What do you mean by incomplete AR? A rolling snapshot is like a physical inventory in a Warehouse system. It contains all data relating to the current state of
                                Message 15 of 30 , Nov 12, 2009
                                  What do you mean by incomplete AR?

                                  A rolling snapshot is like a physical inventory in a Warehouse system.
                                   It contains all data relating to the current state of the AR so the AR has a baseline of data to work from. If you are looking at two ARs at any single point in time there should be no difference in current state from one loaded from a snapshot to one loaded with all events.


                                  On Thu, Nov 12, 2009 at 10:37 AM, sebaszipp <sebaszipp@...> wrote:
                                   


                                  Hi Mark,

                                  Great blog. Thanks for clarifying in detail things about CQRS.

                                  Still a grey zone I'd like to get better is about AR load performance when the event storage is large enough to kill performance.
                                  I know rolling snapshots takes care of this field, but by rolling snapthost I might get an incomplete AR?
                                  Could you please explain this?

                                  Thanks.



                                  --- In domaindrivendesign@yahoogroups.com, Mark Nijhof <Mark.Nijhof@...> wrote:
                                  >
                                  > Hi,
                                  >
                                  > I finally got the first blog post about this published, it is long! Not so
                                  > much code, more the explanation behind it (as I understand it).
                                  >
                                  > Link: http://blog.fohjin.com/blog/2009/11/12/CQRS_a_la_Greg_Young
                                  >
                                  > -Mark
                                  >
                                  >
                                  > On Thu, Oct 29, 2009 at 1:09 AM, Mark Nijhof <mark.nijhof@...> wrote:
                                  >
                                  > > Hi,
                                  > >
                                  > > Because that is a nasty home made implementation of a bus :) The Publish
                                  > > method needs to know the exact type of the command/event that gets passed in
                                  > > because that is used to get the correct xxxHandlers from the IoC container.
                                  > > I cannot use an Generic in the PublishMultiple because these commands/events
                                  > > are 99% of the time not of the same type. I will probably change it into
                                  > > something like this:
                                  > > http://codebetter.com/blogs/gregyoung/archive/2009/10/03/delegate-mapper.aspx
                                  > >
                                  > > Also one thing I like to highlight is that in this first version I am not
                                  > > using anything complex because I explicitly wanted to show that the core of
                                  > > this is actually very simple, if I started with NServiceBus and NHibernate
                                  > > than that would have taken away from the simplicity of this type of
                                  > > architecture. That is why I have implemented my own very simple ORM (one has
                                  > > to do that once in their career anyway right) and my own bus. I plan on
                                  > > continuing on this example by introducing these types of options as well,
                                  > > all do the event store will remain custom SQL, actually I will also
                                  > > implement one using SQL Server and that one will use a stored procedure ;)
                                  > >
                                  > > -Mark
                                  > >
                                  > >
                                  > >
                                  > > On Wed, Oct 28, 2009 at 8:16 PM, David Perfors <dnperfors@...>wrote:

                                  > >
                                  > >>
                                  > >>
                                  > >> Hi Mark,
                                  > >>
                                  > >> Thanks a lot for this example. I was looking into the code and looked ad
                                  > >> the implementations of IBus and saw that it is using reflection for the
                                  > >> PublishMultiple method. Can you tell me (us) more about why you are doing
                                  > >> that instead of just calling the Publish method?
                                  > >>
                                  > >> Looking forward to the blogposts :)
                                  > >>
                                  > >> David.
                                  > >>
                                  > >> 2009/10/26 Mark Nijhof <Mark.Nijhof@...>

                                  > >>
                                  > >>> Hi,
                                  > >>>
                                  > >>> Since multiple people have been asking for this and I feel that the
                                  > >>> core is good enough to share I thought I would share the repository
                                  > >>> here already. Disclaimer: Now keep in mind that this has not been
                                  > >>> reviewed by Greg yet and that I am still working on it. I am also
                                  > >>> working on a complete detailed blog post (or several) to explain what
                                  > >>> is going on and why (with diagrams and all that fancy stuff). Once
                                  > >>> that is done it will be published here: http://blog.fohjin.com/ I am
                                  > >>> currently finishing my specifications for the GUI and will split the
                                  > >>> existing domain specifications a bit more per scenario, but I think
                                  > >>> you will like what you see there (hope at least).
                                  > >>>
                                  > >>> The most interesting scenario is a transfer from one account to an
                                  > >>> other account.
                                  > >>>
                                  > >>> Link: http://github.com/MarkNijhof/Fohjin
                                  > >>>
                                  > >>> Note on SQLite: Because I am developing on x64 I have the x64 version
                                  > >>> of SQLite referenced in the projects, except for the test project
                                  > >>> because TestDriven.Net executes everything in x86. Now if you are
                                  > >>> running on a x86 machine all you have to do is copy the x86
                                  > >>> System.Data.SQLite.* from /lib/sqlite/bin to /lib/sqlite/bin/x64 (this
                                  > >>> approach is tested). There are two different SQLite databases, one is
                                  > >>> the event store and the other is the reporting database. I haven't
                                  > >>> figured out yet how, but it is possible to load the SQLite databases
                                  > >>> in Visual Studio to inspect the content. Both databases are created on
                                  > >>> first use, and deleting them will give you a fresh start.
                                  > >>>
                                  > >>> I would like to hear your opinions, I am very enthusiastic about this
                                  > >>> architecture when there is a need for a domain.
                                  > >>>
                                  > >>> -Mark
                                  > >>>
                                  > >>>
                                  > >>> ------------------------------------
                                  > >>>
                                  > >>> Yahoo! Groups Links
                                  > >>>
                                  > >>>
                                  > >>>
                                  > >>>
                                  > >>
                                  > >>
                                  > >
                                  > >
                                  >


                                • Mark Nijhof
                                  Your rolling snapshot will never be assumed to be the latest state of the AR, after loading the snapshot the repository will always get all events that have
                                  Message 16 of 30 , Nov 12, 2009
                                    Your rolling snapshot will never be assumed to be the latest state of the AR, after loading the snapshot the repository will always get all events that have occurred after the snapshot was made. The process creating the snapshots will most likely be a independent process that would just load AR verify if a snapshot needs to be made. If this is the case it would make it. Say after 100 events you want a snapshot. Instead of putting this responsibility in the domain repository?

                                    So current version of the snapshot is 20 version of the last event is 25 so after loading the snapshot it also needs to replay the last 5 events.

                                    Does this make sense?

                                    -Mark

                                    On Thu, Nov 12, 2009 at 4:37 PM, sebaszipp <sebaszipp@...> wrote:
                                     


                                    Hi Mark,

                                    Great blog. Thanks for clarifying in detail things about CQRS.

                                    Still a grey zone I'd like to get better is about AR load performance when the event storage is large enough to kill performance.
                                    I know rolling snapshots takes care of this field, but by rolling snapthost I might get an incomplete AR?
                                    Could you please explain this?

                                    Thanks.



                                    --- In domaindrivendesign@yahoogroups.com, Mark Nijhof <Mark.Nijhof@...> wrote:
                                    >
                                    > Hi,
                                    >
                                    > I finally got the first blog post about this published, it is long! Not so
                                    > much code, more the explanation behind it (as I understand it).
                                    >
                                    > Link: http://blog.fohjin.com/blog/2009/11/12/CQRS_a_la_Greg_Young
                                    >
                                    > -Mark
                                    >
                                    >
                                    > On Thu, Oct 29, 2009 at 1:09 AM, Mark Nijhof <mark.nijhof@...> wrote:
                                    >
                                    > > Hi,
                                    > >
                                    > > Because that is a nasty home made implementation of a bus :) The Publish
                                    > > method needs to know the exact type of the command/event that gets passed in
                                    > > because that is used to get the correct xxxHandlers from the IoC container.
                                    > > I cannot use an Generic in the PublishMultiple because these commands/events
                                    > > are 99% of the time not of the same type. I will probably change it into
                                    > > something like this:
                                    > > http://codebetter.com/blogs/gregyoung/archive/2009/10/03/delegate-mapper.aspx
                                    > >
                                    > > Also one thing I like to highlight is that in this first version I am not
                                    > > using anything complex because I explicitly wanted to show that the core of
                                    > > this is actually very simple, if I started with NServiceBus and NHibernate
                                    > > than that would have taken away from the simplicity of this type of
                                    > > architecture. That is why I have implemented my own very simple ORM (one has
                                    > > to do that once in their career anyway right) and my own bus. I plan on
                                    > > continuing on this example by introducing these types of options as well,
                                    > > all do the event store will remain custom SQL, actually I will also
                                    > > implement one using SQL Server and that one will use a stored procedure ;)
                                    > >
                                    > > -Mark
                                    > >
                                    > >
                                    > >
                                    > > On Wed, Oct 28, 2009 at 8:16 PM, David Perfors <dnperfors@...>wrote:

                                    > >
                                    > >>
                                    > >>
                                    > >> Hi Mark,
                                    > >>
                                    > >> Thanks a lot for this example. I was looking into the code and looked ad
                                    > >> the implementations of IBus and saw that it is using reflection for the
                                    > >> PublishMultiple method. Can you tell me (us) more about why you are doing
                                    > >> that instead of just calling the Publish method?
                                    > >>
                                    > >> Looking forward to the blogposts :)
                                    > >>
                                    > >> David.
                                    > >>
                                    > >> 2009/10/26 Mark Nijhof <Mark.Nijhof@...>

                                    > >>
                                    > >>> Hi,
                                    > >>>
                                    > >>> Since multiple people have been asking for this and I feel that the
                                    > >>> core is good enough to share I thought I would share the repository
                                    > >>> here already. Disclaimer: Now keep in mind that this has not been
                                    > >>> reviewed by Greg yet and that I am still working on it. I am also
                                    > >>> working on a complete detailed blog post (or several) to explain what
                                    > >>> is going on and why (with diagrams and all that fancy stuff). Once
                                    > >>> that is done it will be published here: http://blog.fohjin.com/ I am
                                    > >>> currently finishing my specifications for the GUI and will split the
                                    > >>> existing domain specifications a bit more per scenario, but I think
                                    > >>> you will like what you see there (hope at least).
                                    > >>>
                                    > >>> The most interesting scenario is a transfer from one account to an
                                    > >>> other account.
                                    > >>>
                                    > >>> Link: http://github.com/MarkNijhof/Fohjin
                                    > >>>
                                    > >>> Note on SQLite: Because I am developing on x64 I have the x64 version
                                    > >>> of SQLite referenced in the projects, except for the test project
                                    > >>> because TestDriven.Net executes everything in x86. Now if you are
                                    > >>> running on a x86 machine all you have to do is copy the x86
                                    > >>> System.Data.SQLite.* from /lib/sqlite/bin to /lib/sqlite/bin/x64 (this
                                    > >>> approach is tested). There are two different SQLite databases, one is
                                    > >>> the event store and the other is the reporting database. I haven't
                                    > >>> figured out yet how, but it is possible to load the SQLite databases
                                    > >>> in Visual Studio to inspect the content. Both databases are created on
                                    > >>> first use, and deleting them will give you a fresh start.
                                    > >>>
                                    > >>> I would like to hear your opinions, I am very enthusiastic about this
                                    > >>> architecture when there is a need for a domain.
                                    > >>>
                                    > >>> -Mark
                                    > >>>
                                    > >>>
                                    > >>> ------------------------------------
                                    > >>>
                                    > >>> Yahoo! Groups Links
                                    > >>>
                                    > >>>
                                    > >>>
                                    > >>>
                                    > >>
                                    > >>
                                    > >
                                    > >
                                    >


                                  • sebaszipp
                                    I got it :) I don t know why I was relating the concept of a snapshot with a stack of events and not with the domain AR (and since I m not an english native
                                    Message 17 of 30 , Nov 12, 2009
                                      I got it :)

                                      I don't know why I was relating the concept of a snapshot with a stack of events and not with the domain AR (and since I'm not an english native speaker I got a lil confused about the term 'rolling').

                                      So you take a picture of the domain entity after N events and then make the repository hold a reference to that picture indexed by its identity (ID) (or the separate process yoou mention)

                                      Let's assume you want to load the AR having the same ID that the picture hold by the repo has. You calculate the position in the event stack from where you would start replying events, then create an AR instance, copy its state with the picture (Memento) that you took previosly, and apply the events representing the DELTA.

                                      The Snapshot shouldn't be kept by the repo because we would run into the same performance problem if too many instances live in memory. I guess we should serialize the snapshot to disk or something similar?

                                      Am I ok?

                                      Thanks Mark.


                                      --- In domaindrivendesign@yahoogroups.com, Mark Nijhof <Mark.Nijhof@...> wrote:
                                      >
                                      > Your rolling snapshot will never be assumed to be the latest state of the
                                      > AR, after loading the snapshot the repository will always get all events
                                      > that have occurred after the snapshot was made. The process creating the
                                      > snapshots will most likely be a independent process that would just load AR
                                      > verify if a snapshot needs to be made. If this is the case it would make it.
                                      > Say after 100 events you want a snapshot. Instead of putting this
                                      > responsibility in the domain repository?
                                      >
                                      > So current version of the snapshot is 20 version of the last event is 25 so
                                      > after loading the snapshot it also needs to replay the last 5 events.
                                      >
                                      > Does this make sense?
                                      >
                                      > -Mark
                                      >
                                      > On Thu, Nov 12, 2009 at 4:37 PM, sebaszipp <sebaszipp@...> wrote:
                                      >
                                      > >
                                      > >
                                      > >
                                      > > Hi Mark,
                                      > >
                                      > > Great blog. Thanks for clarifying in detail things about CQRS.
                                      > >
                                      > > Still a grey zone I'd like to get better is about AR load performance when
                                      > > the event storage is large enough to kill performance.
                                      > > I know rolling snapshots takes care of this field, but by rolling snapthost
                                      > > I might get an incomplete AR?
                                      > > Could you please explain this?
                                      > >
                                      > > Thanks.
                                      > >
                                      > >
                                      > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>,
                                      > > Mark Nijhof <Mark.Nijhof@> wrote:
                                      > > >
                                      > > > Hi,
                                      > > >
                                      > > > I finally got the first blog post about this published, it is long! Not
                                      > > so
                                      > > > much code, more the explanation behind it (as I understand it).
                                      > > >
                                      > > > Link: http://blog.fohjin.com/blog/2009/11/12/CQRS_a_la_Greg_Young
                                      > > >
                                      > > > -Mark
                                      > > >
                                      > > >
                                      > > > On Thu, Oct 29, 2009 at 1:09 AM, Mark Nijhof <mark.nijhof@> wrote:
                                      > > >
                                      > > > > Hi,
                                      > > > >
                                      > > > > Because that is a nasty home made implementation of a bus :) The
                                      > > Publish
                                      > > > > method needs to know the exact type of the command/event that gets
                                      > > passed in
                                      > > > > because that is used to get the correct xxxHandlers from the IoC
                                      > > container.
                                      > > > > I cannot use an Generic in the PublishMultiple because these
                                      > > commands/events
                                      > > > > are 99% of the time not of the same type. I will probably change it
                                      > > into
                                      > > > > something like this:
                                      > > > >
                                      > > http://codebetter.com/blogs/gregyoung/archive/2009/10/03/delegate-mapper.aspx
                                      > > > >
                                      > > > > Also one thing I like to highlight is that in this first version I am
                                      > > not
                                      > > > > using anything complex because I explicitly wanted to show that the
                                      > > core of
                                      > > > > this is actually very simple, if I started with NServiceBus and
                                      > > NHibernate
                                      > > > > than that would have taken away from the simplicity of this type of
                                      > > > > architecture. That is why I have implemented my own very simple ORM
                                      > > (one has
                                      > > > > to do that once in their career anyway right) and my own bus. I plan on
                                      > > > > continuing on this example by introducing these types of options as
                                      > > well,
                                      > > > > all do the event store will remain custom SQL, actually I will also
                                      > > > > implement one using SQL Server and that one will use a stored procedure
                                      > > ;)
                                      > > > >
                                      > > > > -Mark
                                      > > > >
                                      > > > >
                                      > > > >
                                      > > > > On Wed, Oct 28, 2009 at 8:16 PM, David Perfors <dnperfors@>wrote:
                                      > >
                                      > > > >
                                      > > > >>
                                      > > > >>
                                      > > > >> Hi Mark,
                                      > > > >>
                                      > > > >> Thanks a lot for this example. I was looking into the code and looked
                                      > > ad
                                      > > > >> the implementations of IBus and saw that it is using reflection for
                                      > > the
                                      > > > >> PublishMultiple method. Can you tell me (us) more about why you are
                                      > > doing
                                      > > > >> that instead of just calling the Publish method?
                                      > > > >>
                                      > > > >> Looking forward to the blogposts :)
                                      > > > >>
                                      > > > >> David.
                                      > > > >>
                                      > > > >> 2009/10/26 Mark Nijhof <Mark.Nijhof@>
                                      > >
                                      > > > >>
                                      > > > >>> Hi,
                                      > > > >>>
                                      > > > >>> Since multiple people have been asking for this and I feel that the
                                      > > > >>> core is good enough to share I thought I would share the repository
                                      > > > >>> here already. Disclaimer: Now keep in mind that this has not been
                                      > > > >>> reviewed by Greg yet and that I am still working on it. I am also
                                      > > > >>> working on a complete detailed blog post (or several) to explain what
                                      > > > >>> is going on and why (with diagrams and all that fancy stuff). Once
                                      > > > >>> that is done it will be published here: http://blog.fohjin.com/ I am
                                      > > > >>> currently finishing my specifications for the GUI and will split the
                                      > > > >>> existing domain specifications a bit more per scenario, but I think
                                      > > > >>> you will like what you see there (hope at least).
                                      > > > >>>
                                      > > > >>> The most interesting scenario is a transfer from one account to an
                                      > > > >>> other account.
                                      > > > >>>
                                      > > > >>> Link: http://github.com/MarkNijhof/Fohjin
                                      > > > >>>
                                      > > > >>> Note on SQLite: Because I am developing on x64 I have the x64 version
                                      > > > >>> of SQLite referenced in the projects, except for the test project
                                      > > > >>> because TestDriven.Net executes everything in x86. Now if you are
                                      > > > >>> running on a x86 machine all you have to do is copy the x86
                                      > > > >>> System.Data.SQLite.* from /lib/sqlite/bin to /lib/sqlite/bin/x64
                                      > > (this
                                      > > > >>> approach is tested). There are two different SQLite databases, one is
                                      > > > >>> the event store and the other is the reporting database. I haven't
                                      > > > >>> figured out yet how, but it is possible to load the SQLite databases
                                      > > > >>> in Visual Studio to inspect the content. Both databases are created
                                      > > on
                                      > > > >>> first use, and deleting them will give you a fresh start.
                                      > > > >>>
                                      > > > >>> I would like to hear your opinions, I am very enthusiastic about this
                                      > > > >>> architecture when there is a need for a domain.
                                      > > > >>>
                                      > > > >>> -Mark
                                      > > > >>>
                                      > > > >>>
                                      > > > >>> ------------------------------------
                                      > > > >>>
                                      > > > >>> Yahoo! Groups Links
                                      > > > >>>
                                      > > > >>>
                                      > > > >>>
                                      > > > >>>
                                      > > > >>
                                      > > > >>
                                      > > > >
                                      > > > >
                                      > > >
                                      > >
                                      > >
                                      > >
                                      >
                                    • Greg Young
                                      Yes the snapshots are generally not in memory, they live in the event store. Cheers, Greg ... -- Les erreurs de grammaire et de syntaxe ont été incluses pour
                                      Message 18 of 30 , Nov 12, 2009
                                        Yes the snapshots are generally not in memory, they live in the event store.

                                        Cheers,

                                        Greg

                                        On Thu, Nov 12, 2009 at 8:30 PM, sebaszipp <sebaszipp@...> wrote:
                                         


                                        I got it :)

                                        I don't know why I was relating the concept of a snapshot with a stack of events and not with the domain AR (and since I'm not an english native speaker I got a lil confused about the term 'rolling').

                                        So you take a picture of the domain entity after N events and then make the repository hold a reference to that picture indexed by its identity (ID) (or the separate process yoou mention)

                                        Let's assume you want to load the AR having the same ID that the picture hold by the repo has. You calculate the position in the event stack from where you would start replying events, then create an AR instance, copy its state with the picture (Memento) that you took previosly, and apply the events representing the DELTA.

                                        The Snapshot shouldn't be kept by the repo because we would run into the same performance problem if too many instances live in memory. I guess we should serialize the snapshot to disk or something similar?

                                        Am I ok?

                                        Thanks Mark.



                                        --- In domaindrivendesign@yahoogroups.com, Mark Nijhof <Mark.Nijhof@...> wrote:
                                        >
                                        > Your rolling snapshot will never be assumed to be the latest state of the
                                        > AR, after loading the snapshot the repository will always get all events
                                        > that have occurred after the snapshot was made. The process creating the
                                        > snapshots will most likely be a independent process that would just load AR
                                        > verify if a snapshot needs to be made. If this is the case it would make it.
                                        > Say after 100 events you want a snapshot. Instead of putting this
                                        > responsibility in the domain repository?
                                        >
                                        > So current version of the snapshot is 20 version of the last event is 25 so
                                        > after loading the snapshot it also needs to replay the last 5 events.
                                        >
                                        > Does this make sense?
                                        >
                                        > -Mark
                                        >
                                        > On Thu, Nov 12, 2009 at 4:37 PM, sebaszipp <sebaszipp@...> wrote:
                                        >
                                        > >
                                        > >
                                        > >
                                        > > Hi Mark,
                                        > >
                                        > > Great blog. Thanks for clarifying in detail things about CQRS.
                                        > >
                                        > > Still a grey zone I'd like to get better is about AR load performance when
                                        > > the event storage is large enough to kill performance.
                                        > > I know rolling snapshots takes care of this field, but by rolling snapthost
                                        > > I might get an incomplete AR?
                                        > > Could you please explain this?
                                        > >
                                        > > Thanks.
                                        > >
                                        > >
                                        > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>,

                                        > > Mark Nijhof <Mark.Nijhof@> wrote:
                                        > > >
                                        > > > Hi,
                                        > > >
                                        > > > I finally got the first blog post about this published, it is long! Not
                                        > > so
                                        > > > much code, more the explanation behind it (as I understand it).
                                        > > >
                                        > > > Link: http://blog.fohjin.com/blog/2009/11/12/CQRS_a_la_Greg_Young
                                        > > >
                                        > > > -Mark
                                        > > >
                                        > > >
                                        > > > On Thu, Oct 29, 2009 at 1:09 AM, Mark Nijhof <mark.nijhof@> wrote:
                                        > > >
                                        > > > > Hi,
                                        > > > >
                                        > > > > Because that is a nasty home made implementation of a bus :) The
                                        > > Publish
                                        > > > > method needs to know the exact type of the command/event that gets
                                        > > passed in
                                        > > > > because that is used to get the correct xxxHandlers from the IoC
                                        > > container.
                                        > > > > I cannot use an Generic in the PublishMultiple because these
                                        > > commands/events
                                        > > > > are 99% of the time not of the same type. I will probably change it
                                        > > into
                                        > > > > something like this:
                                        > > > >
                                        > > http://codebetter.com/blogs/gregyoung/archive/2009/10/03/delegate-mapper.aspx
                                        > > > >
                                        > > > > Also one thing I like to highlight is that in this first version I am
                                        > > not
                                        > > > > using anything complex because I explicitly wanted to show that the
                                        > > core of
                                        > > > > this is actually very simple, if I started with NServiceBus and
                                        > > NHibernate
                                        > > > > than that would have taken away from the simplicity of this type of
                                        > > > > architecture. That is why I have implemented my own very simple ORM
                                        > > (one has
                                        > > > > to do that once in their career anyway right) and my own bus. I plan on
                                        > > > > continuing on this example by introducing these types of options as
                                        > > well,
                                        > > > > all do the event store will remain custom SQL, actually I will also
                                        > > > > implement one using SQL Server and that one will use a stored procedure
                                        > > ;)
                                        > > > >
                                        > > > > -Mark
                                        > > > >
                                        > > > >
                                        > > > >
                                        > > > > On Wed, Oct 28, 2009 at 8:16 PM, David Perfors <dnperfors@>wrote:
                                        > >
                                        > > > >
                                        > > > >>
                                        > > > >>
                                        > > > >> Hi Mark,
                                        > > > >>
                                        > > > >> Thanks a lot for this example. I was looking into the code and looked
                                        > > ad
                                        > > > >> the implementations of IBus and saw that it is using reflection for
                                        > > the
                                        > > > >> PublishMultiple method. Can you tell me (us) more about why you are
                                        > > doing
                                        > > > >> that instead of just calling the Publish method?
                                        > > > >>
                                        > > > >> Looking forward to the blogposts :)
                                        > > > >>
                                        > > > >> David.
                                        > > > >>
                                        > > > >> 2009/10/26 Mark Nijhof <Mark.Nijhof@>
                                        > >
                                        > > > >>
                                        > > > >>> Hi,
                                        > > > >>>
                                        > > > >>> Since multiple people have been asking for this and I feel that the
                                        > > > >>> core is good enough to share I thought I would share the repository
                                        > > > >>> here already. Disclaimer: Now keep in mind that this has not been
                                        > > > >>> reviewed by Greg yet and that I am still working on it. I am also
                                        > > > >>> working on a complete detailed blog post (or several) to explain what
                                        > > > >>> is going on and why (with diagrams and all that fancy stuff). Once
                                        > > > >>> that is done it will be published here: http://blog.fohjin.com/ I am
                                        > > > >>> currently finishing my specifications for the GUI and will split the
                                        > > > >>> existing domain specifications a bit more per scenario, but I think
                                        > > > >>> you will like what you see there (hope at least).
                                        > > > >>>
                                        > > > >>> The most interesting scenario is a transfer from one account to an
                                        > > > >>> other account.
                                        > > > >>>
                                        > > > >>> Link: http://github.com/MarkNijhof/Fohjin
                                        > > > >>>
                                        > > > >>> Note on SQLite: Because I am developing on x64 I have the x64 version
                                        > > > >>> of SQLite referenced in the projects, except for the test project
                                        > > > >>> because TestDriven.Net executes everything in x86. Now if you are
                                        > > > >>> running on a x86 machine all you have to do is copy the x86
                                        > > > >>> System.Data.SQLite.* from /lib/sqlite/bin to /lib/sqlite/bin/x64
                                        > > (this
                                        > > > >>> approach is tested). There are two different SQLite databases, one is
                                        > > > >>> the event store and the other is the reporting database. I haven't
                                        > > > >>> figured out yet how, but it is possible to load the SQLite databases
                                        > > > >>> in Visual Studio to inspect the content. Both databases are created
                                        > > on
                                        > > > >>> first use, and deleting them will give you a fresh start.
                                        > > > >>>
                                        > > > >>> I would like to hear your opinions, I am very enthusiastic about this
                                        > > > >>> architecture when there is a need for a domain.
                                        > > > >>>
                                        > > > >>> -Mark
                                        > > > >>>
                                        > > > >>>
                                        > > > >>> ------------------------------------
                                        > > > >>>
                                        > > > >>> Yahoo! Groups Links
                                        > > > >>>
                                        > > > >>>
                                        > > > >>>
                                        > > > >>>
                                        > > > >>
                                        > > > >>
                                        > > > >
                                        > > > >
                                        > > >
                                        > >
                                        > >
                                        > >
                                        >




                                        --
                                        Les erreurs de grammaire et de syntaxe ont été incluses pour m'assurer de votre attention
                                      • sebaszipp
                                        Great. Thanks Greg. I more question: As far as I ve been reading about CQS I ve been all examples matching the same association: AR - AGG where the AR is the
                                        Message 19 of 30 , Nov 12, 2009
                                          Great. Thanks Greg.

                                          I more question:

                                          As far as I've been reading about CQS I've been all examples matching the same association: AR -> AGG where the AR is the one firing up domain events. I would like to add another association supposing our graph is more complex than just AR -> AGG.

                                          In this case we would have the following graph:
                                          Order AR -> OrderSection AGG -> OrderLine AGG

                                          Suppose there are 2 rules dictating that products under 10 dollars should be placed into Section1 and the others should be placed into Section2. In the case a product that is $5 is bought we would fire up an event from the Order AR:

                                          super.apply(new ProductSaleEvent(sectionOneID, productDescription))

                                          and then the event handler of the Order AR should be:

                                          handle(ProductSaleEvent event)
                                          {
                                          OrderSection orderSection = orderSections.get(event.sectionId)
                                          if (orderSection == null) {
                                          orderSection = new OrderSection();
                                          orderSections.put(event.sectionId, orderSection);
                                          }
                                          orderSection.processSale(productDescription); // which will create a Line internally
                                          }

                                          Should be handled this way?
                                          I mean, the AR is the leading with the graph hierarchy no matter how deep it's?

                                          Cheers,


                                          --- In domaindrivendesign@yahoogroups.com, Greg Young <gregoryyoung1@...> wrote:
                                          >
                                          > Yes the snapshots are generally not in memory, they live in the event store.
                                          >
                                          > Cheers,
                                          >
                                          > Greg
                                          >
                                          > On Thu, Nov 12, 2009 at 8:30 PM, sebaszipp <sebaszipp@...> wrote:
                                          >
                                          > >
                                          > >
                                          > >
                                          > > I got it :)
                                          > >
                                          > > I don't know why I was relating the concept of a snapshot with a stack of
                                          > > events and not with the domain AR (and since I'm not an english native
                                          > > speaker I got a lil confused about the term 'rolling').
                                          > >
                                          > > So you take a picture of the domain entity after N events and then make the
                                          > > repository hold a reference to that picture indexed by its identity (ID) (or
                                          > > the separate process yoou mention)
                                          > >
                                          > > Let's assume you want to load the AR having the same ID that the picture
                                          > > hold by the repo has. You calculate the position in the event stack from
                                          > > where you would start replying events, then create an AR instance, copy its
                                          > > state with the picture (Memento) that you took previosly, and apply the
                                          > > events representing the DELTA.
                                          > >
                                          > > The Snapshot shouldn't be kept by the repo because we would run into the
                                          > > same performance problem if too many instances live in memory. I guess we
                                          > > should serialize the snapshot to disk or something similar?
                                          > >
                                          > > Am I ok?
                                          > >
                                          > > Thanks Mark.
                                          > >
                                          > >
                                          > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>,
                                          > > Mark Nijhof <Mark.Nijhof@> wrote:
                                          > > >
                                          > > > Your rolling snapshot will never be assumed to be the latest state of the
                                          > > > AR, after loading the snapshot the repository will always get all events
                                          > > > that have occurred after the snapshot was made. The process creating the
                                          > > > snapshots will most likely be a independent process that would just load
                                          > > AR
                                          > > > verify if a snapshot needs to be made. If this is the case it would make
                                          > > it.
                                          > > > Say after 100 events you want a snapshot. Instead of putting this
                                          > > > responsibility in the domain repository?
                                          > > >
                                          > > > So current version of the snapshot is 20 version of the last event is 25
                                          > > so
                                          > > > after loading the snapshot it also needs to replay the last 5 events.
                                          > > >
                                          > > > Does this make sense?
                                          > > >
                                          > > > -Mark
                                          > > >
                                          > > > On Thu, Nov 12, 2009 at 4:37 PM, sebaszipp <sebaszipp@> wrote:
                                          > > >
                                          > > > >
                                          > > > >
                                          > > > >
                                          > > > > Hi Mark,
                                          > > > >
                                          > > > > Great blog. Thanks for clarifying in detail things about CQRS.
                                          > > > >
                                          > > > > Still a grey zone I'd like to get better is about AR load performance
                                          > > when
                                          > > > > the event storage is large enough to kill performance.
                                          > > > > I know rolling snapshots takes care of this field, but by rolling
                                          > > snapthost
                                          > > > > I might get an incomplete AR?
                                          > > > > Could you please explain this?
                                          > > > >
                                          > > > > Thanks.
                                          > > > >
                                          > > > >
                                          > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                          > > <domaindrivendesign%40yahoogroups.com>,
                                          > >
                                          > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                          > > > > >
                                          > > > > > Hi,
                                          > > > > >
                                          > > > > > I finally got the first blog post about this published, it is long!
                                          > > Not
                                          > > > > so
                                          > > > > > much code, more the explanation behind it (as I understand it).
                                          > > > > >
                                          > > > > > Link: http://blog.fohjin.com/blog/2009/11/12/CQRS_a_la_Greg_Young
                                          > > > > >
                                          > > > > > -Mark
                                          > > > > >
                                          > > > > >
                                          > > > > > On Thu, Oct 29, 2009 at 1:09 AM, Mark Nijhof <mark.nijhof@> wrote:
                                          > > > > >
                                          > > > > > > Hi,
                                          > > > > > >
                                          > > > > > > Because that is a nasty home made implementation of a bus :) The
                                          > > > > Publish
                                          > > > > > > method needs to know the exact type of the command/event that gets
                                          > > > > passed in
                                          > > > > > > because that is used to get the correct xxxHandlers from the IoC
                                          > > > > container.
                                          > > > > > > I cannot use an Generic in the PublishMultiple because these
                                          > > > > commands/events
                                          > > > > > > are 99% of the time not of the same type. I will probably change it
                                          > > > > into
                                          > > > > > > something like this:
                                          > > > > > >
                                          > > > >
                                          > > http://codebetter.com/blogs/gregyoung/archive/2009/10/03/delegate-mapper.aspx
                                          > > > > > >
                                          > > > > > > Also one thing I like to highlight is that in this first version I
                                          > > am
                                          > > > > not
                                          > > > > > > using anything complex because I explicitly wanted to show that the
                                          > > > > core of
                                          > > > > > > this is actually very simple, if I started with NServiceBus and
                                          > > > > NHibernate
                                          > > > > > > than that would have taken away from the simplicity of this type of
                                          > > > > > > architecture. That is why I have implemented my own very simple ORM
                                          > > > > (one has
                                          > > > > > > to do that once in their career anyway right) and my own bus. I
                                          > > plan on
                                          > > > > > > continuing on this example by introducing these types of options as
                                          > > > > well,
                                          > > > > > > all do the event store will remain custom SQL, actually I will also
                                          > > > > > > implement one using SQL Server and that one will use a stored
                                          > > procedure
                                          > > > > ;)
                                          > > > > > >
                                          > > > > > > -Mark
                                          > > > > > >
                                          > > > > > >
                                          > > > > > >
                                          > > > > > > On Wed, Oct 28, 2009 at 8:16 PM, David Perfors <dnperfors@>wrote:
                                          > > > >
                                          > > > > > >
                                          > > > > > >>
                                          > > > > > >>
                                          > > > > > >> Hi Mark,
                                          > > > > > >>
                                          > > > > > >> Thanks a lot for this example. I was looking into the code and
                                          > > looked
                                          > > > > ad
                                          > > > > > >> the implementations of IBus and saw that it is using reflection
                                          > > for
                                          > > > > the
                                          > > > > > >> PublishMultiple method. Can you tell me (us) more about why you
                                          > > are
                                          > > > > doing
                                          > > > > > >> that instead of just calling the Publish method?
                                          > > > > > >>
                                          > > > > > >> Looking forward to the blogposts :)
                                          > > > > > >>
                                          > > > > > >> David.
                                          > > > > > >>
                                          > > > > > >> 2009/10/26 Mark Nijhof <Mark.Nijhof@>
                                          > > > >
                                          > > > > > >>
                                          > > > > > >>> Hi,
                                          > > > > > >>>
                                          > > > > > >>> Since multiple people have been asking for this and I feel that
                                          > > the
                                          > > > > > >>> core is good enough to share I thought I would share the
                                          > > repository
                                          > > > > > >>> here already. Disclaimer: Now keep in mind that this has not been
                                          > > > > > >>> reviewed by Greg yet and that I am still working on it. I am also
                                          > > > > > >>> working on a complete detailed blog post (or several) to explain
                                          > > what
                                          > > > > > >>> is going on and why (with diagrams and all that fancy stuff).
                                          > > Once
                                          > > > > > >>> that is done it will be published here: http://blog.fohjin.com/I am
                                          > > > > > >>> currently finishing my specifications for the GUI and will split
                                          > > the
                                          > > > > > >>> existing domain specifications a bit more per scenario, but I
                                          > > think
                                          > > > > > >>> you will like what you see there (hope at least).
                                          > > > > > >>>
                                          > > > > > >>> The most interesting scenario is a transfer from one account to
                                          > > an
                                          > > > > > >>> other account.
                                          > > > > > >>>
                                          > > > > > >>> Link: http://github.com/MarkNijhof/Fohjin
                                          > > > > > >>>
                                          > > > > > >>> Note on SQLite: Because I am developing on x64 I have the x64
                                          > > version
                                          > > > > > >>> of SQLite referenced in the projects, except for the test project
                                          > > > > > >>> because TestDriven.Net executes everything in x86. Now if you are
                                          > > > > > >>> running on a x86 machine all you have to do is copy the x86
                                          > > > > > >>> System.Data.SQLite.* from /lib/sqlite/bin to /lib/sqlite/bin/x64
                                          > > > > (this
                                          > > > > > >>> approach is tested). There are two different SQLite databases,
                                          > > one is
                                          > > > > > >>> the event store and the other is the reporting database. I
                                          > > haven't
                                          > > > > > >>> figured out yet how, but it is possible to load the SQLite
                                          > > databases
                                          > > > > > >>> in Visual Studio to inspect the content. Both databases are
                                          > > created
                                          > > > > on
                                          > > > > > >>> first use, and deleting them will give you a fresh start.
                                          > > > > > >>>
                                          > > > > > >>> I would like to hear your opinions, I am very enthusiastic about
                                          > > this
                                          > > > > > >>> architecture when there is a need for a domain.
                                          > > > > > >>>
                                          > > > > > >>> -Mark
                                          > > > > > >>>
                                          > > > > > >>>
                                          > > > > > >>> ------------------------------------
                                          > > > > > >>>
                                          > > > > > >>> Yahoo! Groups Links
                                          > > > > > >>>
                                          > > > > > >>>
                                          > > > > > >>>
                                          > > > > > >>>
                                          > > > > > >>
                                          > > > > > >>
                                          > > > > > >
                                          > > > > > >
                                          > > > > >
                                          > > > >
                                          > > > >
                                          > > > >
                                          > > >
                                          > >
                                          > >
                                          > >
                                          >
                                          >
                                          >
                                          > --
                                          > Les erreurs de grammaire et de syntaxe ont été incluses pour m'assurer de
                                          > votre attention
                                          >
                                        • Mark Nijhof
                                          Each AGG can apply its own events and store them in itself, then when you ask for changes from the AR it will ask changes from it s AGG. Loading events from
                                          Message 20 of 30 , Nov 12, 2009
                                            Each AGG can apply its own events and store them in itself, then when you ask for changes from the AR it will ask changes from it's AGG.

                                            Loading events from history would load them all in the AR which would delegate them back to the AGG. I am not 100% sure yet what the best approach for this is. You could just send all of them and have the AGG decide which one to skip, or you could make the AR aware what types of events need to be forwarded to the AGG. This can be done by creating an event handler in the AR that would just forward the event to the specific AGG. But if you have collections of AGG then this would be a problem.

                                            -Mark


                                            On Thu, Nov 12, 2009 at 8:46 PM, sebaszipp <sebaszipp@...> wrote:
                                             


                                            Great. Thanks Greg.

                                            I more question:

                                            As far as I've been reading about CQS I've been all examples matching the same association: AR -> AGG where the AR is the one firing up domain events. I would like to add another association supposing our graph is more complex than just AR -> AGG.

                                            In this case we would have the following graph:
                                            Order AR -> OrderSection AGG -> OrderLine AGG

                                            Suppose there are 2 rules dictating that products under 10 dollars should be placed into Section1 and the others should be placed into Section2. In the case a product that is $5 is bought we would fire up an event from the Order AR:

                                            super.apply(new ProductSaleEvent(sectionOneID, productDescription))

                                            and then the event handler of the Order AR should be:

                                            handle(ProductSaleEvent event)
                                            {
                                            OrderSection orderSection = orderSections.get(event.sectionId)
                                            if (orderSection == null) {
                                            orderSection = new OrderSection();
                                            orderSections.put(event.sectionId, orderSection);
                                            }
                                            orderSection.processSale(productDescription); // which will create a Line internally
                                            }

                                            Should be handled this way?
                                            I mean, the AR is the leading with the graph hierarchy no matter how deep it's?

                                            Cheers,



                                            --- In domaindrivendesign@yahoogroups.com, Greg Young <gregoryyoung1@...> wrote:
                                            >
                                            > Yes the snapshots are generally not in memory, they live in the event store.
                                            >
                                            > Cheers,
                                            >
                                            > Greg
                                            >
                                            > On Thu, Nov 12, 2009 at 8:30 PM, sebaszipp <sebaszipp@...> wrote:
                                            >
                                            > >
                                            > >
                                            > >
                                            > > I got it :)
                                            > >
                                            > > I don't know why I was relating the concept of a snapshot with a stack of
                                            > > events and not with the domain AR (and since I'm not an english native
                                            > > speaker I got a lil confused about the term 'rolling').
                                            > >
                                            > > So you take a picture of the domain entity after N events and then make the
                                            > > repository hold a reference to that picture indexed by its identity (ID) (or
                                            > > the separate process yoou mention)
                                            > >
                                            > > Let's assume you want to load the AR having the same ID that the picture
                                            > > hold by the repo has. You calculate the position in the event stack from
                                            > > where you would start replying events, then create an AR instance, copy its
                                            > > state with the picture (Memento) that you took previosly, and apply the
                                            > > events representing the DELTA.
                                            > >
                                            > > The Snapshot shouldn't be kept by the repo because we would run into the
                                            > > same performance problem if too many instances live in memory. I guess we
                                            > > should serialize the snapshot to disk or something similar?
                                            > >
                                            > > Am I ok?
                                            > >
                                            > > Thanks Mark.
                                            > >
                                            > >
                                            > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>,
                                            > > Mark Nijhof <Mark.Nijhof@> wrote:
                                            > > >
                                            > > > Your rolling snapshot will never be assumed to be the latest state of the
                                            > > > AR, after loading the snapshot the repository will always get all events
                                            > > > that have occurred after the snapshot was made. The process creating the
                                            > > > snapshots will most likely be a independent process that would just load
                                            > > AR
                                            > > > verify if a snapshot needs to be made. If this is the case it would make
                                            > > it.
                                            > > > Say after 100 events you want a snapshot. Instead of putting this
                                            > > > responsibility in the domain repository?
                                            > > >
                                            > > > So current version of the snapshot is 20 version of the last event is 25
                                            > > so
                                            > > > after loading the snapshot it also needs to replay the last 5 events.
                                            > > >
                                            > > > Does this make sense?
                                            > > >
                                            > > > -Mark
                                            > > >
                                            > > > On Thu, Nov 12, 2009 at 4:37 PM, sebaszipp <sebaszipp@> wrote:
                                            > > >
                                            > > > >
                                            > > > >
                                            > > > >
                                            > > > > Hi Mark,
                                            > > > >
                                            > > > > Great blog. Thanks for clarifying in detail things about CQRS.
                                            > > > >
                                            > > > > Still a grey zone I'd like to get better is about AR load performance
                                            > > when
                                            > > > > the event storage is large enough to kill performance.
                                            > > > > I know rolling snapshots takes care of this field, but by rolling
                                            > > snapthost
                                            > > > > I might get an incomplete AR?
                                            > > > > Could you please explain this?
                                            > > > >
                                            > > > > Thanks.
                                            > > > >
                                            > > > >
                                            > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                            > > <domaindrivendesign%40yahoogroups.com>,
                                            > >
                                            > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                            > > > > >
                                            > > > > > Hi,
                                            > > > > >
                                            > > > > > I finally got the first blog post about this published, it is long!
                                            > > Not
                                            > > > > so
                                            > > > > > much code, more the explanation behind it (as I understand it).
                                            > > > > >
                                            > > > > > Link: http://blog.fohjin.com/blog/2009/11/12/CQRS_a_la_Greg_Young
                                            > > > > >
                                            > > > > > -Mark
                                            > > > > >
                                            > > > > >
                                            > > > > > On Thu, Oct 29, 2009 at 1:09 AM, Mark Nijhof <mark.nijhof@> wrote:
                                            > > > > >
                                            > > > > > > Hi,
                                            > > > > > >
                                            > > > > > > Because that is a nasty home made implementation of a bus :) The
                                            > > > > Publish
                                            > > > > > > method needs to know the exact type of the command/event that gets
                                            > > > > passed in
                                            > > > > > > because that is used to get the correct xxxHandlers from the IoC
                                            > > > > container.
                                            > > > > > > I cannot use an Generic in the PublishMultiple because these
                                            > > > > commands/events
                                            > > > > > > are 99% of the time not of the same type. I will probably change it
                                            > > > > into
                                            > > > > > > something like this:
                                            > > > > > >
                                            > > > >
                                            > > http://codebetter.com/blogs/gregyoung/archive/2009/10/03/delegate-mapper.aspx
                                            > > > > > >
                                            > > > > > > Also one thing I like to highlight is that in this first version I
                                            > > am
                                            > > > > not
                                            > > > > > > using anything complex because I explicitly wanted to show that the
                                            > > > > core of
                                            > > > > > > this is actually very simple, if I started with NServiceBus and
                                            > > > > NHibernate
                                            > > > > > > than that would have taken away from the simplicity of this type of
                                            > > > > > > architecture. That is why I have implemented my own very simple ORM
                                            > > > > (one has
                                            > > > > > > to do that once in their career anyway right) and my own bus. I
                                            > > plan on
                                            > > > > > > continuing on this example by introducing these types of options as
                                            > > > > well,
                                            > > > > > > all do the event store will remain custom SQL, actually I will also
                                            > > > > > > implement one using SQL Server and that one will use a stored
                                            > > procedure
                                            > > > > ;)
                                            > > > > > >
                                            > > > > > > -Mark
                                            > > > > > >
                                            > > > > > >
                                            > > > > > >
                                            > > > > > > On Wed, Oct 28, 2009 at 8:16 PM, David Perfors <dnperfors@>wrote:
                                            > > > >
                                            > > > > > >
                                            > > > > > >>
                                            > > > > > >>
                                            > > > > > >> Hi Mark,
                                            > > > > > >>
                                            > > > > > >> Thanks a lot for this example. I was looking into the code and
                                            > > looked
                                            > > > > ad
                                            > > > > > >> the implementations of IBus and saw that it is using reflection
                                            > > for
                                            > > > > the
                                            > > > > > >> PublishMultiple method. Can you tell me (us) more about why you
                                            > > are
                                            > > > > doing
                                            > > > > > >> that instead of just calling the Publish method?
                                            > > > > > >>
                                            > > > > > >> Looking forward to the blogposts :)
                                            > > > > > >>
                                            > > > > > >> David.
                                            > > > > > >>
                                            > > > > > >> 2009/10/26 Mark Nijhof <Mark.Nijhof@>
                                            > > > >
                                            > > > > > >>
                                            > > > > > >>> Hi,
                                            > > > > > >>>
                                            > > > > > >>> Since multiple people have been asking for this and I feel that
                                            > > the
                                            > > > > > >>> core is good enough to share I thought I would share the
                                            > > repository
                                            > > > > > >>> here already. Disclaimer: Now keep in mind that this has not been
                                            > > > > > >>> reviewed by Greg yet and that I am still working on it. I am also
                                            > > > > > >>> working on a complete detailed blog post (or several) to explain
                                            > > what
                                            > > > > > >>> is going on and why (with diagrams and all that fancy stuff).
                                            > > Once
                                            > > > > > >>> that is done it will be published here: http://blog.fohjin.com/I am
                                            > > > > > >>> currently finishing my specifications for the GUI and will split
                                            > > the
                                            > > > > > >>> existing domain specifications a bit more per scenario, but I
                                            > > think
                                            > > > > > >>> you will like what you see there (hope at least).
                                            > > > > > >>>
                                            > > > > > >>> The most interesting scenario is a transfer from one account to
                                            > > an
                                            > > > > > >>> other account.
                                            > > > > > >>>
                                            > > > > > >>> Link: http://github.com/MarkNijhof/Fohjin
                                            > > > > > >>>
                                            > > > > > >>> Note on SQLite: Because I am developing on x64 I have the x64
                                            > > version
                                            > > > > > >>> of SQLite referenced in the projects, except for the test project
                                            > > > > > >>> because TestDriven.Net executes everything in x86. Now if you are
                                            > > > > > >>> running on a x86 machine all you have to do is copy the x86
                                            > > > > > >>> System.Data.SQLite.* from /lib/sqlite/bin to /lib/sqlite/bin/x64
                                            > > > > (this
                                            > > > > > >>> approach is tested). There are two different SQLite databases,
                                            > > one is
                                            > > > > > >>> the event store and the other is the reporting database. I
                                            > > haven't
                                            > > > > > >>> figured out yet how, but it is possible to load the SQLite
                                            > > databases
                                            > > > > > >>> in Visual Studio to inspect the content. Both databases are
                                            > > created
                                            > > > > on
                                            > > > > > >>> first use, and deleting them will give you a fresh start.
                                            > > > > > >>>
                                            > > > > > >>> I would like to hear your opinions, I am very enthusiastic about
                                            > > this
                                            > > > > > >>> architecture when there is a need for a domain.
                                            > > > > > >>>
                                            > > > > > >>> -Mark
                                            > > > > > >>>
                                            > > > > > >>>
                                            > > > > > >>> ------------------------------------
                                            > > > > > >>>
                                            > > > > > >>> Yahoo! Groups Links
                                            > > > > > >>>
                                            > > > > > >>>
                                            > > > > > >>>
                                            > > > > > >>>
                                            > > > > > >>
                                            > > > > > >>
                                            > > > > > >
                                            > > > > > >
                                            > > > > >
                                            > > > >
                                            > > > >
                                            > > > >
                                            > > >
                                            > >
                                            > >
                                            > >
                                            >
                                            >
                                            >
                                            > --
                                            > Les erreurs de grammaire et de syntaxe ont été incluses pour m'assurer de
                                            > votre attention
                                            >


                                          • sebaszipp
                                            Yes, for the case we have predifined/fixed order sections for an order we could fire up events according to the section in cuestion. But in case of having
                                            Message 21 of 30 , Nov 12, 2009
                                              Yes, for the case we have predifined/fixed order sections for an order we could fire up events according to the section in cuestion. But in case of having collection of AGGs (AR -> List<AGG> -> List<AGG>) the situation comes kind of weird.
                                              Maybe we should take a look into our BC, in order to rethink and see whether the BC graph should be pruned and the remaing is responsability of another BC?


                                              --- In domaindrivendesign@yahoogroups.com, Mark Nijhof <Mark.Nijhof@...> wrote:
                                              >
                                              > Each AGG can apply its own events and store them in itself, then when you
                                              > ask for changes from the AR it will ask changes from it's AGG.
                                              >
                                              > Loading events from history would load them all in the AR which would
                                              > delegate them back to the AGG. I am not 100% sure yet what the best approach
                                              > for this is. You could just send all of them and have the AGG decide which
                                              > one to skip, or you could make the AR aware what types of events need to be
                                              > forwarded to the AGG. This can be done by creating an event handler in the
                                              > AR that would just forward the event to the specific AGG. But if you have
                                              > collections of AGG then this would be a problem.
                                              >
                                              > -Mark
                                              >
                                              >
                                              > On Thu, Nov 12, 2009 at 8:46 PM, sebaszipp <sebaszipp@...> wrote:
                                              >
                                              > >
                                              > >
                                              > >
                                              > > Great. Thanks Greg.
                                              > >
                                              > > I more question:
                                              > >
                                              > > As far as I've been reading about CQS I've been all examples matching the
                                              > > same association: AR -> AGG where the AR is the one firing up domain events.
                                              > > I would like to add another association supposing our graph is more complex
                                              > > than just AR -> AGG.
                                              > >
                                              > > In this case we would have the following graph:
                                              > > Order AR -> OrderSection AGG -> OrderLine AGG
                                              > >
                                              > > Suppose there are 2 rules dictating that products under 10 dollars should
                                              > > be placed into Section1 and the others should be placed into Section2. In
                                              > > the case a product that is $5 is bought we would fire up an event from the
                                              > > Order AR:
                                              > >
                                              > > super.apply(new ProductSaleEvent(sectionOneID, productDescription))
                                              > >
                                              > > and then the event handler of the Order AR should be:
                                              > >
                                              > > handle(ProductSaleEvent event)
                                              > > {
                                              > > OrderSection orderSection = orderSections.get(event.sectionId)
                                              > > if (orderSection == null) {
                                              > > orderSection = new OrderSection();
                                              > > orderSections.put(event.sectionId, orderSection);
                                              > > }
                                              > > orderSection.processSale(productDescription); // which will create a Line
                                              > > internally
                                              > > }
                                              > >
                                              > > Should be handled this way?
                                              > > I mean, the AR is the leading with the graph hierarchy no matter how deep
                                              > > it's?
                                              > >
                                              > > Cheers,
                                              > >
                                              > >
                                              > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>,
                                              > > Greg Young <gregoryyoung1@> wrote:
                                              > > >
                                              > > > Yes the snapshots are generally not in memory, they live in the event
                                              > > store.
                                              > > >
                                              > > > Cheers,
                                              > > >
                                              > > > Greg
                                              > > >
                                              > > > On Thu, Nov 12, 2009 at 8:30 PM, sebaszipp <sebaszipp@> wrote:
                                              > > >
                                              > > > >
                                              > > > >
                                              > > > >
                                              > > > > I got it :)
                                              > > > >
                                              > > > > I don't know why I was relating the concept of a snapshot with a stack
                                              > > of
                                              > > > > events and not with the domain AR (and since I'm not an english native
                                              > > > > speaker I got a lil confused about the term 'rolling').
                                              > > > >
                                              > > > > So you take a picture of the domain entity after N events and then make
                                              > > the
                                              > > > > repository hold a reference to that picture indexed by its identity
                                              > > (ID) (or
                                              > > > > the separate process yoou mention)
                                              > > > >
                                              > > > > Let's assume you want to load the AR having the same ID that the
                                              > > picture
                                              > > > > hold by the repo has. You calculate the position in the event stack
                                              > > from
                                              > > > > where you would start replying events, then create an AR instance, copy
                                              > > its
                                              > > > > state with the picture (Memento) that you took previosly, and apply the
                                              > > > > events representing the DELTA.
                                              > > > >
                                              > > > > The Snapshot shouldn't be kept by the repo because we would run into
                                              > > the
                                              > > > > same performance problem if too many instances live in memory. I guess
                                              > > we
                                              > > > > should serialize the snapshot to disk or something similar?
                                              > > > >
                                              > > > > Am I ok?
                                              > > > >
                                              > > > > Thanks Mark.
                                              > > > >
                                              > > > >
                                              > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                              > > <domaindrivendesign%40yahoogroups.com>,
                                              > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                              > > > > >
                                              > > > > > Your rolling snapshot will never be assumed to be the latest state of
                                              > > the
                                              > > > > > AR, after loading the snapshot the repository will always get all
                                              > > events
                                              > > > > > that have occurred after the snapshot was made. The process creating
                                              > > the
                                              > > > > > snapshots will most likely be a independent process that would just
                                              > > load
                                              > > > > AR
                                              > > > > > verify if a snapshot needs to be made. If this is the case it would
                                              > > make
                                              > > > > it.
                                              > > > > > Say after 100 events you want a snapshot. Instead of putting this
                                              > > > > > responsibility in the domain repository?
                                              > > > > >
                                              > > > > > So current version of the snapshot is 20 version of the last event is
                                              > > 25
                                              > > > > so
                                              > > > > > after loading the snapshot it also needs to replay the last 5 events.
                                              > > > > >
                                              > > > > > Does this make sense?
                                              > > > > >
                                              > > > > > -Mark
                                              > > > > >
                                              > > > > > On Thu, Nov 12, 2009 at 4:37 PM, sebaszipp <sebaszipp@> wrote:
                                              > > > > >
                                              > > > > > >
                                              > > > > > >
                                              > > > > > >
                                              > > > > > > Hi Mark,
                                              > > > > > >
                                              > > > > > > Great blog. Thanks for clarifying in detail things about CQRS.
                                              > > > > > >
                                              > > > > > > Still a grey zone I'd like to get better is about AR load
                                              > > performance
                                              > > > > when
                                              > > > > > > the event storage is large enough to kill performance.
                                              > > > > > > I know rolling snapshots takes care of this field, but by rolling
                                              > > > > snapthost
                                              > > > > > > I might get an incomplete AR?
                                              > > > > > > Could you please explain this?
                                              > > > > > >
                                              > > > > > > Thanks.
                                              > > > > > >
                                              > > > > > >
                                              > > > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                              > > <domaindrivendesign%40yahoogroups.com>
                                              > > > > <domaindrivendesign%40yahoogroups.com>,
                                              > > > >
                                              > > > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                              > > > > > > >
                                              > > > > > > > Hi,
                                              > > > > > > >
                                              > > > > > > > I finally got the first blog post about this published, it is
                                              > > long!
                                              > > > > Not
                                              > > > > > > so
                                              > > > > > > > much code, more the explanation behind it (as I understand it).
                                              > > > > > > >
                                              > > > > > > > Link:
                                              > > http://blog.fohjin.com/blog/2009/11/12/CQRS_a_la_Greg_Young
                                              > > > > > > >
                                              > > > > > > > -Mark
                                              > > > > > > >
                                              > > > > > > >
                                              > > > > > > > On Thu, Oct 29, 2009 at 1:09 AM, Mark Nijhof <mark.nijhof@>
                                              > > wrote:
                                              > > > > > > >
                                              > > > > > > > > Hi,
                                              > > > > > > > >
                                              > > > > > > > > Because that is a nasty home made implementation of a bus :)
                                              > > The
                                              > > > > > > Publish
                                              > > > > > > > > method needs to know the exact type of the command/event that
                                              > > gets
                                              > > > > > > passed in
                                              > > > > > > > > because that is used to get the correct xxxHandlers from the
                                              > > IoC
                                              > > > > > > container.
                                              > > > > > > > > I cannot use an Generic in the PublishMultiple because these
                                              > > > > > > commands/events
                                              > > > > > > > > are 99% of the time not of the same type. I will probably
                                              > > change it
                                              > > > > > > into
                                              > > > > > > > > something like this:
                                              > > > > > > > >
                                              > > > > > >
                                              > > > >
                                              > > http://codebetter.com/blogs/gregyoung/archive/2009/10/03/delegate-mapper.aspx
                                              > > > > > > > >
                                              > > > > > > > > Also one thing I like to highlight is that in this first
                                              > > version I
                                              > > > > am
                                              > > > > > > not
                                              > > > > > > > > using anything complex because I explicitly wanted to show that
                                              > > the
                                              > > > > > > core of
                                              > > > > > > > > this is actually very simple, if I started with NServiceBus and
                                              > > > > > > NHibernate
                                              > > > > > > > > than that would have taken away from the simplicity of this
                                              > > type of
                                              > > > > > > > > architecture. That is why I have implemented my own very simple
                                              > > ORM
                                              > > > > > > (one has
                                              > > > > > > > > to do that once in their career anyway right) and my own bus. I
                                              > > > > plan on
                                              > > > > > > > > continuing on this example by introducing these types of
                                              > > options as
                                              > > > > > > well,
                                              > > > > > > > > all do the event store will remain custom SQL, actually I will
                                              > > also
                                              > > > > > > > > implement one using SQL Server and that one will use a stored
                                              > > > > procedure
                                              > > > > > > ;)
                                              > > > > > > > >
                                              > > > > > > > > -Mark
                                              > > > > > > > >
                                              > > > > > > > >
                                              > > > > > > > >
                                              > > > > > > > > On Wed, Oct 28, 2009 at 8:16 PM, David Perfors <dnperfors@
                                              > > >wrote:
                                              > > > > > >
                                              > > > > > > > >
                                              > > > > > > > >>
                                              > > > > > > > >>
                                              > > > > > > > >> Hi Mark,
                                              > > > > > > > >>
                                              > > > > > > > >> Thanks a lot for this example. I was looking into the code and
                                              > > > > looked
                                              > > > > > > ad
                                              > > > > > > > >> the implementations of IBus and saw that it is using
                                              > > reflection
                                              > > > > for
                                              > > > > > > the
                                              > > > > > > > >> PublishMultiple method. Can you tell me (us) more about why
                                              > > you
                                              > > > > are
                                              > > > > > > doing
                                              > > > > > > > >> that instead of just calling the Publish method?
                                              > > > > > > > >>
                                              > > > > > > > >> Looking forward to the blogposts :)
                                              > > > > > > > >>
                                              > > > > > > > >> David.
                                              > > > > > > > >>
                                              > > > > > > > >> 2009/10/26 Mark Nijhof <Mark.Nijhof@>
                                              > > > > > >
                                              > > > > > > > >>
                                              > > > > > > > >>> Hi,
                                              > > > > > > > >>>
                                              > > > > > > > >>> Since multiple people have been asking for this and I feel
                                              > > that
                                              > > > > the
                                              > > > > > > > >>> core is good enough to share I thought I would share the
                                              > > > > repository
                                              > > > > > > > >>> here already. Disclaimer: Now keep in mind that this has not
                                              > > been
                                              > > > > > > > >>> reviewed by Greg yet and that I am still working on it. I am
                                              > > also
                                              > > > > > > > >>> working on a complete detailed blog post (or several) to
                                              > > explain
                                              > > > > what
                                              > > > > > > > >>> is going on and why (with diagrams and all that fancy stuff).
                                              > > > > Once
                                              > > > > > > > >>> that is done it will be published here:
                                              > > http://blog.fohjin.com/I am
                                              > > > > > > > >>> currently finishing my specifications for the GUI and will
                                              > > split
                                              > > > > the
                                              > > > > > > > >>> existing domain specifications a bit more per scenario, but I
                                              > > > > think
                                              > > > > > > > >>> you will like what you see there (hope at least).
                                              > > > > > > > >>>
                                              > > > > > > > >>> The most interesting scenario is a transfer from one account
                                              > > to
                                              > > > > an
                                              > > > > > > > >>> other account.
                                              > > > > > > > >>>
                                              > > > > > > > >>> Link: http://github.com/MarkNijhof/Fohjin
                                              > > > > > > > >>>
                                              > > > > > > > >>> Note on SQLite: Because I am developing on x64 I have the x64
                                              > > > > version
                                              > > > > > > > >>> of SQLite referenced in the projects, except for the test
                                              > > project
                                              > > > > > > > >>> because TestDriven.Net executes everything in x86. Now if you
                                              > > are
                                              > > > > > > > >>> running on a x86 machine all you have to do is copy the x86
                                              > > > > > > > >>> System.Data.SQLite.* from /lib/sqlite/bin to
                                              > > /lib/sqlite/bin/x64
                                              > > > > > > (this
                                              > > > > > > > >>> approach is tested). There are two different SQLite
                                              > > databases,
                                              > > > > one is
                                              > > > > > > > >>> the event store and the other is the reporting database. I
                                              > > > > haven't
                                              > > > > > > > >>> figured out yet how, but it is possible to load the SQLite
                                              > > > > databases
                                              > > > > > > > >>> in Visual Studio to inspect the content. Both databases are
                                              > > > > created
                                              > > > > > > on
                                              > > > > > > > >>> first use, and deleting them will give you a fresh start.
                                              > > > > > > > >>>
                                              > > > > > > > >>> I would like to hear your opinions, I am very enthusiastic
                                              > > about
                                              > > > > this
                                              > > > > > > > >>> architecture when there is a need for a domain.
                                              > > > > > > > >>>
                                              > > > > > > > >>> -Mark
                                              > > > > > > > >>>
                                              > > > > > > > >>>
                                              > > > > > > > >>> ------------------------------------
                                              > > > > > > > >>>
                                              > > > > > > > >>> Yahoo! Groups Links
                                              > > > > > > > >>>
                                              > > > > > > > >>>
                                              > > > > > > > >>>
                                              > > > > > > > >>>
                                              > > > > > > > >>
                                              > > > > > > > >>
                                              > > > > > > > >
                                              > > > > > > > >
                                              > > > > > > >
                                              > > > > > >
                                              > > > > > >
                                              > > > > > >
                                              > > > > >
                                              > > > >
                                              > > > >
                                              > > > >
                                              > > >
                                              > > >
                                              > > >
                                              > > > --
                                              > > > Les erreurs de grammaire et de syntaxe ont été incluses pour m'assurer de
                                              > > > votre attention
                                              > > >
                                              > >
                                              > >
                                              > >
                                              >
                                            • Mark Nijhof
                                              You could still have the AR be responsible for managing the collection including the internal state, but that feels wrong. -Mark ... You could still have the
                                              Message 22 of 30 , Nov 12, 2009
                                                You could still have the AR be responsible for managing the collection including the internal state, but that feels wrong.

                                                -Mark

                                                On Thu, Nov 12, 2009 at 9:32 PM, sebaszipp <sebaszipp@...> wrote:
                                                 


                                                Yes, for the case we have predifined/fixed order sections for an order we could fire up events according to the section in cuestion. But in case of having collection of AGGs (AR -> List<AGG> -> List<AGG>) the situation comes kind of weird.
                                                Maybe we should take a look into our BC, in order to rethink and see whether the BC graph should be pruned and the remaing is responsability of another BC?



                                                --- In domaindrivendesign@yahoogroups.com, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                >
                                                > Each AGG can apply its own events and store them in itself, then when you
                                                > ask for changes from the AR it will ask changes from it's AGG.
                                                >
                                                > Loading events from history would load them all in the AR which would
                                                > delegate them back to the AGG. I am not 100% sure yet what the best approach
                                                > for this is. You could just send all of them and have the AGG decide which
                                                > one to skip, or you could make the AR aware what types of events need to be
                                                > forwarded to the AGG. This can be done by creating an event handler in the
                                                > AR that would just forward the event to the specific AGG. But if you have
                                                > collections of AGG then this would be a problem.
                                                >
                                                > -Mark
                                                >
                                                >
                                                > On Thu, Nov 12, 2009 at 8:46 PM, sebaszipp <sebaszipp@...> wrote:
                                                >
                                                > >
                                                > >
                                                > >
                                                > > Great. Thanks Greg.
                                                > >
                                                > > I more question:
                                                > >
                                                > > As far as I've been reading about CQS I've been all examples matching the
                                                > > same association: AR -> AGG where the AR is the one firing up domain events.
                                                > > I would like to add another association supposing our graph is more complex
                                                > > than just AR -> AGG.
                                                > >
                                                > > In this case we would have the following graph:
                                                > > Order AR -> OrderSection AGG -> OrderLine AGG
                                                > >
                                                > > Suppose there are 2 rules dictating that products under 10 dollars should
                                                > > be placed into Section1 and the others should be placed into Section2. In
                                                > > the case a product that is $5 is bought we would fire up an event from the
                                                > > Order AR:
                                                > >
                                                > > super.apply(new ProductSaleEvent(sectionOneID, productDescription))
                                                > >
                                                > > and then the event handler of the Order AR should be:
                                                > >
                                                > > handle(ProductSaleEvent event)
                                                > > {
                                                > > OrderSection orderSection = orderSections.get(event.sectionId)
                                                > > if (orderSection == null) {
                                                > > orderSection = new OrderSection();
                                                > > orderSections.put(event.sectionId, orderSection);
                                                > > }
                                                > > orderSection.processSale(productDescription); // which will create a Line
                                                > > internally
                                                > > }
                                                > >
                                                > > Should be handled this way?
                                                > > I mean, the AR is the leading with the graph hierarchy no matter how deep
                                                > > it's?
                                                > >
                                                > > Cheers,
                                                > >
                                                > >
                                                > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>,

                                                > > Greg Young <gregoryyoung1@> wrote:
                                                > > >
                                                > > > Yes the snapshots are generally not in memory, they live in the event
                                                > > store.
                                                > > >
                                                > > > Cheers,
                                                > > >
                                                > > > Greg
                                                > > >
                                                > > > On Thu, Nov 12, 2009 at 8:30 PM, sebaszipp <sebaszipp@> wrote:
                                                > > >
                                                > > > >
                                                > > > >
                                                > > > >
                                                > > > > I got it :)
                                                > > > >
                                                > > > > I don't know why I was relating the concept of a snapshot with a stack
                                                > > of
                                                > > > > events and not with the domain AR (and since I'm not an english native
                                                > > > > speaker I got a lil confused about the term 'rolling').
                                                > > > >
                                                > > > > So you take a picture of the domain entity after N events and then make
                                                > > the
                                                > > > > repository hold a reference to that picture indexed by its identity
                                                > > (ID) (or
                                                > > > > the separate process yoou mention)
                                                > > > >
                                                > > > > Let's assume you want to load the AR having the same ID that the
                                                > > picture
                                                > > > > hold by the repo has. You calculate the position in the event stack
                                                > > from
                                                > > > > where you would start replying events, then create an AR instance, copy
                                                > > its
                                                > > > > state with the picture (Memento) that you took previosly, and apply the
                                                > > > > events representing the DELTA.
                                                > > > >
                                                > > > > The Snapshot shouldn't be kept by the repo because we would run into
                                                > > the
                                                > > > > same performance problem if too many instances live in memory. I guess
                                                > > we
                                                > > > > should serialize the snapshot to disk or something similar?
                                                > > > >
                                                > > > > Am I ok?
                                                > > > >
                                                > > > > Thanks Mark.
                                                > > > >
                                                > > > >
                                                > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                                > > <domaindrivendesign%40yahoogroups.com>,
                                                > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                                > > > > >
                                                > > > > > Your rolling snapshot will never be assumed to be the latest state of
                                                > > the
                                                > > > > > AR, after loading the snapshot the repository will always get all
                                                > > events
                                                > > > > > that have occurred after the snapshot was made. The process creating
                                                > > the
                                                > > > > > snapshots will most likely be a independent process that would just
                                                > > load
                                                > > > > AR
                                                > > > > > verify if a snapshot needs to be made. If this is the case it would
                                                > > make
                                                > > > > it.
                                                > > > > > Say after 100 events you want a snapshot. Instead of putting this
                                                > > > > > responsibility in the domain repository?
                                                > > > > >
                                                > > > > > So current version of the snapshot is 20 version of the last event is
                                                > > 25
                                                > > > > so
                                                > > > > > after loading the snapshot it also needs to replay the last 5 events.
                                                > > > > >
                                                > > > > > Does this make sense?
                                                > > > > >
                                                > > > > > -Mark
                                                > > > > >
                                                > > > > > On Thu, Nov 12, 2009 at 4:37 PM, sebaszipp <sebaszipp@> wrote:
                                                > > > > >
                                                > > > > > >
                                                > > > > > >
                                                > > > > > >
                                                > > > > > > Hi Mark,
                                                > > > > > >
                                                > > > > > > Great blog. Thanks for clarifying in detail things about CQRS.
                                                > > > > > >
                                                > > > > > > Still a grey zone I'd like to get better is about AR load
                                                > > performance
                                                > > > > when
                                                > > > > > > the event storage is large enough to kill performance.
                                                > > > > > > I know rolling snapshots takes care of this field, but by rolling
                                                > > > > snapthost
                                                > > > > > > I might get an incomplete AR?
                                                > > > > > > Could you please explain this?
                                                > > > > > >
                                                > > > > > > Thanks.
                                                > > > > > >
                                                > > > > > >
                                                > > > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                                > > <domaindrivendesign%40yahoogroups.com>
                                                > > > > <domaindrivendesign%40yahoogroups.com>,
                                                > > > >
                                                > > > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                                > > > > > > >
                                                > > > > > > > Hi,
                                                > > > > > > >
                                                > > > > > > > I finally got the first blog post about this published, it is
                                                > > long!
                                                > > > > Not
                                                > > > > > > so
                                                > > > > > > > much code, more the explanation behind it (as I understand it).
                                                > > > > > > >
                                                > > > > > > > Link:
                                                > > http://blog.fohjin.com/blog/2009/11/12/CQRS_a_la_Greg_Young
                                                > > > > > > >
                                                > > > > > > > -Mark
                                                > > > > > > >
                                                > > > > > > >
                                                > > > > > > > On Thu, Oct 29, 2009 at 1:09 AM, Mark Nijhof <mark.nijhof@>
                                                > > wrote:
                                                > > > > > > >
                                                > > > > > > > > Hi,
                                                > > > > > > > >
                                                > > > > > > > > Because that is a nasty home made implementation of a bus :)
                                                > > The
                                                > > > > > > Publish
                                                > > > > > > > > method needs to know the exact type of the command/event that
                                                > > gets
                                                > > > > > > passed in
                                                > > > > > > > > because that is used to get the correct xxxHandlers from the
                                                > > IoC
                                                > > > > > > container.
                                                > > > > > > > > I cannot use an Generic in the PublishMultiple because these
                                                > > > > > > commands/events
                                                > > > > > > > > are 99% of the time not of the same type. I will probably
                                                > > change it
                                                > > > > > > into
                                                > > > > > > > > something like this:
                                                > > > > > > > >
                                                > > > > > >
                                                > > > >
                                                > > http://codebetter.com/blogs/gregyoung/archive/2009/10/03/delegate-mapper.aspx
                                                > > > > > > > >
                                                > > > > > > > > Also one thing I like to highlight is that in this first
                                                > > version I
                                                > > > > am
                                                > > > > > > not
                                                > > > > > > > > using anything complex because I explicitly wanted to show that
                                                > > the
                                                > > > > > > core of
                                                > > > > > > > > this is actually very simple, if I started with NServiceBus and
                                                > > > > > > NHibernate
                                                > > > > > > > > than that would have taken away from the simplicity of this
                                                > > type of
                                                > > > > > > > > architecture. That is why I have implemented my own very simple
                                                > > ORM
                                                > > > > > > (one has
                                                > > > > > > > > to do that once in their career anyway right) and my own bus. I
                                                > > > > plan on
                                                > > > > > > > > continuing on this example by introducing these types of
                                                > > options as
                                                > > > > > > well,
                                                > > > > > > > > all do the event store will remain custom SQL, actually I will
                                                > > also
                                                > > > > > > > > implement one using SQL Server and that one will use a stored
                                                > > > > procedure
                                                > > > > > > ;)
                                                > > > > > > > >
                                                > > > > > > > > -Mark
                                                > > > > > > > >
                                                > > > > > > > >
                                                > > > > > > > >
                                                > > > > > > > > On Wed, Oct 28, 2009 at 8:16 PM, David Perfors <dnperfors@
                                                > > >wrote:
                                                > > > > > >
                                                > > > > > > > >
                                                > > > > > > > >>
                                                > > > > > > > >>
                                                > > > > > > > >> Hi Mark,
                                                > > > > > > > >>
                                                > > > > > > > >> Thanks a lot for this example. I was looking into the code and
                                                > > > > looked
                                                > > > > > > ad
                                                > > > > > > > >> the implementations of IBus and saw that it is using
                                                > > reflection
                                                > > > > for
                                                > > > > > > the
                                                > > > > > > > >> PublishMultiple method. Can you tell me (us) more about why
                                                > > you
                                                > > > > are
                                                > > > > > > doing
                                                > > > > > > > >> that instead of just calling the Publish method?
                                                > > > > > > > >>
                                                > > > > > > > >> Looking forward to the blogposts :)
                                                > > > > > > > >>
                                                > > > > > > > >> David.
                                                > > > > > > > >>
                                                > > > > > > > >> 2009/10/26 Mark Nijhof <Mark.Nijhof@>
                                                > > > > > >
                                                > > > > > > > >>
                                                > > > > > > > >>> Hi,
                                                > > > > > > > >>>
                                                > > > > > > > >>> Since multiple people have been asking for this and I feel
                                                > > that
                                                > > > > the
                                                > > > > > > > >>> core is good enough to share I thought I would share the
                                                > > > > repository
                                                > > > > > > > >>> here already. Disclaimer: Now keep in mind that this has not
                                                > > been
                                                > > > > > > > >>> reviewed by Greg yet and that I am still working on it. I am
                                                > > also
                                                > > > > > > > >>> working on a complete detailed blog post (or several) to
                                                > > explain
                                                > > > > what
                                                > > > > > > > >>> is going on and why (with diagrams and all that fancy stuff).
                                                > > > > Once
                                                > > > > > > > >>> that is done it will be published here:
                                                > > http://blog.fohjin.com/I am
                                                > > > > > > > >>> currently finishing my specifications for the GUI and will
                                                > > split
                                                > > > > the
                                                > > > > > > > >>> existing domain specifications a bit more per scenario, but I
                                                > > > > think
                                                > > > > > > > >>> you will like what you see there (hope at least).
                                                > > > > > > > >>>
                                                > > > > > > > >>> The most interesting scenario is a transfer from one account
                                                > > to
                                                > > > > an
                                                > > > > > > > >>> other account.
                                                > > > > > > > >>>
                                                > > > > > > > >>> Link: http://github.com/MarkNijhof/Fohjin
                                                > > > > > > > >>>
                                                > > > > > > > >>> Note on SQLite: Because I am developing on x64 I have the x64
                                                > > > > version
                                                > > > > > > > >>> of SQLite referenced in the projects, except for the test
                                                > > project
                                                > > > > > > > >>> because TestDriven.Net executes everything in x86. Now if you
                                                > > are
                                                > > > > > > > >>> running on a x86 machine all you have to do is copy the x86
                                                > > > > > > > >>> System.Data.SQLite.* from /lib/sqlite/bin to
                                                > > /lib/sqlite/bin/x64
                                                > > > > > > (this
                                                > > > > > > > >>> approach is tested). There are two different SQLite
                                                > > databases,
                                                > > > > one is
                                                > > > > > > > >>> the event store and the other is the reporting database. I
                                                > > > > haven't
                                                > > > > > > > >>> figured out yet how, but it is possible to load the SQLite
                                                > > > > databases
                                                > > > > > > > >>> in Visual Studio to inspect the content. Both databases are
                                                > > > > created
                                                > > > > > > on
                                                > > > > > > > >>> first use, and deleting them will give you a fresh start.
                                                > > > > > > > >>>
                                                > > > > > > > >>> I would like to hear your opinions, I am very enthusiastic
                                                > > about
                                                > > > > this
                                                > > > > > > > >>> architecture when there is a need for a domain.
                                                > > > > > > > >>>
                                                > > > > > > > >>> -Mark
                                                > > > > > > > >>>
                                                > > > > > > > >>>
                                                > > > > > > > >>> ------------------------------------
                                                > > > > > > > >>>
                                                > > > > > > > >>> Yahoo! Groups Links
                                                > > > > > > > >>>
                                                > > > > > > > >>>
                                                > > > > > > > >>>
                                                > > > > > > > >>>
                                                > > > > > > > >>
                                                > > > > > > > >>
                                                > > > > > > > >
                                                > > > > > > > >
                                                > > > > > > >
                                                > > > > > >
                                                > > > > > >
                                                > > > > > >
                                                > > > > >
                                                > > > >
                                                > > > >
                                                > > > >
                                                > > >
                                                > > >
                                                > > >
                                                > > > --
                                                > > > Les erreurs de grammaire et de syntaxe ont été incluses pour m'assurer de
                                                > > > votre attention
                                                > > >
                                                > >
                                                > >
                                                > >
                                                >


                                              • Mark Henke
                                                I think we can break up this AR - AGG issue of replaying events into two parts: 1) How is a Child AGG identified? and 2) How do we figure out what child that
                                                Message 23 of 30 , Nov 13, 2009
                                                  I think we can break up this AR -> AGG issue of replaying events into two parts:

                                                  1) How is a Child AGG identified? and
                                                  2) How do we figure out what child that event belongs to?

                                                  Here is a shot in the dark, but how about this:

                                                  Let's assume all our child AGGs are in a single dictionary based upon type. The AR can then view itself internally as a Repository of AGGs. 
                                                  e.g. AddAGG<OrderSection>(orderSection);

                                                  Then for any event type we can register a Lookup on a specific child type. 
                                                  e.g. RegisterLookupOn<OrderSection>(section => section.Id)
                                                            .For<ProductSaleEvent>(@event => @...);
                                                  The base AR classe, when replaying events, would also check to see if a lookup is registered for that event type and will forward that event to the specified child AGG.

                                                  I could create a patch on Git for your example experimenting with this idea if you want, Mark.


                                                  On Thu, Nov 12, 2009 at 5:03 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                   

                                                  You could still have the AR be responsible for managing the collection including the internal state, but that feels wrong.

                                                  -Mark



                                                  On Thu, Nov 12, 2009 at 9:32 PM, sebaszipp <sebaszipp@...> wrote:
                                                   


                                                  Yes, for the case we have predifined/fixed order sections for an order we could fire up events according to the section in cuestion. But in case of having collection of AGGs (AR -> List<AGG> -> List<AGG>) the situation comes kind of weird.
                                                  Maybe we should take a look into our BC, in order to rethink and see whether the BC graph should be pruned and the remaing is responsability of another BC?



                                                  --- In domaindrivendesign@yahoogroups.com, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                  >
                                                  > Each AGG can apply its own events and store them in itself, then when you
                                                  > ask for changes from the AR it will ask changes from it's AGG.
                                                  >
                                                  > Loading events from history would load them all in the AR which would
                                                  > delegate them back to the AGG. I am not 100% sure yet what the best approach
                                                  > for this is. You could just send all of them and have the AGG decide which
                                                  > one to skip, or you could make the AR aware what types of events need to be
                                                  > forwarded to the AGG. This can be done by creating an event handler in the
                                                  > AR that would just forward the event to the specific AGG. But if you have
                                                  > collections of AGG then this would be a problem.
                                                  >
                                                  > -Mark
                                                  >
                                                  >
                                                  > On Thu, Nov 12, 2009 at 8:46 PM, sebaszipp <sebaszipp@...> wrote:
                                                  >
                                                  > >
                                                  > >
                                                  > >
                                                  > > Great. Thanks Greg.
                                                  > >
                                                  > > I more question:
                                                  > >
                                                  > > As far as I've been reading about CQS I've been all examples matching the
                                                  > > same association: AR -> AGG where the AR is the one firing up domain events.
                                                  > > I would like to add another association supposing our graph is more complex
                                                  > > than just AR -> AGG.
                                                  > >
                                                  > > In this case we would have the following graph:
                                                  > > Order AR -> OrderSection AGG -> OrderLine AGG
                                                  > >
                                                  > > Suppose there are 2 rules dictating that products under 10 dollars should
                                                  > > be placed into Section1 and the others should be placed into Section2. In
                                                  > > the case a product that is $5 is bought we would fire up an event from the
                                                  > > Order AR:
                                                  > >
                                                  > > super.apply(new ProductSaleEvent(sectionOneID, productDescription))
                                                  > >
                                                  > > and then the event handler of the Order AR should be:
                                                  > >
                                                  > > handle(ProductSaleEvent event)
                                                  > > {
                                                  > > OrderSection orderSection = orderSections.get(event.sectionId)
                                                  > > if (orderSection == null) {
                                                  > > orderSection = new OrderSection();
                                                  > > orderSections.put(event.sectionId, orderSection);
                                                  > > }
                                                  > > orderSection.processSale(productDescription); // which will create a Line
                                                  > > internally
                                                  > > }
                                                  > >
                                                  > > Should be handled this way?
                                                  > > I mean, the AR is the leading with the graph hierarchy no matter how deep
                                                  > > it's?
                                                  > >
                                                  > > Cheers,
                                                  > >
                                                  > >
                                                  > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>,

                                                  > > Greg Young <gregoryyoung1@> wrote:
                                                  > > >
                                                  > > > Yes the snapshots are generally not in memory, they live in the event
                                                  > > store.
                                                  > > >
                                                  > > > Cheers,
                                                  > > >
                                                  > > > Greg
                                                  > > >
                                                  > > > On Thu, Nov 12, 2009 at 8:30 PM, sebaszipp <sebaszipp@> wrote:
                                                  > > >
                                                  > > > >
                                                  > > > >
                                                  > > > >
                                                  > > > > I got it :)
                                                  > > > >
                                                  > > > > I don't know why I was relating the concept of a snapshot with a stack
                                                  > > of
                                                  > > > > events and not with the domain AR (and since I'm not an english native
                                                  > > > > speaker I got a lil confused about the term 'rolling').
                                                  > > > >
                                                  > > > > So you take a picture of the domain entity after N events and then make
                                                  > > the
                                                  > > > > repository hold a reference to that picture indexed by its identity
                                                  > > (ID) (or
                                                  > > > > the separate process yoou mention)
                                                  > > > >
                                                  > > > > Let's assume you want to load the AR having the same ID that the
                                                  > > picture
                                                  > > > > hold by the repo has. You calculate the position in the event stack
                                                  > > from
                                                  > > > > where you would start replying events, then create an AR instance, copy
                                                  > > its
                                                  > > > > state with the picture (Memento) that you took previosly, and apply the
                                                  > > > > events representing the DELTA.
                                                  > > > >
                                                  > > > > The Snapshot shouldn't be kept by the repo because we would run into
                                                  > > the
                                                  > > > > same performance problem if too many instances live in memory. I guess
                                                  > > we
                                                  > > > > should serialize the snapshot to disk or something similar?
                                                  > > > >
                                                  > > > > Am I ok?
                                                  > > > >
                                                  > > > > Thanks Mark.
                                                  > > > >
                                                  > > > >
                                                  > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                                  > > <domaindrivendesign%40yahoogroups.com>,
                                                  > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                                  > > > > >
                                                  > > > > > Your rolling snapshot will never be assumed to be the latest state of
                                                  > > the
                                                  > > > > > AR, after loading the snapshot the repository will always get all
                                                  > > events
                                                  > > > > > that have occurred after the snapshot was made. The process creating
                                                  > > the
                                                  > > > > > snapshots will most likely be a independent process that would just
                                                  > > load
                                                  > > > > AR
                                                  > > > > > verify if a snapshot needs to be made. If this is the case it would
                                                  > > make
                                                  > > > > it.
                                                  > > > > > Say after 100 events you want a snapshot. Instead of putting this
                                                  > > > > > responsibility in the domain repository?
                                                  > > > > >
                                                  > > > > > So current version of the snapshot is 20 version of the last event is
                                                  > > 25
                                                  > > > > so
                                                  > > > > > after loading the snapshot it also needs to replay the last 5 events.
                                                  > > > > >
                                                  > > > > > Does this make sense?
                                                  > > > > >
                                                  > > > > > -Mark
                                                  > > > > >
                                                  > > > > > On Thu, Nov 12, 2009 at 4:37 PM, sebaszipp <sebaszipp@> wrote:
                                                  > > > > >
                                                  > > > > > >
                                                  > > > > > >
                                                  > > > > > >
                                                  > > > > > > Hi Mark,
                                                  > > > > > >
                                                  > > > > > > Great blog. Thanks for clarifying in detail things about CQRS.
                                                  > > > > > >
                                                  > > > > > > Still a grey zone I'd like to get better is about AR load
                                                  > > performance
                                                  > > > > when
                                                  > > > > > > the event storage is large enough to kill performance.
                                                  > > > > > > I know rolling snapshots takes care of this field, but by rolling
                                                  > > > > snapthost
                                                  > > > > > > I might get an incomplete AR?
                                                  > > > > > > Could you please explain this?
                                                  > > > > > >
                                                  > > > > > > Thanks.
                                                  > > > > > >
                                                  > > > > > >
                                                  > > > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                                  > > <domaindrivendesign%40yahoogroups.com>
                                                  > > > > <domaindrivendesign%40yahoogroups.com>,
                                                  > > > >
                                                  > > > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                                  > > > > > > >
                                                  > > > > > > > Hi,
                                                  > > > > > > >
                                                  > > > > > > > I finally got the first blog post about this published, it is
                                                  > > long!
                                                  > > > > Not
                                                  > > > > > > so
                                                  > > > > > > > much code, more the explanation behind it (as I understand it).
                                                  > > > > > > >
                                                  > > > > > > > Link:
                                                  > > http://blog.fohjin.com/blog/2009/11/12/CQRS_a_la_Greg_Young
                                                  > > > > > > >
                                                  > > > > > > > -Mark
                                                  > > > > > > >
                                                  > > > > > > >
                                                  > > > > > > > On Thu, Oct 29, 2009 at 1:09 AM, Mark Nijhof <mark.nijhof@>
                                                  > > wrote:
                                                  > > > > > > >
                                                  > > > > > > > > Hi,
                                                  > > > > > > > >
                                                  > > > > > > > > Because that is a nasty home made implementation of a bus :)
                                                  > > The
                                                  > > > > > > Publish
                                                  > > > > > > > > method needs to know the exact type of the command/event that
                                                  > > gets
                                                  > > > > > > passed in
                                                  > > > > > > > > because that is used to get the correct xxxHandlers from the
                                                  > > IoC
                                                  > > > > > > container.
                                                  > > > > > > > > I cannot use an Generic in the PublishMultiple because these
                                                  > > > > > > commands/events
                                                  > > > > > > > > are 99% of the time not of the same type. I will probably
                                                  > > change it
                                                  > > > > > > into
                                                  > > > > > > > > something like this:
                                                  > > > > > > > >
                                                  > > > > > >
                                                  > > > >
                                                  > > http://codebetter.com/blogs/gregyoung/archive/2009/10/03/delegate-mapper.aspx
                                                  > > > > > > > >
                                                  > > > > > > > > Also one thing I like to highlight is that in this first
                                                  > > version I
                                                  > > > > am
                                                  > > > > > > not
                                                  > > > > > > > > using anything complex because I explicitly wanted to show that
                                                  > > the
                                                  > > > > > > core of
                                                  > > > > > > > > this is actually very simple, if I started with NServiceBus and
                                                  > > > > > > NHibernate
                                                  > > > > > > > > than that would have taken away from the simplicity of this
                                                  > > type of
                                                  > > > > > > > > architecture. That is why I have implemented my own very simple
                                                  > > ORM
                                                  > > > > > > (one has
                                                  > > > > > > > > to do that once in their career anyway right) and my own bus. I
                                                  > > > > plan on
                                                  > > > > > > > > continuing on this example by introducing these types of
                                                  > > options as
                                                  > > > > > > well,
                                                  > > > > > > > > all do the event store will remain custom SQL, actually I will
                                                  > > also
                                                  > > > > > > > > implement one using SQL Server and that one will use a stored
                                                  > > > > procedure
                                                  > > > > > > ;)
                                                  > > > > > > > >
                                                  > > > > > > > > -Mark
                                                  > > > > > > > >
                                                  > > > > > > > >
                                                  > > > > > > > >
                                                  > > > > > > > > On Wed, Oct 28, 2009 at 8:16 PM, David Perfors <dnperfors@
                                                  > > >wrote:
                                                  > > > > > >
                                                  > > > > > > > >
                                                  > > > > > > > >>
                                                  > > > > > > > >>
                                                  > > > > > > > >> Hi Mark,
                                                  > > > > > > > >>
                                                  > > > > > > > >> Thanks a lot for this example. I was looking into the code and
                                                  > > > > looked
                                                  > > > > > > ad
                                                  > > > > > > > >> the implementations of IBus and saw that it is using
                                                  > > reflection
                                                  > > > > for
                                                  > > > > > > the
                                                  > > > > > > > >> PublishMultiple method. Can you tell me (us) more about why
                                                  > > you
                                                  > > > > are
                                                  > > > > > > doing
                                                  > > > > > > > >> that instead of just calling the Publish method?
                                                  > > > > > > > >>
                                                  > > > > > > > >> Looking forward to the blogposts :)
                                                  > > > > > > > >>
                                                  > > > > > > > >> David.
                                                  > > > > > > > >>
                                                  > > > > > > > >> 2009/10/26 Mark Nijhof <Mark.Nijhof@>
                                                  > > > > > >
                                                  > > > > > > > >>
                                                  > > > > > > > >>> Hi,
                                                  > > > > > > > >>>
                                                  > > > > > > > >>> Since multiple people have been asking for this and I feel
                                                  > > that
                                                  > > > > the
                                                  > > > > > > > >>> core is good enough to share I thought I would share the
                                                  > > > > repository
                                                  > > > > > > > >>> here already. Disclaimer: Now keep in mind that this has not
                                                  > > been
                                                  > > > > > > > >>> reviewed by Greg yet and that I am still working on it. I am
                                                  > > also
                                                  > > > > > > > >>> working on a complete detailed blog post (or several) to
                                                  > > explain
                                                  > > > > what
                                                  > > > > > > > >>> is going on and why (with diagrams and all that fancy stuff).
                                                  > > > > Once
                                                  > > > > > > > >>> that is done it will be published here:
                                                  > > http://blog.fohjin.com/I am
                                                  > > > > > > > >>> currently finishing my specifications for the GUI and will
                                                  > > split
                                                  > > > > the
                                                  > > > > > > > >>> existing domain specifications a bit more per scenario, but I
                                                  > > > > think
                                                  > > > > > > > >>> you will like what you see there (hope at least).
                                                  > > > > > > > >>>
                                                  > > > > > > > >>> The most interesting scenario is a transfer from one account
                                                  > > to
                                                  > > > > an
                                                  > > > > > > > >>> other account.
                                                  > > > > > > > >>>
                                                  > > > > > > > >>> Link: http://github.com/MarkNijhof/Fohjin
                                                  > > > > > > > >>>
                                                  > > > > > > > >>> Note on SQLite: Because I am developing on x64 I have the x64
                                                  > > > > version
                                                  > > > > > > > >>> of SQLite referenced in the projects, except for the test
                                                  > > project
                                                  > > > > > > > >>> because TestDriven.Net executes everything in x86. Now if you
                                                  > > are
                                                  > > > > > > > >>> running on a x86 machine all you have to do is copy the x86
                                                  > > > > > > > >>> System.Data.SQLite.* from /lib/sqlite/bin to
                                                  > > /lib/sqlite/bin/x64
                                                  > > > > > > (this
                                                  > > > > > > > >>> approach is tested). There are two different SQLite
                                                  > > databases,
                                                  > > > > one is
                                                  > > > > > > > >>> the event store and the other is the reporting database. I
                                                  > > > > haven't
                                                  > > > > > > > >>> figured out yet how, but it is possible to load the SQLite
                                                  > > > > databases
                                                  > > > > > > > >>> in Visual Studio to inspect the content. Both databases are
                                                  > > > > created
                                                  > > > > > > on
                                                  > > > > > > > >>> first use, and deleting them will give you a fresh start.
                                                  > > > > > > > >>>
                                                  > > > > > > > >>> I would like to hear your opinions, I am very enthusiastic
                                                  > > about
                                                  > > > > this
                                                  > > > > > > > >>> architecture when there is a need for a domain.
                                                  > > > > > > > >>>
                                                  > > > > > > > >>> -Mark
                                                  > > > > > > > >>>
                                                  > > > > > > > >>>
                                                  > > > > > > > >>> ------------------------------------
                                                  > > > > > > > >>>
                                                  > > > > > > > >>> Yahoo! Groups Links
                                                  > > > > > > > >>>
                                                  > > > > > > > >>>
                                                  > > > > > > > >>>
                                                  > > > > > > > >>>
                                                  > > > > > > > >>
                                                  > > > > > > > >>
                                                  > > > > > > > >
                                                  > > > > > > > >
                                                  > > > > > > >
                                                  > > > > > >
                                                  > > > > > >
                                                  > > > > > >
                                                  > > > > >
                                                  > > > >
                                                  > > > >
                                                  > > > >
                                                  > > >
                                                  > > >
                                                  > > >
                                                  > > > --
                                                  > > > Les erreurs de grammaire et de syntaxe ont été incluses pour m'assurer de
                                                  > > > votre attention
                                                  > > >
                                                  > >
                                                  > >
                                                  > >
                                                  >



                                                • Mark Nijhof
                                                  One thing I don t like about this solution (or as how I understand it) is that you put all different types into on dictionary wouldn t this ruin a lot of the
                                                  Message 24 of 30 , Nov 13, 2009
                                                    One thing I don't like about this solution (or as how I understand it) is that you put all different types into on dictionary wouldn't this ruin a lot of the readability? Also seems more complex then needed? But as often happens I might just completely understand you wrong :D So an code example would be great. Perhaps I can implement something like this before the upcoming E-VAN talk. (I want to keep it somewhat recognizable for people attending the talk so no major changes).

                                                    Here an example keeping in the same types but different organization:

                                                    Client
                                                    - List<ActiveAccounts> activeAccounts;
                                                    - List<ClosedAccounts> closedAccounts;

                                                    So in the AR I handle both events for the active account and closed account. I could just have two event handlers, one that handles all events for the active account amd one that handles all events for the closed accounts. In this event handler you would just forward the event to the correct instance in the list. Inside the f.ex. Active account it knows how to apply each individual different type of event.

                                                    private void forwardAllEventsForAnActiveAccount(object event)
                                                    {
                                                        ActiveAccount actinveAccount;
                                                        if (!activeAccounts.TryGetById(event.AccountId))
                                                            throw new Exception();

                                                        activeAccount.LoadHistory(event);
                                                    }

                                                    -Mark


                                                    On Fri, Nov 13, 2009 at 3:49 PM, Mark Henke <gilligan128@...> wrote:
                                                     

                                                    I think we can break up this AR -> AGG issue of replaying events into two parts:

                                                    1) How is a Child AGG identified? and
                                                    2) How do we figure out what child that event belongs to?

                                                    Here is a shot in the dark, but how about this:

                                                    Let's assume all our child AGGs are in a single dictionary based upon type. The AR can then view itself internally as a Repository of AGGs. 
                                                    e.g. AddAGG<OrderSection>(orderSection);

                                                    Then for any event type we can register a Lookup on a specific child type. 
                                                    e.g. RegisterLookupOn<OrderSection>(section => section.Id)
                                                              .For<ProductSaleEvent>(@event => @...);
                                                    The base AR classe, when replaying events, would also check to see if a lookup is registered for that event type and will forward that event to the specified child AGG.

                                                    I could create a patch on Git for your example experimenting with this idea if you want, Mark.


                                                    On Thu, Nov 12, 2009 at 5:03 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                     

                                                    You could still have the AR be responsible for managing the collection including the internal state, but that feels wrong.

                                                    -Mark



                                                    On Thu, Nov 12, 2009 at 9:32 PM, sebaszipp <sebaszipp@...> wrote:
                                                     


                                                    Yes, for the case we have predifined/fixed order sections for an order we could fire up events according to the section in cuestion. But in case of having collection of AGGs (AR -> List<AGG> -> List<AGG>) the situation comes kind of weird.
                                                    Maybe we should take a look into our BC, in order to rethink and see whether the BC graph should be pruned and the remaing is responsability of another BC?



                                                    --- In domaindrivendesign@yahoogroups.com, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                    >
                                                    > Each AGG can apply its own events and store them in itself, then when you
                                                    > ask for changes from the AR it will ask changes from it's AGG.
                                                    >
                                                    > Loading events from history would load them all in the AR which would
                                                    > delegate them back to the AGG. I am not 100% sure yet what the best approach
                                                    > for this is. You could just send all of them and have the AGG decide which
                                                    > one to skip, or you could make the AR aware what types of events need to be
                                                    > forwarded to the AGG. This can be done by creating an event handler in the
                                                    > AR that would just forward the event to the specific AGG. But if you have
                                                    > collections of AGG then this would be a problem.
                                                    >
                                                    > -Mark
                                                    >
                                                    >
                                                    > On Thu, Nov 12, 2009 at 8:46 PM, sebaszipp <sebaszipp@...> wrote:
                                                    >
                                                    > >
                                                    > >
                                                    > >
                                                    > > Great. Thanks Greg.
                                                    > >
                                                    > > I more question:
                                                    > >
                                                    > > As far as I've been reading about CQS I've been all examples matching the
                                                    > > same association: AR -> AGG where the AR is the one firing up domain events.
                                                    > > I would like to add another association supposing our graph is more complex
                                                    > > than just AR -> AGG.
                                                    > >
                                                    > > In this case we would have the following graph:
                                                    > > Order AR -> OrderSection AGG -> OrderLine AGG
                                                    > >
                                                    > > Suppose there are 2 rules dictating that products under 10 dollars should
                                                    > > be placed into Section1 and the others should be placed into Section2. In
                                                    > > the case a product that is $5 is bought we would fire up an event from the
                                                    > > Order AR:
                                                    > >
                                                    > > super.apply(new ProductSaleEvent(sectionOneID, productDescription))
                                                    > >
                                                    > > and then the event handler of the Order AR should be:
                                                    > >
                                                    > > handle(ProductSaleEvent event)
                                                    > > {
                                                    > > OrderSection orderSection = orderSections.get(event.sectionId)
                                                    > > if (orderSection == null) {
                                                    > > orderSection = new OrderSection();
                                                    > > orderSections.put(event.sectionId, orderSection);
                                                    > > }
                                                    > > orderSection.processSale(productDescription); // which will create a Line
                                                    > > internally
                                                    > > }
                                                    > >
                                                    > > Should be handled this way?
                                                    > > I mean, the AR is the leading with the graph hierarchy no matter how deep
                                                    > > it's?
                                                    > >
                                                    > > Cheers,
                                                    > >
                                                    > >
                                                    > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>,

                                                    > > Greg Young <gregoryyoung1@> wrote:
                                                    > > >
                                                    > > > Yes the snapshots are generally not in memory, they live in the event
                                                    > > store.
                                                    > > >
                                                    > > > Cheers,
                                                    > > >
                                                    > > > Greg
                                                    > > >
                                                    > > > On Thu, Nov 12, 2009 at 8:30 PM, sebaszipp <sebaszipp@> wrote:
                                                    > > >
                                                    > > > >
                                                    > > > >
                                                    > > > >
                                                    > > > > I got it :)
                                                    > > > >
                                                    > > > > I don't know why I was relating the concept of a snapshot with a stack
                                                    > > of
                                                    > > > > events and not with the domain AR (and since I'm not an english native
                                                    > > > > speaker I got a lil confused about the term 'rolling').
                                                    > > > >
                                                    > > > > So you take a picture of the domain entity after N events and then make
                                                    > > the
                                                    > > > > repository hold a reference to that picture indexed by its identity
                                                    > > (ID) (or
                                                    > > > > the separate process yoou mention)
                                                    > > > >
                                                    > > > > Let's assume you want to load the AR having the same ID that the
                                                    > > picture
                                                    > > > > hold by the repo has. You calculate the position in the event stack
                                                    > > from
                                                    > > > > where you would start replying events, then create an AR instance, copy
                                                    > > its
                                                    > > > > state with the picture (Memento) that you took previosly, and apply the
                                                    > > > > events representing the DELTA.
                                                    > > > >
                                                    > > > > The Snapshot shouldn't be kept by the repo because we would run into
                                                    > > the
                                                    > > > > same performance problem if too many instances live in memory. I guess
                                                    > > we
                                                    > > > > should serialize the snapshot to disk or something similar?
                                                    > > > >
                                                    > > > > Am I ok?
                                                    > > > >
                                                    > > > > Thanks Mark.
                                                    > > > >
                                                    > > > >
                                                    > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                                    > > <domaindrivendesign%40yahoogroups.com>,
                                                    > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                                    > > > > >
                                                    > > > > > Your rolling snapshot will never be assumed to be the latest state of
                                                    > > the
                                                    > > > > > AR, after loading the snapshot the repository will always get all
                                                    > > events
                                                    > > > > > that have occurred after the snapshot was made. The process creating
                                                    > > the
                                                    > > > > > snapshots will most likely be a independent process that would just
                                                    > > load
                                                    > > > > AR
                                                    > > > > > verify if a snapshot needs to be made. If this is the case it would
                                                    > > make
                                                    > > > > it.
                                                    > > > > > Say after 100 events you want a snapshot. Instead of putting this
                                                    > > > > > responsibility in the domain repository?
                                                    > > > > >
                                                    > > > > > So current version of the snapshot is 20 version of the last event is
                                                    > > 25
                                                    > > > > so
                                                    > > > > > after loading the snapshot it also needs to replay the last 5 events.
                                                    > > > > >
                                                    > > > > > Does this make sense?
                                                    > > > > >
                                                    > > > > > -Mark
                                                    > > > > >
                                                    > > > > > On Thu, Nov 12, 2009 at 4:37 PM, sebaszipp <sebaszipp@> wrote:
                                                    > > > > >
                                                    > > > > > >
                                                    > > > > > >
                                                    > > > > > >
                                                    > > > > > > Hi Mark,
                                                    > > > > > >
                                                    > > > > > > Great blog. Thanks for clarifying in detail things about CQRS.
                                                    > > > > > >
                                                    > > > > > > Still a grey zone I'd like to get better is about AR load
                                                    > > performance
                                                    > > > > when
                                                    > > > > > > the event storage is large enough to kill performance.
                                                    > > > > > > I know rolling snapshots takes care of this field, but by rolling
                                                    > > > > snapthost
                                                    > > > > > > I might get an incomplete AR?
                                                    > > > > > > Could you please explain this?
                                                    > > > > > >
                                                    > > > > > > Thanks.
                                                    > > > > > >
                                                    > > > > > >
                                                    > > > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                                    > > <domaindrivendesign%40yahoogroups.com>
                                                    > > > > <domaindrivendesign%40yahoogroups.com>,
                                                    > > > >
                                                    > > > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                                    > > > > > > >
                                                    > > > > > > > Hi,
                                                    > > > > > > >
                                                    > > > > > > > I finally got the first blog post about this published, it is
                                                    > > long!
                                                    > > > > Not
                                                    > > > > > > so
                                                    > > > > > > > much code, more the explanation behind it (as I understand it).
                                                    > > > > > > >
                                                    > > > > > > > Link:
                                                    > > http://blog.fohjin.com/blog/2009/11/12/CQRS_a_la_Greg_Young
                                                    > > > > > > >
                                                    > > > > > > > -Mark
                                                    > > > > > > >
                                                    > > > > > > >
                                                    > > > > > > > On Thu, Oct 29, 2009 at 1:09 AM, Mark Nijhof <mark.nijhof@>
                                                    > > wrote:
                                                    > > > > > > >
                                                    > > > > > > > > Hi,
                                                    > > > > > > > >
                                                    > > > > > > > > Because that is a nasty home made implementation of a bus :)
                                                    > > The
                                                    > > > > > > Publish
                                                    > > > > > > > > method needs to know the exact type of the command/event that
                                                    > > gets
                                                    > > > > > > passed in
                                                    > > > > > > > > because that is used to get the correct xxxHandlers from the
                                                    > > IoC
                                                    > > > > > > container.
                                                    > > > > > > > > I cannot use an Generic in the PublishMultiple because these
                                                    > > > > > > commands/events
                                                    > > > > > > > > are 99% of the time not of the same type. I will probably
                                                    > > change it
                                                    > > > > > > into
                                                    > > > > > > > > something like this:
                                                    > > > > > > > >
                                                    > > > > > >
                                                    > > > >
                                                    > > http://codebetter.com/blogs/gregyoung/archive/2009/10/03/delegate-mapper.aspx
                                                    > > > > > > > >
                                                    > > > > > > > > Also one thing I like to highlight is that in this first
                                                    > > version I
                                                    > > > > am
                                                    > > > > > > not
                                                    > > > > > > > > using anything complex because I explicitly wanted to show that
                                                    > > the
                                                    > > > > > > core of
                                                    > > > > > > > > this is actually very simple, if I started with NServiceBus and
                                                    > > > > > > NHibernate
                                                    > > > > > > > > than that would have taken away from the simplicity of this
                                                    > > type of
                                                    > > > > > > > > architecture. That is why I have implemented my own very simple
                                                    > > ORM
                                                    > > > > > > (one has
                                                    > > > > > > > > to do that once in their career anyway right) and my own bus. I
                                                    > > > > plan on
                                                    > > > > > > > > continuing on this example by introducing these types of
                                                    > > options as
                                                    > > > > > > well,
                                                    > > > > > > > > all do the event store will remain custom SQL, actually I will
                                                    > > also
                                                    > > > > > > > > implement one using SQL Server and that one will use a stored
                                                    > > > > procedure
                                                    > > > > > > ;)
                                                    > > > > > > > >
                                                    > > > > > > > > -Mark
                                                    > > > > > > > >
                                                    > > > > > > > >
                                                    > > > > > > > >
                                                    > > > > > > > > On Wed, Oct 28, 2009 at 8:16 PM, David Perfors <dnperfors@
                                                    > > >wrote:
                                                    > > > > > >
                                                    > > > > > > > >
                                                    > > > > > > > >>
                                                    > > > > > > > >>
                                                    > > > > > > > >> Hi Mark,
                                                    > > > > > > > >>
                                                    > > > > > > > >> Thanks a lot for this example. I was looking into the code and
                                                    > > > > looked
                                                    > > > > > > ad
                                                    > > > > > > > >> the implementations of IBus and saw that it is using
                                                    > > reflection
                                                    > > > > for
                                                    > > > > > > the
                                                    > > > > > > > >> PublishMultiple method. Can you tell me (us) more about why
                                                    > > you
                                                    > > > > are
                                                    > > > > > > doing
                                                    > > > > > > > >> that instead of just calling the Publish method?
                                                    > > > > > > > >>
                                                    > > > > > > > >> Looking forward to the blogposts :)
                                                    > > > > > > > >>
                                                    > > > > > > > >> David.
                                                    > > > > > > > >>
                                                    > > > > > > > >> 2009/10/26 Mark Nijhof <Mark.Nijhof@>
                                                    > > > > > >
                                                    > > > > > > > >>
                                                    > > > > > > > >>> Hi,
                                                    > > > > > > > >>>
                                                    > > > > > > > >>> Since multiple people have been asking for this and I feel
                                                    > > that
                                                    > > > > the
                                                    > > > > > > > >>> core is good enough to share I thought I would share the
                                                    > > > > repository
                                                    > > > > > > > >>> here already. Disclaimer: Now keep in mind that this has not
                                                    > > been
                                                    > > > > > > > >>> reviewed by Greg yet and that I am still working on it. I am
                                                    > > also
                                                    > > > > > > > >>> working on a complete detailed blog post (or several) to
                                                    > > explain
                                                    > > > > what
                                                    > > > > > > > >>> is going on and why (with diagrams and all that fancy stuff).
                                                    > > > > Once
                                                    > > > > > > > >>> that is done it will be published here:
                                                    > > http://blog.fohjin.com/I am
                                                    > > > > > > > >>> currently finishing my specifications for the GUI and will
                                                    > > split
                                                    > > > > the
                                                    > > > > > > > >>> existing domain specifications a bit more per scenario, but I
                                                    > > > > think
                                                    > > > > > > > >>> you will like what you see there (hope at least).
                                                    > > > > > > > >>>
                                                    > > > > > > > >>> The most interesting scenario is a transfer from one account
                                                    > > to
                                                    > > > > an
                                                    > > > > > > > >>> other account.
                                                    > > > > > > > >>>
                                                    > > > > > > > >>> Link: http://github.com/MarkNijhof/Fohjin
                                                    > > > > > > > >>>
                                                    > > > > > > > >>> Note on SQLite: Because I am developing on x64 I have the x64
                                                    > > > > version
                                                    > > > > > > > >>> of SQLite referenced in the projects, except for the test
                                                    > > project
                                                    > > > > > > > >>> because TestDriven.Net executes everything in x86. Now if you
                                                    > > are
                                                    > > > > > > > >>> running on a x86 machine all you have to do is copy the x86
                                                    > > > > > > > >>> System.Data.SQLite.* from /lib/sqlite/bin to
                                                    > > /lib/sqlite/bin/x64
                                                    > > > > > > (this
                                                    > > > > > > > >>> approach is tested). There are two different SQLite
                                                    > > databases,
                                                    > > > > one is
                                                    > > > > > > > >>> the event store and the other is the reporting database. I
                                                    > > > > haven't
                                                    > > > > > > > >>> figured out yet how, but it is possible to load the SQLite
                                                    > > > > databases
                                                    > > > > > > > >>> in Visual Studio to inspect the content. Both databases are
                                                    > > > > created
                                                    > > > > > > on
                                                    > > > > > > > >>> first use, and deleting them will give you a fresh start.
                                                    > > > > > > > >>>
                                                    > > > > > > > >>> I would like to hear your opinions, I am very enthusiastic
                                                    > > about
                                                    > > > > this
                                                    > > > > > > > >>> architecture when there is a need for a domain.
                                                    > > > > > > > >>>
                                                    > > > > > > > >>> -Mark
                                                    > > > > > > > >>>
                                                    > > > > > > > >>>
                                                    > > > > > > > >>> ------------------------------------
                                                    > > > > > > > >>>
                                                    > > > > > > > >>> Yahoo! Groups Links
                                                    > > > > > > > >>>
                                                    > > > > > > > >>>
                                                    > > > > > > > >>>
                                                    > > > > > > > >>>
                                                    > > > > > > > >>
                                                    > > > > > > > >>
                                                    > > > > > > > >
                                                    > > > > > > > >
                                                    > > > > > > >
                                                    > > > > > >
                                                    > > > > > >
                                                    > > > > > >
                                                    > > > > >
                                                    > > > >
                                                    > > > >
                                                    > > > >
                                                    > > >
                                                    > > >
                                                    > > >
                                                    > > > --
                                                    > > > Les erreurs de grammaire et de syntaxe ont été incluses pour m'assurer de
                                                    > > > votre attention
                                                    > > >
                                                    > >
                                                    > >
                                                    > >
                                                    >




                                                  • Mark Henke
                                                    How do you know to what child an event belongs to? Your example below does not seem to handle that. That is what my solution is tackling. Here is a rough-shod
                                                    Message 25 of 30 , Nov 13, 2009
                                                      How do you know to what child an event belongs to? Your example below does not seem to handle that. That is what my solution is tackling. Here is a rough-shod example:

                                                       interface ILookup
                                                              {
                                                                  bool HasChildFor(IDomainEvent @event);
                                                                  void ApplyChildEvent(IDomainEvent @event );
                                                                  IEnumerable<IDomainEvent> GetChanges();
                                                                  void ClearChanges();
                                                              }


                                                              class AggregateRootBase
                                                              {
                                                                  LookupBuilder<T> Lookup<T>(IEnumerable<T> childCollection) where T : EventSource
                                                              {
                                                                  var lookupBuilder = new LookupBuilder<T>(childCollection);
                                                                  lookups.Add(lookupBuilder);

                                                                  return lookupBuilder;
                                                              }


                                                                  public void ForwardToChildrenEventsOfType<T>()
                                                                  {
                                                                      RegisterHandler<T>(@event => lookups.Single(lookup => lookup.HasChildFor(@event)).ApplyChildEvent(@event));
                                                                  }

                                                                 public IEnumerable<IDomainEvent> GetChanges()
                                                                {
                                                                       return events.Concat(lookups.SelectMany(lookup => lookup.GetChanges()));
                                                                }

                                                                
                                                              }

                                                      And the LookupBuilder class:

                                                       class LookupBuilder<T> : ILookup where T : EventSource
                                                              {
                                                                  IEnumerable<T> children;
                                                                  Func<T, object> childKey;
                                                                  IDictionary<Type, Func<IDomainEvent, object>> eventKeys = new Dictionary<Type, Func<IDomainEvent, object>>();

                                                                  AggregateRootBase ar;


                                                                  public LookupBuilder(IEnumerable<T> children, AggregateRootBase ar)
                                                                  {
                                                                      this.children = children;
                                                                      this.ar = ar;
                                                                      childKey = child => child.Id;
                                                                  }

                                                                  public LookupBuilder<T> On(Func<T, object> keyGetter)
                                                                  {
                                                                      childKey = keyGetter;
                                                                      return this;
                                                                  }

                                                                  public LookupBuilder<T> For<TEvent>(Func<TEvent,object> eventKeyGetter)
                                                                  {
                                                                      eventKeys[typeof (TEvent)] = @event =>  eventKeyGetter((TEvent)@event);
                                                                      ar.ForwardToChildrenEventsOfType<TEvent>();
                                                                      return this;
                                                                  }

                                                                  bool ILookup.HasChildFor(IDomainEvent @event)
                                                                  {
                                                                      if(!eventKeys.ContainsKey(@...()))
                                                                      {
                                                                          return false;
                                                                      }

                                                                      var eventKey = eventKeys[@...()];
                                                                      return children.Any(child => childKey(child) == eventKey(@event));
                                                                  }


                                                                  IEnumerable<IDomainEvent> ILookup.GetChanges()
                                                                  {
                                                                      return children.SelectMany(child => child.GetChanges());
                                                                  }

                                                                  void ILookup.ClearChanges()
                                                                  {
                                                                      children.Iterate(x => x.ClearChanges());
                                                                  }

                                                                  void ILookup.ApplyChildEvent(IDomainEvent @event)
                                                                  {
                                                                      var eventKey = eventKeys[@...()];
                                                                      children.Single(child => childKey(child) == eventKey(@event)).LoadEventFromHistory(@event);
                                                                  }
                                                              }


                                                      It may be hard to read at first, but it basically allows us to do things like this:

                                                      public Client()
                                                      {
                                                         Lookup(ActiveAccounts)
                                                          .For<AccountIsOnHold>(@event => @...)
                                                          .For<AccountIsNoLongerOnHold>(@event => @...);

                                                        Lookup(ClosedAccounts)
                                                         .For<AccountReactivated>(@event => @...);

                                                      }

                                                      All the ugly stuff is hidden by the base class and the plumbing is handled for us. We could also add something like Child(CurrentAccount).CanHandle<AccountOnHold>(x => x.AccountId) for simple cases. 

                                                      I hope that helps. Also this is only a rough draft of what I was thinking.

                                                      On Fri, Nov 13, 2009 at 4:07 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                       

                                                      One thing I don't like about this solution (or as how I understand it) is that you put all different types into on dictionary wouldn't this ruin a lot of the readability? Also seems more complex then needed? But as often happens I might just completely understand you wrong :D So an code example would be great. Perhaps I can implement something like this before the upcoming E-VAN talk. (I want to keep it somewhat recognizable for people attending the talk so no major changes).

                                                      Here an example keeping in the same types but different organization:

                                                      Client
                                                      - List<ActiveAccounts> activeAccounts;
                                                      - List<ClosedAccounts> closedAccounts;

                                                      So in the AR I handle both events for the active account and closed account. I could just have two event handlers, one that handles all events for the active account amd one that handles all events for the closed accounts. In this event handler you would just forward the event to the correct instance in the list. Inside the f.ex. Active account it knows how to apply each individual different type of event.

                                                      private void forwardAllEventsForAnActiveAccount(object event)
                                                      {
                                                          ActiveAccount actinveAccount;
                                                          if (!activeAccounts.TryGetById(event.AccountId))
                                                              throw new Exception();

                                                          activeAccount.LoadHistory(event);
                                                      }

                                                      -Mark




                                                      On Fri, Nov 13, 2009 at 3:49 PM, Mark Henke <gilligan128@...> wrote:
                                                       

                                                      I think we can break up this AR -> AGG issue of replaying events into two parts:

                                                      1) How is a Child AGG identified? and
                                                      2) How do we figure out what child that event belongs to?

                                                      Here is a shot in the dark, but how about this:

                                                      Let's assume all our child AGGs are in a single dictionary based upon type. The AR can then view itself internally as a Repository of AGGs. 
                                                      e.g. AddAGG<OrderSection>(orderSection);

                                                      Then for any event type we can register a Lookup on a specific child type. 
                                                      e.g. RegisterLookupOn<OrderSection>(section => section.Id)
                                                                .For<ProductSaleEvent>(@event => @...);
                                                      The base AR classe, when replaying events, would also check to see if a lookup is registered for that event type and will forward that event to the specified child AGG.

                                                      I could create a patch on Git for your example experimenting with this idea if you want, Mark.


                                                      On Thu, Nov 12, 2009 at 5:03 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                       

                                                      You could still have the AR be responsible for managing the collection including the internal state, but that feels wrong.

                                                      -Mark



                                                      On Thu, Nov 12, 2009 at 9:32 PM, sebaszipp <sebaszipp@...> wrote:
                                                       


                                                      Yes, for the case we have predifined/fixed order sections for an order we could fire up events according to the section in cuestion. But in case of having collection of AGGs (AR -> List<AGG> -> List<AGG>) the situation comes kind of weird.
                                                      Maybe we should take a look into our BC, in order to rethink and see whether the BC graph should be pruned and the remaing is responsability of another BC?



                                                      --- In domaindrivendesign@yahoogroups.com, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                      >
                                                      > Each AGG can apply its own events and store them in itself, then when you
                                                      > ask for changes from the AR it will ask changes from it's AGG.
                                                      >
                                                      > Loading events from history would load them all in the AR which would
                                                      > delegate them back to the AGG. I am not 100% sure yet what the best approach
                                                      > for this is. You could just send all of them and have the AGG decide which
                                                      > one to skip, or you could make the AR aware what types of events need to be
                                                      > forwarded to the AGG. This can be done by creating an event handler in the
                                                      > AR that would just forward the event to the specific AGG. But if you have
                                                      > collections of AGG then this would be a problem.
                                                      >
                                                      > -Mark
                                                      >
                                                      >
                                                      > On Thu, Nov 12, 2009 at 8:46 PM, sebaszipp <sebaszipp@...> wrote:
                                                      >
                                                      > >
                                                      > >
                                                      > >
                                                      > > Great. Thanks Greg.
                                                      > >
                                                      > > I more question:
                                                      > >
                                                      > > As far as I've been reading about CQS I've been all examples matching the
                                                      > > same association: AR -> AGG where the AR is the one firing up domain events.
                                                      > > I would like to add another association supposing our graph is more complex
                                                      > > than just AR -> AGG.
                                                      > >
                                                      > > In this case we would have the following graph:
                                                      > > Order AR -> OrderSection AGG -> OrderLine AGG
                                                      > >
                                                      > > Suppose there are 2 rules dictating that products under 10 dollars should
                                                      > > be placed into Section1 and the others should be placed into Section2. In
                                                      > > the case a product that is $5 is bought we would fire up an event from the
                                                      > > Order AR:
                                                      > >
                                                      > > super.apply(new ProductSaleEvent(sectionOneID, productDescription))
                                                      > >
                                                      > > and then the event handler of the Order AR should be:
                                                      > >
                                                      > > handle(ProductSaleEvent event)
                                                      > > {
                                                      > > OrderSection orderSection = orderSections.get(event.sectionId)
                                                      > > if (orderSection == null) {
                                                      > > orderSection = new OrderSection();
                                                      > > orderSections.put(event.sectionId, orderSection);
                                                      > > }
                                                      > > orderSection.processSale(productDescription); // which will create a Line
                                                      > > internally
                                                      > > }
                                                      > >
                                                      > > Should be handled this way?
                                                      > > I mean, the AR is the leading with the graph hierarchy no matter how deep
                                                      > > it's?
                                                      > >
                                                      > > Cheers,
                                                      > >
                                                      > >
                                                      > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>,

                                                      > > Greg Young <gregoryyoung1@> wrote:
                                                      > > >
                                                      > > > Yes the snapshots are generally not in memory, they live in the event
                                                      > > store.
                                                      > > >
                                                      > > > Cheers,
                                                      > > >
                                                      > > > Greg
                                                      > > >
                                                      > > > On Thu, Nov 12, 2009 at 8:30 PM, sebaszipp <sebaszipp@> wrote:
                                                      > > >
                                                      > > > >
                                                      > > > >
                                                      > > > >
                                                      > > > > I got it :)
                                                      > > > >
                                                      > > > > I don't know why I was relating the concept of a snapshot with a stack
                                                      > > of
                                                      > > > > events and not with the domain AR (and since I'm not an english native
                                                      > > > > speaker I got a lil confused about the term 'rolling').
                                                      > > > >
                                                      > > > > So you take a picture of the domain entity after N events and then make
                                                      > > the
                                                      > > > > repository hold a reference to that picture indexed by its identity
                                                      > > (ID) (or
                                                      > > > > the separate process yoou mention)
                                                      > > > >
                                                      > > > > Let's assume you want to load the AR having the same ID that the
                                                      > > picture
                                                      > > > > hold by the repo has. You calculate the position in the event stack
                                                      > > from
                                                      > > > > where you would start replying events, then create an AR instance, copy
                                                      > > its
                                                      > > > > state with the picture (Memento) that you took previosly, and apply the
                                                      > > > > events representing the DELTA.
                                                      > > > >
                                                      > > > > The Snapshot shouldn't be kept by the repo because we would run into
                                                      > > the
                                                      > > > > same performance problem if too many instances live in memory. I guess
                                                      > > we
                                                      > > > > should serialize the snapshot to disk or something similar?
                                                      > > > >
                                                      > > > > Am I ok?
                                                      > > > >
                                                      > > > > Thanks Mark.
                                                      > > > >
                                                      > > > >
                                                      > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                                      > > <domaindrivendesign%40yahoogroups.com>,
                                                      > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                                      > > > > >
                                                      > > > > > Your rolling snapshot will never be assumed to be the latest state of
                                                      > > the
                                                      > > > > > AR, after loading the snapshot the repository will always get all
                                                      > > events
                                                      > > > > > that have occurred after the snapshot was made. The process creating
                                                      > > the
                                                      > > > > > snapshots will most likely be a independent process that would just
                                                      > > load
                                                      > > > > AR
                                                      > > > > > verify if a snapshot needs to be made. If this is the case it would
                                                      > > make
                                                      > > > > it.
                                                      > > > > > Say after 100 events you want a snapshot. Instead of putting this
                                                      > > > > > responsibility in the domain repository?
                                                      > > > > >
                                                      > > > > > So current version of the snapshot is 20 version of the last event is
                                                      > > 25
                                                      > > > > so
                                                      > > > > > after loading the snapshot it also needs to replay the last 5 events.
                                                      > > > > >
                                                      > > > > > Does this make sense?
                                                      > > > > >
                                                      > > > > > -Mark
                                                      > > > > >
                                                      > > > > > On Thu, Nov 12, 2009 at 4:37 PM, sebaszipp <sebaszipp@> wrote:
                                                      > > > > >
                                                      > > > > > >
                                                      > > > > > >
                                                      > > > > > >
                                                      > > > > > > Hi Mark,
                                                      > > > > > >
                                                      > > > > > > Great blog. Thanks for clarifying in detail things about CQRS.
                                                      > > > > > >
                                                      > > > > > > Still a grey zone I'd like to get better is about AR load
                                                      > > performance
                                                      > > > > when
                                                      > > > > > > the event storage is large enough to kill performance.
                                                      > > > > > > I know rolling snapshots takes care of this field, but by rolling
                                                      > > > > snapthost
                                                      > > > > > > I might get an incomplete AR?
                                                      > > > > > > Could you please explain this?
                                                      > > > > > >
                                                      > > > > > > Thanks.
                                                      > > > > > >
                                                      > > > > > >
                                                      > > > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                                      > > <domaindrivendesign%40yahoogroups.com>
                                                      > > > > <domaindrivendesign%40yahoogroups.com>,
                                                      > > > >
                                                      > > > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                                      > > > > > > >
                                                      > > > > > > > Hi,
                                                      > > > > > > >
                                                      > > > > > > > I finally got the first blog post about this published, it is
                                                      > > long!
                                                      > > > > Not
                                                      > > > > > > so
                                                      > > > > > > > much code, more the explanation behind it (as I understand it).
                                                      > > > > > > >
                                                      > > > > > > > Link:
                                                      > > http://blog.fohjin.com/blog/2009/11/12/CQRS_a_la_Greg_Young
                                                      > > > > > > >
                                                      > > > > > > > -Mark
                                                      > > > > > > >
                                                      > > > > > > >
                                                      > > > > > > > On Thu, Oct 29, 2009 at 1:09 AM, Mark Nijhof <mark.nijhof@>
                                                      > > wrote:
                                                      > > > > > > >
                                                      > > > > > > > > Hi,
                                                      > > > > > > > >
                                                      > > > > > > > > Because that is a nasty home made implementation of a bus :)
                                                      > > The
                                                      > > > > > > Publish
                                                      > > > > > > > > method needs to know the exact type of the command/event that
                                                      > > gets
                                                      > > > > > > passed in
                                                      > > > > > > > > because that is used to get the correct xxxHandlers from the
                                                      > > IoC
                                                      > > > > > > container.
                                                      > > > > > > > > I cannot use an Generic in the PublishMultiple because these
                                                      > > > > > > commands/events
                                                      > > > > > > > > are 99% of the time not of the same type. I will probably
                                                      > > change it
                                                      > > > > > > into
                                                      > > > > > > > > something like this:
                                                      > > > > > > > >
                                                      > > > > > >
                                                      > > > >
                                                      > > http://codebetter.com/blogs/gregyoung/archive/2009/10/03/delegate-mapper.aspx
                                                      > > > > > > > >
                                                      > > > > > > > > Also one thing I like to highlight is that in this first
                                                      > > version I
                                                      > > > > am
                                                      > > > > > > not
                                                      > > > > > > > > using anything complex because I explicitly wanted to show that
                                                      > > the
                                                      > > > > > > core of
                                                      > > > > > > > > this is actually very simple, if I started with NServiceBus and
                                                      > > > > > > NHibernate
                                                      > > > > > > > > than that would have taken away from the simplicity of this
                                                      > > type of
                                                      > > > > > > > > architecture. That is why I have implemented my own very simple
                                                      > > ORM
                                                      > > > > > > (one has
                                                      > > > > > > > > to do that once in their career anyway right) and my own bus. I
                                                      > > > > plan on
                                                      > > > > > > > > continuing on this example by introducing these types of
                                                      > > options as
                                                      > > > > > > well,
                                                      > > > > > > > > all do the event store will remain custom SQL, actually I will
                                                      > > also
                                                      > > > > > > > > implement one using SQL Server and that one will use a stored
                                                      > > > > procedure
                                                      > > > > > > ;)
                                                      > > > > > > > >
                                                      > > > > > > > > -Mark
                                                      > > > > > > > >
                                                      > > > > > > > >
                                                      > > > > > > > >
                                                      > > > > > > > > On Wed, Oct 28, 2009 at 8:16 PM, David Perfors <dnperfors@
                                                      > > >wrote:
                                                      > > > > > >
                                                      > > > > > > > >
                                                      > > > > > > > >>
                                                      > > > > > > > >>
                                                      > > > > > > > >> Hi Mark,
                                                      > > > > > > > >>
                                                      > > > > > > > >> Thanks a lot for this example. I was looking into the code and
                                                      > > > > looked
                                                      > > > > > > ad
                                                      > > > > > > > >> the implementations of IBus and saw that it is using
                                                      > > reflection
                                                      > > > > for
                                                      > > > > > > the
                                                      > > > > > > > >> PublishMultiple method. Can you tell me (us) more about why
                                                      > > you
                                                      > > > > are
                                                      > > > > > > doing
                                                      > > > > > > > >> that instead of just calling the Publish method?
                                                      > > > > > > > >>
                                                      > > > > > > > >> Looking forward to the blogposts :)
                                                      > > > > > > > >>
                                                      > > > > > > > >> David.
                                                      > > > > > > > >>
                                                      > > > > > > > >> 2009/10/26 Mark Nijhof <Mark.Nijhof@>
                                                      > > > > > >
                                                      > > > > > > > >>
                                                      > > > > > > > >>> Hi,
                                                      > > > > > > > >>>
                                                      > > > > > > > >>> Since multiple people have been asking for this and I feel
                                                      > > that
                                                      > > > > the
                                                      > > > > > > > >>> core is good enough to share I thought I would share the
                                                      > > > > repository
                                                      > > > > > > > >>> here already. Disclaimer: Now keep in mind that this has not
                                                      > > been
                                                      > > > > > > > >>> reviewed by Greg yet and that I am still working on it. I am
                                                      > > also
                                                      > > > > > > > >>> working on a complete detailed blog post (or several) to
                                                      > > explain
                                                      > > > > what
                                                      > > > > > > > >>> is going on and why (with diagrams and all that fancy stuff).
                                                      > > > > Once
                                                      > > > > > > > >>> that is done it will be published here:
                                                      > > http://blog.fohjin.com/I am
                                                      > > > > > > > >>> currently finishing my specifications for the GUI and will
                                                      > > split
                                                      > > > > the
                                                      > > > > > > > >>> existing domain specifications a bit more per scenario, but I
                                                      > > > > think
                                                      > > > > > > > >>> you will like what you see there (hope at least).
                                                      > > > > > > > >>>
                                                      > > > > > > > >>> The most interesting scenario is a transfer from one account
                                                      > > to
                                                      > > > > an
                                                      > > > > > > > >>> other account.
                                                      > > > > > > > >>>
                                                      > > > > > > > >>> Link: http://github.com/MarkNijhof/Fohjin
                                                      > > > > > > > >>>
                                                      > > > > > > > >>> Note on SQLite: Because I am developing on x64 I have the x64
                                                      > > > > version
                                                      > > > > > > > >>> of SQLite referenced in the projects, except for the test
                                                      > > project
                                                      > > > > > > > >>> because TestDriven.Net executes everything in x86. Now if you
                                                      > > are
                                                      > > > > > > > >>> running on a x86 machine all you have to do is copy the x86
                                                      > > > > > > > >>> System.Data.SQLite.* from /lib/sqlite/bin to
                                                      > > /lib/sqlite/bin/x64
                                                      > > > > > > (this
                                                      > > > > > > > >>> approach is tested). There are two different SQLite
                                                      > > databases,
                                                      > > > > one is
                                                      > > > > > > > >>> the event store and the other is the reporting database. I
                                                      > > > > haven't
                                                      > > > > > > > >>> figured out yet how, but it is possible to load the SQLite
                                                      > > > > databases
                                                      > > > > > > > >>> in Visual Studio to inspect the content. Both databases are
                                                      > > > > created
                                                      > > > > > > on
                                                      > > > > > > > >>> first use, and deleting them will give you a fresh start.
                                                      > > > > > > > >>>
                                                      > > > > > > > >>> I would like to hear your opinions, I am very enthusiastic
                                                      > > about
                                                      > > > > this
                                                      > > > > > > > >>> architecture when there is a need for a domain.
                                                      > > > > > > > >>>
                                                      > > > > > > > >>> -Mark
                                                      > > > > > > > >>>
                                                      > > > > > > > >>>
                                                      > > > > > > > >>> ------------------------------------
                                                      > > > > > > > >>>
                                                      > > > > > > > >>> Yahoo! Groups Links
                                                      > > > > > > > >>>
                                                      > > > > > > > >>>
                                                      > > > > > > > >>>
                                                      > > > > > > > >>>
                                                      > > > > > > > >>
                                                      > > > > > > > >>
                                                      > > > > > > > >
                                                      > > > > > > > >
                                                      > > > > > > >
                                                      > > > > > >
                                                      > > > > > >
                                                      > > > > > >
                                                      > > > > >
                                                      > > > >
                                                      > > > >
                                                      > > > >
                                                      > > >
                                                      > > >
                                                      > > >
                                                      > > > --
                                                      > > > Les erreurs de grammaire et de syntaxe ont été incluses pour m'assurer de
                                                      > > > votre attention
                                                      > > >
                                                      > >
                                                      > >
                                                      > >
                                                      >





                                                    • Mark Nijhof
                                                      Will take a much closer look at the code, just wanted to respond to the question :) If you have a list with children then each child needs to have a unique Id
                                                      Message 26 of 30 , Nov 13, 2009
                                                        Will take a much closer look at the code, just wanted to respond to the question :)

                                                        If you have a list with children then each child needs to have a unique Id within the AR, you need this anyway, this Id also needs to be in the history event, thus you have an easy way to select to which child to forward the event. I am not sure what I am missing here?

                                                        class AR
                                                        {
                                                            list activeAccounts = new List
                                                            {
                                                                new ActiveAccount { Id = 10 }
                                                                new ActiveAccount { Id = 15 }
                                                            }

                                                            forwardEventsToAccount(object event)
                                                            {
                                                                ActiveAccount actinveAccount;
                                                                if (!activeAccounts.TryGetById(event.AccountId, out activeAccount))
                                                                    throw new Exception();

                                                                activeAccount.LoadHistory(event);       
                                                            }
                                                        }

                                                        AR ar = new AR()
                                                        ar.LoadHistory(new[] {
                                                            someEventForAccount { AccountId = 10 }
                                                            someEventForAccount { AccountId = 15 }
                                                            someOtherEventForAccount { AccountId = 10 }
                                                            someOtherEventForAccount { AccountId = 10 }
                                                        });

                                                        -Mark


                                                        On Sat, Nov 14, 2009 at 12:02 AM, Mark Henke <gilligan128@...> wrote:
                                                         

                                                        How do you know to what child an event belongs to? Your example below does not seem to handle that. That is what my solution is tackling. Here is a rough-shod example:

                                                         interface ILookup
                                                                {
                                                                    bool HasChildFor(IDomainEvent @event);
                                                                    void ApplyChildEvent(IDomainEvent @event );
                                                                    IEnumerable<IDomainEvent> GetChanges();
                                                                    void ClearChanges();
                                                                }


                                                                class AggregateRootBase
                                                                {
                                                                    LookupBuilder<T> Lookup<T>(IEnumerable<T> childCollection) where T : EventSource
                                                                {
                                                                    var lookupBuilder = new LookupBuilder<T>(childCollection);
                                                                    lookups.Add(lookupBuilder);

                                                                    return lookupBuilder;
                                                                }


                                                                    public void ForwardToChildrenEventsOfType<T>()
                                                                    {
                                                                        RegisterHandler<T>(@event => lookups.Single(lookup => lookup.HasChildFor(@event)).ApplyChildEvent(@event));
                                                                    }

                                                                   public IEnumerable<IDomainEvent> GetChanges()
                                                                  {
                                                                         return events.Concat(lookups.SelectMany(lookup => lookup.GetChanges()));
                                                                  }

                                                                  
                                                                }

                                                        And the LookupBuilder class:

                                                         class LookupBuilder<T> : ILookup where T : EventSource
                                                                {
                                                                    IEnumerable<T> children;
                                                                    Func<T, object> childKey;
                                                                    IDictionary<Type, Func<IDomainEvent, object>> eventKeys = new Dictionary<Type, Func<IDomainEvent, object>>();

                                                                    AggregateRootBase ar;


                                                                    public LookupBuilder(IEnumerable<T> children, AggregateRootBase ar)
                                                                    {
                                                                        this.children = children;
                                                                        this.ar = ar;
                                                                        childKey = child => child.Id;
                                                                    }

                                                                    public LookupBuilder<T> On(Func<T, object> keyGetter)
                                                                    {
                                                                        childKey = keyGetter;
                                                                        return this;
                                                                    }

                                                                    public LookupBuilder<T> For<TEvent>(Func<TEvent,object> eventKeyGetter)
                                                                    {
                                                                        eventKeys[typeof (TEvent)] = @event =>  eventKeyGetter((TEvent)@event);
                                                                        ar.ForwardToChildrenEventsOfType<TEvent>();
                                                                        return this;
                                                                    }

                                                                    bool ILookup.HasChildFor(IDomainEvent @event)
                                                                    {
                                                                        if(!eventKeys.ContainsKey(@...()))
                                                                        {
                                                                            return false;
                                                                        }

                                                                        var eventKey = eventKeys[@...()];
                                                                        return children.Any(child => childKey(child) == eventKey(@event));
                                                                    }


                                                                    IEnumerable<IDomainEvent> ILookup.GetChanges()
                                                                    {
                                                                        return children.SelectMany(child => child.GetChanges());
                                                                    }

                                                                    void ILookup.ClearChanges()
                                                                    {
                                                                        children.Iterate(x => x.ClearChanges());
                                                                    }

                                                                    void ILookup.ApplyChildEvent(IDomainEvent @event)
                                                                    {
                                                                        var eventKey = eventKeys[@...()];
                                                                        children.Single(child => childKey(child) == eventKey(@event)).LoadEventFromHistory(@event);
                                                                    }
                                                                }


                                                        It may be hard to read at first, but it basically allows us to do things like this:

                                                        public Client()
                                                        {
                                                           Lookup(ActiveAccounts)
                                                            .For<AccountIsOnHold>(@event => @...)
                                                            .For<AccountIsNoLongerOnHold>(@event => @...);

                                                          Lookup(ClosedAccounts)
                                                           .For<AccountReactivated>(@event => @...);

                                                        }

                                                        All the ugly stuff is hidden by the base class and the plumbing is handled for us. We could also add something like Child(CurrentAccount).CanHandle<AccountOnHold>(x => x.AccountId) for simple cases. 

                                                        I hope that helps. Also this is only a rough draft of what I was thinking.

                                                        On Fri, Nov 13, 2009 at 4:07 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                         

                                                        One thing I don't like about this solution (or as how I understand it) is that you put all different types into on dictionary wouldn't this ruin a lot of the readability? Also seems more complex then needed? But as often happens I might just completely understand you wrong :D So an code example would be great. Perhaps I can implement something like this before the upcoming E-VAN talk. (I want to keep it somewhat recognizable for people attending the talk so no major changes).

                                                        Here an example keeping in the same types but different organization:

                                                        Client
                                                        - List<ActiveAccounts> activeAccounts;
                                                        - List<ClosedAccounts> closedAccounts;

                                                        So in the AR I handle both events for the active account and closed account. I could just have two event handlers, one that handles all events for the active account amd one that handles all events for the closed accounts. In this event handler you would just forward the event to the correct instance in the list. Inside the f.ex. Active account it knows how to apply each individual different type of event.

                                                        private void forwardAllEventsForAnActiveAccount(object event)
                                                        {
                                                            ActiveAccount actinveAccount;
                                                            if (!activeAccounts.TryGetById(event.AccountId))
                                                                throw new Exception();

                                                            activeAccount.LoadHistory(event);
                                                        }

                                                        -Mark




                                                        On Fri, Nov 13, 2009 at 3:49 PM, Mark Henke <gilligan128@...> wrote:
                                                         

                                                        I think we can break up this AR -> AGG issue of replaying events into two parts:

                                                        1) How is a Child AGG identified? and
                                                        2) How do we figure out what child that event belongs to?

                                                        Here is a shot in the dark, but how about this:

                                                        Let's assume all our child AGGs are in a single dictionary based upon type. The AR can then view itself internally as a Repository of AGGs. 
                                                        e.g. AddAGG<OrderSection>(orderSection);

                                                        Then for any event type we can register a Lookup on a specific child type. 
                                                        e.g. RegisterLookupOn<OrderSection>(section => section.Id)
                                                                  .For<ProductSaleEvent>(@event => @...);
                                                        The base AR classe, when replaying events, would also check to see if a lookup is registered for that event type and will forward that event to the specified child AGG.

                                                        I could create a patch on Git for your example experimenting with this idea if you want, Mark.


                                                        On Thu, Nov 12, 2009 at 5:03 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                         

                                                        You could still have the AR be responsible for managing the collection including the internal state, but that feels wrong.

                                                        -Mark



                                                        On Thu, Nov 12, 2009 at 9:32 PM, sebaszipp <sebaszipp@...> wrote:
                                                         


                                                        Yes, for the case we have predifined/fixed order sections for an order we could fire up events according to the section in cuestion. But in case of having collection of AGGs (AR -> List<AGG> -> List<AGG>) the situation comes kind of weird.
                                                        Maybe we should take a look into our BC, in order to rethink and see whether the BC graph should be pruned and the remaing is responsability of another BC?



                                                        --- In domaindrivendesign@yahoogroups.com, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                        >
                                                        > Each AGG can apply its own events and store them in itself, then when you
                                                        > ask for changes from the AR it will ask changes from it's AGG.
                                                        >
                                                        > Loading events from history would load them all in the AR which would
                                                        > delegate them back to the AGG. I am not 100% sure yet what the best approach
                                                        > for this is. You could just send all of them and have the AGG decide which
                                                        > one to skip, or you could make the AR aware what types of events need to be
                                                        > forwarded to the AGG. This can be done by creating an event handler in the
                                                        > AR that would just forward the event to the specific AGG. But if you have
                                                        > collections of AGG then this would be a problem.
                                                        >
                                                        > -Mark
                                                        >
                                                        >
                                                        > On Thu, Nov 12, 2009 at 8:46 PM, sebaszipp <sebaszipp@...> wrote:
                                                        >
                                                        > >
                                                        > >
                                                        > >
                                                        > > Great. Thanks Greg.
                                                        > >
                                                        > > I more question:
                                                        > >
                                                        > > As far as I've been reading about CQS I've been all examples matching the
                                                        > > same association: AR -> AGG where the AR is the one firing up domain events.
                                                        > > I would like to add another association supposing our graph is more complex
                                                        > > than just AR -> AGG.
                                                        > >
                                                        > > In this case we would have the following graph:
                                                        > > Order AR -> OrderSection AGG -> OrderLine AGG
                                                        > >
                                                        > > Suppose there are 2 rules dictating that products under 10 dollars should
                                                        > > be placed into Section1 and the others should be placed into Section2. In
                                                        > > the case a product that is $5 is bought we would fire up an event from the
                                                        > > Order AR:
                                                        > >
                                                        > > super.apply(new ProductSaleEvent(sectionOneID, productDescription))
                                                        > >
                                                        > > and then the event handler of the Order AR should be:
                                                        > >
                                                        > > handle(ProductSaleEvent event)
                                                        > > {
                                                        > > OrderSection orderSection = orderSections.get(event.sectionId)
                                                        > > if (orderSection == null) {
                                                        > > orderSection = new OrderSection();
                                                        > > orderSections.put(event.sectionId, orderSection);
                                                        > > }
                                                        > > orderSection.processSale(productDescription); // which will create a Line
                                                        > > internally
                                                        > > }
                                                        > >
                                                        > > Should be handled this way?
                                                        > > I mean, the AR is the leading with the graph hierarchy no matter how deep
                                                        > > it's?
                                                        > >
                                                        > > Cheers,
                                                        > >
                                                        > >
                                                        > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>,

                                                        > > Greg Young <gregoryyoung1@> wrote:
                                                        > > >
                                                        > > > Yes the snapshots are generally not in memory, they live in the event
                                                        > > store.
                                                        > > >
                                                        > > > Cheers,
                                                        > > >
                                                        > > > Greg
                                                        > > >
                                                        > > > On Thu, Nov 12, 2009 at 8:30 PM, sebaszipp <sebaszipp@> wrote:
                                                        > > >
                                                        > > > >
                                                        > > > >
                                                        > > > >
                                                        > > > > I got it :)
                                                        > > > >
                                                        > > > > I don't know why I was relating the concept of a snapshot with a stack
                                                        > > of
                                                        > > > > events and not with the domain AR (and since I'm not an english native
                                                        > > > > speaker I got a lil confused about the term 'rolling').
                                                        > > > >
                                                        > > > > So you take a picture of the domain entity after N events and then make
                                                        > > the
                                                        > > > > repository hold a reference to that picture indexed by its identity
                                                        > > (ID) (or
                                                        > > > > the separate process yoou mention)
                                                        > > > >
                                                        > > > > Let's assume you want to load the AR having the same ID that the
                                                        > > picture
                                                        > > > > hold by the repo has. You calculate the position in the event stack
                                                        > > from
                                                        > > > > where you would start replying events, then create an AR instance, copy
                                                        > > its
                                                        > > > > state with the picture (Memento) that you took previosly, and apply the
                                                        > > > > events representing the DELTA.
                                                        > > > >
                                                        > > > > The Snapshot shouldn't be kept by the repo because we would run into
                                                        > > the
                                                        > > > > same performance problem if too many instances live in memory. I guess
                                                        > > we
                                                        > > > > should serialize the snapshot to disk or something similar?
                                                        > > > >
                                                        > > > > Am I ok?
                                                        > > > >
                                                        > > > > Thanks Mark.
                                                        > > > >
                                                        > > > >
                                                        > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                                        > > <domaindrivendesign%40yahoogroups.com>,
                                                        > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                                        > > > > >
                                                        > > > > > Your rolling snapshot will never be assumed to be the latest state of
                                                        > > the
                                                        > > > > > AR, after loading the snapshot the repository will always get all
                                                        > > events
                                                        > > > > > that have occurred after the snapshot was made. The process creating
                                                        > > the
                                                        > > > > > snapshots will most likely be a independent process that would just
                                                        > > load
                                                        > > > > AR
                                                        > > > > > verify if a snapshot needs to be made. If this is the case it would
                                                        > > make
                                                        > > > > it.
                                                        > > > > > Say after 100 events you want a snapshot. Instead of putting this
                                                        > > > > > responsibility in the domain repository?
                                                        > > > > >
                                                        > > > > > So current version of the snapshot is 20 version of the last event is
                                                        > > 25
                                                        > > > > so
                                                        > > > > > after loading the snapshot it also needs to replay the last 5 events.
                                                        > > > > >
                                                        > > > > > Does this make sense?
                                                        > > > > >
                                                        > > > > > -Mark
                                                        > > > > >
                                                        > > > > > On Thu, Nov 12, 2009 at 4:37 PM, sebaszipp <sebaszipp@> wrote:
                                                        > > > > >
                                                        > > > > > >
                                                        > > > > > >
                                                        > > > > > >
                                                        > > > > > > Hi Mark,
                                                        > > > > > >
                                                        > > > > > > Great blog. Thanks for clarifying in detail things about CQRS.
                                                        > > > > > >
                                                        > > > > > > Still a grey zone I'd like to get better is about AR load
                                                        > > performance
                                                        > > > > when
                                                        > > > > > > the event storage is large enough to kill performance.
                                                        > > > > > > I know rolling snapshots takes care of this field, but by rolling
                                                        > > > > snapthost
                                                        > > > > > > I might get an incomplete AR?
                                                        > > > > > > Could you please explain this?
                                                        > > > > > >
                                                        > > > > > > Thanks.
                                                        > > > > > >
                                                        > > > > > >
                                                        > > > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                                        > > <domaindrivendesign%40yahoogroups.com>
                                                        > > > > <domaindrivendesign%40yahoogroups.com>,
                                                        > > > >
                                                        > > > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                                        > > > > > > >
                                                        > > > > > > > Hi,
                                                        > > > > > > >
                                                        > > > > > > > I finally got the first blog post about this published, it is
                                                        > > long!
                                                        > > > > Not
                                                        > > > > > > so
                                                        > > > > > > > much code, more the explanation behind it (as I understand it).
                                                        > > > > > > >
                                                        > > > > > > > Link:
                                                        > > http://blog.fohjin.com/blog/2009/11/12/CQRS_a_la_Greg_Young
                                                        > > > > > > >
                                                        > > > > > > > -Mark
                                                        > > > > > > >
                                                        > > > > > > >
                                                        > > > > > > > On Thu, Oct 29, 2009 at 1:09 AM, Mark Nijhof <mark.nijhof@>
                                                        > > wrote:
                                                        > > > > > > >
                                                        > > > > > > > > Hi,
                                                        > > > > > > > >
                                                        > > > > > > > > Because that is a nasty home made implementation of a bus :)
                                                        > > The
                                                        > > > > > > Publish
                                                        > > > > > > > > method needs to know the exact type of the command/event that
                                                        > > gets
                                                        > > > > > > passed in
                                                        > > > > > > > > because that is used to get the correct xxxHandlers from the
                                                        > > IoC
                                                        > > > > > > container.
                                                        > > > > > > > > I cannot use an Generic in the PublishMultiple because these
                                                        > > > > > > commands/events
                                                        > > > > > > > > are 99% of the time not of the same type. I will probably
                                                        > > change it
                                                        > > > > > > into
                                                        > > > > > > > > something like this:
                                                        > > > > > > > >
                                                        > > > > > >
                                                        > > > >
                                                        > > http://codebetter.com/blogs/gregyoung/archive/2009/10/03/delegate-mapper.aspx
                                                        > > > > > > > >
                                                        > > > > > > > > Also one thing I like to highlight is that in this first
                                                        > > version I
                                                        > > > > am
                                                        > > > > > > not
                                                        > > > > > > > > using anything complex because I explicitly wanted to show that
                                                        > > the
                                                        > > > > > > core of
                                                        > > > > > > > > this is actually very simple, if I started with NServiceBus and
                                                        > > > > > > NHibernate
                                                        > > > > > > > > than that would have taken away from the simplicity of this
                                                        > > type of
                                                        > > > > > > > > architecture. That is why I have implemented my own very simple
                                                        > > ORM
                                                        > > > > > > (one has
                                                        > > > > > > > > to do that once in their career anyway right) and my own bus. I
                                                        > > > > plan on
                                                        > > > > > > > > continuing on this example by introducing these types of
                                                        > > options as
                                                        > > > > > > well,
                                                        > > > > > > > > all do the event store will remain custom SQL, actually I will
                                                        > > also
                                                        > > > > > > > > implement one using SQL Server and that one will use a stored
                                                        > > > > procedure
                                                        > > > > > > ;)
                                                        > > > > > > > >
                                                        > > > > > > > > -Mark
                                                        > > > > > > > >
                                                        > > > > > > > >
                                                        > > > > > > > >
                                                        > > > > > > > > On Wed, Oct 28, 2009 at 8:16 PM, David Perfors <dnperfors@
                                                        > > >wrote:
                                                        > > > > > >
                                                        > > > > > > > >
                                                        > > > > > > > >>
                                                        > > > > > > > >>
                                                        > > > > > > > >> Hi Mark,
                                                        > > > > > > > >>
                                                        > > > > > > > >> Thanks a lot for this example. I was looking into the code and
                                                        > > > > looked
                                                        > > > > > > ad
                                                        > > > > > > > >> the implementations of IBus and saw that it is using
                                                        > > reflection
                                                        > > > > for
                                                        > > > > > > the
                                                        > > > > > > > >> PublishMultiple method. Can you tell me (us) more about why
                                                        > > you
                                                        > > > > are
                                                        > > > > > > doing
                                                        > > > > > > > >> that instead of just calling the Publish method?
                                                        > > > > > > > >>
                                                        > > > > > > > >> Looking forward to the blogposts :)
                                                        > > > > > > > >>
                                                        > > > > > > > >> David.
                                                        > > > > > > > >>
                                                        > > > > > > > >> 2009/10/26 Mark Nijhof <Mark.Nijhof@>
                                                        > > > > > >
                                                        > > > > > > > >>
                                                        > > > > > > > >>> Hi,
                                                        > > > > > > > >>>
                                                        > > > > > > > >>> Since multiple people have been asking for this and I feel
                                                        > > that
                                                        > > > > the
                                                        > > > > > > > >>> core is good enough to share I thought I would share the
                                                        > > > > repository
                                                        > > > > > > > >>> here already. Disclaimer: Now keep in mind that this has not
                                                        > > been
                                                        > > > > > > > >>> reviewed by Greg yet and that I am still working on it. I am
                                                        > > also
                                                        > > > > > > > >>> working on a complete detailed blog post (or several) to
                                                        > > explain
                                                        > > > > what
                                                        > > > > > > > >>> is going on and why (with diagrams and all that fancy stuff).
                                                        > > > > Once
                                                        > > > > > > > >>> that is done it will be published here:
                                                        > > http://blog.fohjin.com/I am
                                                        > > > > > > > >>> currently finishing my specifications for the GUI and will
                                                        > > split
                                                        > > > > the
                                                        > > > > > > > >>> existing domain specifications a bit more per scenario, but I
                                                        > > > > think
                                                        > > > > > > > >>> you will like what you see there (hope at least).
                                                        > > > > > > > >>>
                                                        > > > > > > > >>> The most interesting scenario is a transfer from one account
                                                        > > to
                                                        > > > > an
                                                        > > > > > > > >>> other account.
                                                        > > > > > > > >>>
                                                        > > > > > > > >>> Link: http://github.com/MarkNijhof/Fohjin
                                                        > > > > > > > >>>
                                                        > > > > > > > >>> Note on SQLite: Because I am developing on x64 I have the x64
                                                        > > > > version
                                                        > > > > > > > >>> of SQLite referenced in the projects, except for the test
                                                        > > project
                                                        > > > > > > > >>> because TestDriven.Net executes everything in x86. Now if you
                                                        > > are
                                                        > > > > > > > >>> running on a x86 machine all you have to do is copy the x86
                                                        > > > > > > > >>> System.Data.SQLite.* from /lib/sqlite/bin to
                                                        > > /lib/sqlite/bin/x64
                                                        > > > > > > (this
                                                        > > > > > > > >>> approach is tested). There are two different SQLite
                                                        > > databases,
                                                        > > > > one is
                                                        > > > > > > > >>> the event store and the other is the reporting database. I
                                                        > > > > haven't
                                                        > > > > > > > >>> figured out yet how, but it is possible to load the SQLite
                                                        > > > > databases
                                                        > > > > > > > >>> in Visual Studio to inspect the content. Both databases are
                                                        > > > > created
                                                        > > > > > > on
                                                        > > > > > > > >>> first use, and deleting them will give you a fresh start.
                                                        > > > > > > > >>>
                                                        > > > > > > > >>> I would like to hear your opinions, I am very enthusiastic
                                                        > > about
                                                        > > > > this
                                                        > > > > > > > >>> architecture when there is a need for a domain.
                                                        > > > > > > > >>>
                                                        > > > > > > > >>> -Mark
                                                        > > > > > > > >>>
                                                        > > > > > > > >>>
                                                        > > > > > > > >>> ------------------------------------
                                                        > > > > > > > >>>
                                                        > > > > > > > >>> Yahoo! Groups Links
                                                        > > > > > > > >>>
                                                        > > > > > > > >>>
                                                        > > > > > > > >>>
                                                        > > > > > > > >>>
                                                        > > > > > > > >>
                                                        > > > > > > > >>
                                                        > > > > > > > >
                                                        > > > > > > > >
                                                        > > > > > > >
                                                        > > > > > >
                                                        > > > > > >
                                                        > > > > > >
                                                        > > > > >
                                                        > > > >
                                                        > > > >
                                                        > > > >
                                                        > > >
                                                        > > >
                                                        > > >
                                                        > > > --
                                                        > > > Les erreurs de grammaire et de syntaxe ont été incluses pour m'assurer de
                                                        > > > votre attention
                                                        > > >
                                                        > >
                                                        > >
                                                        > >
                                                        >






                                                      • Mark Nijhof
                                                        In the registration method you would register all the events that the ActiveAccount has to be handled by the forwardEventsToAccount. Since when you write your
                                                        Message 27 of 30 , Nov 13, 2009
                                                          In the registration method you would register all the events that the ActiveAccount has to be handled by the forwardEventsToAccount. Since when you write your domain you know the events that the children can handle so this should be easy, you could perhaps even apply convention here.

                                                          -Mark


                                                          On Sat, Nov 14, 2009 at 12:20 AM, Mark Nijhof <mark.nijhof@...> wrote:
                                                          Will take a much closer look at the code, just wanted to respond to the question :)

                                                          If you have a list with children then each child needs to have a unique Id within the AR, you need this anyway, this Id also needs to be in the history event, thus you have an easy way to select to which child to forward the event. I am not sure what I am missing here?

                                                          class AR
                                                          {
                                                              list activeAccounts = new List
                                                              {
                                                                  new ActiveAccount { Id = 10 }
                                                                  new ActiveAccount { Id = 15 }
                                                              }

                                                              forwardEventsToAccount(object event)
                                                              {
                                                                  ActiveAccount actinveAccount;
                                                                  if (!activeAccounts.TryGetById(event.AccountId, out activeAccount))

                                                                      throw new Exception();

                                                                  activeAccount.LoadHistory(event);       
                                                              }
                                                          }

                                                          AR ar = new AR()
                                                          ar.LoadHistory(new[] {
                                                              someEventForAccount { AccountId = 10 }
                                                              someEventForAccount { AccountId = 15 }
                                                              someOtherEventForAccount { AccountId = 10 }
                                                              someOtherEventForAccount { AccountId = 10 }
                                                          });

                                                          -Mark



                                                          On Sat, Nov 14, 2009 at 12:02 AM, Mark Henke <gilligan128@...> wrote:
                                                           

                                                          How do you know to what child an event belongs to? Your example below does not seem to handle that. That is what my solution is tackling. Here is a rough-shod example:

                                                           interface ILookup
                                                                  {
                                                                      bool HasChildFor(IDomainEvent @event);
                                                                      void ApplyChildEvent(IDomainEvent @event );
                                                                      IEnumerable<IDomainEvent> GetChanges();
                                                                      void ClearChanges();
                                                                  }


                                                                  class AggregateRootBase
                                                                  {
                                                                      LookupBuilder<T> Lookup<T>(IEnumerable<T> childCollection) where T : EventSource
                                                                  {
                                                                      var lookupBuilder = new LookupBuilder<T>(childCollection);
                                                                      lookups.Add(lookupBuilder);

                                                                      return lookupBuilder;
                                                                  }


                                                                      public void ForwardToChildrenEventsOfType<T>()
                                                                      {
                                                                          RegisterHandler<T>(@event => lookups.Single(lookup => lookup.HasChildFor(@event)).ApplyChildEvent(@event));
                                                                      }

                                                                     public IEnumerable<IDomainEvent> GetChanges()
                                                                    {
                                                                           return events.Concat(lookups.SelectMany(lookup => lookup.GetChanges()));
                                                                    }

                                                                    
                                                                  }

                                                          And the LookupBuilder class:

                                                           class LookupBuilder<T> : ILookup where T : EventSource
                                                                  {
                                                                      IEnumerable<T> children;
                                                                      Func<T, object> childKey;
                                                                      IDictionary<Type, Func<IDomainEvent, object>> eventKeys = new Dictionary<Type, Func<IDomainEvent, object>>();

                                                                      AggregateRootBase ar;


                                                                      public LookupBuilder(IEnumerable<T> children, AggregateRootBase ar)
                                                                      {
                                                                          this.children = children;
                                                                          this.ar = ar;
                                                                          childKey = child => child.Id;
                                                                      }

                                                                      public LookupBuilder<T> On(Func<T, object> keyGetter)
                                                                      {
                                                                          childKey = keyGetter;
                                                                          return this;
                                                                      }

                                                                      public LookupBuilder<T> For<TEvent>(Func<TEvent,object> eventKeyGetter)
                                                                      {
                                                                          eventKeys[typeof (TEvent)] = @event =>  eventKeyGetter((TEvent)@event);
                                                                          ar.ForwardToChildrenEventsOfType<TEvent>();
                                                                          return this;
                                                                      }

                                                                      bool ILookup.HasChildFor(IDomainEvent @event)
                                                                      {
                                                                          if(!eventKeys.ContainsKey(@...()))
                                                                          {
                                                                              return false;
                                                                          }

                                                                          var eventKey = eventKeys[@...()];
                                                                          return children.Any(child => childKey(child) == eventKey(@event));
                                                                      }


                                                                      IEnumerable<IDomainEvent> ILookup.GetChanges()
                                                                      {
                                                                          return children.SelectMany(child => child.GetChanges());
                                                                      }

                                                                      void ILookup.ClearChanges()
                                                                      {
                                                                          children.Iterate(x => x.ClearChanges());
                                                                      }

                                                                      void ILookup.ApplyChildEvent(IDomainEvent @event)
                                                                      {
                                                                          var eventKey = eventKeys[@...()];
                                                                          children.Single(child => childKey(child) == eventKey(@event)).LoadEventFromHistory(@event);
                                                                      }
                                                                  }


                                                          It may be hard to read at first, but it basically allows us to do things like this:

                                                          public Client()
                                                          {
                                                             Lookup(ActiveAccounts)
                                                              .For<AccountIsOnHold>(@event => @...)
                                                              .For<AccountIsNoLongerOnHold>(@event => @...);

                                                            Lookup(ClosedAccounts)
                                                             .For<AccountReactivated>(@event => @...);

                                                          }

                                                          All the ugly stuff is hidden by the base class and the plumbing is handled for us. We could also add something like Child(CurrentAccount).CanHandle<AccountOnHold>(x => x.AccountId) for simple cases. 

                                                          I hope that helps. Also this is only a rough draft of what I was thinking.

                                                          On Fri, Nov 13, 2009 at 4:07 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                           

                                                          One thing I don't like about this solution (or as how I understand it) is that you put all different types into on dictionary wouldn't this ruin a lot of the readability? Also seems more complex then needed? But as often happens I might just completely understand you wrong :D So an code example would be great. Perhaps I can implement something like this before the upcoming E-VAN talk. (I want to keep it somewhat recognizable for people attending the talk so no major changes).

                                                          Here an example keeping in the same types but different organization:

                                                          Client
                                                          - List<ActiveAccounts> activeAccounts;
                                                          - List<ClosedAccounts> closedAccounts;

                                                          So in the AR I handle both events for the active account and closed account. I could just have two event handlers, one that handles all events for the active account amd one that handles all events for the closed accounts. In this event handler you would just forward the event to the correct instance in the list. Inside the f.ex. Active account it knows how to apply each individual different type of event.

                                                          private void forwardAllEventsForAnActiveAccount(object event)
                                                          {
                                                              ActiveAccount actinveAccount;
                                                              if (!activeAccounts.TryGetById(event.AccountId))
                                                                  throw new Exception();

                                                              activeAccount.LoadHistory(event);
                                                          }

                                                          -Mark




                                                          On Fri, Nov 13, 2009 at 3:49 PM, Mark Henke <gilligan128@...> wrote:
                                                           

                                                          I think we can break up this AR -> AGG issue of replaying events into two parts:

                                                          1) How is a Child AGG identified? and
                                                          2) How do we figure out what child that event belongs to?

                                                          Here is a shot in the dark, but how about this:

                                                          Let's assume all our child AGGs are in a single dictionary based upon type. The AR can then view itself internally as a Repository of AGGs. 
                                                          e.g. AddAGG<OrderSection>(orderSection);

                                                          Then for any event type we can register a Lookup on a specific child type. 
                                                          e.g. RegisterLookupOn<OrderSection>(section => section.Id)
                                                                    .For<ProductSaleEvent>(@event => @...);
                                                          The base AR classe, when replaying events, would also check to see if a lookup is registered for that event type and will forward that event to the specified child AGG.

                                                          I could create a patch on Git for your example experimenting with this idea if you want, Mark.


                                                          On Thu, Nov 12, 2009 at 5:03 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                           

                                                          You could still have the AR be responsible for managing the collection including the internal state, but that feels wrong.

                                                          -Mark



                                                          On Thu, Nov 12, 2009 at 9:32 PM, sebaszipp <sebaszipp@...> wrote:
                                                           


                                                          Yes, for the case we have predifined/fixed order sections for an order we could fire up events according to the section in cuestion. But in case of having collection of AGGs (AR -> List<AGG> -> List<AGG>) the situation comes kind of weird.
                                                          Maybe we should take a look into our BC, in order to rethink and see whether the BC graph should be pruned and the remaing is responsability of another BC?



                                                          --- In domaindrivendesign@yahoogroups.com, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                          >
                                                          > Each AGG can apply its own events and store them in itself, then when you
                                                          > ask for changes from the AR it will ask changes from it's AGG.
                                                          >
                                                          > Loading events from history would load them all in the AR which would
                                                          > delegate them back to the AGG. I am not 100% sure yet what the best approach
                                                          > for this is. You could just send all of them and have the AGG decide which
                                                          > one to skip, or you could make the AR aware what types of events need to be
                                                          > forwarded to the AGG. This can be done by creating an event handler in the
                                                          > AR that would just forward the event to the specific AGG. But if you have
                                                          > collections of AGG then this would be a problem.
                                                          >
                                                          > -Mark
                                                          >
                                                          >
                                                          > On Thu, Nov 12, 2009 at 8:46 PM, sebaszipp <sebaszipp@...> wrote:
                                                          >
                                                          > >
                                                          > >
                                                          > >
                                                          > > Great. Thanks Greg.
                                                          > >
                                                          > > I more question:
                                                          > >
                                                          > > As far as I've been reading about CQS I've been all examples matching the
                                                          > > same association: AR -> AGG where the AR is the one firing up domain events.
                                                          > > I would like to add another association supposing our graph is more complex
                                                          > > than just AR -> AGG.
                                                          > >
                                                          > > In this case we would have the following graph:
                                                          > > Order AR -> OrderSection AGG -> OrderLine AGG
                                                          > >
                                                          > > Suppose there are 2 rules dictating that products under 10 dollars should
                                                          > > be placed into Section1 and the others should be placed into Section2. In
                                                          > > the case a product that is $5 is bought we would fire up an event from the
                                                          > > Order AR:
                                                          > >
                                                          > > super.apply(new ProductSaleEvent(sectionOneID, productDescription))
                                                          > >
                                                          > > and then the event handler of the Order AR should be:
                                                          > >
                                                          > > handle(ProductSaleEvent event)
                                                          > > {
                                                          > > OrderSection orderSection = orderSections.get(event.sectionId)
                                                          > > if (orderSection == null) {
                                                          > > orderSection = new OrderSection();
                                                          > > orderSections.put(event.sectionId, orderSection);
                                                          > > }
                                                          > > orderSection.processSale(productDescription); // which will create a Line
                                                          > > internally
                                                          > > }
                                                          > >
                                                          > > Should be handled this way?
                                                          > > I mean, the AR is the leading with the graph hierarchy no matter how deep
                                                          > > it's?
                                                          > >
                                                          > > Cheers,
                                                          > >
                                                          > >
                                                          > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>,

                                                          > > Greg Young <gregoryyoung1@> wrote:
                                                          > > >
                                                          > > > Yes the snapshots are generally not in memory, they live in the event
                                                          > > store.
                                                          > > >
                                                          > > > Cheers,
                                                          > > >
                                                          > > > Greg
                                                          > > >
                                                          > > > On Thu, Nov 12, 2009 at 8:30 PM, sebaszipp <sebaszipp@> wrote:
                                                          > > >
                                                          > > > >
                                                          > > > >
                                                          > > > >
                                                          > > > > I got it :)
                                                          > > > >
                                                          > > > > I don't know why I was relating the concept of a snapshot with a stack
                                                          > > of
                                                          > > > > events and not with the domain AR (and since I'm not an english native
                                                          > > > > speaker I got a lil confused about the term 'rolling').
                                                          > > > >
                                                          > > > > So you take a picture of the domain entity after N events and then make
                                                          > > the
                                                          > > > > repository hold a reference to that picture indexed by its identity
                                                          > > (ID) (or
                                                          > > > > the separate process yoou mention)
                                                          > > > >
                                                          > > > > Let's assume you want to load the AR having the same ID that the
                                                          > > picture
                                                          > > > > hold by the repo has. You calculate the position in the event stack
                                                          > > from
                                                          > > > > where you would start replying events, then create an AR instance, copy
                                                          > > its
                                                          > > > > state with the picture (Memento) that you took previosly, and apply the
                                                          > > > > events representing the DELTA.
                                                          > > > >
                                                          > > > > The Snapshot shouldn't be kept by the repo because we would run into
                                                          > > the
                                                          > > > > same performance problem if too many instances live in memory. I guess
                                                          > > we
                                                          > > > > should serialize the snapshot to disk or something similar?
                                                          > > > >
                                                          > > > > Am I ok?
                                                          > > > >
                                                          > > > > Thanks Mark.
                                                          > > > >
                                                          > > > >
                                                          > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                                          > > <domaindrivendesign%40yahoogroups.com>,
                                                          > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                                          > > > > >
                                                          > > > > > Your rolling snapshot will never be assumed to be the latest state of
                                                          > > the
                                                          > > > > > AR, after loading the snapshot the repository will always get all
                                                          > > events
                                                          > > > > > that have occurred after the snapshot was made. The process creating
                                                          > > the
                                                          > > > > > snapshots will most likely be a independent process that would just
                                                          > > load
                                                          > > > > AR
                                                          > > > > > verify if a snapshot needs to be made. If this is the case it would
                                                          > > make
                                                          > > > > it.
                                                          > > > > > Say after 100 events you want a snapshot. Instead of putting this
                                                          > > > > > responsibility in the domain repository?
                                                          > > > > >
                                                          > > > > > So current version of the snapshot is 20 version of the last event is
                                                          > > 25
                                                          > > > > so
                                                          > > > > > after loading the snapshot it also needs to replay the last 5 events.
                                                          > > > > >
                                                          > > > > > Does this make sense?
                                                          > > > > >
                                                          > > > > > -Mark
                                                          > > > > >
                                                          > > > > > On Thu, Nov 12, 2009 at 4:37 PM, sebaszipp <sebaszipp@> wrote:
                                                          > > > > >
                                                          > > > > > >
                                                          > > > > > >
                                                          > > > > > >
                                                          > > > > > > Hi Mark,
                                                          > > > > > >
                                                          > > > > > > Great blog. Thanks for clarifying in detail things about CQRS.
                                                          > > > > > >
                                                          > > > > > > Still a grey zone I'd like to get better is about AR load
                                                          > > performance
                                                          > > > > when
                                                          > > > > > > the event storage is large enough to kill performance.
                                                          > > > > > > I know rolling snapshots takes care of this field, but by rolling
                                                          > > > > snapthost
                                                          > > > > > > I might get an incomplete AR?
                                                          > > > > > > Could you please explain this?
                                                          > > > > > >
                                                          > > > > > > Thanks.
                                                          > > > > > >
                                                          > > > > > >
                                                          > > > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                                          > > <domaindrivendesign%40yahoogroups.com>
                                                          > > > > <domaindrivendesign%40yahoogroups.com>,
                                                          > > > >
                                                          > > > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                                          > > > > > > >
                                                          > > > > > > > Hi,
                                                          > > > > > > >
                                                          > > > > > > > I finally got the first blog post about this published, it is
                                                          > > long!
                                                          > > > > Not
                                                          > > > > > > so
                                                          > > > > > > > much code, more the explanation behind it (as I understand it).
                                                          > > > > > > >
                                                          > > > > > > > Link:
                                                          > > http://blog.fohjin.com/blog/2009/11/12/CQRS_a_la_Greg_Young
                                                          > > > > > > >
                                                          > > > > > > > -Mark
                                                          > > > > > > >
                                                          > > > > > > >
                                                          > > > > > > > On Thu, Oct 29, 2009 at 1:09 AM, Mark Nijhof <mark.nijhof@>
                                                          > > wrote:
                                                          > > > > > > >
                                                          > > > > > > > > Hi,
                                                          > > > > > > > >
                                                          > > > > > > > > Because that is a nasty home made implementation of a bus :)
                                                          > > The
                                                          > > > > > > Publish
                                                          > > > > > > > > method needs to know the exact type of the command/event that
                                                          > > gets
                                                          > > > > > > passed in
                                                          > > > > > > > > because that is used to get the correct xxxHandlers from the
                                                          > > IoC
                                                          > > > > > > container.
                                                          > > > > > > > > I cannot use an Generic in the PublishMultiple because these
                                                          > > > > > > commands/events
                                                          > > > > > > > > are 99% of the time not of the same type. I will probably
                                                          > > change it
                                                          > > > > > > into
                                                          > > > > > > > > something like this:
                                                          > > > > > > > >
                                                          > > > > > >
                                                          > > > >
                                                          > > http://codebetter.com/blogs/gregyoung/archive/2009/10/03/delegate-mapper.aspx
                                                          > > > > > > > >
                                                          > > > > > > > > Also one thing I like to highlight is that in this first
                                                          > > version I
                                                          > > > > am
                                                          > > > > > > not
                                                          > > > > > > > > using anything complex because I explicitly wanted to show that
                                                          > > the
                                                          > > > > > > core of
                                                          > > > > > > > > this is actually very simple, if I started with NServiceBus and
                                                          > > > > > > NHibernate
                                                          > > > > > > > > than that would have taken away from the simplicity of this
                                                          > > type of
                                                          > > > > > > > > architecture. That is why I have implemented my own very simple
                                                          > > ORM
                                                          > > > > > > (one has
                                                          > > > > > > > > to do that once in their career anyway right) and my own bus. I
                                                          > > > > plan on
                                                          > > > > > > > > continuing on this example by introducing these types of
                                                          > > options as
                                                          > > > > > > well,
                                                          > > > > > > > > all do the event store will remain custom SQL, actually I will
                                                          > > also
                                                          > > > > > > > > implement one using SQL Server and that one will use a stored
                                                          > > > > procedure
                                                          > > > > > > ;)
                                                          > > > > > > > >
                                                          > > > > > > > > -Mark
                                                          > > > > > > > >
                                                          > > > > > > > >
                                                          > > > > > > > >
                                                          > > > > > > > > On Wed, Oct 28, 2009 at 8:16 PM, David Perfors <dnperfors@
                                                          > > >wrote:
                                                          > > > > > >
                                                          > > > > > > > >
                                                          > > > > > > > >>
                                                          > > > > > > > >>
                                                          > > > > > > > >> Hi Mark,
                                                          > > > > > > > >>
                                                          > > > > > > > >> Thanks a lot for this example. I was looking into the code and
                                                          > > > > looked
                                                          > > > > > > ad
                                                          > > > > > > > >> the implementations of IBus and saw that it is using
                                                          > > reflection
                                                          > > > > for
                                                          > > > > > > the
                                                          > > > > > > > >> PublishMultiple method. Can you tell me (us) more about why
                                                          > > you
                                                          > > > > are
                                                          > > > > > > doing
                                                          > > > > > > > >> that instead of just calling the Publish method?
                                                          > > > > > > > >>
                                                          > > > > > > > >> Looking forward to the blogposts :)
                                                          > > > > > > > >>
                                                          > > > > > > > >> David.
                                                          > > > > > > > >>
                                                          > > > > > > > >> 2009/10/26 Mark Nijhof <Mark.Nijhof@>
                                                          > > > > > >
                                                          > > > > > > > >>
                                                          > > > > > > > >>> Hi,
                                                          > > > > > > > >>>
                                                          > > > > > > > >>> Since multiple people have been asking for this and I feel
                                                          > > that
                                                          > > > > the
                                                          > > > > > > > >>> core is good enough to share I thought I would share the
                                                          > > > > repository
                                                          > > > > > > > >>> here already. Disclaimer: Now keep in mind that this has not
                                                          > > been
                                                          > > > > > > > >>> reviewed by Greg yet and that I am still working on it. I am
                                                          > > also
                                                          > > > > > > > >>> working on a complete detailed blog post (or several) to
                                                          > > explain
                                                          > > > > what
                                                          > > > > > > > >>> is going on and why (with diagrams and all that fancy stuff).
                                                          > > > > Once
                                                          > > > > > > > >>> that is done it will be published here:
                                                          > > http://blog.fohjin.com/I am
                                                          > > > > > > > >>> currently finishing my specifications for the GUI and will
                                                          > > split
                                                          > > > > the
                                                          > > > > > > > >>> existing domain specifications a bit more per scenario, but I
                                                          > > > > think
                                                          > > > > > > > >>> you will like what you see there (hope at least).
                                                          > > > > > > > >>>
                                                          > > > > > > > >>> The most interesting scenario is a transfer from one account
                                                          > > to
                                                          > > > > an
                                                          > > > > > > > >>> other account.
                                                          > > > > > > > >>>
                                                          > > > > > > > >>> Link: http://github.com/MarkNijhof/Fohjin
                                                          > > > > > > > >>>
                                                          > > > > > > > >>> Note on SQLite: Because I am developing on x64 I have the x64
                                                          > > > > version
                                                          > > > > > > > >>> of SQLite referenced in the projects, except for the test
                                                          > > project
                                                          > > > > > > > >>> because TestDriven.Net executes everything in x86. Now if you
                                                          > > are
                                                          > > > > > > > >>> running on a x86 machine all you have to do is copy the x86
                                                          > > > > > > > >>> System.Data.SQLite.* from /lib/sqlite/bin to
                                                          > > /lib/sqlite/bin/x64
                                                          > > > > > > (this
                                                          > > > > > > > >>> approach is tested). There are two different SQLite
                                                          > > databases,
                                                          > > > > one is
                                                          > > > > > > > >>> the event store and the other is the reporting database. I
                                                          > > > > haven't
                                                          > > > > > > > >>> figured out yet how, but it is possible to load the SQLite
                                                          > > > > databases
                                                          > > > > > > > >>> in Visual Studio to inspect the content. Both databases are
                                                          > > > > created
                                                          > > > > > > on
                                                          > > > > > > > >>> first use, and deleting them will give you a fresh start.
                                                          > > > > > > > >>>
                                                          > > > > > > > >>> I would like to hear your opinions, I am very enthusiastic
                                                          > > about
                                                          > > > > this
                                                          > > > > > > > >>> architecture when there is a need for a domain.
                                                          > > > > > > > >>>
                                                          > > > > > > > >>> -Mark
                                                          > > > > > > > >>>
                                                          > > > > > > > >>>
                                                          > > > > > > > >>> ------------------------------------
                                                          > > > > > > > >>>
                                                          > > > > > > > >>> Yahoo! Groups Links
                                                          > > > > > > > >>>
                                                          > > > > > > > >>>
                                                          > > > > > > > >>>
                                                          > > > > > > > >>>
                                                          > > > > > > > >>
                                                          > > > > > > > >>
                                                          > > > > > > > >
                                                          > > > > > > > >
                                                          > > > > > > >
                                                          > > > > > >
                                                          > > > > > >
                                                          > > > > > >
                                                          > > > > >
                                                          > > > >
                                                          > > > >
                                                          > > > >
                                                          > > >
                                                          > > >
                                                          > > >
                                                          > > > --
                                                          > > > Les erreurs de grammaire et de syntaxe ont été incluses pour m'assurer de
                                                          > > > votre attention
                                                          > > >
                                                          > >
                                                          > >
                                                          > >
                                                          >







                                                        • Mark Henke
                                                          That answers the questions I had. But here is the thing. In your system every registration is different, example, in addition to your posted code, we might
                                                          Message 28 of 30 , Nov 13, 2009
                                                            That answers the questions I had. But here is the thing. In your system every registration is different, example, 
                                                            in addition to your posted code, we might have this:

                                                            void forwardEventsToClosedAccount(object event)
                                                            {
                                                                  ClosedAccount closedAccount;
                                                                    if (!closedAccounts.TryGetById(event.AccountId, out closedAccount))

                                                                        throw new Exception();

                                                                    closedAccount.LoadHistory(event);        
                                                            }

                                                            Now we are doing the same thing over and over again for every child AGG collection. Additionally, you will have to have duplicate code for aggregating changes:

                                                            override IEnumerable<object> GetChanges()
                                                            {
                                                               return base.GetChanges().Concat(activeAccounts).Concat(closedAccounts); 
                                                            }

                                                            You could reduce some repetitiveness by having something like this in the base class:

                                                            override IEnumerable<object> GetChanges()
                                                            {
                                                               return base.GetChanges().Concat(children.SelectMany(child => child.GetChanges()));
                                                            }

                                                            but to do that you need some sort of centralized store for your children. Thus the idea of a registry. And since we have a registry of sorts, a standard way of saving them, why not have a standard way of retrieving them which we can specify more declaratively instead of repeating plumbing code for each collection. 
                                                            This is the stream of thought that led to my example code. I hope that clarifies things. I could be way over thinking it. 


                                                            On Fri, Nov 13, 2009 at 6:22 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                             

                                                            In the registration method you would register all the events that the ActiveAccount has to be handled by the forwardEventsToAccount. Since when you write your domain you know the events that the children can handle so this should be easy, you could perhaps even apply convention here.

                                                            -Mark




                                                            On Sat, Nov 14, 2009 at 12:20 AM, Mark Nijhof <mark.nijhof@...> wrote:
                                                            Will take a much closer look at the code, just wanted to respond to the question :)

                                                            If you have a list with children then each child needs to have a unique Id within the AR, you need this anyway, this Id also needs to be in the history event, thus you have an easy way to select to which child to forward the event. I am not sure what I am missing here?

                                                            class AR
                                                            {
                                                                list activeAccounts = new List
                                                                {
                                                                    new ActiveAccount { Id = 10 }
                                                                    new ActiveAccount { Id = 15 }
                                                                }

                                                                forwardEventsToAccount(object event)
                                                                {
                                                                    ActiveAccount actinveAccount;
                                                                    if (!activeAccounts.TryGetById(event.AccountId, out activeAccount))

                                                                        throw new Exception();

                                                                    activeAccount.LoadHistory(event);       
                                                                }
                                                            }

                                                            AR ar = new AR()
                                                            ar.LoadHistory(new[] {
                                                                someEventForAccount { AccountId = 10 }
                                                                someEventForAccount { AccountId = 15 }
                                                                someOtherEventForAccount { AccountId = 10 }
                                                                someOtherEventForAccount { AccountId = 10 }
                                                            });

                                                            -Mark



                                                            On Sat, Nov 14, 2009 at 12:02 AM, Mark Henke <gilligan128@...> wrote:
                                                             

                                                            How do you know to what child an event belongs to? Your example below does not seem to handle that. That is what my solution is tackling. Here is a rough-shod example:

                                                             interface ILookup
                                                                    {
                                                                        bool HasChildFor(IDomainEvent @event);
                                                                        void ApplyChildEvent(IDomainEvent @event );
                                                                        IEnumerable<IDomainEvent> GetChanges();
                                                                        void ClearChanges();
                                                                    }


                                                                    class AggregateRootBase
                                                                    {
                                                                        LookupBuilder<T> Lookup<T>(IEnumerable<T> childCollection) where T : EventSource
                                                                    {
                                                                        var lookupBuilder = new LookupBuilder<T>(childCollection);
                                                                        lookups.Add(lookupBuilder);

                                                                        return lookupBuilder;
                                                                    }


                                                                        public void ForwardToChildrenEventsOfType<T>()
                                                                        {
                                                                            RegisterHandler<T>(@event => lookups.Single(lookup => lookup.HasChildFor(@event)).ApplyChildEvent(@event));
                                                                        }

                                                                       public IEnumerable<IDomainEvent> GetChanges()
                                                                      {
                                                                             return events.Concat(lookups.SelectMany(lookup => lookup.GetChanges()));
                                                                      }

                                                                      
                                                                    }

                                                            And the LookupBuilder class:

                                                             class LookupBuilder<T> : ILookup where T : EventSource
                                                                    {
                                                                        IEnumerable<T> children;
                                                                        Func<T, object> childKey;
                                                                        IDictionary<Type, Func<IDomainEvent, object>> eventKeys = new Dictionary<Type, Func<IDomainEvent, object>>();

                                                                        AggregateRootBase ar;


                                                                        public LookupBuilder(IEnumerable<T> children, AggregateRootBase ar)
                                                                        {
                                                                            this.children = children;
                                                                            this.ar = ar;
                                                                            childKey = child => child.Id;
                                                                        }

                                                                        public LookupBuilder<T> On(Func<T, object> keyGetter)
                                                                        {
                                                                            childKey = keyGetter;
                                                                            return this;
                                                                        }

                                                                        public LookupBuilder<T> For<TEvent>(Func<TEvent,object> eventKeyGetter)
                                                                        {
                                                                            eventKeys[typeof (TEvent)] = @event =>  eventKeyGetter((TEvent)@event);
                                                                            ar.ForwardToChildrenEventsOfType<TEvent>();
                                                                            return this;
                                                                        }

                                                                        bool ILookup.HasChildFor(IDomainEvent @event)
                                                                        {
                                                                            if(!eventKeys.ContainsKey(@...()))
                                                                            {
                                                                                return false;
                                                                            }

                                                                            var eventKey = eventKeys[@...()];
                                                                            return children.Any(child => childKey(child) == eventKey(@event));
                                                                        }


                                                                        IEnumerable<IDomainEvent> ILookup.GetChanges()
                                                                        {
                                                                            return children.SelectMany(child => child.GetChanges());
                                                                        }

                                                                        void ILookup.ClearChanges()
                                                                        {
                                                                            children.Iterate(x => x.ClearChanges());
                                                                        }

                                                                        void ILookup.ApplyChildEvent(IDomainEvent @event)
                                                                        {
                                                                            var eventKey = eventKeys[@...()];
                                                                            children.Single(child => childKey(child) == eventKey(@event)).LoadEventFromHistory(@event);
                                                                        }
                                                                    }


                                                            It may be hard to read at first, but it basically allows us to do things like this:

                                                            public Client()
                                                            {
                                                               Lookup(ActiveAccounts)
                                                                .For<AccountIsOnHold>(@event => @...)
                                                                .For<AccountIsNoLongerOnHold>(@event => @...);

                                                              Lookup(ClosedAccounts)
                                                               .For<AccountReactivated>(@event => @...);

                                                            }

                                                            All the ugly stuff is hidden by the base class and the plumbing is handled for us. We could also add something like Child(CurrentAccount).CanHandle<AccountOnHold>(x => x.AccountId) for simple cases. 

                                                            I hope that helps. Also this is only a rough draft of what I was thinking.

                                                            On Fri, Nov 13, 2009 at 4:07 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                             

                                                            One thing I don't like about this solution (or as how I understand it) is that you put all different types into on dictionary wouldn't this ruin a lot of the readability? Also seems more complex then needed? But as often happens I might just completely understand you wrong :D So an code example would be great. Perhaps I can implement something like this before the upcoming E-VAN talk. (I want to keep it somewhat recognizable for people attending the talk so no major changes).

                                                            Here an example keeping in the same types but different organization:

                                                            Client
                                                            - List<ActiveAccounts> activeAccounts;
                                                            - List<ClosedAccounts> closedAccounts;

                                                            So in the AR I handle both events for the active account and closed account. I could just have two event handlers, one that handles all events for the active account amd one that handles all events for the closed accounts. In this event handler you would just forward the event to the correct instance in the list. Inside the f.ex. Active account it knows how to apply each individual different type of event.

                                                            private void forwardAllEventsForAnActiveAccount(object event)
                                                            {
                                                                ActiveAccount actinveAccount;
                                                                if (!activeAccounts.TryGetById(event.AccountId))
                                                                    throw new Exception();

                                                                activeAccount.LoadHistory(event);
                                                            }

                                                            -Mark




                                                            On Fri, Nov 13, 2009 at 3:49 PM, Mark Henke <gilligan128@...> wrote:
                                                             

                                                            I think we can break up this AR -> AGG issue of replaying events into two parts:

                                                            1) How is a Child AGG identified? and
                                                            2) How do we figure out what child that event belongs to?

                                                            Here is a shot in the dark, but how about this:

                                                            Let's assume all our child AGGs are in a single dictionary based upon type. The AR can then view itself internally as a Repository of AGGs. 
                                                            e.g. AddAGG<OrderSection>(orderSection);

                                                            Then for any event type we can register a Lookup on a specific child type. 
                                                            e.g. RegisterLookupOn<OrderSection>(section => section.Id)
                                                                      .For<ProductSaleEvent>(@event => @...);
                                                            The base AR classe, when replaying events, would also check to see if a lookup is registered for that event type and will forward that event to the specified child AGG.

                                                            I could create a patch on Git for your example experimenting with this idea if you want, Mark.


                                                            On Thu, Nov 12, 2009 at 5:03 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                             

                                                            You could still have the AR be responsible for managing the collection including the internal state, but that feels wrong.

                                                            -Mark



                                                            On Thu, Nov 12, 2009 at 9:32 PM, sebaszipp <sebaszipp@...> wrote:
                                                             


                                                            Yes, for the case we have predifined/fixed order sections for an order we could fire up events according to the section in cuestion. But in case of having collection of AGGs (AR -> List<AGG> -> List<AGG>) the situation comes kind of weird.
                                                            Maybe we should take a look into our BC, in order to rethink and see whether the BC graph should be pruned and the remaing is responsability of another BC?



                                                            --- In domaindrivendesign@yahoogroups.com, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                            >
                                                            > Each AGG can apply its own events and store them in itself, then when you
                                                            > ask for changes from the AR it will ask changes from it's AGG.
                                                            >
                                                            > Loading events from history would load them all in the AR which would
                                                            > delegate them back to the AGG. I am not 100% sure yet what the best approach
                                                            > for this is. You could just send all of them and have the AGG decide which
                                                            > one to skip, or you could make the AR aware what types of events need to be
                                                            > forwarded to the AGG. This can be done by creating an event handler in the
                                                            > AR that would just forward the event to the specific AGG. But if you have
                                                            > collections of AGG then this would be a problem.
                                                            >
                                                            > -Mark
                                                            >
                                                            >
                                                            > On Thu, Nov 12, 2009 at 8:46 PM, sebaszipp <sebaszipp@...> wrote:
                                                            >
                                                            > >
                                                            > >
                                                            > >
                                                            > > Great. Thanks Greg.
                                                            > >
                                                            > > I more question:
                                                            > >
                                                            > > As far as I've been reading about CQS I've been all examples matching the
                                                            > > same association: AR -> AGG where the AR is the one firing up domain events.
                                                            > > I would like to add another association supposing our graph is more complex
                                                            > > than just AR -> AGG.
                                                            > >
                                                            > > In this case we would have the following graph:
                                                            > > Order AR -> OrderSection AGG -> OrderLine AGG
                                                            > >
                                                            > > Suppose there are 2 rules dictating that products under 10 dollars should
                                                            > > be placed into Section1 and the others should be placed into Section2. In
                                                            > > the case a product that is $5 is bought we would fire up an event from the
                                                            > > Order AR:
                                                            > >
                                                            > > super.apply(new ProductSaleEvent(sectionOneID, productDescription))
                                                            > >
                                                            > > and then the event handler of the Order AR should be:
                                                            > >
                                                            > > handle(ProductSaleEvent event)
                                                            > > {
                                                            > > OrderSection orderSection = orderSections.get(event.sectionId)
                                                            > > if (orderSection == null) {
                                                            > > orderSection = new OrderSection();
                                                            > > orderSections.put(event.sectionId, orderSection);
                                                            > > }
                                                            > > orderSection.processSale(productDescription); // which will create a Line
                                                            > > internally
                                                            > > }
                                                            > >
                                                            > > Should be handled this way?
                                                            > > I mean, the AR is the leading with the graph hierarchy no matter how deep
                                                            > > it's?
                                                            > >
                                                            > > Cheers,
                                                            > >
                                                            > >
                                                            > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>,

                                                            > > Greg Young <gregoryyoung1@> wrote:
                                                            > > >
                                                            > > > Yes the snapshots are generally not in memory, they live in the event
                                                            > > store.
                                                            > > >
                                                            > > > Cheers,
                                                            > > >
                                                            > > > Greg
                                                            > > >
                                                            > > > On Thu, Nov 12, 2009 at 8:30 PM, sebaszipp <sebaszipp@> wrote:
                                                            > > >
                                                            > > > >
                                                            > > > >
                                                            > > > >
                                                            > > > > I got it :)
                                                            > > > >
                                                            > > > > I don't know why I was relating the concept of a snapshot with a stack
                                                            > > of
                                                            > > > > events and not with the domain AR (and since I'm not an english native
                                                            > > > > speaker I got a lil confused about the term 'rolling').
                                                            > > > >
                                                            > > > > So you take a picture of the domain entity after N events and then make
                                                            > > the
                                                            > > > > repository hold a reference to that picture indexed by its identity
                                                            > > (ID) (or
                                                            > > > > the separate process yoou mention)
                                                            > > > >
                                                            > > > > Let's assume you want to load the AR having the same ID that the
                                                            > > picture
                                                            > > > > hold by the repo has. You calculate the position in the event stack
                                                            > > from
                                                            > > > > where you would start replying events, then create an AR instance, copy
                                                            > > its
                                                            > > > > state with the picture (Memento) that you took previosly, and apply the
                                                            > > > > events representing the DELTA.
                                                            > > > >
                                                            > > > > The Snapshot shouldn't be kept by the repo because we would run into
                                                            > > the
                                                            > > > > same performance problem if too many instances live in memory. I guess
                                                            > > we
                                                            > > > > should serialize the snapshot to disk or something similar?
                                                            > > > >
                                                            > > > > Am I ok?
                                                            > > > >
                                                            > > > > Thanks Mark.
                                                            > > > >
                                                            > > > >
                                                            > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                                            > > <domaindrivendesign%40yahoogroups.com>,
                                                            > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                                            > > > > >
                                                            > > > > > Your rolling snapshot will never be assumed to be the latest state of
                                                            > > the
                                                            > > > > > AR, after loading the snapshot the repository will always get all
                                                            > > events
                                                            > > > > > that have occurred after the snapshot was made. The process creating
                                                            > > the
                                                            > > > > > snapshots will most likely be a independent process that would just
                                                            > > load
                                                            > > > > AR
                                                            > > > > > verify if a snapshot needs to be made. If this is the case it would
                                                            > > make
                                                            > > > > it.
                                                            > > > > > Say after 100 events you want a snapshot. Instead of putting this
                                                            > > > > > responsibility in the domain repository?
                                                            > > > > >
                                                            > > > > > So current version of the snapshot is 20 version of the last event is
                                                            > > 25
                                                            > > > > so
                                                            > > > > > after loading the snapshot it also needs to replay the last 5 events.
                                                            > > > > >
                                                            > > > > > Does this make sense?
                                                            > > > > >
                                                            > > > > > -Mark
                                                            > > > > >
                                                            > > > > > On Thu, Nov 12, 2009 at 4:37 PM, sebaszipp <sebaszipp@> wrote:
                                                            > > > > >
                                                            > > > > > >
                                                            > > > > > >
                                                            > > > > > >
                                                            > > > > > > Hi Mark,
                                                            > > > > > >
                                                            > > > > > > Great blog. Thanks for clarifying in detail things about CQRS.
                                                            > > > > > >
                                                            > > > > > > Still a grey zone I'd like to get better is about AR load
                                                            > > performance
                                                            > > > > when
                                                            > > > > > > the event storage is large enough to kill performance.
                                                            > > > > > > I know rolling snapshots takes care of this field, but by rolling
                                                            > > > > snapthost
                                                            > > > > > > I might get an incomplete AR?
                                                            > > > > > > Could you please explain this?
                                                            > > > > > >
                                                            > > > > > > Thanks.
                                                            > > > > > >
                                                            > > > > > >
                                                            > > > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                                            > > <domaindrivendesign%40yahoogroups.com>
                                                            > > > > <domaindrivendesign%40yahoogroups.com>,
                                                            > > > >
                                                            > > > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                                            > > > > > > >
                                                            > > > > > > > Hi,
                                                            > > > > > > >
                                                            > > > > > > > I finally got the first blog post about this published, it is
                                                            > > long!
                                                            > > > > Not
                                                            > > > > > > so
                                                            > > > > > > > much code, more the explanation behind it (as I understand it).
                                                            > > > > > > >
                                                            > > > > > > > Link:
                                                            > > http://blog.fohjin.com/blog/2009/11/12/CQRS_a_la_Greg_Young
                                                            > > > > > > >
                                                            > > > > > > > -Mark
                                                            > > > > > > >
                                                            > > > > > > >
                                                            > > > > > > > On Thu, Oct 29, 2009 at 1:09 AM, Mark Nijhof <mark.nijhof@>
                                                            > > wrote:
                                                            > > > > > > >
                                                            > > > > > > > > Hi,
                                                            > > > > > > > >
                                                            > > > > > > > > Because that is a nasty home made implementation of a bus :)
                                                            > > The
                                                            > > > > > > Publish
                                                            > > > > > > > > method needs to know the exact type of the command/event that
                                                            > > gets
                                                            > > > > > > passed in
                                                            > > > > > > > > because that is used to get the correct xxxHandlers from the
                                                            > > IoC
                                                            > > > > > > container.
                                                            > > > > > > > > I cannot use an Generic in the PublishMultiple because these
                                                            > > > > > > commands/events
                                                            > > > > > > > > are 99% of the time not of the same type. I will probably
                                                            > > change it
                                                            > > > > > > into
                                                            > > > > > > > > something like this:
                                                            > > > > > > > >
                                                            > > > > > >
                                                            > > > >
                                                            > > http://codebetter.com/blogs/gregyoung/archive/2009/10/03/delegate-mapper.aspx
                                                            > > > > > > > >
                                                            > > > > > > > > Also one thing I like to highlight is that in this first
                                                            > > version I
                                                            > > > > am
                                                            > > > > > > not
                                                            > > > > > > > > using anything complex because I explicitly wanted to show that
                                                            > > the
                                                            > > > > > > core of
                                                            > > > > > > > > this is actually very simple, if I started with NServiceBus and
                                                            > > > > > > NHibernate
                                                            > > > > > > > > than that would have taken away from the simplicity of this
                                                            > > type of
                                                            > > > > > > > > architecture. That is why I have implemented my own very simple
                                                            > > ORM
                                                            > > > > > > (one has
                                                            > > > > > > > > to do that once in their career anyway right) and my own bus. I
                                                            > > > > plan on
                                                            > > > > > > > > continuing on this example by introducing these types of
                                                            > > options as
                                                            > > > > > > well,
                                                            > > > > > > > > all do the event store will remain custom SQL, actually I will
                                                            > > also
                                                            > > > > > > > > implement one using SQL Server and that one will use a stored
                                                            > > > > procedure
                                                            > > > > > > ;)
                                                            > > > > > > > >
                                                            > > > > > > > > -Mark
                                                            > > > > > > > >
                                                            > > > > > > > >
                                                            > > > > > > > >
                                                            > > > > > > > > On Wed, Oct 28, 2009 at 8:16 PM, David Perfors <dnperfors@
                                                            > > >wrote:
                                                            > > > > > >
                                                            > > > > > > > >
                                                            > > > > > > > >>
                                                            > > > > > > > >>
                                                            > > > > > > > >> Hi Mark,
                                                            > > > > > > > >>
                                                            > > > > > > > >> Thanks a lot for this example. I was looking into the code and
                                                            > > > > looked
                                                            > > > > > > ad
                                                            > > > > > > > >> the implementations of IBus and saw that it is using
                                                            > > reflection
                                                            > > > > for
                                                            > > > > > > the
                                                            > > > > > > > >> PublishMultiple method. Can you tell me (us) more about why
                                                            > > you
                                                            > > > > are
                                                            > > > > > > doing
                                                            > > > > > > > >> that instead of just calling the Publish method?
                                                            > > > > > > > >>
                                                            > > > > > > > >> Looking forward to the blogposts :)
                                                            > > > > > > > >>
                                                            > > > > > > > >> David.
                                                            > > > > > > > >>
                                                            > > > > > > > >> 2009/10/26 Mark Nijhof <Mark.Nijhof@>
                                                            > > > > > >
                                                            > > > > > > > >>
                                                            > > > > > > > >>> Hi,
                                                            > > > > > > > >>>
                                                            > > > > > > > >>> Since multiple people have been asking for this and I feel
                                                            > > that
                                                            > > > > the
                                                            > > > > > > > >>> core is good enough to share I thought I would share the
                                                            > > > > repository
                                                            > > > > > > > >>> here already. Disclaimer: Now keep in mind that this has not
                                                            > > been
                                                            > > > > > > > >>> reviewed by Greg yet and that I am still working on it. I am
                                                            > > also
                                                            > > > > > > > >>> working on a complete detailed blog post (or several) to
                                                            > > explain
                                                            > > > > what
                                                            > > > > > > > >>> is going on and why (with diagrams and all that fancy stuff).
                                                            > > > > Once
                                                            > > > > > > > >>> that is done it will be published here:
                                                            > > http://blog.fohjin.com/I am
                                                            > > > > > > > >>> currently finishing my specifications for the GUI and will
                                                            > > split
                                                            > > > > the
                                                            > > > > > > > >>> existing domain specifications a bit more per scenario, but I
                                                            > > > > think
                                                            > > > > > > > >>> you will like what you see there (hope at least).
                                                            > > > > > > > >>>
                                                            > > > > > > > >>> The most interesting scenario is a transfer from one account
                                                            > > to
                                                            > > > > an
                                                            > > > > > > > >>> other account.
                                                            > > > > > > > >>>
                                                            > > > > > > > >>> Link: http://github.com/MarkNijhof/Fohjin
                                                            > > > > > > > >>>
                                                            > > > > > > > >>> Note on SQLite: Because I am developing on x64 I have the x64
                                                            > > > > version
                                                            > > > > > > > >>> of SQLite referenced in the projects, except for the test
                                                            > > project
                                                            > > > > > > > >>> because TestDriven.Net executes everything in x86. Now if you
                                                            > > are
                                                            > > > > > > > >>> running on a x86 machine all you have to do is copy the x86
                                                            > > > > > > > >>> System.Data.SQLite.* from /lib/sqlite/bin to
                                                            > > /lib/sqlite/bin/x64
                                                            > > > > > > (this
                                                            > > > > > > > >>> approach is tested). There are two different SQLite
                                                            > > databases,
                                                            > > > > one is
                                                            > > > > > > > >>> the event store and the other is the reporting database. I
                                                            > > > > haven't
                                                            > > > > > > > >>> figured out yet how, but it is possible to load the SQLite
                                                            > > > > databases
                                                            > > > > > > > >>> in Visual Studio to inspect the content. Both databases are
                                                            > > > > created
                                                            > > > > > > on
                                                            > > > > > > > >>> first use, and deleting them will give you a fresh start.
                                                            > > > > > > > >>>
                                                            > > > > > > > >>> I would like to hear your opinions, I am very enthusiastic
                                                            > > about
                                                            > > > > this
                                                            > > > > > > > >>> architecture when there is a need for a domain.
                                                            > > > > > > > >>>
                                                            > > > > > > > >>> -Mark
                                                            > > > > > > > >>>
                                                            > > > > > > > >>>
                                                            > > > > > > > >>> ------------------------------------
                                                            > > > > > > > >>>
                                                            > > > > > > > >>> Yahoo! Groups Links
                                                            > > > > > > > >>>
                                                            > > > > > > > >>>
                                                            > > > > > > > >>>
                                                            > > > > > > > >>>
                                                            > > > > > > > >>
                                                            > > > > > > > >>
                                                            > > > > > > > >
                                                            > > > > > > > >
                                                            > > > > > > >
                                                            > > > > > >
                                                            > > > > > >
                                                            > > > > > >
                                                            > > > > >
                                                            > > > >
                                                            > > > >
                                                            > > > >
                                                            > > >
                                                            > > >
                                                            > > >
                                                            > > > --
                                                            > > > Les erreurs de grammaire et de syntaxe ont été incluses pour m'assurer de
                                                            > > > votre attention
                                                            > > >
                                                            > >
                                                            > >
                                                            > >
                                                            >








                                                          • Mark Nijhof
                                                            Ah ok I see where you where going, but just to be sure, you would then have a specific list with children in the AR and then register each child as being a
                                                            Message 29 of 30 , Nov 13, 2009
                                                              Ah ok I see where you where going, but just to be sure, you would then have a specific list with children in the AR and then register each child as being a child that has events. (quickly said) so you AR structure would still look very OO ;) you just also register the childs. Hmm that could be worth it indeed, especially if these childs have many events. I am currently extending the example with similar functionality as I discussed to demonstrate it, but perhaps I'll try your suggestion as well, only with one change ;)

                                                              The List that contains the children I will make this a special list that would register the children automatically when adding them to the list, how does that sound? I want to limit the possibility for mistakes.

                                                              -Mark


                                                              On Sat, Nov 14, 2009 at 2:36 AM, Mark Henke <gilligan128@...> wrote:
                                                               

                                                              That answers the questions I had. But here is the thing. In your system every registration is different, example, 

                                                              in addition to your posted code, we might have this:

                                                              void forwardEventsToClosedAccount(object event)
                                                              {
                                                                    ClosedAccount closedAccount;
                                                                      if (!closedAccounts.TryGetById(event.AccountId, out closedAccount))

                                                                          throw new Exception();

                                                                      closedAccount.LoadHistory(event);        
                                                              }

                                                              Now we are doing the same thing over and over again for every child AGG collection. Additionally, you will have to have duplicate code for aggregating changes:

                                                              override IEnumerable<object> GetChanges()
                                                              {
                                                                 return base.GetChanges().Concat(activeAccounts).Concat(closedAccounts); 
                                                              }

                                                              You could reduce some repetitiveness by having something like this in the base class:

                                                              override IEnumerable<object> GetChanges()
                                                              {
                                                                 return base.GetChanges().Concat(children.SelectMany(child => child.GetChanges()));
                                                              }

                                                              but to do that you need some sort of centralized store for your children. Thus the idea of a registry. And since we have a registry of sorts, a standard way of saving them, why not have a standard way of retrieving them which we can specify more declaratively instead of repeating plumbing code for each collection. 
                                                              This is the stream of thought that led to my example code. I hope that clarifies things. I could be way over thinking it. 


                                                              On Fri, Nov 13, 2009 at 6:22 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                               

                                                              In the registration method you would register all the events that the ActiveAccount has to be handled by the forwardEventsToAccount. Since when you write your domain you know the events that the children can handle so this should be easy, you could perhaps even apply convention here.

                                                              -Mark




                                                              On Sat, Nov 14, 2009 at 12:20 AM, Mark Nijhof <mark.nijhof@...> wrote:
                                                              Will take a much closer look at the code, just wanted to respond to the question :)

                                                              If you have a list with children then each child needs to have a unique Id within the AR, you need this anyway, this Id also needs to be in the history event, thus you have an easy way to select to which child to forward the event. I am not sure what I am missing here?

                                                              class AR
                                                              {
                                                                  list activeAccounts = new List
                                                                  {
                                                                      new ActiveAccount { Id = 10 }
                                                                      new ActiveAccount { Id = 15 }
                                                                  }

                                                                  forwardEventsToAccount(object event)
                                                                  {
                                                                      ActiveAccount actinveAccount;
                                                                      if (!activeAccounts.TryGetById(event.AccountId, out activeAccount))

                                                                          throw new Exception();

                                                                      activeAccount.LoadHistory(event);       
                                                                  }
                                                              }

                                                              AR ar = new AR()
                                                              ar.LoadHistory(new[] {
                                                                  someEventForAccount { AccountId = 10 }
                                                                  someEventForAccount { AccountId = 15 }
                                                                  someOtherEventForAccount { AccountId = 10 }
                                                                  someOtherEventForAccount { AccountId = 10 }
                                                              });

                                                              -Mark



                                                              On Sat, Nov 14, 2009 at 12:02 AM, Mark Henke <gilligan128@...> wrote:
                                                               

                                                              How do you know to what child an event belongs to? Your example below does not seem to handle that. That is what my solution is tackling. Here is a rough-shod example:

                                                               interface ILookup
                                                                      {
                                                                          bool HasChildFor(IDomainEvent @event);
                                                                          void ApplyChildEvent(IDomainEvent @event );
                                                                          IEnumerable<IDomainEvent> GetChanges();
                                                                          void ClearChanges();
                                                                      }


                                                                      class AggregateRootBase
                                                                      {
                                                                          LookupBuilder<T> Lookup<T>(IEnumerable<T> childCollection) where T : EventSource
                                                                      {
                                                                          var lookupBuilder = new LookupBuilder<T>(childCollection);
                                                                          lookups.Add(lookupBuilder);

                                                                          return lookupBuilder;
                                                                      }


                                                                          public void ForwardToChildrenEventsOfType<T>()
                                                                          {
                                                                              RegisterHandler<T>(@event => lookups.Single(lookup => lookup.HasChildFor(@event)).ApplyChildEvent(@event));
                                                                          }

                                                                         public IEnumerable<IDomainEvent> GetChanges()
                                                                        {
                                                                               return events.Concat(lookups.SelectMany(lookup => lookup.GetChanges()));
                                                                        }

                                                                        
                                                                      }

                                                              And the LookupBuilder class:

                                                               class LookupBuilder<T> : ILookup where T : EventSource
                                                                      {
                                                                          IEnumerable<T> children;
                                                                          Func<T, object> childKey;
                                                                          IDictionary<Type, Func<IDomainEvent, object>> eventKeys = new Dictionary<Type, Func<IDomainEvent, object>>();

                                                                          AggregateRootBase ar;


                                                                          public LookupBuilder(IEnumerable<T> children, AggregateRootBase ar)
                                                                          {
                                                                              this.children = children;
                                                                              this.ar = ar;
                                                                              childKey = child => child.Id;
                                                                          }

                                                                          public LookupBuilder<T> On(Func<T, object> keyGetter)
                                                                          {
                                                                              childKey = keyGetter;
                                                                              return this;
                                                                          }

                                                                          public LookupBuilder<T> For<TEvent>(Func<TEvent,object> eventKeyGetter)
                                                                          {
                                                                              eventKeys[typeof (TEvent)] = @event =>  eventKeyGetter((TEvent)@event);
                                                                              ar.ForwardToChildrenEventsOfType<TEvent>();
                                                                              return this;
                                                                          }

                                                                          bool ILookup.HasChildFor(IDomainEvent @event)
                                                                          {
                                                                              if(!eventKeys.ContainsKey(@...()))
                                                                              {
                                                                                  return false;
                                                                              }

                                                                              var eventKey = eventKeys[@...()];
                                                                              return children.Any(child => childKey(child) == eventKey(@event));
                                                                          }


                                                                          IEnumerable<IDomainEvent> ILookup.GetChanges()
                                                                          {
                                                                              return children.SelectMany(child => child.GetChanges());
                                                                          }

                                                                          void ILookup.ClearChanges()
                                                                          {
                                                                              children.Iterate(x => x.ClearChanges());
                                                                          }

                                                                          void ILookup.ApplyChildEvent(IDomainEvent @event)
                                                                          {
                                                                              var eventKey = eventKeys[@...()];
                                                                              children.Single(child => childKey(child) == eventKey(@event)).LoadEventFromHistory(@event);
                                                                          }
                                                                      }


                                                              It may be hard to read at first, but it basically allows us to do things like this:

                                                              public Client()
                                                              {
                                                                 Lookup(ActiveAccounts)
                                                                  .For<AccountIsOnHold>(@event => @...)
                                                                  .For<AccountIsNoLongerOnHold>(@event => @...);

                                                                Lookup(ClosedAccounts)
                                                                 .For<AccountReactivated>(@event => @...);

                                                              }

                                                              All the ugly stuff is hidden by the base class and the plumbing is handled for us. We could also add something like Child(CurrentAccount).CanHandle<AccountOnHold>(x => x.AccountId) for simple cases. 

                                                              I hope that helps. Also this is only a rough draft of what I was thinking.

                                                              On Fri, Nov 13, 2009 at 4:07 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                               

                                                              One thing I don't like about this solution (or as how I understand it) is that you put all different types into on dictionary wouldn't this ruin a lot of the readability? Also seems more complex then needed? But as often happens I might just completely understand you wrong :D So an code example would be great. Perhaps I can implement something like this before the upcoming E-VAN talk. (I want to keep it somewhat recognizable for people attending the talk so no major changes).

                                                              Here an example keeping in the same types but different organization:

                                                              Client
                                                              - List<ActiveAccounts> activeAccounts;
                                                              - List<ClosedAccounts> closedAccounts;

                                                              So in the AR I handle both events for the active account and closed account. I could just have two event handlers, one that handles all events for the active account amd one that handles all events for the closed accounts. In this event handler you would just forward the event to the correct instance in the list. Inside the f.ex. Active account it knows how to apply each individual different type of event.

                                                              private void forwardAllEventsForAnActiveAccount(object event)
                                                              {
                                                                  ActiveAccount actinveAccount;
                                                                  if (!activeAccounts.TryGetById(event.AccountId))
                                                                      throw new Exception();

                                                                  activeAccount.LoadHistory(event);
                                                              }

                                                              -Mark




                                                              On Fri, Nov 13, 2009 at 3:49 PM, Mark Henke <gilligan128@...> wrote:
                                                               

                                                              I think we can break up this AR -> AGG issue of replaying events into two parts:

                                                              1) How is a Child AGG identified? and
                                                              2) How do we figure out what child that event belongs to?

                                                              Here is a shot in the dark, but how about this:

                                                              Let's assume all our child AGGs are in a single dictionary based upon type. The AR can then view itself internally as a Repository of AGGs. 
                                                              e.g. AddAGG<OrderSection>(orderSection);

                                                              Then for any event type we can register a Lookup on a specific child type. 
                                                              e.g. RegisterLookupOn<OrderSection>(section => section.Id)
                                                                        .For<ProductSaleEvent>(@event => @...);
                                                              The base AR classe, when replaying events, would also check to see if a lookup is registered for that event type and will forward that event to the specified child AGG.

                                                              I could create a patch on Git for your example experimenting with this idea if you want, Mark.


                                                              On Thu, Nov 12, 2009 at 5:03 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                               

                                                              You could still have the AR be responsible for managing the collection including the internal state, but that feels wrong.

                                                              -Mark



                                                              On Thu, Nov 12, 2009 at 9:32 PM, sebaszipp <sebaszipp@...> wrote:
                                                               


                                                              Yes, for the case we have predifined/fixed order sections for an order we could fire up events according to the section in cuestion. But in case of having collection of AGGs (AR -> List<AGG> -> List<AGG>) the situation comes kind of weird.
                                                              Maybe we should take a look into our BC, in order to rethink and see whether the BC graph should be pruned and the remaing is responsability of another BC?



                                                              --- In domaindrivendesign@yahoogroups.com, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                              >
                                                              > Each AGG can apply its own events and store them in itself, then when you
                                                              > ask for changes from the AR it will ask changes from it's AGG.
                                                              >
                                                              > Loading events from history would load them all in the AR which would
                                                              > delegate them back to the AGG. I am not 100% sure yet what the best approach
                                                              > for this is. You could just send all of them and have the AGG decide which
                                                              > one to skip, or you could make the AR aware what types of events need to be
                                                              > forwarded to the AGG. This can be done by creating an event handler in the
                                                              > AR that would just forward the event to the specific AGG. But if you have
                                                              > collections of AGG then this would be a problem.
                                                              >
                                                              > -Mark
                                                              >
                                                              >
                                                              > On Thu, Nov 12, 2009 at 8:46 PM, sebaszipp <sebaszipp@...> wrote:
                                                              >
                                                              > >
                                                              > >
                                                              > >
                                                              > > Great. Thanks Greg.
                                                              > >
                                                              > > I more question:
                                                              > >
                                                              > > As far as I've been reading about CQS I've been all examples matching the
                                                              > > same association: AR -> AGG where the AR is the one firing up domain events.
                                                              > > I would like to add another association supposing our graph is more complex
                                                              > > than just AR -> AGG.
                                                              > >
                                                              > > In this case we would have the following graph:
                                                              > > Order AR -> OrderSection AGG -> OrderLine AGG
                                                              > >
                                                              > > Suppose there are 2 rules dictating that products under 10 dollars should
                                                              > > be placed into Section1 and the others should be placed into Section2. In
                                                              > > the case a product that is $5 is bought we would fire up an event from the
                                                              > > Order AR:
                                                              > >
                                                              > > super.apply(new ProductSaleEvent(sectionOneID, productDescription))
                                                              > >
                                                              > > and then the event handler of the Order AR should be:
                                                              > >
                                                              > > handle(ProductSaleEvent event)
                                                              > > {
                                                              > > OrderSection orderSection = orderSections.get(event.sectionId)
                                                              > > if (orderSection == null) {
                                                              > > orderSection = new OrderSection();
                                                              > > orderSections.put(event.sectionId, orderSection);
                                                              > > }
                                                              > > orderSection.processSale(productDescription); // which will create a Line
                                                              > > internally
                                                              > > }
                                                              > >
                                                              > > Should be handled this way?
                                                              > > I mean, the AR is the leading with the graph hierarchy no matter how deep
                                                              > > it's?
                                                              > >
                                                              > > Cheers,
                                                              > >
                                                              > >
                                                              > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>,

                                                              > > Greg Young <gregoryyoung1@> wrote:
                                                              > > >
                                                              > > > Yes the snapshots are generally not in memory, they live in the event
                                                              > > store.
                                                              > > >
                                                              > > > Cheers,
                                                              > > >
                                                              > > > Greg
                                                              > > >
                                                              > > > On Thu, Nov 12, 2009 at 8:30 PM, sebaszipp <sebaszipp@> wrote:
                                                              > > >
                                                              > > > >
                                                              > > > >
                                                              > > > >
                                                              > > > > I got it :)
                                                              > > > >
                                                              > > > > I don't know why I was relating the concept of a snapshot with a stack
                                                              > > of
                                                              > > > > events and not with the domain AR (and since I'm not an english native
                                                              > > > > speaker I got a lil confused about the term 'rolling').
                                                              > > > >
                                                              > > > > So you take a picture of the domain entity after N events and then make
                                                              > > the
                                                              > > > > repository hold a reference to that picture indexed by its identity
                                                              > > (ID) (or
                                                              > > > > the separate process yoou mention)
                                                              > > > >
                                                              > > > > Let's assume you want to load the AR having the same ID that the
                                                              > > picture
                                                              > > > > hold by the repo has. You calculate the position in the event stack
                                                              > > from
                                                              > > > > where you would start replying events, then create an AR instance, copy
                                                              > > its
                                                              > > > > state with the picture (Memento) that you took previosly, and apply the
                                                              > > > > events representing the DELTA.
                                                              > > > >
                                                              > > > > The Snapshot shouldn't be kept by the repo because we would run into
                                                              > > the
                                                              > > > > same performance problem if too many instances live in memory. I guess
                                                              > > we
                                                              > > > > should serialize the snapshot to disk or something similar?
                                                              > > > >
                                                              > > > > Am I ok?
                                                              > > > >
                                                              > > > > Thanks Mark.
                                                              > > > >
                                                              > > > >
                                                              > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                                              > > <domaindrivendesign%40yahoogroups.com>,
                                                              > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                                              > > > > >
                                                              > > > > > Your rolling snapshot will never be assumed to be the latest state of
                                                              > > the
                                                              > > > > > AR, after loading the snapshot the repository will always get all
                                                              > > events
                                                              > > > > > that have occurred after the snapshot was made. The process creating
                                                              > > the
                                                              > > > > > snapshots will most likely be a independent process that would just
                                                              > > load
                                                              > > > > AR
                                                              > > > > > verify if a snapshot needs to be made. If this is the case it would
                                                              > > make
                                                              > > > > it.
                                                              > > > > > Say after 100 events you want a snapshot. Instead of putting this
                                                              > > > > > responsibility in the domain repository?
                                                              > > > > >
                                                              > > > > > So current version of the snapshot is 20 version of the last event is
                                                              > > 25
                                                              > > > > so
                                                              > > > > > after loading the snapshot it also needs to replay the last 5 events.
                                                              > > > > >
                                                              > > > > > Does this make sense?
                                                              > > > > >
                                                              > > > > > -Mark
                                                              > > > > >
                                                              > > > > > On Thu, Nov 12, 2009 at 4:37 PM, sebaszipp <sebaszipp@> wrote:
                                                              > > > > >
                                                              > > > > > >
                                                              > > > > > >
                                                              > > > > > >
                                                              > > > > > > Hi Mark,
                                                              > > > > > >
                                                              > > > > > > Great blog. Thanks for clarifying in detail things about CQRS.
                                                              > > > > > >
                                                              > > > > > > Still a grey zone I'd like to get better is about AR load
                                                              > > performance
                                                              > > > > when
                                                              > > > > > > the event storage is large enough to kill performance.
                                                              > > > > > > I know rolling snapshots takes care of this field, but by rolling
                                                              > > > > snapthost
                                                              > > > > > > I might get an incomplete AR?
                                                              > > > > > > Could you please explain this?
                                                              > > > > > >
                                                              > > > > > > Thanks.
                                                              > > > > > >
                                                              > > > > > >
                                                              > > > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                                              > > <domaindrivendesign%40yahoogroups.com>
                                                              > > > > <domaindrivendesign%40yahoogroups.com>,
                                                              > > > >
                                                              > > > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                                              > > > > > > >
                                                              > > > > > > > Hi,
                                                              > > > > > > >
                                                              > > > > > > > I finally got the first blog post about this published, it is
                                                              > > long!
                                                              > > > > Not
                                                              > > > > > > so
                                                              > > > > > > > much code, more the explanation behind it (as I understand it).
                                                              > > > > > > >
                                                              > > > > > > > Link:
                                                              > > http://blog.fohjin.com/blog/2009/11/12/CQRS_a_la_Greg_Young
                                                              > > > > > > >
                                                              > > > > > > > -Mark
                                                              > > > > > > >
                                                              > > > > > > >
                                                              > > > > > > > On Thu, Oct 29, 2009 at 1:09 AM, Mark Nijhof <mark.nijhof@>
                                                              > > wrote:
                                                              > > > > > > >
                                                              > > > > > > > > Hi,
                                                              > > > > > > > >
                                                              > > > > > > > > Because that is a nasty home made implementation of a bus :)
                                                              > > The
                                                              > > > > > > Publish
                                                              > > > > > > > > method needs to know the exact type of the command/event that
                                                              > > gets
                                                              > > > > > > passed in
                                                              > > > > > > > > because that is used to get the correct xxxHandlers from the
                                                              > > IoC
                                                              > > > > > > container.
                                                              > > > > > > > > I cannot use an Generic in the PublishMultiple because these
                                                              > > > > > > commands/events
                                                              > > > > > > > > are 99% of the time not of the same type. I will probably
                                                              > > change it
                                                              > > > > > > into
                                                              > > > > > > > > something like this:
                                                              > > > > > > > >
                                                              > > > > > >
                                                              > > > >
                                                              > > http://codebetter.com/blogs/gregyoung/archive/2009/10/03/delegate-mapper.aspx
                                                              > > > > > > > >
                                                              > > > > > > > > Also one thing I like to highlight is that in this first
                                                              > > version I
                                                              > > > > am
                                                              > > > > > > not
                                                              > > > > > > > > using anything complex because I explicitly wanted to show that
                                                              > > the
                                                              > > > > > > core of
                                                              > > > > > > > > this is actually very simple, if I started with NServiceBus and
                                                              > > > > > > NHibernate
                                                              > > > > > > > > than that would have taken away from the simplicity of this
                                                              > > type of
                                                              > > > > > > > > architecture. That is why I have implemented my own very simple
                                                              > > ORM
                                                              > > > > > > (one has
                                                              > > > > > > > > to do that once in their career anyway right) and my own bus. I
                                                              > > > > plan on
                                                              > > > > > > > > continuing on this example by introducing these types of
                                                              > > options as
                                                              > > > > > > well,
                                                              > > > > > > > > all do the event store will remain custom SQL, actually I will
                                                              > > also
                                                              > > > > > > > > implement one using SQL Server and that one will use a stored
                                                              > > > > procedure
                                                              > > > > > > ;)
                                                              > > > > > > > >
                                                              > > > > > > > > -Mark
                                                              > > > > > > > >
                                                              > > > > > > > >
                                                              > > > > > > > >
                                                              > > > > > > > > On Wed, Oct 28, 2009 at 8:16 PM, David Perfors <dnperfors@
                                                              > > >wrote:
                                                              > > > > > >
                                                              > > > > > > > >
                                                              > > > > > > > >>
                                                              > > > > > > > >>
                                                              > > > > > > > >> Hi Mark,
                                                              > > > > > > > >>
                                                              > > > > > > > >> Thanks a lot for this example. I was looking into the code and
                                                              > > > > looked
                                                              > > > > > > ad
                                                              > > > > > > > >> the implementations of IBus and saw that it is using
                                                              > > reflection
                                                              > > > > for
                                                              > > > > > > the
                                                              > > > > > > > >> PublishMultiple method. Can you tell me (us) more about why
                                                              > > you
                                                              > > > > are
                                                              > > > > > > doing
                                                              > > > > > > > >> that instead of just calling the Publish method?
                                                              > > > > > > > >>
                                                              > > > > > > > >> Looking forward to the blogposts :)
                                                              > > > > > > > >>
                                                              > > > > > > > >> David.
                                                              > > > > > > > >>
                                                              > > > > > > > >> 2009/10/26 Mark Nijhof <Mark.Nijhof@>
                                                              > > > > > >
                                                              > > > > > > > >>
                                                              > > > > > > > >>> Hi,
                                                              > > > > > > > >>>
                                                              > > > > > > > >>> Since multiple people have been asking for this and I feel
                                                              > > that
                                                              > > > > the
                                                              > > > > > > > >>> core is good enough to share I thought I would share the
                                                              > > > > repository
                                                              > > > > > > > >>> here already. Disclaimer: Now keep in mind that this has not
                                                              > > been
                                                              > > > > > > > >>> reviewed by Greg yet and that I am still working on it. I am
                                                              > > also
                                                              > > > > > > > >>> working on a complete detailed blog post (or several) to
                                                              > > explain
                                                              > > > > what
                                                              > > > > > > > >>> is going on and why (with diagrams and all that fancy stuff).
                                                              > > > > Once
                                                              > > > > > > > >>> that is done it will be published here:
                                                              > > http://blog.fohjin.com/I am
                                                              > > > > > > > >>> currently finishing my specifications for the GUI and will
                                                              > > split
                                                              > > > > the
                                                              > > > > > > > >>> existing domain specifications a bit more per scenario, but I
                                                              > > > > think
                                                              > > > > > > > >>> you will like what you see there (hope at least).
                                                              > > > > > > > >>>
                                                              > > > > > > > >>> The most interesting scenario is a transfer from one account
                                                              > > to
                                                              > > > > an
                                                              > > > > > > > >>> other account.
                                                              > > > > > > > >>>
                                                              > > > > > > > >>> Link: http://github.com/MarkNijhof/Fohjin
                                                              > > > > > > > >>>
                                                              > > > > > > > >>> Note on SQLite: Because I am developing on x64 I have the x64
                                                              > > > > version
                                                              > > > > > > > >>> of SQLite referenced in the projects, except for the test
                                                              > > project
                                                              > > > > > > > >>> because TestDriven.Net executes everything in x86. Now if you
                                                              > > are
                                                              > > > > > > > >>> running on a x86 machine all you have to do is copy the x86
                                                              > > > > > > > >>> System.Data.SQLite.* from /lib/sqlite/bin to
                                                              > > /lib/sqlite/bin/x64
                                                              > > > > > > (this
                                                              > > > > > > > >>> approach is tested). There are two different SQLite
                                                              > > databases,
                                                              > > > > one is
                                                              > > > > > > > >>> the event store and the other is the reporting database. I
                                                              > > > > haven't
                                                              > > > > > > > >>> figured out yet how, but it is possible to load the SQLite
                                                              > > > > databases
                                                              > > > > > > > >>> in Visual Studio to inspect the content. Both databases are
                                                              > > > > created
                                                              > > > > > > on
                                                              > > > > > > > >>> first use, and deleting them will give you a fresh start.
                                                              > > > > > > > >>>
                                                              > > > > > > > >>> I would like to hear your opinions, I am very enthusiastic
                                                              > > about
                                                              > > > > this
                                                              > > > > > > > >>> architecture when there is a need for a domain.
                                                              > > > > > > > >>>
                                                              > > > > > > > >>> -Mark
                                                              > > > > > > > >>>
                                                              > > > > > > > >>>
                                                              > > > > > > > >>> ------------------------------------
                                                              > > > > > > > >>>
                                                              > > > > > > > >>> Yahoo! Groups Links
                                                              > > > > > > > >>>
                                                              > > > > > > > >>>
                                                              > > > > > > > >>>
                                                              > > > > > > > >>>
                                                              > > > > > > > >>
                                                              > > > > > > > >>
                                                              > > > > > > > >
                                                              > > > > > > > >
                                                              > > > > > > >
                                                              > > > > > >
                                                              > > > > > >
                                                              > > > > > >
                                                              > > > > >
                                                              > > > >
                                                              > > > >
                                                              > > > >
                                                              > > >
                                                              > > >
                                                              > > >
                                                              > > > --
                                                              > > > Les erreurs de grammaire et de syntaxe ont été incluses pour m'assurer de
                                                              > > > votre attention
                                                              > > >
                                                              > >
                                                              > >
                                                              > >
                                                              >









                                                            • Mark Henke
                                                              Sounds great! I am looking forward to seeing the changes. ... Sounds great! I am looking forward to seeing the changes. On Fri, Nov 13, 2009 at 9:18 PM, Mark
                                                              Message 30 of 30 , Nov 13, 2009
                                                                Sounds great! I am looking forward to seeing the changes.

                                                                On Fri, Nov 13, 2009 at 9:18 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                                 

                                                                Ah ok I see where you where going, but just to be sure, you would then have a specific list with children in the AR and then register each child as being a child that has events. (quickly said) so you AR structure would still look very OO ;) you just also register the childs. Hmm that could be worth it indeed, especially if these childs have many events. I am currently extending the example with similar functionality as I discussed to demonstrate it, but perhaps I'll try your suggestion as well, only with one change ;)

                                                                The List that contains the children I will make this a special list that would register the children automatically when adding them to the list, how does that sound? I want to limit the possibility for mistakes.

                                                                -Mark




                                                                On Sat, Nov 14, 2009 at 2:36 AM, Mark Henke <gilligan128@...> wrote:
                                                                 

                                                                That answers the questions I had. But here is the thing. In your system every registration is different, example, 

                                                                in addition to your posted code, we might have this:

                                                                void forwardEventsToClosedAccount(object event)
                                                                {
                                                                      ClosedAccount closedAccount;
                                                                        if (!closedAccounts.TryGetById(event.AccountId, out closedAccount))

                                                                            throw new Exception();

                                                                        closedAccount.LoadHistory(event);        
                                                                }

                                                                Now we are doing the same thing over and over again for every child AGG collection. Additionally, you will have to have duplicate code for aggregating changes:

                                                                override IEnumerable<object> GetChanges()
                                                                {
                                                                   return base.GetChanges().Concat(activeAccounts).Concat(closedAccounts); 
                                                                }

                                                                You could reduce some repetitiveness by having something like this in the base class:

                                                                override IEnumerable<object> GetChanges()
                                                                {
                                                                   return base.GetChanges().Concat(children.SelectMany(child => child.GetChanges()));
                                                                }

                                                                but to do that you need some sort of centralized store for your children. Thus the idea of a registry. And since we have a registry of sorts, a standard way of saving them, why not have a standard way of retrieving them which we can specify more declaratively instead of repeating plumbing code for each collection. 
                                                                This is the stream of thought that led to my example code. I hope that clarifies things. I could be way over thinking it. 


                                                                On Fri, Nov 13, 2009 at 6:22 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                                 

                                                                In the registration method you would register all the events that the ActiveAccount has to be handled by the forwardEventsToAccount. Since when you write your domain you know the events that the children can handle so this should be easy, you could perhaps even apply convention here.

                                                                -Mark




                                                                On Sat, Nov 14, 2009 at 12:20 AM, Mark Nijhof <mark.nijhof@...> wrote:
                                                                Will take a much closer look at the code, just wanted to respond to the question :)

                                                                If you have a list with children then each child needs to have a unique Id within the AR, you need this anyway, this Id also needs to be in the history event, thus you have an easy way to select to which child to forward the event. I am not sure what I am missing here?

                                                                class AR
                                                                {
                                                                    list activeAccounts = new List
                                                                    {
                                                                        new ActiveAccount { Id = 10 }
                                                                        new ActiveAccount { Id = 15 }
                                                                    }

                                                                    forwardEventsToAccount(object event)
                                                                    {
                                                                        ActiveAccount actinveAccount;
                                                                        if (!activeAccounts.TryGetById(event.AccountId, out activeAccount))

                                                                            throw new Exception();

                                                                        activeAccount.LoadHistory(event);       
                                                                    }
                                                                }

                                                                AR ar = new AR()
                                                                ar.LoadHistory(new[] {
                                                                    someEventForAccount { AccountId = 10 }
                                                                    someEventForAccount { AccountId = 15 }
                                                                    someOtherEventForAccount { AccountId = 10 }
                                                                    someOtherEventForAccount { AccountId = 10 }
                                                                });

                                                                -Mark



                                                                On Sat, Nov 14, 2009 at 12:02 AM, Mark Henke <gilligan128@...> wrote:
                                                                 

                                                                How do you know to what child an event belongs to? Your example below does not seem to handle that. That is what my solution is tackling. Here is a rough-shod example:

                                                                 interface ILookup
                                                                        {
                                                                            bool HasChildFor(IDomainEvent @event);
                                                                            void ApplyChildEvent(IDomainEvent @event );
                                                                            IEnumerable<IDomainEvent> GetChanges();
                                                                            void ClearChanges();
                                                                        }


                                                                        class AggregateRootBase
                                                                        {
                                                                            LookupBuilder<T> Lookup<T>(IEnumerable<T> childCollection) where T : EventSource
                                                                        {
                                                                            var lookupBuilder = new LookupBuilder<T>(childCollection);
                                                                            lookups.Add(lookupBuilder);

                                                                            return lookupBuilder;
                                                                        }


                                                                            public void ForwardToChildrenEventsOfType<T>()
                                                                            {
                                                                                RegisterHandler<T>(@event => lookups.Single(lookup => lookup.HasChildFor(@event)).ApplyChildEvent(@event));
                                                                            }

                                                                           public IEnumerable<IDomainEvent> GetChanges()
                                                                          {
                                                                                 return events.Concat(lookups.SelectMany(lookup => lookup.GetChanges()));
                                                                          }

                                                                          
                                                                        }

                                                                And the LookupBuilder class:

                                                                 class LookupBuilder<T> : ILookup where T : EventSource
                                                                        {
                                                                            IEnumerable<T> children;
                                                                            Func<T, object> childKey;
                                                                            IDictionary<Type, Func<IDomainEvent, object>> eventKeys = new Dictionary<Type, Func<IDomainEvent, object>>();

                                                                            AggregateRootBase ar;


                                                                            public LookupBuilder(IEnumerable<T> children, AggregateRootBase ar)
                                                                            {
                                                                                this.children = children;
                                                                                this.ar = ar;
                                                                                childKey = child => child.Id;
                                                                            }

                                                                            public LookupBuilder<T> On(Func<T, object> keyGetter)
                                                                            {
                                                                                childKey = keyGetter;
                                                                                return this;
                                                                            }

                                                                            public LookupBuilder<T> For<TEvent>(Func<TEvent,object> eventKeyGetter)
                                                                            {
                                                                                eventKeys[typeof (TEvent)] = @event =>  eventKeyGetter((TEvent)@event);
                                                                                ar.ForwardToChildrenEventsOfType<TEvent>();
                                                                                return this;
                                                                            }

                                                                            bool ILookup.HasChildFor(IDomainEvent @event)
                                                                            {
                                                                                if(!eventKeys.ContainsKey(@...()))
                                                                                {
                                                                                    return false;
                                                                                }

                                                                                var eventKey = eventKeys[@...()];
                                                                                return children.Any(child => childKey(child) == eventKey(@event));
                                                                            }


                                                                            IEnumerable<IDomainEvent> ILookup.GetChanges()
                                                                            {
                                                                                return children.SelectMany(child => child.GetChanges());
                                                                            }

                                                                            void ILookup.ClearChanges()
                                                                            {
                                                                                children.Iterate(x => x.ClearChanges());
                                                                            }

                                                                            void ILookup.ApplyChildEvent(IDomainEvent @event)
                                                                            {
                                                                                var eventKey = eventKeys[@...()];
                                                                                children.Single(child => childKey(child) == eventKey(@event)).LoadEventFromHistory(@event);
                                                                            }
                                                                        }


                                                                It may be hard to read at first, but it basically allows us to do things like this:

                                                                public Client()
                                                                {
                                                                   Lookup(ActiveAccounts)
                                                                    .For<AccountIsOnHold>(@event => @...)
                                                                    .For<AccountIsNoLongerOnHold>(@event => @...);

                                                                  Lookup(ClosedAccounts)
                                                                   .For<AccountReactivated>(@event => @...);

                                                                }

                                                                All the ugly stuff is hidden by the base class and the plumbing is handled for us. We could also add something like Child(CurrentAccount).CanHandle<AccountOnHold>(x => x.AccountId) for simple cases. 

                                                                I hope that helps. Also this is only a rough draft of what I was thinking.

                                                                On Fri, Nov 13, 2009 at 4:07 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                                 

                                                                One thing I don't like about this solution (or as how I understand it) is that you put all different types into on dictionary wouldn't this ruin a lot of the readability? Also seems more complex then needed? But as often happens I might just completely understand you wrong :D So an code example would be great. Perhaps I can implement something like this before the upcoming E-VAN talk. (I want to keep it somewhat recognizable for people attending the talk so no major changes).

                                                                Here an example keeping in the same types but different organization:

                                                                Client
                                                                - List<ActiveAccounts> activeAccounts;
                                                                - List<ClosedAccounts> closedAccounts;

                                                                So in the AR I handle both events for the active account and closed account. I could just have two event handlers, one that handles all events for the active account amd one that handles all events for the closed accounts. In this event handler you would just forward the event to the correct instance in the list. Inside the f.ex. Active account it knows how to apply each individual different type of event.

                                                                private void forwardAllEventsForAnActiveAccount(object event)
                                                                {
                                                                    ActiveAccount actinveAccount;
                                                                    if (!activeAccounts.TryGetById(event.AccountId))
                                                                        throw new Exception();

                                                                    activeAccount.LoadHistory(event);
                                                                }

                                                                -Mark




                                                                On Fri, Nov 13, 2009 at 3:49 PM, Mark Henke <gilligan128@...> wrote:
                                                                 

                                                                I think we can break up this AR -> AGG issue of replaying events into two parts:

                                                                1) How is a Child AGG identified? and
                                                                2) How do we figure out what child that event belongs to?

                                                                Here is a shot in the dark, but how about this:

                                                                Let's assume all our child AGGs are in a single dictionary based upon type. The AR can then view itself internally as a Repository of AGGs. 
                                                                e.g. AddAGG<OrderSection>(orderSection);

                                                                Then for any event type we can register a Lookup on a specific child type. 
                                                                e.g. RegisterLookupOn<OrderSection>(section => section.Id)
                                                                          .For<ProductSaleEvent>(@event => @...);
                                                                The base AR classe, when replaying events, would also check to see if a lookup is registered for that event type and will forward that event to the specified child AGG.

                                                                I could create a patch on Git for your example experimenting with this idea if you want, Mark.


                                                                On Thu, Nov 12, 2009 at 5:03 PM, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                                 

                                                                You could still have the AR be responsible for managing the collection including the internal state, but that feels wrong.

                                                                -Mark



                                                                On Thu, Nov 12, 2009 at 9:32 PM, sebaszipp <sebaszipp@...> wrote:
                                                                 


                                                                Yes, for the case we have predifined/fixed order sections for an order we could fire up events according to the section in cuestion. But in case of having collection of AGGs (AR -> List<AGG> -> List<AGG>) the situation comes kind of weird.
                                                                Maybe we should take a look into our BC, in order to rethink and see whether the BC graph should be pruned and the remaing is responsability of another BC?



                                                                --- In domaindrivendesign@yahoogroups.com, Mark Nijhof <Mark.Nijhof@...> wrote:
                                                                >
                                                                > Each AGG can apply its own events and store them in itself, then when you
                                                                > ask for changes from the AR it will ask changes from it's AGG.
                                                                >
                                                                > Loading events from history would load them all in the AR which would
                                                                > delegate them back to the AGG. I am not 100% sure yet what the best approach
                                                                > for this is. You could just send all of them and have the AGG decide which
                                                                > one to skip, or you could make the AR aware what types of events need to be
                                                                > forwarded to the AGG. This can be done by creating an event handler in the
                                                                > AR that would just forward the event to the specific AGG. But if you have
                                                                > collections of AGG then this would be a problem.
                                                                >
                                                                > -Mark
                                                                >
                                                                >
                                                                > On Thu, Nov 12, 2009 at 8:46 PM, sebaszipp <sebaszipp@...> wrote:
                                                                >
                                                                > >
                                                                > >
                                                                > >
                                                                > > Great. Thanks Greg.
                                                                > >
                                                                > > I more question:
                                                                > >
                                                                > > As far as I've been reading about CQS I've been all examples matching the
                                                                > > same association: AR -> AGG where the AR is the one firing up domain events.
                                                                > > I would like to add another association supposing our graph is more complex
                                                                > > than just AR -> AGG.
                                                                > >
                                                                > > In this case we would have the following graph:
                                                                > > Order AR -> OrderSection AGG -> OrderLine AGG
                                                                > >
                                                                > > Suppose there are 2 rules dictating that products under 10 dollars should
                                                                > > be placed into Section1 and the others should be placed into Section2. In
                                                                > > the case a product that is $5 is bought we would fire up an event from the
                                                                > > Order AR:
                                                                > >
                                                                > > super.apply(new ProductSaleEvent(sectionOneID, productDescription))
                                                                > >
                                                                > > and then the event handler of the Order AR should be:
                                                                > >
                                                                > > handle(ProductSaleEvent event)
                                                                > > {
                                                                > > OrderSection orderSection = orderSections.get(event.sectionId)
                                                                > > if (orderSection == null) {
                                                                > > orderSection = new OrderSection();
                                                                > > orderSections.put(event.sectionId, orderSection);
                                                                > > }
                                                                > > orderSection.processSale(productDescription); // which will create a Line
                                                                > > internally
                                                                > > }
                                                                > >
                                                                > > Should be handled this way?
                                                                > > I mean, the AR is the leading with the graph hierarchy no matter how deep
                                                                > > it's?
                                                                > >
                                                                > > Cheers,
                                                                > >
                                                                > >
                                                                > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>,

                                                                > > Greg Young <gregoryyoung1@> wrote:
                                                                > > >
                                                                > > > Yes the snapshots are generally not in memory, they live in the event
                                                                > > store.
                                                                > > >
                                                                > > > Cheers,
                                                                > > >
                                                                > > > Greg
                                                                > > >
                                                                > > > On Thu, Nov 12, 2009 at 8:30 PM, sebaszipp <sebaszipp@> wrote:
                                                                > > >
                                                                > > > >
                                                                > > > >
                                                                > > > >
                                                                > > > > I got it :)
                                                                > > > >
                                                                > > > > I don't know why I was relating the concept of a snapshot with a stack
                                                                > > of
                                                                > > > > events and not with the domain AR (and since I'm not an english native
                                                                > > > > speaker I got a lil confused about the term 'rolling').
                                                                > > > >
                                                                > > > > So you take a picture of the domain entity after N events and then make
                                                                > > the
                                                                > > > > repository hold a reference to that picture indexed by its identity
                                                                > > (ID) (or
                                                                > > > > the separate process yoou mention)
                                                                > > > >
                                                                > > > > Let's assume you want to load the AR having the same ID that the
                                                                > > picture
                                                                > > > > hold by the repo has. You calculate the position in the event stack
                                                                > > from
                                                                > > > > where you would start replying events, then create an AR instance, copy
                                                                > > its
                                                                > > > > state with the picture (Memento) that you took previosly, and apply the
                                                                > > > > events representing the DELTA.
                                                                > > > >
                                                                > > > > The Snapshot shouldn't be kept by the repo because we would run into
                                                                > > the
                                                                > > > > same performance problem if too many instances live in memory. I guess
                                                                > > we
                                                                > > > > should serialize the snapshot to disk or something similar?
                                                                > > > >
                                                                > > > > Am I ok?
                                                                > > > >
                                                                > > > > Thanks Mark.
                                                                > > > >
                                                                > > > >
                                                                > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                                                > > <domaindrivendesign%40yahoogroups.com>,
                                                                > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                                                > > > > >
                                                                > > > > > Your rolling snapshot will never be assumed to be the latest state of
                                                                > > the
                                                                > > > > > AR, after loading the snapshot the repository will always get all
                                                                > > events
                                                                > > > > > that have occurred after the snapshot was made. The process creating
                                                                > > the
                                                                > > > > > snapshots will most likely be a independent process that would just
                                                                > > load
                                                                > > > > AR
                                                                > > > > > verify if a snapshot needs to be made. If this is the case it would
                                                                > > make
                                                                > > > > it.
                                                                > > > > > Say after 100 events you want a snapshot. Instead of putting this
                                                                > > > > > responsibility in the domain repository?
                                                                > > > > >
                                                                > > > > > So current version of the snapshot is 20 version of the last event is
                                                                > > 25
                                                                > > > > so
                                                                > > > > > after loading the snapshot it also needs to replay the last 5 events.
                                                                > > > > >
                                                                > > > > > Does this make sense?
                                                                > > > > >
                                                                > > > > > -Mark
                                                                > > > > >
                                                                > > > > > On Thu, Nov 12, 2009 at 4:37 PM, sebaszipp <sebaszipp@> wrote:
                                                                > > > > >
                                                                > > > > > >
                                                                > > > > > >
                                                                > > > > > >
                                                                > > > > > > Hi Mark,
                                                                > > > > > >
                                                                > > > > > > Great blog. Thanks for clarifying in detail things about CQRS.
                                                                > > > > > >
                                                                > > > > > > Still a grey zone I'd like to get better is about AR load
                                                                > > performance
                                                                > > > > when
                                                                > > > > > > the event storage is large enough to kill performance.
                                                                > > > > > > I know rolling snapshots takes care of this field, but by rolling
                                                                > > > > snapthost
                                                                > > > > > > I might get an incomplete AR?
                                                                > > > > > > Could you please explain this?
                                                                > > > > > >
                                                                > > > > > > Thanks.
                                                                > > > > > >
                                                                > > > > > >
                                                                > > > > > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%40yahoogroups.com>
                                                                > > <domaindrivendesign%40yahoogroups.com>
                                                                > > > > <domaindrivendesign%40yahoogroups.com>,
                                                                > > > >
                                                                > > > > > > Mark Nijhof <Mark.Nijhof@> wrote:
                                                                > > > > > > >
                                                                > > > > > > > Hi,
                                                                > > > > > > >
                                                                > > > > > > > I finally got the first blog post about this published, it is
                                                                > > long!
                                                                > > > > Not
                                                                > > > > > > so
                                                                > > > > > > > much code, more the explanation behind it (as I understand it).
                                                                > > > > > > >
                                                                > > > > > > > Link:
                                                                > > http://blog.fohjin.com/blog/2009/11/12/CQRS_a_la_Greg_Young
                                                                > > > > > > >
                                                                > > > > > > > -Mark
                                                                > > > > > > >
                                                                > > > > > > >
                                                                > > > > > > > On Thu, Oct 29, 2009 at 1:09 AM, Mark Nijhof <mark.nijhof@>
                                                                > > wrote:
                                                                > > > > > > >
                                                                > > > > > > > > Hi,
                                                                > > > > > > > >
                                                                > > > > > > > > Because that is a nasty home made implementation of a bus :)
                                                                > > The
                                                                > > > > > > Publish
                                                                > > > > > > > > method needs to know the exact type of the command/event that
                                                                > > gets
                                                                > > > > > > passed in
                                                                > > > > > > > > because that is used to get the correct xxxHandlers from the
                                                                > > IoC
                                                                > > > > > > container.
                                                                > > > > > > > > I cannot use an Generic in the PublishMultiple because these
                                                                > > > > > > commands/events
                                                                > > > > > > > > are 99% of the time not of the same type. I will probably
                                                                > > change it
                                                                > > > > > > into
                                                                > > > > > > > > something like this:
                                                                > > > > > > > >
                                                                > > > > > >
                                                                > > > >
                                                                > > http://codebetter.com/blogs/gregyoung/archive/2009/10/03/delegate-mapper.aspx
                                                                > > > > > > > >
                                                                > > > > > > > > Also one thing I like to highlight is that in this first
                                                                > > version I
                                                                > > > > am
                                                                > > > > > > not
                                                                > > > > > > > > using anything complex because I explicitly wanted to show that
                                                                > > the
                                                                > > > > > > core of
                                                                > > > > > > > > this is actually very simple, if I started with NServiceBus and
                                                                > > > > > > NHibernate
                                                                > > > > > > > > than that would have taken away from the simplicity of this
                                                                > > type of
                                                                > > > > > > > > architecture. That is why I have implemented my own very simple
                                                                > > ORM
                                                                > > > > > > (one has
                                                                > > > > > > > > to do that once in their career anyway right) and my own bus. I
                                                                > > > > plan on
                                                                > > > > > > > > continuing on this example by introducing these types of
                                                                > > options as
                                                                > > > > > > well,
                                                                > > > > > > > > all do the event store will remain custom SQL, actually I will
                                                                > > also
                                                                > > > > > > > > implement one using SQL Server and that one will use a stored
                                                                > > > > procedure
                                                                > > > > > > ;)
                                                                > > > > > > > >
                                                                > > > > > > > > -Mark
                                                                > > > > > > > >
                                                                > > > > > > > >
                                                                > > > > > > > >
                                                                > > > > > > > > On Wed, Oct 28, 2009 at 8:16 PM, David Perfors <dnperfors@
                                                                > > >wrote:
                                                                > > > > > >
                                                                > > > > > > > >
                                                                > > > > > > > >>
                                                                > > > > > > > >>
                                                                > > > > > > > >> Hi Mark,
                                                                > > > > > > > >>
                                                                > > > > > > > >> Thanks a lot for this example. I was looking into the code and
                                                                > > > > looked
                                                                > > > > > > ad
                                                                > > > > > > > >> the implementations of IBus and saw that it is using
                                                                > > reflection
                                                                > > > > for
                                                                > > > > > > the
                                                                > > > > > > > >> PublishMultiple method. Can you tell me (us) more about why
                                                                > > you
                                                                > > > > are
                                                                > > > > > > doing
                                                                > > > > > > > >> that instead of just calling the Publish method?
                                                                > > > > > > > >>
                                                                > > > > > > > >> Looking forward to the blogposts :)
                                                                > > > > > > > >>
                                                                > > > > > > > >> David.
                                                                > > > > > > > >>
                                                                > > > > > > > >> 2009/10/26 Mark Nijhof <Mark.Nijhof@>
                                                                > > > > > >
                                                                > > > > > > > >>
                                                                > > > > > > > >>> Hi,
                                                                > > > > > > > >>>
                                                                > > > > > > > >>> Since multiple people have been asking for this and I feel
                                                                > > that
                                                                > > > > the
                                                                > > > > > > > >>> core is good enough to share I thought I would share the
                                                                > > > > repository
                                                                > > > > > > > >>> here already. Disclaimer: Now keep in mind that this has not
                                                                > > been
                                                                > > > > > > > >>> reviewed by Greg yet and that I am still working on it. I am
                                                                > > also
                                                                > > > > > > > >>> working on a complete detailed blog post (or several) to
                                                                > > explain
                                                                > > > > what
                                                                > > > > > > > >>> is going on and why (with diagrams and all that fancy stuff).
                                                                > > > > Once
                                                                > > > > > > > >>> that is done it will be published here:
                                                                > > http://blog.fohjin.com/I am
                                                                > > > > > > > >>> currently finishing my specifications for the GUI and will
                                                                > > split
                                                                > > > > the
                                                                > > > > > > > >>> existing domain specifications a bit more per scenario, but I
                                                                > > > > think
                                                                > > > > > > > >>> you will like what you see there (hope at least).
                                                                > > > > > > > >>>
                                                                > > > > > > > >>> The most interesting scenario is a transfer from one account
                                                                > > to
                                                                > > > > an
                                                                > > > > > > > >>> other account.
                                                                > > > > > > > >>>
                                                                > > > > > > > >>> Link: http://github.com/MarkNijhof/Fohjin
                                                                > > > > > > > >>>
                                                                > > > > > > > >>> Note on SQLite: Because I am developing on x64 I have the x64
                                                                > > > > version
                                                                > > > > > > > >>> of SQLite referenced in the projects, except for the test
                                                                > > project
                                                                > > > > > > > >>> because TestDriven.Net executes everything in x86. Now if you
                                                                > > are
                                                                > > > > > > > >>> running on a x86 machine all you have to do is copy the x86
                                                                > > > > > > > >>> System.Data.SQLite.* from /lib/sqlite/bin to
                                                                > > /lib/sqlite/bin/x64
                                                                > > > > > > (this
                                                                > > > > > > > >>> approach is tested). There are two different SQLite
                                                                > > databases,
                                                                > > > > one is
                                                                > > > > > > > >>> the event store and the other is the reporting database. I
                                                                > > > > haven't
                                                                > > > > > > > >>> figured out yet how, but it is possible to load the SQLite
                                                                > > > > databases
                                                                > > > > > > > >>> in Visual Studio to inspect the content. Both databases are
                                                                > > > > created
                                                                > > > > > > on
                                                                > > > > > > > >>> first use, and deleting them will give you a fresh start.
                                                                > > > > > > > >>>
                                                                > > > > > > > >>> I would like to hear your opinions, I am very enthusiastic
                                                                > > about
                                                                > > > > this
                                                                > > > > > > > >>> architecture when there is a need for a domain.
                                                                > > > > > > > >>>
                                                                > > > > > > > >>> -Mark
                                                                > > > > > > > >>>
                                                                > > > > > > > >>>
                                                                > > > > > > > >>> ------------------------------------
                                                                > > > > > > > >>>
                                                                > > > > > > > >>> Yahoo! Groups Links
                                                                > > > > > > > >>>
                                                                > > > > > > > >>>
                                                                > > > > > > > >>>
                                                                > > > > > > > >>>
                                                                > > > > > > > >>
                                                                > > > > > > > >>
                                                                > > > > > > > >
                                                                > > > > > > > >
                                                                > > > > > > >
                                                                > > > > > >
                                                                > > > > > >
                                                                > > > > > >
                                                                > > > > >
                                                                > > > >
                                                                > > > >
                                                                > > > >
                                                                > > >
                                                                > > >
                                                                > > >
                                                                > > > --
                                                                > > > 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.