Al fine di non ripetere le cose più volte volevo prendere in considerazione elementi comuni. Per esempio, diciamo che abbiamo una mucca e un cavallo. La mucca produce latte, il cavallo corre veloce, ma entrambi mangiano erba.
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;
}
}
Per mangiare Grass, la mia applicazione riceve un comando in Json o xml o qualsiasi altra cosa che deserializza in questa classe:
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;}
}
}
Il gestore comandi dovrebbe essere:
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);
}
}
Fin qui tutto bene. Prendo un oggetto erbivoro, ho accesso alla funzione EatGrass, non importa se sia un cavallo o una mucca. L'unico problema è qui:
EventRepository.GetById<Herbivorous>(cmd.Id)
In effetti, immaginiamo di avere una mucca che ha prodotto latte durante la mattinata e ora vuole mangiare erba. EventRepository contiene un evento MilkProduced, quindi viene il comando EatGrass. Con CommandHandler, non siamo più in presenza di una mucca e gli erbivori non sanno nulla della produzione di latte. cosa dovrebbe fare?
Devo avere un comando contestuale esplicito come:
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;}
}
}
Ciò significherebbe che la componente esterna che chiede al mio erbivoro di mangiare erba dovrebbe sapere che in questo contesto limitato parliamo di una mucca. nel precedente comando, stavamo parlando di un comportamento erbivoro generale, quindi il contesto della mia chiamata non era importante. Sapevamo che avevamo bisogno di erbivori per mangiare l'erba che era tutto.
Questo è il mio problema principale possibile perdita di dominio specifico da un contesto limitato a un altro. In realtà potrebbe anche significare che non posso supportare l'astrazione quando lavoro su interfacce tra diverse applicazioni. Mi chiedo ...
O potrei semplicemente accettare qualsiasi evento per ricostruire il mio erbivoro. Significa che se non trova un metodo per applicare questo evento a, andrà bene cercando di applicare il prossimo del suo stream. Questa è la vera soluzione semplice, ma non mi mette a mio agio sapere che gli eventi potrebbero non essere applicati (e non produrre errori) durante la reidratazione del mio oggetto. (In realtà più ci penso meno mi sento in colpa ..)
Grazie per il tuo aiuto, sto solo iniziando con questo tipo di problemi e sarei lieto di ricevere notizie da qualcuno più esperto.