Am struggling to identify whenever to create new domain service or capture business rules in my domain model.
Assume we cannot assign Account to Invoice if Account IsInactive or Blocked
class AccountAR
{
int id;
bool _isInactive;
bool _isBlocked;
public int GetID() { return id; }
public bool GetIsInactive() { return _isInactive; }
public bool GetIsBlocked() { return _isBlocked; }
string _name;
}
class InvoiceAR
{
int _id;
decimal _amount;
DateTime _date;
int _AccountID; // another aggregate root
int _customerid;// another aggregate root
List<InvoiceLine> InvoiceLines;
//attemp 1
//clear separation but lucks of businees rule behavior?
public void SetAccount(int accountID)
{
//how do i enforce business rule here?
//we cannot set account if is blocked or inactive or some other business requirments
_AccountID = accountID;
}
//attemp 2
//dose it violate ddd principles?
public void SetAccount(AccountAR account)
{
if (account.GetIsBlocked() || account.GetIsInactive())
{
throw new Exception("Invalid account state : only Active and non blocked accounts are allowed");
}
//other business rule might evolved over time
_AccountID = account.GetID();
}
//attemp3
//introduce a value object specific for invoice bounded context
public void SetAccount(InvoiceAR.InvoiceAccountValueObject accountValueObjectwithID)
{
if (accountValueObjectwithID.IsInactive || accountValueObjectwithID.IsBlocked)
throw new Exception("Invalid account state : only Active and non blocked accounts are allowed");
_AccountID = accountValueObjectwithID.id;
}
//attemp4
//assume this a domain service
public class InvoiceDomainService
{
public InvoiceDomainService()
{
}
public void ChangeInvoiceAccount(InvoiceAR invoice,AccountAR account)
{
//validate account
invoice.SetAccount(account.GetID());
}
}
//attemp5
//similar to above domain service we introduce an invoiceValidationService?
public class InvoiceValidationDomainService
{
public List<string> Validate(InvoiceAR invoice,List<AccountAR> accounts)
{
var _errors = new List<string>();
var findaccount = accounts.FirstOrDefault(x => x.GetID() == invoice.GetAccountID());
if (findaccount.GetIsBlocked() || findaccount.GetIsInactive())
_errors.Add("invalid account");
return _errors;
}
}
class InvoiceLine
{
//internal fields and properties
}
public class InvoiceAccountValueObject
{
public int id;
public bool IsInactive;
public bool IsBlocked;
public InvoiceAccountValueObject(int id, bool isInactive, bool isBlocked)
{
this.id = id;
IsInactive = isInactive;
IsBlocked = isBlocked;
}
}
}