Skip to content

Commit

Permalink
Merge pull request #70 from roadtoagility/feature_aggregate_factory
Browse files Browse the repository at this point in the history
Feature aggregate factory
  • Loading branch information
drr00t authored Aug 12, 2021
2 parents 04b10aa + d1eb68e commit 71d014d
Show file tree
Hide file tree
Showing 17 changed files with 180 additions and 60 deletions.
5 changes: 4 additions & 1 deletion src/DFlow.Business.Cqrs/CommandHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using DFlow.Business.Cqrs.CommandHandlers;
using DFlow.Domain.Events;
using DFlow.Domain.Validation;
using Microsoft.Extensions.Logging;

namespace DFlow.Business.Cqrs
{
public abstract class CommandHandler<TCommand, TResult> : ICommandHandler<TCommand, TResult>
public abstract class CommandHandler<TCommand, TResult>:
ICommandHandler<TCommand, TResult>
{
protected IDomainEventBus Publisher { get; }

Expand Down
2 changes: 1 addition & 1 deletion src/DFlow.Domain/Aggregates/EventBasedAggregationRoot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ protected void Raise(IDomainEvent @event)

public EventStream<TEntityId> GetChange()
{
return EventStream<TEntityId>.From(AggregateId,Name ,Version, _changes.ToImmutableList());
return EventStream<TEntityId>.From(AggregateId,Name ,Version, _currentStream.ToImmutableList());
}

public IReadOnlyList<IDomainEvent> GetEvents()
Expand Down
16 changes: 16 additions & 0 deletions src/DFlow.Domain/Aggregates/IAggregateFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (C) 2020 Road to Agility
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

using DFlow.Domain.Validation;

namespace DFlow.Domain.Aggregates
{
public interface IAggregateFactory<out TAggregate, in TCreateFrom>
where TCreateFrom: BaseValidation
{
TAggregate Create(TCreateFrom source);
}
}
22 changes: 22 additions & 0 deletions src/DFlow.Domain/Command/BaseCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (C) 2020 Road to Agility
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.


using System;
using DFlow.Domain.Validation;

namespace DFlow.Domain.Command
{
public class BaseCommand: BaseValidation, ICommand
{
public DateTime When { get; }

public BaseCommand()
{
When = DateTime.Now;
}
}
}
16 changes: 16 additions & 0 deletions src/DFlow.Domain/Command/ICommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (C) 2020 Road to Agility
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.


using System;

namespace DFlow.Domain.Command
{
public interface ICommand
{
DateTime When { get; }
}
}
2 changes: 1 addition & 1 deletion tests/DFlow.Tests/Business/Cqrs/CommandHandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
using AutoFixture.AutoNSubstitute;
using DFlow.Domain.Events;
using DFlow.Tests.Supporting;
using DFlow.Tests.Supporting.Commands;
using DFlow.Tests.Supporting.DomainObjects.Commands;
using DFlow.Tests.Supporting.DomainObjects.Events;
using NSubstitute;
using Xunit;
Expand Down
4 changes: 0 additions & 4 deletions tests/DFlow.Tests/DFlow.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,4 @@
</PackageReference>
</ItemGroup>

<ItemGroup>
<Folder Include="Supporting\Commands\Validator" />
</ItemGroup>

</Project>
33 changes: 17 additions & 16 deletions tests/DFlow.Tests/Domain/AggregatesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using AutoFixture;
using AutoFixture.AutoNSubstitute;
using DFlow.Domain.BusinessObjects;
using DFlow.Domain.DomainEvents;
using DFlow.Domain.Events;
using DFlow.Tests.Supporting.DomainObjects;
using DFlow.Tests.Supporting.DomainObjects.Commands;
using Xunit;

namespace DFlow.Tests.Domain
Expand All @@ -31,7 +28,9 @@ public void Aggregate_create_a_valid()
public void Aggregate_reconstruct_a_valid()
{
var be = BusinessEntity.From(EntityTestId.GetNext(), VersionId.New());
var agg = BusinessEntityAggregateRoot.ReconstructFrom(be);

var factory = new ObjectBasedAggregateFactory();
var agg = factory.Create(be);

Assert.True(agg.IsValid);
}
Expand All @@ -44,19 +43,19 @@ public void Aggregate_EventBased_create_a_valid()
fixture.Register<Name>(()=> Name.From(fixture.Create<String>()));
fixture.Register<Email>(()=> Email.From("[email protected]"));

var name = fixture.Create<Name>();
var email = fixture.Create<Email>();
var agg = EventStreamBusinessEntityAggregateRoot.Create(EntityTestId.GetNext(), name, email);
var addEntity = fixture.Create<AddEntityCommand>();

var factory = new EventBasedAggregateFactory();
var agg = factory.Create(addEntity);
Assert.Equal(nameof(EventStreamBusinessEntityAggregateRoot),agg.GetChange().Name.Value);
Assert.True(agg.IsValid);
}

[Fact]
public void Aggregate_EventBased_create_an_invalid()
{
var name = Name.Empty();
var email = Email.Empty();
var agg = EventStreamBusinessEntityAggregateRoot.Create(EntityTestId.GetNext(), name, email);
var factory = new EventBasedAggregateFactory();
var agg = factory.Create(new AddEntityCommand("", ""));
Assert.False(agg.IsValid);
}

Expand All @@ -65,12 +64,14 @@ public void Aggregate_EventBased_valid_Entity_create()
{
var fixture = new Fixture()
.Customize(new AutoNSubstituteCustomization{ ConfigureMembers = true });
fixture.Register<Name>(()=> Name.From(fixture.Create<String>()));
fixture.Register<Email>(()=> Email.From("[email protected]"));
fixture.Register<string>(()=> "[email protected]");

var name = fixture.Create<string>();
var email = fixture.Create<string>();

var factory = new EventBasedAggregateFactory();
var agg = factory.Create(new AddEntityCommand(name, email));

var name = fixture.Create<Name>();
var email = fixture.Create<Email>();
var agg = EventStreamBusinessEntityAggregateRoot.Create(EntityTestId.GetNext(), name, email);
var change = agg.GetChange();
Assert.True(agg.IsValid);
Assert.True(change.IsValid);
Expand Down
2 changes: 1 addition & 1 deletion tests/DFlow.Tests/Supporting/AddEntityCommandHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
using DFlow.Business.Cqrs;
using DFlow.Business.Cqrs.CommandHandlers;
using DFlow.Domain.Events;
using DFlow.Tests.Supporting.Commands;
using DFlow.Tests.Supporting.DomainObjects;
using DFlow.Tests.Supporting.DomainObjects.Commands;

namespace DFlow.Tests.Supporting
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,29 @@
using System.Threading.Tasks;
using DFlow.Business.Cqrs;
using DFlow.Business.Cqrs.CommandHandlers;
using DFlow.Domain.Aggregates;
using DFlow.Domain.BusinessObjects;
using DFlow.Domain.Events;
using DFlow.Tests.Supporting.Commands;
using DFlow.Tests.Supporting.DomainObjects;
using DFlow.Tests.Supporting.DomainObjects.Commands;
using FluentValidation.Results;

namespace DFlow.Tests.Supporting
{
public sealed class AddEntityEventBasedCommandHandler : CommandHandler<AddEntityCommand, CommandResult<Guid>>
{
public AddEntityEventBasedCommandHandler(IDomainEventBus publisher)
private IAggregateFactory<EventStreamBusinessEntityAggregateRoot, AddEntityCommand> _aggregateFactory;

public AddEntityEventBasedCommandHandler(IDomainEventBus publisher,
IAggregateFactory<EventStreamBusinessEntityAggregateRoot, AddEntityCommand> aggregateFactory)
:base(publisher)
{
_aggregateFactory = aggregateFactory;
}

protected override Task<CommandResult<Guid>> ExecuteCommand(AddEntityCommand command, CancellationToken cancellationToken)
{
var agg = EventStreamBusinessEntityAggregateRoot.Create(EntityTestId.GetNext(),
Name.From(command.Name), Email.From(command.Mail));
var agg = _aggregateFactory.Create(command);

var isSucceed = false;
var okId = Guid.Empty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace DFlow.Tests.Supporting.DomainObjects
{
public sealed class BusinessEntityAggregateRoot:ObjectBasedAggregationRoot<BusinessEntity, EntityTestId>
{
private BusinessEntityAggregateRoot(BusinessEntity businessEntity)
internal BusinessEntityAggregateRoot(BusinessEntity businessEntity)
{
if (businessEntity.IsValid)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,23 @@
//


namespace DFlow.Tests.Supporting.Commands
using System.Collections.Immutable;
using DFlow.Domain.Command;
using DFlow.Domain.Validation;

namespace DFlow.Tests.Supporting.DomainObjects.Commands
{
public class AddEntityCommand
public class AddEntityCommand: BaseCommand
{
public string Name { get; set; }
public string Mail { get; set; }
public AddEntityCommand(string name, string email)
{
Name = Name.From(name);
Mail = Email.From(email);

AppendValidationResult(Name.ValidationStatus.Errors.ToImmutableList());
AppendValidationResult(Mail.ValidationStatus.Errors.ToImmutableList());
}
public Name Name { get; set; }
public Email Mail { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@


using System;
using DFlow.Domain.Validation;

namespace DFlow.Tests.Supporting.Commands
namespace DFlow.Tests.Supporting.DomainObjects.Commands
{
public class UpdateEntityCommand
public class UpdateEntityCommand: BaseValidation
{
public string Name { get; set; }
public Guid AggregateId { get; set; }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (C) 2020 Road to Agility
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

using DFlow.Domain.Aggregates;
using DFlow.Domain.BusinessObjects;
using DFlow.Tests.Supporting.DomainObjects.Commands;

namespace DFlow.Tests.Supporting.DomainObjects
{
public class EventBasedAggregateFactory:
IAggregateFactory<EventStreamBusinessEntityAggregateRoot, AddEntityCommand>,
IAggregateFactory<EventStreamBusinessEntityAggregateRoot, EventStream<EntityTestId>>
{
public EventStreamBusinessEntityAggregateRoot Create(AddEntityCommand command)
{
return new EventStreamBusinessEntityAggregateRoot(command.Name,
command.Mail,
VersionId.New());
}

public EventStreamBusinessEntityAggregateRoot Create(EventStream<EntityTestId> source)
{
return new EventStreamBusinessEntityAggregateRoot(source);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ namespace DFlow.Tests.Supporting.DomainObjects
{
public sealed class EventStreamBusinessEntityAggregateRoot:EventBasedAggregationRoot<EntityTestId>
{
private EventStreamBusinessEntityAggregateRoot(EntityTestId aggregationId, Name name, Email email, VersionId version)
:base(aggregationId,version, AggregationName.From(nameof(EventStreamBusinessEntityAggregateRoot)))
internal EventStreamBusinessEntityAggregateRoot(Name name, Email email, VersionId version)
:base(EntityTestId.GetNext(),version, AggregationName.From(nameof(EventStreamBusinessEntityAggregateRoot)))
{
if (name.ValidationStatus.IsValid && email.ValidationStatus.IsValid)
{
var change = TestEntityAggregateAddedDomainEvent.From(aggregationId, name, email, version);
var change = TestEntityAggregateAddedDomainEvent.From(AggregateId, name, email, version);
Apply(change);

// it is always new
Expand All @@ -23,7 +23,7 @@ private EventStreamBusinessEntityAggregateRoot(EntityTestId aggregationId, Name
AppendValidationResult(email.ValidationStatus.Errors.ToImmutableList());
}

private EventStreamBusinessEntityAggregateRoot(EventStream<EntityTestId> eventStream)
internal EventStreamBusinessEntityAggregateRoot(EventStream<EntityTestId> eventStream)
: base(eventStream.AggregationId, eventStream.Version,
AggregationName.From(nameof(EventStreamBusinessEntityAggregateRoot)))
{
Expand All @@ -43,16 +43,5 @@ public void UpdateName(EntityTestId aggregateId, Name name)

AppendValidationResult(name.ValidationStatus.Errors.ToImmutableList());
}

public static EventStreamBusinessEntityAggregateRoot Create(EntityTestId aggregateId, Name name, Email email)
{
return new EventStreamBusinessEntityAggregateRoot(aggregateId, name, email, VersionId.New());
}

public static EventStreamBusinessEntityAggregateRoot ReconstructFrom(EventStream<EntityTestId> eventStream)
{
return new EventStreamBusinessEntityAggregateRoot(EventStream<EntityTestId>.From(eventStream.AggregationId,
eventStream.Name,VersionId.Next(eventStream.Version), eventStream.Events));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (C) 2020 Road to Agility
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

using DFlow.Domain.Aggregates;
using DFlow.Domain.BusinessObjects;
using DFlow.Tests.Supporting.DomainObjects.Commands;

namespace DFlow.Tests.Supporting.DomainObjects
{
public class ObjectBasedAggregateFactory:
IAggregateFactory<BusinessEntityAggregateRoot, AddEntityCommand>,
IAggregateFactory<BusinessEntityAggregateRoot, BusinessEntity>
{
public BusinessEntityAggregateRoot Create(AddEntityCommand command)
{
return new BusinessEntityAggregateRoot(BusinessEntity.New());
}

public BusinessEntityAggregateRoot Create(BusinessEntity source)
{
return new BusinessEntityAggregateRoot(source);
}
}
}
Loading

0 comments on commit 71d014d

Please sign in to comment.