Getting Additional Data for a Domain Entity - domain-driven-design

I have a domain Aggregate, call it "Order" that contains a List of OrderLines. The Order keeps track of the sum of the Amount on the Order Lines. The customer has a running "credit" balance that they can order from that is calculated by summing the history of their database transactions. Once they use up all the money in the "pool" they can't order any more products.
So every time a line is added to the order, I need to get to check how much is left in the pool and if the order pushes them over it. The amount in the pool is continually changing because other related customers are continually using it.
The question is, thinking in terms of DDD, how do I get that amount since I don't want to pollute my Domain Layer with DataContext concerns (using L2S here). Since I can't just query out to the database from the domain, how would I get that data so I can validate the business rule?
Is this an instance where Domain Events are used?

Your Order aggregate should be fully encapsulated. It therefore needs to be able to determine whether it's valid to add an item, i.e. whether or not the customer credit is exceeded. There are various ways to do this but they all depend on the Order repository returning a specific aggregate that knows how to do this particular thing. This will probably be a different Order aggregate from one you'd use for satisfying orders, for example.
You have to recognise, then capture in code, the fact that you're expecting the order to fulfil a particular role in this case, i.e. the role of adding additional line items. You do this by creating an interface for this role and a corresponding aggregate that has the internal support for the role.
Then, your service layer can ask your Order repository for an order that satisfies this explicit role interface and the repository thus has enough information about what you need to be able to build something that can satisfy that requirement.
For example:
public interface IOrder
{
IList<LineItem> LineItems { get; }
// ... other core order "stuff"
}
public interface IAddItemsToOrder: IOrder
{
void AddItem( LineItem item );
}
public interface IOrderRepository
{
T Get<T>( int orderId ) where T: IOrder;
}
Now, your service code would look something like:
public class CartService
{
public void AddItemToOrder( int orderId, LineItem item )
{
var order = orderRepository.Get<IAddItemsToOrder>( orderId );
order.AddItem( item );
}
}
Next, your Order class that implements IAddItemsToOrder needs a customer entity so that it can check the credit balance. So you just cascade the same technique by defining a specific interface. The order repository can call on the customer repository to return a customer entity that fulfils that role and add it to the order aggregate.
Thus you'd have a base ICustomer interface and then an explicit role in the form of an ICustomerCreditBalance interface that descends from it. The ICustomerCreditBalance acts both as a marker interface to your Customer repository to tell it what you need the customer for, so it can create the appropriate customer entity, and it has the methods and/or properties on it to support the specific role. Something like:
public interface ICustomer
{
string Name { get; }
// core customer stuff
}
public interface ICustomerCreditBalance: ICustomer
{
public decimal CreditBalance { get; }
}
public interface ICustomerRepository
{
T Get<T>( int customerId ) where T: ICustomer;
}
Explicit role interfaces give repositories the key information they need to make the right decision about what data to fetch from the database, and whether to fetch it eagerly or lazily.
Note that I've put the CreditBalance property on the ICustomerCreditBalance interface in this case. However, it could just as well be on the base ICustomer interface and ICustomerCreditBalance then becomes an empty "marker" interface to let the repository know that you're going to be querying the credit balance. It's all about letting the repository know just what role you want for the entity it returns.
The final part which brings this all together, as you mentioned in your question, is domain events. The order can raise a failure domain event if the customer's credit balance would be exceeded, to notify the service layer that the order is invalid. If the customer has enough credit, on the other hand, it can either update the balance on the customer object or raise a domain event to notify the rest of the system that the balance needs to be reduced.
I've not added the domain event code to the CartService class since this answer is already rather long! If you want to know more about how to do that, I suggest you post another question targeting that specific issue and I'll expand on it there ;-)

In such a scenario, I off-load responsibility using events or delegates. Maybe the easiest way to show you is with some code.
Your Order class will have a Predicate<T> that is used to determine if the customer's credit line is big enough to handle the order line.
public class Order
{
public Predicate<decimal> CanAddOrderLine;
// more Order class stuff here...
public void AddOrderLine(OrderLine orderLine)
{
if (CanAddOrderLine(orderLine.Amount))
{
OrderLines.Add(orderLine);
Console.WriteLine("Added {0}", orderLine.Amount);
}
else
{
Console.WriteLine(
"Cannot add order. Customer credit line too small.");
}
}
}
You will probably have a CustomerService class or something like that to pull the available credit line. You set the CanAddOrderLine predicate before adding any order lines. This will perform a check of the customer's credit each time a line is added.
// App code.
var customerService = new CustomerService();
var customer = new Customer();
var order = new Order();
order.CanAddOrderLine =
amount => customerService.GetAvailableCredit(customer) >= amount;
order.AddOrderLine(new OrderLine { Amount = 5m });
customerService.DecrementCredit(5m);
No doubt your real scenario will be more complicated than this. You may also want to check out the Func<T> delegate. A delegate or event could be useful for decrementing the credit amount after the order line is placed or firing some functionality if the customer goes over their credit limit in the order.
Good luck!

In addition to the problem of getting the "pool" value (where I would query the value using a method on an OrderRepository), have you considered the locking implications for this problem?
If the "pool" is constantly changing, is there a chance that someone elses transaction creeps in just after your rule passes, but just before you commit your changes to the db?
Eric Evans refers to this very problem in Chapter 6 of his book ("Aggregates").

Related

Aggregate or entity without business attributes

Regarding below excerpt, concerning cqrs and ddd, from Patterns, Principles, and Practices of Domain-Driven Design by Nick Tune, Scott Millett
Does it mean that domain model on command side can omit most of business attributes ?
How would it look like for eg Customer Entity?
Could Customer entity omit FirstName, Surname etc?
If so, where would these business attributes be? Only in read model in CustomerEntity?
Or maybe apart from CustomerEntity containing all business attributes there would also be CustomerAggregate wrapping CustomerEntity with 1:1 relation, and command object would operate on CustomerAggregate? (seems strange to me).
What does it mean "Customer entity desn't make sense"?
The text you pointed means that you do not have to model a reusable Entity for your whole system or even for your whole bounded context (Do not model reusable real life things). Doing this is a bad design.
You have to model an Aggregate that performs an action. You feed the Aggregate with only, and just only, the data needed to perform that action and the aggregate response, the changes the domain suffered, is what you have to persist.
Why Entities and V.O.'s then?
To model consistency, encapsulation and decoupling is the basic part but these are implementation details. For DDD what matters is that are different roles (or concepts).
When feeding the aggregate (constructor, function call parameters, etc) the aggregate has to know if it is working with entities and/or with V.O. to build its response.
If the domain action means a change in an attribute of a entity (something with unique identification in your whole system) the response of the aggregate (once all rules and invariants has been checked) should include the new attribute value and the identification of that entity that allows persist the changes.
So, by default, every aggregate has its own entity with the unique identification and the attributes needed for the aggregate action.
One aggregate could have a Customer entity with ID and its Name.
Another aggregate could have a Customer entity with ID and its Karma points.
So every aggregate has its own inner Customer entity to work with. When you feed an aggregate you pass Customer data (i.e. ID and name or ID and Karma points) and the aggregate treats that info as a entity (It is a matter of implementation details if there is a struct, class, etc internally to the aggregate to represent the entity).
One important thing: If you just need to deal with entities ID's then treat it as a V.O. (CustomerIdentityVO) because the ID is immutable and, probably, in that action you just need to write this CustomerIdentityVO in some field in persistence, not change any Customer attribute.
This is the standard vision. Once you start to identify common structures relevant to several aggregates or one aggregate that can perform several actions with the same data fed you start to refactoring, reusing, etc. It just a matter of good OOP design and SOLID principles.
Please, note that I am trying to be higly above of implementation details. I know that you almost always will have unwanted artifacts that depends of programing paradigm type, chosen programing language, etc. but this approach helps a lot avoiding the worse artifact you could have.
Recommended readings:
http://blog.sapiensworks.com/post/2016/07/29/DDD-Entities-Value-Objects-Explained
http://blog.sapiensworks.com/post/2016/07/14/DDD-Aggregate-Decoded-1
http://blog.sapiensworks.com/post/2016/07/14/DDD-Aggregate-Decoded-2
https://blog.sapiensworks.com/post/2016/07/14/DDD-Aggregate-Decoded-3
and
https://blog.sapiensworks.com/post/2016/08/19/DDD-Application-Services-Explained
for a complete puzzle vision.
If you are using Event Sourcing then it's true that you can model aggregates without adding attributes that they don't need for implementing the business logic.
Here's an example:
class Customer {
public Guid ID { get; private set; }
public Customer(Guid id, firstName, lastName, ...) {
ID = id;
this.AddEvent(new CustomerCreatedEvent(id, firstName, ....);
}
public void ChangeName(firstName, lastName) {
this.AddEvent(new CustomerRenamedEvent(this.ID, firstName, lastName),
}
}
Custom only has ID attribute because it needs it to add it to every event that it generates. FirstName and LastName are omitted as they are not needed even when ChangeName method is called. It only records an event that this happened. If your logic requires the FirstName then you can add it. You can omit any properties that you don't need.
Your Repository in this case will save only the events and won't care about the values of the attributes of the Customer.
On the Read side you will probably need these properties as you will display them to your users.
If your aggregates are not event sourced, then you probably will need more attributes on your aggregate to implement it's logic and they will be saved to the database.
Here's an example:
class Customer {
public Guid ID { get; private set; }
public string FirstName { get; private set; }
public string LastName { get; private set; }
public void ChangeName(firstName, lastName) {
FirstName = firstName;
LastName = lastName;
}
}
In this case your Repository will need these properties as it will generate a query to update the database with the new values.
Not sure what "Customer entity doesn't make sense" means.

DDDD: Event data

I'm trying to get my head around DDDD in Greg Young's style.
There is much talk about how to implement DDDD with CQRS+EventSourcing and there are some sample implementations ... and altogether it can be quite confusing...
In Gregs view aggregates don't have getters or setters - just state-changing methods which emit an corresponding event.
Basicly a event decribes a state-transitions that happend in the past. It's data describes what changed.
Some say, that this data can be "enriched" by additional data.
Where can this additional data come from?
i.e. I have User and Usergroup - both aggregate roots (can exist independently, have identity). User has a method called AddToUsergroup.
public class User : AggregateRoot
{
// ...
public void AddToUsergroup(Usergroup usergroup)
{
// validate state
RaiseEvent(new UserJoinedUsergroup(this.Id, usergroup.Id));
}
// ...
}
public class Usergroup : AggregateRoot
{
private string _displayName;
// ...
public void ChangeDisplayName(string displayName)
{
// validate state
RaiseEvent(new DisplayNameChanged(this.Id, displayName));
}
public void Apply(DisplayNameChanged e)
{
this._displayName = e.DisplayName;
}
// ...
}
If I would like to "enrich" the event with the name of the Usergroup (for debug reasons or something like this), how would I do that?
getters are nonexistent
internal state of usergroup is inaccessible
Injecting such things as repositories into User is not allowed (am I right here?!?), like
Read-side repository
Event-store repository
Bottomline questions:
Can Should something like repositories be injected to aggregate roots?
Should a event only use data available through parameters and internal state of the aggregate?
Should events only contain the minimum data describing the state-change?
And (little off-topic but the sample is here)
Should AddToUsergroup take an Guid instead of an full aggregate root?
Looking forward to your answers!
Lg
warappa
Should something like repositories be injected to aggregate roots?
No and there is no need to in this case. It can be appropriate to pass a domain service to a behavioral method on an aggregate, but again, not needed in this case.
Should a event only use data available through parameters and internal
state of the aggregate?
Yes, the original domain event should be such that it can be easily built by the aggregate and can be replayed in a deterministic fashion.
Should events only contain the minimum data describing the
state-change?
Yes. However, to address requirements of external subscribers, this is where content enricher comes into play. To dispatch a domain event externally, it is first committed to the event store then you can dispatch in the same tx or have an out of process mechanism which publishes events externally. At the point of publishing externally, you will normally use a different contract for the message since subscribers may need more than what is on the domain event itself. In this case, you need the user group name. The publisher, then, can pull up the user group name and place that data into the enriched event. This publisher can have access to a read-model repository for user groups which would allow it to retrieve the name.
Should AddToUsergroup take an Guid instead of an full aggregate root?
Yes. Passing the entire aggregate may not be possible and also creates the illusion that something other than the ID may be used, which should not be the case.

DDD class design dilemma with Value Objects with DB id and Entities

This is a long question so i am gonna go straight to the point. This is pseudo code for better illustration of the problem
DB Structure
User (UserID, Name, LastName)
Address(AddressID, UserID, Street, City, State, ZipCode) =>Many to One User relationship
Phone (PhoneID, UserID, Number, IsPrimary) =>Many to One User relationship
Domain Classes
class User:IEntity
{
public string Name {get;set;}
public string LastName {get;set;}
public ContactInfo{get;set;}
}
class Phone: IValueObject or IEntity? will see later.
{
public int id; // persistence ID, not domain ID
public string Number {get;set;}
}
class Address: IValueObject or IEntity? will see later.
{
public string Line1 {get;set;}
public string City {get;set;}
public string State {get;set;}
public string ZipCode {get;set;}
}
class ContactInfo: IValueObject or IEntity? will see later.
{
List<Address> Addresses {get;set;}
List<Phone> PhoneNumbers {get;set;}
}
So, so far we have a very basic representation of this domain and its models.
My question is the following. Let's say that i want to Update one of the addreses or fix the area code for one of the numbers because of misspelling wnen it was initially typed in.
If i follow Evan's bible about DDD, Value Objects should be immutable. Meaning, no changes to its properties or fields after it was created.
If that's the case, then i guess, none of my classes are a ValueObject, since i can't just recreate the whole ContactInfo class just because one portion of the string in the phone number is wrong. So, i guess that makes all my classes Entities?
Keep in mind that i have a "persistence id" for each of this classes since they are stored in a database.
Let's say that i decide to make Phone a value object, since it's easy to recreate in the constructor
public Phone(string newNumber)
so, it would be something like adding a method to User (agg root) AND contactinfo? (Demeter Law)
like...
User....
public void UpdatePrimaryPhoneNumber(string number)
{
this.ContactInfo.UpdatePrimaryPhoneNumber(number);
}
ContactInfo....
public void UpdatePrimaryPhoneNumber(string number)
{
var oldPhone = Phones.Where(p=>p.IsPrimary).Single();
var newPhone = new Phone(number, oldPhone.persistenceid???-> this is not part of the domain)
oldPhone = newPhone;
}
but i still have to deal with persistence id... grrrrr. what a headache.
Sometimes i feel when i read those blogs that most "ddd experts" that value objects are overused or i would say misused.
What would be the best solution to this scenario?
Thank you
If i follow Evan's bible about DDD, Value Objects should be immutable.
Meaning, no changes to its properties or fields after it was created.
If that's the case, then i guess, none of my classes are a
ValueObject, since i can't just recreate the whole ContactInfo class
just because one portion of the string in the phone number is wrong.
So, i guess that makes all my classes Entities?
While the VO itself may be immutable, a VO doesn't exist on its own - it is always part of an aggregate. Therefore, a VO can be immutable, but the object which references that VO doesn't have to be. What helped me understand VOs is to compare them to something like a primitive Int32 value. The value of each individual integer is immutable - a 5 is always a 5. But anywhere you have an Int32 you can set another value there.
For you domain, what that means is that you can have an immutable address VO, but a given use entity can reference any instance of an address VO. This is what will allow corrections and any other changes to be made. You don't change the individual fields on the address VO - you replace it with a whole new VO instance.
Next, "Persistence ids" shouldn't be expressed in anywhere in domain code. They exist solely to satisfy the needs of the relational databases and NoSQL databases don't require them at all.
The primary phone scenario should look more like this:
public void UpdatePrimaryPhoneNumber(string number)
{
var existingPrimaryNumber = this.Phones.FirstOrDefault(x => x.IsPrimary == true);
if (existingPrimaryNumber != null)
this.Phones.Remove(existingPrimaryNumber);
this.Phones.Add(new Phone(phoneNumber: number, isPrimary = true));
}
This method encapsulates the idea of updating an existing primary phone number. The fact that phone number VOs are immutable means that you have to remove an existing value and replace it with a new one. What usually happens on the database end, especially with ORMs like NHibernate, is it will issue a SQL delete and a subsequent insert to effectively replace all phone numbers. This is OK since the ID of the VOs doesn't matter.
An Entity has a rather unique and individual life-cycle. It has meaning when it stands alone.
The classic example of Order/OrderItem may help with this.
If an OrderItem becomes an Entity it would have a life-cycle of its own. However, this doesn't make too much sense since it is part of an Order. This always seems obvious when looking at an order but less so when looking at your own classes because there can be some references between classes. For instance, an OrderItem represents some Product that we are selling. A Product has a life-cycle of its own. We can have an independent list of Products. How we model the link between an OrderItem and the Product is probably another discussion but I would denormalize the Product data I require into the OrderItem and store the original Product.Id also.
So is the Address class an Entity or a Value Object? This is always an interesting one in that we have that favourite of answers: it depends.
It will be context-specific. But ask yourself whether you have (or need) an independent list of Addresss and then only have a need for the link to that Address in your User. If this is the case then it is an Entity. If, however, your Address makes sense only when it is part of your User then it is a Value Object.
The fact that a Value Object is immutable does not mean you need to replace more than just the specific Value Object. I don't know if I would have a ContactInfo class in your current design since it only wraps the two collections (Address/PhoneNumber) but I would keep it if there is more to it (probably is). So simply replace the relevant PhoneNumber. If you have something like primary/secondary then it is as simple as:
AR.ReplacePrimaryPhoneNumber(new PhoneNumber('...'))
If it is a list of arbitrary numbers then a Remove/Add would be appropriate.
Now for the persistence Id. You do not need one. When you have a primary/secondary scenario you know what your use case is and you can execute the relevant queries in your DB (to update the primary PhoneNumber, for instance). If you have an arbitrary list you may go for add all new numbers in my list and delete those numbers from the DB not in my list; else just delete all the numbers and add everything you have. If this seems like a lot of heavy movement: it is. Event sourcing would move a lot of this to in-memory processing and it is something I will be pushing for seriously going forward.
I hope this all makes sense. Getting away from focusing on the data side of things is rather difficult but necessary. Focus on the domain as though you have no database. When you find friction then do your utmost to not pull database thinking into your domain but try to think about ways you could keep your domain clean and still use your DB of choice.
I would create a class PhoneNumber which contains the String number of the current Phone class and use that as a Value object within your Phone class:
class Phone implements IEntity
{
public int id; // persistence ID, not domain ID
public PhoneNumber number {get;set;}
}
class PhoneNumber implements IValueObject
{
public String number {get;set;};
}
Later when your code evolves you will need (for example) phone number validation and you can put it in the PhoneNumber class. This class can then be reused over the whole application at different places.
The Address is in my opinion a Value object which you can treat like a whole. Although you could model Street, City, etc... which are normally entities, but this is probably over-modelling. No part of the address can change, the whole object is always replaced when changing after initial creation.
The User class is within this example with these boundaries an Aggregate root (and thus also an Entity).
The ContactInfo class is not a ValueObject (not immutable) and not an Entity (no real identity) but an Aggregate. It contains multiple classes which should be seen as a whole.
More info on http://martinfowler.com/bliki/DDD_Aggregate.html
Usually whenever a persistence id is there you should be thinking of an Entity.
If however you would want to add the persistence id's, I would start splitting like the Phone and PhoneNumber class. For example Address (Entity containing id) and AddressValue containing all the other fields (and logic about address values).
This should also solve the headache about managing the persistence identities, since you replace the whole value object and the persistence identity stays the same in case of the updatePrimaryPhoneNumber.

Should I add item using repository pattern or a create event if I am using domain events?

I am trying to understand the Domain Event pattern illustrated by Udi Dahan with regard to adding new domain entities in a certain situation.
Now normally with entities I would create them and then add them via repository. I assume I would still do this?
My example is we normally add assets to the system. Like this:
var asset= new Asset();
/*bunch of prop setting*/
_assetRepository.Add(asset);
However asset creation is an event that we want to follow certain processes as a result of. Therefore it was suggested by developer we no longer need to do this as it could be handled by domain event:
var asset= new Asset();
/*bunch of prop setting*/
asset.Create(location);
Now a create method would raise an event and be handled by a create event handler that basically just inserts it into the repo and does some other stuff email the warehouse manager of the create location etc.
However having a create event on the asset looks pretty active record to me. However in the domain people talk about new assets being created. So we were not sure.
Thoughts?
The created domain event should be raised in the constructor of the Asset class because that is when that particular entity is created. In your current implementation, this would be erroneous because the Asset entity provides a parameterless constructor. Instead, create a constructor which has all required properties as parameters thereby preventing creation of an Asset entity in an inconsistent state. It could look like this:
public class Asset
{
public Asset(string prop1, decimal prop2)
{
this.Prop1 = prop1;
this.Prop2 = prop2;
DomainEvents.Raise(new AssetCreated(prop1, prop2));
}
public string Id { get; private set; }
public string Prop1 { get; private set; }
public decimal Prop2 { get; private set; }
}
You still have to persist the entity using the repository after creating it. This can be problematic because the handlers for the AssetCreated cannot reference its ID since it is not yet assigned when they are notified. If using event sourcing, then the creation event would be explicitly stored in the underlying event store.
I've been struggling for this problem for quite a long time. But no good solution. I think,
A domain event shouldn't be published or handled before the aggregate it belongs to being successfully persisted
It's not the application layer's responsibility to publish any domain events
So far, I think the best approach is to take advantage of AOP. We can "fire" events in the aggregate, but instead of dispatching them instantly, we keep it in a queue, and really dispatch it after the corresponding transaction successes. We can define a custom #Transactional interceptor to achieve this, thus keeping the app service from knowning any concept of "event publishing".

Domain Driven Design: Repository per aggregate root?

I'm trying to figure out how to accomplish the following:
User can have many Websites
What I need to do before adding a new website to a user, is to take the website URL and pass it to a method which will check whether the Website already exist in the database (another User has the same website associated), or whether to create a new record. <= The reason for this is whether to create a new thumbnail or use an existing.
The problem is that the repository should be per aggregate root, which means I Cant do what I've Explained above? - I could first get ALL users in the database and then foreach look with if statement that checks where the user has a website record with same URL, but that would result in an endless and slow process.
Whatever repository approach you're using, you should be able to specify criteria in some fashion. Therefore, search for a user associated with the website in question - if the search returns no users, the website is not in use.
For example, you might add a method with the following signature (or you'd pass a query object as described in this article):
User GetUser(string hasUrl);
That method should generate SQL more or less like this:
select u.userId
from User u
join Website w
on w.UserId = u.UserId
where w.Url = #url
This should be nearly as efficient as querying the Website table directly; there's no need to load all the users and website records into memory. Let your relational database do the heavy lifting and let your repository implementation (or object-relational mapper) handle the translation.
I think there is a fundamental problem with your model. Websites are part of a User aggregate group if I understand correctly. Which means a website instance does not have global scope, it is meaningful only in the context of belonging to a user.
But now when a user wants to add a new website, you first want to check to see if the "website exists in the database" before you create a new one. Which means websites in fact do have a global scope. Otherwise anytime a user requested a new website, you would create a new website for that specific user with that website being meaningful in the scope of that user. Here you have websites which are shared and therefore meaningful in the scope of many users and therefore not part of the user aggregate.
Fix your model and you will fix your query difficulties.
One strategy is to implement a service that can verify the constraint.
public interface IWebsiteUniquenessValidator
{
bool IsWebsiteUnique(string websiteUrl);
}
You will then have to implement it, how you do that will depend on factors I don't know, but I suggest not worrying about going through the domain. Make it simple, it's just a query (* - I'll add to this at the bottom).
public class WebsiteUniquenessValidator : IWebsiteUniquenessValidator
{
//.....
}
Then, "inject" it into the method where it is needed. I say "inject" because we will provide it to the domain object from outside the domain, but .. we will do so with a method parameter rather than a constructor parameter (in order to avoid requiring our entities to be instantiated by our IoC container).
public class User
{
public void AddWebsite(string websiteUrl, IWebsiteUniquenessValidator uniquenessValidator)
{
if (!uniquenessValidator.IsWebsiteUnique(websiteUrl) {
throw new ValidationException(...);
}
//....
}
}
Whatever the consumer of your User and its Repository is - if that's a Service class or a CommandHandler - can provide that uniqueness validator dependency. This consumer should already by wired up through IoC, since it will be consuming the UserRepository:
public class UserService
{
private readonly IUserRepository _repo;
private readonly IWebsiteUniquenessValidator _validator;
public UserService(IUserRepository repo, IWebsiteUniquenessValidator validator)
{
_repo = repo;
_validator = validator;
}
public Result AddWebsiteToUser(Guid userId, string websiteUrl)
{
try {
var user = _repo.Get(userId);
user.AddWebsite(websiteUrl, _validator);
}
catch (AggregateNotFoundException ex) {
//....
}
catch (ValidationException ex) {
//....
}
}
}
*I mentioned making the validation simple and avoiding the Domain.
We build Domains to encapsulate the often complex behavior that is involved with modifying data.
What experience shows, is that the requirements around changing data are very different from those around querying data.
This seems like a pain point you are experiencing because you are trying to force a read to go through a write system.
It is possible to separate the reading of data from the Domain, from the write side, in order to alleviate these pain points.
CQRS is the name given to this technique. I'll just say that a whole bunch of lightbulbs went click once I viewed DDD in the context of CQRS. I highly recommend trying to understand the concepts of CQRS.

Resources