Thinking in the classic example of orders and lines.
I would like to use the domain classes in the presentation layer, so as to check if an action or a property is correct, the main code is in the domain classes and I only need to adapt the specific aspects for the UI, for example, nulls, that in the domain it common don't use null values but in the UI it is more common.
The order is the root entity and the line the child entity.
To check if a line can be created I have this:
class Line
{
//bool to tell if it is enabled or not. string to tell the reason why it is not enabled.
internal static (bool, string?) IsCreateEnabled(deicmal amount, decimal price)
{
//check if amount is correct.
//check if price is correct.
}
public Line(decimal amount, decimal price)
{
(bool, string?) = IsCreateEnabled(amount, decimal);
//if bool false throw exception.
//Create the line
}
}
class Order
{
//bool to tell if it is enabled or not. string to tell the reason why it is not enabled.
public static (bool, string?) IsCreateLineEnabled(deicmal amount, decimal price)
{
return Line.IsCreateEnabled(amount, price);
}
public CreateLine(decimal amount, decimal price)
{
(bool, string?) = IsCreateLineEnabled(amount, decimal);
//if bool false throw exception.
//Create the line
}
}
How from a consumer it shouldn't access to the child entities directly, all it is through the root aggregate, I think that this is a possible solution. Internally the root aggregate delegates the validations to the child entity.
But the reason to can't access from a consumer to the child entities is to avoid incoherences, but if it is only for validations, not modify data, perhaps it would be not a bad idea to expose this kind of methods of the child entities to the consumers.
Although there could be better solutions.