DDD: Create one aggregate root within another AR - domain-driven-design

Suppose that I have 2 aggregate roots (AR) in my domain and invoking some method on the 1st requires access to an instance of the 2nd. In DDD how and where should retrieval and creation of the 2nd AR happen?
Here's a contrived example TravelerEntity that needs access to a SuitcaseEntity. I'm looking for an answer that doesn't pollute the domain layer with infrastructure code.
public class TravelerEntity {
// null if traveler has no suitcase yet.
private String suitcaseId = ...;
...
// Returns an empty suitcase ready for packing. Caller
public SuitcaseEntity startTrip(SuitcaseRepository repo) {
SuitcaseEntity suitcase;
if (suitcaseId == null) {
suitcase = new SuitcaseFactory().create();
suitcase = repo.save(suitcase);
suitcaseId = suitcase.getId();
} else {
suitcase = repo.findOne(suitcaseId);
}
suitcase.emptyContents();
return suitcase;
}
}
An application layer service handling the start trip request would get the appropriate SuitcaseRepository implementation via DI, get the TravelerEntity via a TravelerRepository implementation and call its startTrip() method.
The only alternative I thought of was to move SuitcaseEntity management to a domain service, but I don't want to create the suitcase before starting the trip, and I don't want to end up with an anemic TravelerEntity.
I'm a little uncertain about one AR creating and saving another AR. Is this OK since the repo and factory encapsulate specifics about the 2nd AR? Is there a danger I'm missing? Is there a better alternative?
I'm new enough to DDD to question my thinking on this. And the other questions I found about ARs seem to focus on identifying them properly, not on managing their lifecycles in relation to one another.

Ideally TravelerEntity wouldn't manipulate a SuitcaseRepository because it shouldn't know about an external thing where suitcases are stored, only about its own internals. Instead, it could new up a SuitCase and add it to its internal [list of] suitcases. If you wanted that to work with ORMs without specifically adding the suitcase to the repository though, you'd have to store the whole suitcase object in TravelerEntity.suitcaseList and not just its ID, which conflicts with the "store references to other AR's as IDs" best practice.
Moreover, TravelerEntity.startTrip() returning a suitcase seems a bit artificial and unexplicit and you'll be in trouble if you need to return other entities created by startTrip(). So a good solution could be to have TravelerEntity emit a SuitcaseAdded event with the suitcase data in it once it has added the suitcase to its list. An application service could subscribe to the event, add the suitcase to SuitcaseRepository and commit the transaction, effectively saving both the new suitcase and the modified traveler to the database.
Alternatively, you could place startTrip() in a Domain Service instead of an Entity. There it might be more legit to use SuitcaseRepository since a domain service is allowed know about multiple domain entities and the overall domain process going on.

First of all persistence is not domain's job so i would get rid of all the repositories from the domain models and create a service that would use them.
Second of all you should rethink your design. Why a StartTrip method of a Traveller should return a SuitCase?
A Traveller either has or hasn't a suitcase. Once you have retrieved the Traveller you should already have their SuitCases too.
public class StartTripService {
public void StartTrip(int travellerId) {
var traveller = travellerRepo.Get(travellerId);
traveller.StartTrip();
}
}

Related

Use value object in command and event?

Can we use value object in command ?
Suppose I have a Shop (aggregate) in which there is one value object Address.
In the value object constructor Address ,I was put the some validation logic for address.
So if I am using that Address object in command (CreateShopCmd) , then it get validated at the making of command , but What I want or Read that validation should be present in command handler.
But problem is that , I have to put that validation again in command handler (Since validation is already present in it Address constructor) and if I am not putting that in command handler , then the validation will occur when I am making the Address object in event handler and assign to Shop aggregate(Which is incorrect)
So, please guide me.
Below are code example
#Aggregate
#AggregateRoot
public class Shop {
#AggregateIdentifier
private ShopId shopId;
private String shopName;
private Address address;
#CommandHandler
public Shop(CreateShopCmd cmd){
//Validation Logic here , if not using the Address in
// in cmd
//Fire an event after validation
ShopRegistredEvt shopRegistredEvt = new ShopRegistredEvt();
AggregateLifecycle.apply(shopRegistredEvt);
}
#EventSourcingHandler
public void on(ShopRegistredEvt evt) {
this.shopName = evt.getShopName();
//Validation happend here if not put in cmd at the time of making
//Address object - this is wrong
this.address = new Address(evt.getCity(),evt.getCountry(),evt.getZipCode())
}
}
public class CreateShopCmd{
private String shopId;
private String shopName;
private String city;
private String zipCode;
private String country;
}
public ShopCreatedEvent{
private String shopId;
private String shopName;
private String city;
private String zipCode;
private String country;
}
There is nothing conceptually wrong with using Value Objects in Commands or Events. However, you should use them with caution.
The structure of a Message may change over time. If you have used Value Object excessively inside your messages, it may become less clear how a change in one of the value objects changes the structure of different messages.
For Value Objects that represent a "common" concept, such as an Address, this is not so much of a problem. But as soon as the Value Objects become more domain-specific, this may come up as an issue.
This is a very good question and I have been thoroughly thinking about embedding value objects in commands or not. I came to the conclusion you should definitely not use Value Objects in commands:
Commands are part of the application layer, they are supposed to work as simple as possible, avoiding any typed objects, and work best using literal (think serialization). What happen when an external system wants to plugin on your hexagon (application layer) and send commands to your application, do they need your command library to be able to use the objects and the structure defined ? Hell no ! You don't want that, so keep command simple.
Another reason is, as DmitriBodiu said, VO contains business logic and validation, they belong to the domain layer, do not ever put them in commands. Application service will do the translation, and be responsible of throwing validation error to any non conforming commands at the client.
There is nothing wrong in your design, its actually how Vaughn Vernon (the author of Implementing Domain Driven Design - IDDD book) did in his repository, you might want to check the application layer at this link:
https://github.com/VaughnVernon/IDDD_Samples/blob/master/iddd_identityaccess/src/main/java/com/saasovation/identityaccess/application/IdentityApplicationService.java
Notice how he reconstruct every objects from flat commands to value object belonging to the domain layer:
#Transactional
public void changeUserContactInformation(ChangeContactInfoCommand aCommand) {
User user = this.existingUser(aCommand.getTenantId(), aCommand.getUsername());
this.internalChangeUserContactInformation(
user,
new ContactInformation(
new EmailAddress(aCommand.getEmailAddress()),
new PostalAddress(
aCommand.getAddressStreetAddress(),
aCommand.getAddressCity(),
aCommand.getAddressStateProvince(),
aCommand.getAddressPostalCode(),
aCommand.getAddressCountryCode()),
new Telephone(aCommand.getPrimaryTelephone()),
new Telephone(aCommand.getSecondaryTelephone())));
}
Commands must not contain business logic, so they cannot carry a value object.
I wouldn't suggest using Value Objects in commands. Cause your commands are part of the application layer, but Value Objects are kept in Domain Layer. You can use your ValueObjects in DomainEvens though. Because if domain model changes, modification of your domain event wouln't be that painful, cause the modification is done in the same bounded context. You should never use ValueObjects in integration events though.
Short answer: Have you ever thought about Integer, String, Boolean, etc.? Those are Value Objects, too. The only difference is, that you didn't create them yourself. Now try to build a Command without any Value Objects ;-)
Long answer:
In general I don't see any issue with Value Objects within Commands. As long as you follow a few simple guidelines:
The most important code in your application is your Domain Model. The Domain Model defines the data structures it expects for Command handling. This means: The only reason to change your Command Model is if your Domain Model requires this change. The same applies to your Value Objects: Value Objects only change if this change is required by your Domain Model. No exceptions!
Commands can in general fail either because of business constraints, or because of invalid data (or because of optimistic locking, or whatever).
As said above: Integers and Strings are Value Objects, too. If you only use basic types within your Command, it will already throw an exception if you try new SetAgeCommand(aggId, "foo"), because String cannot be assigned to int. The same applies if you don't provide an Aggregate ID to your UpdatePersonCommand. These are no business constraints, but instead very basic data and type validation. Your Command will never be created if you pass malformed data.
Now let's say you have a PersonAge Value Object. I doesn't matter where you construct this object, because in any case it must throw an Exception if you try to construct it with a negative number: -5 cannot be assigned to PersonAge - looks familiar? As long as you can make sure that your code created those Value Object instances, you can know for sure that they are valid.
Business rules should be checked by the Command Handler within your Domain Model. In general business constraints are specific to your Domain, and most often they rely on the data within your Aggregate. Take for example SendMoneyCommand. Your Money Value Object can validate if it's a valid currency, but it cannot validate if the user's bank account has enough money to execute the transaction. This is a business validation and it's part of your Domain Model.
And a word regarding Events: I'd suggest to only use very basic Value Objects inside your events. For example: String, Integer, Date, etc. Basically every kind of Value Object that will never change. The reason behind it: Business requirements can change. For example: Maybe your Domain Model requires your Address Value Object to change, and it's now required to provide geo-coordinates. Then this will implicitly change your NewAddressAddedEvent. But your already persisted Events didn't have this requirement, though you're unable to construct Address Value Objects from your past event data, because the new Address Value Object will throw an Exception if there are no geo-coordinates provided.
There are (at least) two solutions for this problem:
Versioned Events: After modifying your Address Value Object, you have now a NewAddressAddedEvent_Version2 which uses the new Address Value Object, and you have the old NewAddressAddedEvent which must use a backup copy of the old Address Value Object.
Write a Script that "repairs" your event database by adding geo-coordinates to every Event that uses the Address Value Object. So you can throw away the old NewAddressAddedEvent.
That's OK as long as the value objects are conceptually a part of your message contract, and not used in entities.
And if they are a part of your entity, don't expose them as public properties of your message or you'll be in soop.

DDD - Invalidating expirable

Currently diving into DDD and i've read most of the big blue book of Eric Evans. Quite interesting so far :)
I've been modeling some aggregates where they hold a collection of entities which expire. I've come up with a generic approach of expressing that:
public class Expirable<T>
{
public T Value { get; protected set; }
public DateTime ValidTill { get; protected set; }
public Expirable(T value, DateTime validTill)
{
Value = value;
ValidTill = validTill;
}
}
I am curious what the best way is to invalidate an Expirable (nullify or omit it when working in a set). So far I've been thinking to do that in the Repository constructor since that's the place where you access the aggregates from and acts as a 'collection'.
I am curious if someone has come up with a solution to tackle this and I would be glad to hear it :) Other approaches are also very welcome.
UPDATE 10-1-2013:
This is not DDD with the CQRS/ES approach from Greg Young. But the approach Evans had, since I just started with the book and the first app. Like Greg Young said, if you have to make good tables, you have to make a few first ;)
There are probably multiple ways to approach this, but I, personally, would solve this using the Specification pattern. Assuming object expiration is a business rule that belongs in the domain, I would have a specification in addition to the class you have written. Here is an example:
public class NotExpiredSpecification
{
public bool IsSatisfiedBy(Expirable<T> expirableValue)
{
//Return true if not expired; otherwise, false.
}
}
Then, when your repositories are returning a list of aggregates or when performing any business actions on a set, this can be utilized to restrict the set to un-expired values which will make your code expressive and keep the business logic within the domain.
To learn more about the Specification pattern, see this paper.
I've added a method to my abstract repository InvalidateExpirable. An example would be the UserRepository where I remove in active user sessions like this: InvalidateExpirable(x => x.Sessions, (user, expiredSession) => user.RemoveSession(expiredSession));.
The signature of InvalidateExpirable looks like this: protected void InvalidateExpirable<TExpirableValue>(Expression<Func<T, IEnumerable<Expirable<TExpirableValue>>>> selector, Action<T, Expirable<TExpirableValue>> remover). The method itself uses reflection to extract the selected property from the selector parameter. That property name is glued in a generic HQL query which will traverse over the set calling the remove lambda. user.RemoveSession will remove the session from the aggregate. This way the I keep the aggregate responsible for it's own data. Also in RemoveSession an domain event is raised for future cases.
See: https://gist.github.com/4484261 for an example
Works quite well sofar, I have to see how it works further down in the application though.
Have been reading up on DDD with CQRS/ES (Greg Young approach) and found a great example on the MSDN site about CQRS/ES: http://msdn.microsoft.com/en-us/library/jj554200.aspx
In this example they use the command message queue to queue a Expire message in the future, which will call the Aggregate at the specified time removing/deactivate the expirable construct from the aggregate.

Connecting the dots with DDD

I have read Evans, Nilsson and McCarthy, amongst others, and understand the concepts and reasoning behind a domain driven design; however, I'm finding it difficult to put all of these together in a real-world application. The lack of complete examples has left me scratching my head. I've found a lot of frameworks and simple examples but nothing so far that really demonstrates how to build a real business application following a DDD.
Using the typical order management system as an example, take the case of order cancellation. In my design I can see an OrderCancellationService with a CancelOrder method which accepts the order # and a reason as parameters. It then has to perform the following 'steps':
Verify that the current user has the necessary permission to cancel an Order
Retrieve the Order entity with the specified order # from the OrderRepository
Verify that the Order may be canceled (should the service interrogate the state of the Order to evaluate the rules or should the Order have a CanCancel property that encapsulates the rules?)
Update the state of the Order entity by calling Order.Cancel(reason)
Persist the updated Order to the data store
Contact the CreditCardService to revert any credit card charges that have already been processed
Add an audit entry for the operation
Of course, all of this should happen in a transaction and none of the operations should be allowed to occur independently. What I mean is, I must revert the credit card transaction if I cancel the order, I cannot cancel and not perform this step. This, imo, suggests better encapsulation but I don't want to have a dependency on the CreditCardService in my domain object (Order), so it seems like this is the responsibility of the domain service.
I am looking for someone to show me code examples how this could/should be "assembled". The thought-process behind the code would be helpful in getting me to connect all of the dots for myself. Thx!
Your domain service may look like this. Note that we want to keep as much logic as possible in the entities, keeping the domain service thin. Also note that there is no direct dependency on credit card or auditor implementation (DIP). We only depend on interfaces that are defined in our domain code. The implementation can later be injected in the application layer. Application layer would also be responsible for finding Order by number and, more importantly, for wrapping 'Cancel' call in a transaction (rolling back on exceptions).
class OrderCancellationService {
private readonly ICreditCardGateway _creditCardGateway;
private readonly IAuditor _auditor;
public OrderCancellationService(
ICreditCardGateway creditCardGateway,
IAuditor auditor) {
if (creditCardGateway == null) {
throw new ArgumentNullException("creditCardGateway");
}
if (auditor == null) {
throw new ArgumentNullException("auditor");
}
_creditCardGateway = creditCardGateway;
_auditor = auditor;
}
public void Cancel(Order order) {
if (order == null) {
throw new ArgumentNullException("order");
}
// get current user through Ambient Context:
// http://blogs.msdn.com/b/ploeh/archive/2007/07/23/ambientcontext.aspx
if (!CurrentUser.CanCancelOrders()) {
throw new InvalidOperationException(
"Not enough permissions to cancel order. Use 'CanCancelOrders' to check.");
}
// try to keep as much domain logic in entities as possible
if(!order.CanBeCancelled()) {
throw new ArgumentException(
"Order can not be cancelled. Use 'CanBeCancelled' to check.");
}
order.Cancel();
// this can throw GatewayException that would be caught by the
// 'Cancel' caller and rollback the transaction
_creditCardGateway.RevertChargesFor(order);
_auditor.AuditCancellationFor(order);
}
}
A slightly different take on it:
//UI
public class OrderController
{
private readonly IApplicationService _applicationService;
[HttpPost]
public ActionResult CancelOrder(CancelOrderViewModel viewModel)
{
_applicationService.CancelOrder(new CancelOrderCommand
{
OrderId = viewModel.OrderId,
UserChangedTheirMind = viewModel.UserChangedTheirMind,
UserFoundItemCheaperElsewhere = viewModel.UserFoundItemCheaperElsewhere
});
return RedirectToAction("CancelledSucessfully");
}
}
//App Service
public class ApplicationService : IApplicationService
{
private readonly IOrderRepository _orderRepository;
private readonly IPaymentGateway _paymentGateway;
//provided by DI
public ApplicationService(IOrderRepository orderRepository, IPaymentGateway paymentGateway)
{
_orderRepository = orderRepository;
_paymentGateway = paymentGateway;
}
[RequiredPermission(PermissionNames.CancelOrder)]
public void CancelOrder(CancelOrderCommand command)
{
using (IUnitOfWork unitOfWork = UnitOfWorkFactory.Create())
{
Order order = _orderRepository.GetById(command.OrderId);
if (!order.CanBeCancelled())
throw new InvalidOperationException("The order cannot be cancelled");
if (command.UserChangedTheirMind)
order.Cancel(CancellationReason.UserChangeTheirMind);
if (command.UserFoundItemCheaperElsewhere)
order.Cancel(CancellationReason.UserFoundItemCheaperElsewhere);
_orderRepository.Save(order);
_paymentGateway.RevertCharges(order.PaymentAuthorisationCode, order.Amount);
}
}
}
Notes:
In general I only see the need for a domain service when a command/use case involves the state change of more than one aggregate. For example, if I needed to invoke methods on the Customer aggregate as well as Order, then I'd create the domain service OrderCancellationService that invoked the methods on both aggregates.
The application layer orchestrates between infrastructure (payment gateways) and the domain. Like domain objects, domain services should only be concerned with domain logic, and ignorant of infrastructure such as payment gateways; even if you've abstracted it using your own adapter.
With regards to permissions, I would use aspect oriented programming to extract this away from the logic itself. As you see in my example, I've added an attribute to the CancelOrder method. You can use an intercepter on that method to see if the current user (which I would set on Thread.CurrentPrincipal) has that permission.
With regards to auditing, you simply said 'audit for the operation'. If you just mean auditing in general, (i.e. for all app service calls), again I would use interceptors on the method, logging the user, which method was called, and with what parameters. If however you meant auditing specifically for the cancellation of orders/payments then do something similar to Dmitry's example.

Ncqrs: How to raise an Event without having an Aggregate Root

Given I have two Bounded Contexts:
Fleet Mgt - simple CRUD-based supporting sub-domain
Sales - which is my CQRS-based Core Domain
When a CRUD operation occurs in the fleet management, an event reflecting the operation should be published:
AircraftCreated
AircraftUpdated
AircraftDeleted
etc.
These events are required a) to update various index tables that are needed in the Sales domain and b) to provide a unified audit log.
Question: Is there an easy way to store and publish these events (to the InProcessEventBus, I'm not using NSB here) without going through an AggregateRoot, which I wouldn't need in a simple CRUD context.
If you want to publish the event about something, this something probably is an aggregate root, because it is an externally identified object about a bundle of interest, otherwise why would you want to keep track of them?
Keeping that in mind, you don't need index tables (I understand these are for querying) in the sales BC. You need the GUIDs of the Aircraft and only lookups/joins on the read side.
For auditing I would just add a generic audit event via reflection in the repositories/unit of work.
According to Pieter, the main contributor of Ncqrs, there is no way to do this out of the box.
In this scenario I don't want to go through the whole ceremony of creating and executing a command, then loading an aggregate root from the event store just to have it emit the event.
The behavior is simple CRUD, implemented using the simplest possible solution, which in this specific case is forms-over-data using Entity Framework. The only thing I need is an event being published once a transaction occurred.
My solution looks like this:
// Abstract base class that provides a Unit Of Work
public abstract class EventPublisherMappedByConvention
: AggregateRootMappedByConvention
{
public void Raise(ISourcedEvent e)
{
var context = NcqrsEnvironment.Get<IUnitOfWorkFactory>()
.CreateUnitOfWork(e.EventIdentifier);
ApplyEvent(e);
context.Accept();
}
}
// Concrete implementation for my specific domain
// Note: The events only reflect the CRUD that's happened.
// The methods themselves can stay empty, state has been persisted through
// other means anyway.
public class FleetManagementEventSource : EventPublisherMappedByConvention
{
protected void OnAircraftTypeCreated(AircraftTypeCreated e) { }
protected void OnAircraftTypeUpdated(AircraftTypeUpdated e) { }
// ...
}
// This can be called from anywhere in my application, once the
// EF-based transaction has succeeded:
new FleetManagementEventSource().Raise(new AircraftTypeUpdated { ... });

DDD: keep a link to an entity inside an aggregate root, for reporting only

I'm refactoring a project using DDD, but am concerned about not making too many Entities their own Aggregate Root.
I have a Store, which has a list of ProductOptions and a list of Products. A ProductOption can be used by several Products. These entities seem to fit the Store aggregate pretty well.
Then I have an Order, which transiently uses a Product to build its OrderLines:
class Order {
// ...
public function addOrderLine(Product $product, $quantity) {
$orderLine = new OrderLine($product, $quantity);
$this->orderLines->add($orderLine);
}
}
class OrderLine {
// ...
public function __construct(Product $product, $quantity) {
$this->productName = $product->getName();
$this->basePrice = $product->getPrice();
$this->quantity = $quantity;
}
}
Looks like for now, DDD rules as respected. But I'd like to add a requirement, that might break the rules of the aggregate: the Store owner will sometimes need to check statistics about the Orders which included a particular Product.
That means that basically, we would need to keep a reference to the Product in the OrderLine, but this would never be used by any method inside the entity. We would only use this information for reporting purposes, when querying the database; thus it would not be possible to "break" anything inside the Store aggregate because of this internal reference:
class OrderLine {
// ...
public function __construct(Product $product, $quantity) {
$this->productName = $product->getName();
$this->basePrice = $product->getPrice();
$this->quantity = $quantity;
// store this information, but don't use it in any method
$this->product = $product;
}
}
Does this simple requirement dictates that Product becomes an aggregate root? That would also cascade to the ProductOption becoming an aggregate root, as Product has a reference to it, thus resulting in two aggregates which have no meaning outside a Store, and will not need any Repository; looks weird to me.
Any comment is welcome!
Even though it is for 'reporting only' there is still a business / domain meaning there. I think that your design is good. Although I would not handle the new requirement by storing OrderLine -> Product reference. I would do something similar to what you already doing with product name and price. You just need to store some sort of product identifier (SKU?) in the order line. This identifier/SKU can later be used in a query. SKU can be a combination of Store and Product natural keys:
class Sku {
private String _storeNumber;
private String _someProductIdUniqueWithinStore;
}
class OrderLine {
private Money _price;
private int _quantity;
private String _productName;
private Sku _productSku;
}
This way you don't violate any aggregate rules and the product and stores can be safely deleted without affecting existing or archived orders. And you can still have your 'Orders with ProductX from StoreY'.
Update: Regarding your concern about foreign key. In my opinion foreign key is just a mechanism that enforces long-living Domain relationships at the database level. Since you don't have a domain relationship you don't need the enforcement mechanism as well.
In this case you need the information for reporting which has nothing to do with the aggregate root.
So the most suitable place for it would be a service (could be a domain service if it is related to business or better to application service like querying service which query the required data and return them as DTOs customizable for presentation or consumer.
I suggest you create a statistics services which query the required data using read only repositories (or preferable Finders) which returns DTOs instead of corrupting the domain with query models.
Check this

Resources