Alexey Markov
Alexey Markov

Reputation: 1566

Logic place in Domain Driven Design

I read much about DDD, but I can't steel see how use it in a real life. I make some examples (with C# and Entity Framework) for things which I can't understand.

  1. Add money for User. User has just amount of money.

Ok, It's simple. It's example of model User

class User
{
    public decimal Balance {get; private set; }

    public void AddMoney(decimal sum)
    {
        if(sum>0)
           Balance+=sum;
    }
}

But how can I use it?

  1. Fetch user from database
  2. Update user - performed by domain model
  3. Save changes

So, the first question is where I should perform fetching and saving data from database (repository)? I can't do this inside my domain model.

  1. User has history of transaction, not just simple sum
class User
{
    public ICollection<Transaction> Transactions {get; private set; }

    public void AddMoney(decimal sum)
    {
        if(sum>0)
            Transactions.Add(new Transaction(sum));
    }
}

In this case I should fetch user from database and then EF will add new Entity to collection. But it isn't efficient, more efficient is do something like this:

transactionsRepository.Add(new Transaction(sum, userId)); 

but it isn't DDD-way.

  1. Get money from one user and transfer to another

In this case operation affects multiple models. Where I should put logic which works with multiple models? (Maybe this example isn't good enough).

  1. Get users' current balance

User's balance is a sum of all transactions

decimal Balance() => transactionsRepository.Get().Sum(x=>x.TransactionSum);

In this case query contains logic - how I should fetch data to do something, not simple fetch\save entities like in other examples. Where I should place queries with logic? Get total balance, get last unread messages etc.

Upvotes: 1

Views: 549

Answers (1)

Constantin Galbenu
Constantin Galbenu

Reputation: 17683

So, the first question is where I should perform fetching and saving data from database (repository)? I can't do this inside my domain model.

You do this in an Application service in a Layered architecture or a command handler in a CQRS architecture .

But it isn't efficient, more efficient is do something like this

It is more efficient but indeed not the DDD way. Aggregates should have no dependency to repository. They work only with state that is stored in memory. An application service is responsible fir loading and storing an aggregate.

Where I should put logic which works with multiple models?

In Sagas/Process managers.

Where I should place queries with logic?

It depends on what do you query.

If not using CQRS:

If you query data from an Aggregate in an Aggregate's method.

If you query a specific lists of Aggregates them you put that logic in the repository.

If using CQRS then any query is done on a read-model/projection.

Upvotes: 1

Related Questions