The commonly known advise in DDD is that an Aggregate Roots don't user a domain service. The domain service is to coordinate two Aggregate Roots to achieve a behavior.
It really surprised me when I saw this blog written by Rinat Abdullin with the title Building Blocks Of CQRS. Under the Domain Service section, you will read that a domain service is injected to an Aggregate Root.
Can an Aggregate Root accept a domain service?
Please, disregard that article. It was written a long time ago and is plain wrong. If implementing a module with AggregateRoot and DomainService patterns, I would recommend to have a higher logic (e.g. request handler) which is responsible for:
Loading the aggregate
Performing calculations with the help of domain services
Mutating the aggregate state accordingly.
In a way yes. If the AR really needs a service to do some of its job, then you can inject it as a method argument. If the AR needs a service for most of its behavior then probably it's modeled incorrectly.
I find the following explanation quite good. It's based on the book by Vaughn Vernon and 'injects' the domain service in the domain model through the method call that actually needs this service.
public class PurchaseOrder
{
public string Id { get; private set; }
public string VendorId { get; private set; }
public string PONumber { get; private set; }
public string Description { get; private set; }
public decimal Total { get; private set; }
public DateTime SubmissionDate { get; private set; }
public ICollection<Invoice> Invoices { get; private set; }
public decimal InvoiceTotal
{
get { return this.Invoices.Select(x => x.Amount).Sum(); }
}
public bool IsFullyInvoiced
{
get { return this.Total <= this.InvoiceTotal; }
}
bool ContainsInvoice(string vendorInvoiceNumber)
{
return this.Invoices.Any(x => x.VendorInvoiceNumber.Equals(
vendorInvoiceNumber, StringComparison.OrdinalIgnoreCase));
}
public Invoice Invoice(IInvoiceNumberGenerator generator,
string vendorInvoiceNumber, DateTime date, decimal amount)
{
// These guards maintain business integrity of the PO.
if (this.IsFullyInvoiced)
throw new Exception("The PO is fully invoiced.");
if (ContainsInvoice(vendorInvoiceNumber))
throw new Exception("Duplicate invoice!");
var invoiceNumber = generator.GenerateInvoiceNumber(
this.VendorId, vendorInvoiceNumber, date);
var invoice = new Invoice(invoiceNumber, vendorInvoiceNumber, date, amount);
this.Invoices.Add(invoice);
DomainEvents.Raise(new PurchaseOrderInvoicedEvent(this.Id, invoice.InvoiceNumber));
return invoice;
}
}
public class PurchaseOrderService
{
public PurchaseOrderService(IPurchaseOrderRepository repository,
IInvoiceNumberGenerator invoiceNumberGenerator)
{
this.repository = repository;
this.invoiceNumberGenerator = invoiceNumberGenerator;
}
readonly IPurchaseOrderRepository repository;
readonly IInvoiceNumberGenerator invoiceNumberGenerator;
public void Invoice(string purchaseOrderId,
string vendorInvoiceNumber, DateTime date, decimal amount)
{
// Transaction management, along with committing the unit of work
// can be moved to ambient infrastructure.
using (var ts = new TransactionScope())
{
var purchaseOrder = this.repository.Get(purchaseOrderId);
if (purchaseOrder == null)
throw new Exception("PO not found!");
purchaseOrder.Invoice(this.invoiceNumberGenerator,
vendorInvoiceNumber, date, amount);
this.repository.Commit();
ts.Complete();
}
}
}
It's very hard to inject anything into domain objects, and doing so is quite technology specific. In java it requires compile time weaving of aspects into your domain classes. And although I could be mistaken on this, I think that most DDD leaders think that this is, generally, a bad idea. Both Evans and Vernon both actively discourage it, and I like to listen to them. For a full explanation, read Vernon.
Related
If we have a bounded context with lets say 2 aggregates where aggregate1 publishes event1 and aggregate2 wants to react to it, we have 1 ways of doing it:
in process raising event1 > aggregate2 reacting to it
publish event1 to message bus and have some separate process pick it up & invoke aggregate2 method(s)
regardless of being within the same bounded context, if we want to make sure we don't lose event1 (application crashes between aggregate1 is saved, and aggregate2 is saved in reaction to event1, e.g.) i have a hard time finding examples of when would option 1 be better than option 2 (beyond maybe validation)?
i must be missing something but at this point of my knowledge, it seems like a pure theoretical concept to me without some real world value in terms of reliability and ability to maintain correct state.
of course that publishing a message and having separate process listen/react to it might seem like an overkill but is there any practical use of domain events that are not persisted somewhere (even within local DB which gets polled in which case i'd call that a primitive message bus)?
what am i missing?
What is a real world application of domain events within a bounded
context and process?
Requirements:
User can create categories.
Category names must be unique.
User can rename categories.
(Category will have a number of other properties unrelated to naming).
DDD Concepts:
A Category aggregate should be responsible for its own internal invariants, but cannot know the details about other Category aggregates.
How are you going to ensure that the Category Name for the current Category is globally unique without the Category having access to all other categories?
Answer: Domain Events
DomainEvent
public CategoryRenamed : DomainEvent
{
public Category Category { get; }
internal CategoryRenamed(Category category)
{
this.Category = category;
}
}
DomainEventHandler
public CategoryRenamedHandler : IDomainEventHandler<CategoryRenamed>
{
public CategoryRenamedHandler(CategoryRenamed domainEvent)
{
string proposedName = domainEvent.Category.Name;
// query database to ensure that proposedName is not already in use
if (inUse)
throw new Exception($"Name {proposedName} already in use." ;
}
}
Entity
public abstract class Entity
{
List<DomainEvent> _domainEvents = new List<DomainEvent>();
protected AddDomainEvent(DomainEvent domainEvent)
{
_domainEvents.Add(domainEvent);
}
public List<DomainEvent> DomainEvents => _domainEvents;
}
Category
public class Category : Entity
{
public Guid Id { get; private set; }
public string Name { get; private set; }
public Category(Guid id, string name)
{
Id = id;
SetName(name);
}
public Rename(string name)
{
SetName(name);
}
void SetName(string name)
{
// Local Invariants
if (string.IsNullOrWhitespace(name))
throw new Exception("Invalid name");
Name = name;
// Add a domain event for the infrastructure to process
AddDomainEvent(new CategoryRenamed(this));
}
}
Command
public class AddCategoryCommand
{
public Guid Id { get; set; }
public string Name { get; set; }
}
CommandHandler
public class CommandHandler : ICommandHandler<AddCategoryCommand>
{
readonly ICategoryRepository _categoryRepository;
public CommandHandler(ICategoryRepository categoryRepository)
{
_categoryRepository = categoryRepository;
}
public void HandleCommand(AndCategoryCommand command)
{
Category newCategory = new(command.Id, command.Name);
// Check for domain events before committing to repository
DomainEventDispatcher.DispatchEvents(newCategory.DomainEvents);
// Dispatcher will find the CategoryRenamed event and send 'in-process'
// to CategoryRenamedHandler
// If name was is in use an error will be thrown by the handler (see above)
_categoryRepository.Add(newCategory);
}
}
Outcome
Your Category aggregate has enforced its own local invariants and the domain command and domainevent handling infrastructure has been leveraged to ensure uniqueness of name across all categories.
What I want to achieve is to figure out where to initialize my sub-collections with aggregate root itself and validate business rules in a best practice way.
Here is my AppService:
public async Task<ReservationDto> CreateReservationAsync(CreateReservationInputDto input)
{
var reservation = await _reservationSystemManager.CreateAsync(
input.ReserverNotes
);
//should i send them directly to manager's createasync method but RequestedItems are dto objects.
//should i iterate through RequestedItems here and send them to manager one by one.
// where to throw business exception if RequestedItems count is 0.
}
Here is my inputdto:
public class CreateReservationInputDto
{
public string ReserverNotes { get; set; }
public Enum.Status Status { get; set; }
public List<CreateReservationItemInputDto> RequestedItems { get; set; }
}
Here is my aggregate root:
public class Reservation : FullAuditedAggregateRoot<Guid>
{
public Enum.Status Status { get; private set; }
public string ReserverNote { get; private set; }
public ICollection<ReservationItem> ReservationItems { get; set; }
public ICollection<OverduePayment> OverduePayments { get; set; }
private Reservation() { }
internal Reservation(
Guid id,
Enum.Status status,
[NotNull] string reserverNote,
) : base(id)
{
ReserverNote = reserverNote;
Status = status;
ReservationItems = new Collection<ReservationItem>();
OverduePayments = new Collection<OverduePayment>();
}
//I could not decide where and how to call this function from Domain Service.
internal void AddReservationItem(ReservationItem reservationItem)
{
if (ReservationItems.Any(r => r.Id == reservationItem.Id))
{
return;
}
ReservationItems.Add(reservationItem);
}
}
Well, depends on your business rules and your use cases. For example, if a reservation must have some reservation items, then I would create it in reservation constructor. Otherwise, if after creating reservation I can add new reservation items then I would be another use case and then AddReservationItem has sense for me.
Generally, if you need to inject more than one service (E.g. IUserRepository and IReservationItemsRepository) for validating your collection or any other property, you can create a domain service and implement your business logic and validate your collection with your needs.
If you don't need to inject any service to implement your business rules you can do it directly in your application service methods. In such cases, you can use data annotations for validating your properties in DTO classes as stated in here.
//should i send them directly to manager's createasync method but RequestedItems are dto objects.
//should i iterate through RequestedItems here and send them to manager one by one.
//where to throw business exception if RequestedItems count is 0.
In these three questions you've asked, should take it separately.
For instance, If you create a domain service class, it could be better to throw an exception if the RequestedItems count is 0 in that class' method. (And you can call, your AddReservationItem method from the domain service's method in that case.)
You can also check the best-practices documents of ABP.
I am a bit confused with ServiceStack 'old' and 'new' API and need some clarification and best practices, especially with Request / Response DTO's and routing. I watched some courses on Pluralsight and have the first three books listet on servicestack.net in my electronic bookshelf.
I like to 'restify' an existing application which is built using DDD patterns which means I have a high level of abstraction. The client is WPF and follows the MVVM pattern. I have 'client side service', 'server side service' and repository classes (and some aggregates too). I use NHibernate 4 (with fluent API and a code-first approach) as ORM. Only my repository classes know about the ORM. I have DTO's for all my Entity objects and in my WPF client I only work with those DTOs in the ViewModel classes. I heavily use AutoMapper to 'transfer' Entity objects to my DTO's and vice versa.
My confusion starts exactly with these DTO's and the Request / Response DTOs used in ServiceStack. Here is a very much simplified example of an Address Entity which illustrates the problem:
All my Entity Objects derive from EntityBase which contains basic properties used in all Entities:
public abstract class EntityBase : IEntity
{
public virtual Guid Id { get; protected set; }
public virtual DateTime CDate { get; set; } //creation date
public virtual string CUser { get; set; } //creation user
public virtual DateTime MDate { get; set; } //last modification date
public virtual string MUser { get; set; } //last modification user
//
// some operators and helper methods irrelevant for the question
// ....
}
public class Address : EntityBase
{
public string Street { get; private set; }
public string AdrInfo1 { get; private set; }
public string AdrInfo2 { get; private set; }
public string ZipCode { get; private set; }
public string City { get; private set; }
public string Country { get; private set; }
}
Of course there are collections and references to related objects which are ignored here as well as database mappers, naming conventions etc. The DTO I have looks like this:
public class AddressDto
{
public Guid Id { get; set; } // NHibernate GUID.comb, NO autoincrement ints!!
public DateTime CDate { get; set; }
public string CUser { get; set; }
public DateTime MDate { get; set; }
public string MUser { get; set; }
public string Street { get; private set; }
public string AdrInfo1 { get; private set; }
public string AdrInfo2 { get; private set; }
public string ZipCode { get; private set; }
public string City { get; private set; }
public string Country { get; private set; }
}
To use this with ServiceStack I need to support the following:
CRUD functionality
Filter / search functionality
So my 'Address service' should have the following methods:
GetAddresses (ALL, ById, ByZip, ByCountry, ByCity)
AddAddress (Complete AddressDTO without Id. CDate, CUser are filled automatically without user input)
UpdateAddress (Complete AddressDTO without CUser and CDate, MDate and MUser filled automatically without user input)
DeleteAddress (Just the Id)
For me it is pretty clear, that all Requests return either a single AddressDto or a List<AddressDto> as ResponseDTO except for the delete which should just return a status object.
But how to define all those RequestDTO's? Do I really have to define one DTO for EACH scenario?? In the books I only saw samples like:
[Route("/addresses", "GET")]
public class GetAddresses : IReturn<AddressesResponse> { }
[Route("/addresses/{Id}", "GET")]
public class GetAddressById : IReturn<AddressResponse>
{
public Guid Id { get; set; }
}
[Route("/addresses/{City}", "GET")]
public class GetAddressByCity : IReturn<AddressResponse>
{
public string City { get; set; }
}
// .... etc.
This is a lot of boilerplate code and remembers me a lot of old IDL compilers I used in C++ and CORBA.....
Especially for Create and Update I should be able to 'share' one DTO or even better reuse my existing DTO... For delete there is probably not much choice....
And then the filters. I have other DTOs with a lot more properties. A function approach like used in WCF, RPC etc is hell to code...
In my repositories I pass an entire DTO and use a predicate builder class which composes the LINQ where clause depending on the properties filled. This looks something like this:
List<AddressDto> addresses;
Expression<Func<Address, bool>> filter = PredicateBuilder.True<Address>();
if (!string.IsNullOrEmpty(address.Zip))
filter = filter.And(s => s.Zip == address.Zip);
// .... etc check all properties and dynamically build the filter
addresses = NhSession.Query<Address>()
.Where(filter)
.Select(a => new AddressDto
{
Id = a.Id,
CDate = a.CDate,
//.... etc
}).ToList();
Is there anything similar I could do with my RequestDTO and how should the routing be defined?
A lot of questions raised here have been covered in existing linked answers below. The Request / Response DTOs are what you use to define your Service Contract, i.e. instead of using RPC method signatures, you define your contract with messages that your Service accepts (Request DTO) and returns (Response DTO). This previous example also walks through guidelines on designing HTTP APIs with ServicesStack.
Use of well-defined DTOs have a very important role in Services:
You want to ensure all types your Services return are in DTOs since this, along with the base url of where your Services are hosted is all that's required for your Service Consumers to know in order to consume your Services. Which they can use with any of the .NET Service Clients to get an end-to-end Typed API without code-gen, tooling or any other artificial machinery.
DTOs are what defines your Services contract, keeping them isolated from any Server implementation is how your Service is able to encapsulate its capabilities (which can be of unbounded complexity) and make them available behind a remote facade. It separates what your Service provides from the complexity in how it realizes it. It defines the API for your Service and tells Service Consumers the minimum info they need to know to discover what functionality your Services provide and how to consume them (maintaining a similar role to Header files in C/C++ source code). Well-defined Service contracts decoupled from implementation, enforces interoperability ensuring that your Services don't mandate specific client implementations, ensuring they can be consumed by any HTTP Client on any platform. DTOs also define the shape and structure of your Services wire-format, ensuring they can be cleanly deserialized into native data structures, eliminating the effort in manually parsing Service Responses.
Auto Queryable Services
If you're doing a lot of data driven Services I recommend taking a look at AutoQuery which lets you define fully queryable Services without an implementation using just your Services Request DTO definition.
BACKGROUND: I have a Person domain object. It is an aggregate root. I have included a portion of the class below.
I am exposing methods to perform the objects behaviors. For instance, to add a BankAccount I have the AddBankAccount() method. I have not included all the methods of the class but suffice to say that any public property must be updated using a method.
I am going to create an IPerson repository to handle the CRUD operations.
public interface IPersonRepository
{
void Save(Person p);
//...other methods
}
QUESTION: How do I tell the repository which fields need to be updated when we are updating an existing person? For example, If I add a bank account to an existing person how do I communicate this information to the repository when repository.Save() is called?
In the repository it is easy to determine when a new person is created, but when an existing person exists and you update fields on that person, i'm not sure how to communicate this to the repository.
I don't want to pollute my Person object with information about which fields are updated.
I could have separate methods on the repository like .UpdateEmail(), AddBankAccount() but that feels like overkill. I would like a simple .Save() method on the repository and it determines what needs to update in some manner.
How have others handled this situation?
I have searched the web and stackoverflow but haven't found anything. I must not be searching correctly because this seems like something simple when it comes to persistence within the DDD paradigm. I could also be way off on my understanding of DDD :-)
public class Person : DomainObject
{
public Person(int Id, string FirstName, string LastName,
string Name, string Email)
{
this.Id = Id;
this.CreditCards = new List<CreditCard>();
this.BankAccounts = new List<BankAccount>();
this.PhoneNumbers = new List<PhoneNumber>();
this.Sponsorships = new List<Sponsorship>();
}
public string FirstName { get; private set; }
public string LastName { get; private set; }
public string Name{ get; private set; }
public string Email { get; private set; }
public string LoginName { get; private set; }
public ICollection<CreditCard> CreditCards { get; private set; }
public ICollection<BankAccount> BankAccounts { get; private set; }
public ICollection<PhoneNumber> PhoneNumbers { get; private set; }
public void AddBankAccount(BankAccount accountToAdd, IBankAccountValidator bankAccountValidator)
{
bankAccountValidator.Validate(accountToAdd);
this.BankAccounts.Add(accountToAdd);
}
public void AddCreditCard(CreditCard creditCardToAdd, ICreditCardValidator ccValidator)
{
ccValidator.Validate(creditCardToAdd);
this.CreditCards.Add(creditCardToAdd);
}
public void UpdateEmail(string NewEmail)
{
this.Email = NewEmail;
}
There is an example of Repository interface from S#arp Architecture project. It is similar to PoEAA Data Mapper because it used to CRUD operations also.
public interface IRepositoryWithTypedId<T, IdT>
{
T Get(IdT id);
IList<T> GetAll();
IList<T> FindAll(IDictionary<string, object> propertyValuePairs);
T FindOne(IDictionary<string, object> propertyValuePairs);
T SaveOrUpdate(T entity);
void Delete(T entity);
IDbContext DbContext { get; }
}
As you can see, there is no update method for specific properties of an entity. The whole entity is provided as an argument into the method SaveOrUpdate.
When properties of your domain entity are being updated you should tell your Unit of Work that entity is 'dirty' and should be saved into storage (e.g. database)
You should not pollute your Person object with information about updated fields but it is needed to track information if entity is updated.
There might be methods of the class DomainObject which tell 'Unit of Work' if entity is 'new', 'dirty' or 'deleted'. And then your UoW itself might invoke proper repository methods - 'SaveOrUpdate' or 'Delete'.
Despite the fact that modern ORM Frameworks like NHibernate or EntityFramework have their own implementations of 'Unit of Work', people tend to write their own wrappers/ abstractions for them.
What I'm doing to solve this problem, is adding an interface to my domain objects:
interface IDirtyTracker {
bool IsDirty {get;}
void MarkClean();
void MarkDirty();
}
The base DomainObject class could implement IDirtyTracker, and then repositories etc. could use IsDirty to check if it's dirty or clean.
In each setter that makes a change:
void SetValue() {
this._value = newValue;
this.MarkDirty();
}
This does not give you fine grain checking, but it's a simple way to avoid some unnecessary updates at the repository level.
To make this a little easier, a GetPropertiesToIncludeInDirtyCheck method could be added, which would retrieve a list of properties which need to be checked.
interface IDirtyTracker {
IENumerable<Object> GetPropertiesToIncludeInDirtyCheck();
}
We have a class Event (it's actually named differently, but I'm just making abstraction):
public class Event
{
public string Name { get; set; }
public string Description { get; set; }
public EventType EventType { get; set; }
}
We need to build an instance of a Message class with this object, but depending on the EventType, we use a different builder:
switch (event.EventType)
{
case EventType.First:
message = FirstMessageBuilder.Build(event);
break;
case EventType.Second:
message = SecondMessageBuilder.Build(event);
break;
}
Do you think this is acceptable, or should we take the following approach:
Make an abstract class:
public class Event
{
public string Name { get; set; }
public string Description { get; set; }
public abstract Message BuildMessage();
}
Then derive two classes: class FirstMessage and class SecondMessage and make the domain objects responsible for building the message.
I hope it isn't too abstract. The bottom line is we need to transform one class to another. A simple mapper won't do, because there are properties with XML content and such (due to a legacy application making the events). Just accept what we're trying to do here.
The real question is: can a domain object be responsible for such a transformation, or would you not recommend it? I would avoid the ugly switch statement, but add complexity somewhere else.
Whilst I agree with Thomas, you might want to look at the following design patterns to see if they help you:
Vistor Pattern
Double-Dispatch Pattern
Builder Pattern
Strictly speaking, a domain object shouldn't be responsible for anything other than representing the domain. "Changing type" is clearly a technical issue and should be done by some kind of service class, to maintain a clear separation of concerns...
In order to gain the readability of
var message = eventInstance.AsMessage();
as well following the single responsibility principle, you could define AsMessage() as an extension method of the event type.
There are few possible solutions. To use abstract factory:
public interface IMessageFactory
{
Message Create();
}
public class FirstMessageFactory : IMessageFactory
{
public Message Create()
{
//...
}
}
public class SomeService
{
private readonly IMessageFactory _factory;
public SomeService(IMessageFactory factory)
{
_factory = factory;
}
public void DoSomething()
{
var message = _factory.Create();
//...
}
}
Now you can wire IoC container to right factory for requested service.
To use Assembler which makes the transformation:
public interface IAssembler<TSource, TDestination>
{
TDestination Transform(TSource source);
}
This is quite similar to factory pattern, but if you are dependent on EventType, its possible to do it like:
public interface IAssembler<TEventType>
{
object Transform(object source);
}
I would encapsulate the logic into a separate Factory/Builder class, and use an extension method on Event to call the builder.
This would give you the best of both worlds.