Role of services in domain driven design

1.4k Views Asked by At

I have recently found that domain driven design (DDD) is the better option for some applications (i.e., applications in which complex business logic is involved rather than simple CRUD operations exposed through UI).

I have gone through the below sites on domain driven design (DDD).

https://www.infoq.com/articles/ddd-in-practice

Domain Driven Design: Domain Service, Application Service

What I could not conclude/understand are the following points:

(1) What is the role of services in domain driven design (DDD) ? Can you explain with an example Service, Domain object, DAO (using Java) ?

(2) If I need to use Java to create Domain/Business Objects, then what is the naming convention to be followed ? Is it like CustomerBO, ProductBO, etc.. ?

Could you please help me with simple examples using Java ?

I did not like the example given below (in the answer) as the domain object is not doing anything below except carrying the data, which is still an anemic model. Can anyone help me with one clear example by having some behaviour inside domain object ?

1

There are 1 best solutions below

4
Amin J On

This is a loaded question but I'll try to answer it to some extend. I highly recommend looking at the github sample from Vaughn Vernon. He is the author of Implementing Domain Driven Design.

The definition of services is laid out very nicely in the SO link you provided. So I'm going to just give you sample codes to digest with that description.

Take the example of provisioning a tenant in an identity access domain.

Here are a few pretty clear examples from Vaughn's github:

Here is the tenant domain object:

package com.saasovation.identityaccess.domain.model.identity;

    public class Tenant extends extends ConcurrencySafeEntit {
        public Tenant(TenantId aTenantId, String aName, String aDescription, boolean anActive) {
         ...   
        }
        public Role provisionRole(String aName, String aDescription) {
          ...
        }
        public void activate(){}
        public void deactivate(){}
        ....

    }

The tenant Repository:

package com.saasovation.identityaccess.domain.model.identity;

public interface TenantRepository {

    public void add(Tenant aTenant);
}

Tenant domain service:

package com.saasovation.identityaccess.domain.model.identity;

public class TenantProvisioningService {

    private TenantRepository tenantRepository;

    public Tenant provisionTenant(
            String aTenantName,
            String aTenantDescription,
            FullName anAdministorName,
            EmailAddress anEmailAddress,
            PostalAddress aPostalAddress,
            Telephone aPrimaryTelephone,
            Telephone aSecondaryTelephone) {

            Tenant tenant = new Tenant(
                        this.tenantRepository().nextIdentity(),
                        aTenantName,
                        aTenantDescription,
                        true); // must be active to register admin

            this.tenantRepository().add(tenant);

    }

}

This is an application service:

package com.saasovation.identityaccess.application;

@Transactional
public class IdentityApplicationService {

    @Autowired
    private TenantProvisioningService tenantProvisioningService;


    @Transactional
    public Tenant provisionTenant(ProvisionTenantCommand aCommand) {

        return
            this.tenantProvisioningService().provisionTenant(
                        aCommand.getTenantName(),
                        aCommand.getTenantDescription(),
                        new FullName(
                                aCommand.getAdministorFirstName(),
                                aCommand.getAdministorLastName()),
                        new EmailAddress(aCommand.getEmailAddress()),
                        new PostalAddress(
                                aCommand.getAddressStateProvince(),
                                aCommand.getAddressCity(),
                                aCommand.getAddressStateProvince(),
                                aCommand.getAddressPostalCode(),
                                aCommand.getAddressCountryCode()),
                        new Telephone(aCommand.getPrimaryTelephone()),
                        new Telephone(aCommand.getSecondaryTelephone()));
    }
}