2

How domain model capture business logic / domain logic since i cannot access repository?

I see many posts saying that domain model = business objects

But Business objects live in application layer (service layer "not domain services") where they constructed after a repository call and returned to the view

if that is true, then why define domain models in domain layer and isolate them since most of the methods require to access repositories and not just have business objects defined in application layer? e.g ReceivePayment_Business_Object?

I'm sure somewhere i've been lost...

Trying to follow ddd

I have the following domain model ( Receive Payment)

 public class ReceivePayment
{
    public string ID { get; private set; }

    //this should be auto complete when customer change
    public string AccountID { get; private set; }
    public string DepositToAccountID { get; set; }

    public EntityContact Customer { get; private set; }
    public decimal ExchangeRate { get; private set; }
    public CurrencyItem BaseCurrency { get; }

    public void SetCustomer(EntityContact contact)
    {
        //business rules / domain logic        
        if (contact.Type != EntityType.Customer)
            throw new Exception("Entity must be of type customer");

        if (contact.IsInactive == true)
            throw new Exception("Cannot set Inactive customer.");

        
        if (BaseCurrency.ID == contact.CurrencyID)
        {
            SetExRate(1);
        }
        else
        {
            //get latest ex rate from database based on customer currency ID
            //but domain model not allow us to access IRepositories
            //Then how do i procceed?
        }
        

        //AccountID must be auto set
        //I need access to Customer and get back property DefaultAccountID to accociate with AccountID
        //How DDD solve this ?

        

    }
    public void SetExRate(decimal ex_rate)
    {
        ExchangeRate = ex_rate;
        Recalculate();
    }
    public void Recalculate()
    {

        // Calulcations things
    }

For reference this how our accounting solution looks like

  • Domain Layer ( isolated - reference nothing )

    • Irepositories
    • Domain Models
  • DAL Layer (Infrastructure)

    • Reference Domain Layer
    • Repositories implementation
    • Persistence mechanism ( entity framework or ado.net sql)
  • Application Layer (Service Layer)

    • Reference DAL and just orchestrate the flow of the application
    • Reference Domain Layer
  • UI Layer (reference application Layer & Domain Layer)

    • WPF
    • Andoird (Xamarin forms)

3 Answers 3

2

In my experience it’s better not to have repository interfaces in the domain layer. Of course methods will depend on data, but that can be just as easily passed in as arguments.

Your sample code can be improved quite a bit; there are many primitives which can be converted to Value Objects (to encapsulate the business rules that belong to the type) and in the class itself I would definitely use a constructor to provide its dependencies. One of its dependencies could be some domain concept called CustomerExchangeRate, but I know absolutely nothing about your domain, so talk to the domain experts about the model. It has to make sense to them. It has to be written in their language. (Do they really use terms like EntityContact or CurrencyItem?)

One of the biggest advantages of a pure domain model without repositories is that it’s easy to test. You only have to mock the domain objects used by the system under test. With all business rules encapsulated in the domain model, nicely covered with unit tests, you will not only have tackled a lot of the complexity of the application, but will also feel confident to take on new requirements and refine the model as needed.

1

You are not lost! Your observations are correct. What's happening is that people have wildly different interpretations what DDD or even OO is or should be.

Your interpretation seems to be (which is also mine), that "domain" objects should capture the "logic", the behavior of a domain. When I first read the Blue Book, I came away with this interpretation, which is also consistent with object-orientation.

However, there is a seemingly more popular approach, in which "domain objects" are simply data structures, or very close to data structures, with some minor logic at most. This interpretation, as you can probably imagine, does not require "repositories" or indeed any collaborating objects.

So yes, the "domain" should capture logic / behavior, but most projects simply don't. It's that simple.

0

I am not sure if I understood your question completely, but I can smell the source of confusion.

Domain models and repositories are solving completely different problems.

Domain models are a representation of business logic and repositories abstracts data access.

For the sake of simplicity, let's forget about all the patterns and think logically about what we want to achieve from our code in long run.

In the end, we want our code to be readable, maintainable and embrace changes in future without creating any unexpected bugs.

The most intuitive way to achieve it to divide the code base into layers and have specific contracts between those layers (Interfaces). Also, we need to ensure that we are not repeating our code so that we have to make changes at minimal places whenever required. This gives us a very good encapsulation and abstracts the implementation details away from the clients.

The result is that we can swap internal implementations, whenever required and still be confident that nothing is going to break.

Now the number of layers you are going to create will totally depend on your project's complexity. Having too many layers will make your codebase very brittle and will reduce cohesion. Having fewer layers will induce more coupling eventually, and will make your layer very fat.

Most of the patterns that we see online or read about are mostly focused on big and complex projects. If you will try to fit in your less complex projects in some pattern meant for more complex projects, you will most of the time have too many wirings that won't make sense to you, confuse your peers, and also yourself after a couple of months.

Domain models are meant to encapsulate business logic. That is the sole purpose of the domain layer. But that business logic has to operate on some data. In the end, all business logic has to run on some data. But, you can not keep all the data loaded in the memory all the time. So, you need to fetch and persist data in some storage.

In simple applications, it is ok to have data access logic inbuilt into the domain classes. But when the project grows big, this will lead to repetitive code, if multiple domain objects need access to the same datasets. Also, in future, you might want to change the underlying data storage. In case your domain layer is very complex, then it makes sense to abstract the data access logic into a separate layer(repository). That gives you a lot of flexibility to change the data storage layer.

So you can just forget about the naming conventions and simply inspect how many abstracted layers you want as per the complexity of your project.

Hope this answers your question. If it does not, let me know in the comments.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.