Inheritance, commands and event sourcing

cqrsevent-sourcing

In order not to redo things several times I wanted to factorize common stuff. For Instance, let's say we have a cow and a horse. The cow produces milk, the horse runs fast, but both eat grass.

public class Herbivorous
{
   protected int Quantity;

   public void EatGrass(int quantity)
   {
      var evt= Build.GrassEaten
                    .WithQuantity(quantity);
      RaiseEvent(evt);
   }

   public void Apply(GrassEaten evt)
   {
       _quantity= evt.Quantity;
   }
}

public class Horse : Herbivorous
{
   private bool _HasFastRun;

   public void RunFast()
   {
      var evt= Build.FastRun;
      RaiseEvent(evt);
   }

   public void Apply(FastRunevt)
   {
       _HasFastRun= true;
   }
}

public class Cow: Herbivorous
{
   private bool _IsMilkProduced;

   public void ProduceMilk()
   {
      var evt= Build.MilkProduced;
      RaiseEvent(evt);
   }

   public void Apply(MilkProduced evt)
   {
       _IsMilkProduced= true;
   }
}

To eat Grass, my application receives a command in Json or xml, or whatever that deserialise into this class:

namespace Herbivorous
{
   public class EatGrass : CommandBase
   {
      public Guid IdHerbivorous {get; set;}
      public Guid CommitId {get; set;}
      public long Version {get; set;}
      public int Quantity {get; set;}
   }
}

The command handler should be :

public class EatGrassHandler : CommandHandler<EatGrass>
{
   public override CommandValidation Execute(EatGrass cmd)
   {
      Contract.Requires<ArgumentNullException>(cmd != null);
      Herbivorous herbivorous= EventRepository.GetById<Herbivorous>(cmd.Id);
      if (herbivorous.IsNull())
         throw new AggregateRootInstanceNotFoundException();
      herbivorous.EatGrass(cmd.Quantity);
      EventRepository.Save(herbivorous, cmd.CommitId);
   }
}

so far so good. I get a Herbivorous object , I have access to its EatGrass function, whether it is a horse or a cow doesn't matter really. The only problem is here :

EventRepository.GetById<Herbivorous>(cmd.Id)

Indeed, let's imagine we have a cow that has produced milk during the morning and now wants to eat grass. The EventRepository contains an event MilkProduced, and then come the command EatGrass.
With the CommandHandler, we are no longer in the presence of a cow and the herbivorious doesn't know anything about producing milk . what should it do?

Should I have explicit contextual command like :

namespace Herbivorous.Cow
    {
       public class EatGrass : CommandBase
       {
          public Guid IdHerbivorous {get; set;}
          public Guid CommitId {get; set;}
          public long Version {get; set;}
          public int Quantity {get; set;}
       }
       public class ProduceMilk : CommandBase
       {
          public Guid IdHerbivorous {get; set;}
          public Guid CommitId {get; set;}
          public long Version {get; set;}
       }
    }

This would mean that the external component that asks my herbivorous to eat grass should know that in this bounded context we talk about a cow. in the former command, we were talking about a general Herbivorous behavior, so the context of my call was not important. We knew that we needed herbivorous to eat grass that was all.

This is my main problem possible leakage of domain specific from one bounded context to another.
Actually It might mean too that I cannot support abstraction when working on interfaces between several applications. I wonder…

Or I could just accept any event when rebuilding my herbivorous. It means that if it does not find a method to apply this event to, he will goes just fine trying to apply the next one of its stream. This is the real simple solution, but it does not put me at ease to know that events might not be applied ( and not producing errors) when rehydrating my object. (Actually the more I think about it the less I feel guilty..)

Thanks for your help, I am just beginning with these kinds of problem, and I would be glad to have some news from someone more experienced.

Best Answer

First, add a virtual method Execute(cmd) to your Herbivorous, and put the code for the dispatching the commands to the command methods there. Then each subclass of Herbivorous can override that method and support all command methods specific to the subclass. Should look somehow like this:

public class Cow: Herbivorous
{
   public override void Execute(Command cmd)
   {
      if(cmd is ProduceMilkCommand)
          ProduceMilk(cmd);  // execute specific command
      else
          base.Execute(cmd); // delegate general commands to the base class
   }
}

For creating a new object from a given command, add a System.Type field to your cmd and use reflection to create an instance of that specific subtype of Herbivorous. Or use the prototype pattern to create a new instance (your command has to store a reference to that prototype object then instead). A third alternative is to use the abstract factory pattern, your command then will have to store a reference to the right factory subtype.

Of course, I guess I could give you a better answer if you had shown us how the command class currently looks like and how the commands are created. And your use of the "var" command in the code snippets hides some details which may be important for a more precise answer.

Related Topic