Let's say we have two aggregates:
public class Order : IAggregateRoot
{
public Address Address { get; private set; }
public int? BuyerId {get; private set}
public OrderStatus OrderStatus { get; private set; }
public string Description {get; private set;}
}
and
public class Buyer : IAggregateRoot
{
public string IdentityGuid { get; private set; }
public string Name { get; private set; }
public IEnumerable<PaymentMethod> PaymentMethods => _paymentMethods.AsReadOnly();
public bool IsActivated { get; private set; }
}
and we want to allow only activated user to create an order. Should this logic be inserted in domain service or in specification pattern like this (and how this will affect always valid domain model state):
interface ISpecification {
bool IsSatisfiedBy(Offer offer);
}
public class OrderSpecification : ISpecification {
private Buyer _buyer;
public OrderSpecification(Buyer buyer) =>
_buyer = buyer;
public bool IsSatisfiedBy(Order order) => buyer.IsActivated
...
}
and then in order
public Order(..., ISpecification spec) {
// field initialize and then
if (!spec.IsSatisfiedBy(this))
throw new OfferConstructionDomainException(...);
}