Domain Driven Design, what is the difference between Domain Services, Infrastructure Services and Application Services

Asked

Viewed 3,213 times

12

Is it correct to state that business rules should be written within the domain service? If yes, as a domain entity is not anemic, it also implements its business rules, then Domain Service would only serve to orchestrate the calls of these rules, correct? And Infrastructure Services and Application Services, what are their purposes? Could you explain these areas to me, if possible with examples?

1 answer

13


Well, the answer to your questions is very similar to the answer to that question. As I ended up answering she will take the liberty of reusing it and supplement it for your case :)

Application Service:

  • It provides the user (via the interfaces) with operations that your software can perform, and controls the execution of these operations by calling objects methods from the other layers (domain, infrastructure, etc.). It is important to say that the Application Service does not contain business rules or domain knowledge, thus, it merely coordinates calls to methods from other layers and maintains the state that reflects the progress of an operation to the user.

Domain Services:

  • Provides for the Application Service methods that allow the execution of operations on Domain objects (inner layer). Although it is common to represent much of the main business concepts and rules here, the ideal is that these details are represented directly in the Domain Models. Therefore, the Domain Service should call and control the execution of methods of the Domain Model objects when it is not trivial or logical to declare a method directly in the domain model

Infrastructure Services:

  • Provides methods that allow you to perform operations on the infrastructure on which the software is running. This means that these services have knowledge about details of concrete infrastructure implementations such as: access to databases, network access, control of IO operations, hardware access etc. Generally this service is used by Application Services to complement and assist their operations, for example, to provide a method that allows the creation and control of a buffer to perform file downloads.

Example

Suppose we have an ATM software that has only the transfer option between accounts.

The first thing to do is declare the elements of the domain. In this case, we need a class Bill, and this class should allow access to balance information and also means for us to add and remove balance. Then we have the following class:

public class Conta {

    private Float saldo;

    public Conta(Float saldo) {
        this.saldo = saldo;
    }

    public Float getSaldo() {
        return saldo;
    }

    // Para deixar mais simples não faço validações de saldo
    public void debitar(Float quantia) {
        saldo = saldo - quantia;
    }

    public void creditar(Float quantia) {
        saldo = saldo + quantia;
    }
}

Well, now we need to provide a way to carry out a transfer. If we take a moment to think about it, it doesn’t make much sense to have a transfer operation within our own account, because a transfer involves two accounts, but it makes a lot of sense to have a transfer service. The role of this service would be to manipulate two objects Bill in order to credit and debit the accounts properly. Then we will create our transfer service.

public class TransferenciaServices {

    public boolean transferir(Float quantia, Conta contaOrigem, Conta contaDestino) {

        if (contaOrigem.getSaldo() < quantia) {
            return false;
        } else {
            contaOrigem.debitar(quantia);
            contaDestino.creditar(quantia);
            return true;
        }
    }
}

Well, we already have our domain fully implemented. We can only now provide the user with a way to execute a transfer.

But before we continue, suppose that for reasons of accessibility, the ATM should emit a sound signal in case of success in the transfer. Let’s also suppose that this sound signal can be sent by calling methods from an API that the ATM manufacturer provided to us. Note that the manipulation of this API and beeping are details of the infrastructure on which the software is running, and therefore they must belong to Infrastructure Services. In that case, we could have the following class:

//Serviço específico para manipulação de sons da infraestrutura
public class SoundServices {

        /* ... */

        // Api do fabricante
        private ApiCaixaEletronico apiCaixaEletronico;

        public void emitirSinal() {

            //Exemplo de possivel função da api do fabricante que permite emitir
            // um sinal sonoro num determinado volume em decibéis (dB)
            int volumeDecibeis = 60; 
            apiCaixaEletronico.emitirSom(volumeDecibeis);
        }
    }

Well, now all we have is Application Services. As seen, it must have services that allow the user to perform a transfer. This service should also be responsible for calling the correct methods of the domain services, being responsible for accessing and correctly saving the data in the database, and also emitting the beep after the transfer is completed. So we have the following class:

public class TransferenciaApplicationServices {

    // Dependências necessárias para que o serviço possa ser executado
    private ContasDatabase database;
    private TransferenciaServices transferenciaServices;
    private SoundServices soundServices;

    /* ... */

    public boolean transferir(Float quantia, Conta contaOrigem, Conta contaDestino) {

        boolean transferidoComSucesso = transferenciaServices.transferir(quantia, contaOrigem, contaDestino);

        if (transferidoComSucesso) {
            // Salva as contas com saldo atualizado no banco 
            database.atualizarConta(contaOrigem);
            database.atualizarConta(contaDestino);

            // Emite sinal sonoro de sucesso
            soundServices.emitirSinal();
            return true;
        } else {
            return false;
        }
    }
}

As can be seen, the responsibility of TransferenciaApplicationServices is to coordinate the execution of repositories, infrastructure and Transference Services methods with the aim of ensuring that a transfer is successfully executed.

  • 1

    Excellent explanation! Thank you very much for having provided examples too, greatly facilitated the understanding. Let’s go ahead!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.