Pular para o conteúdo

Driving e Driven

Cockburn nomeou os lados a partir de quem toma a iniciativa:

  • Driving side (lado que dirige, primário, de entrada): contém os atores que usam a aplicação. Um usuário via REST, um operador via CLI, um teste automatizado, um scheduler. Eles iniciam a conversa.
  • Driven side (lado que é dirigido, secundário, de saída): contém os atores que são usados pela aplicação. Um banco de dados, uma fila, um serviço de e-mail, uma API externa. Eles respondem a pedidos do núcleo.

A terminologia é consistente: primário = driving = de entrada (esquerda); secundário = driven = de saída (direita).

Aspecto Lado Driving (primário) Lado Driven (secundário)
Quem inicia O ator externo O núcleo
Tipo de porta Driving port (caso de uso) Driven port (SPI)
Quem implementa a porta O núcleo O adapter secundário
Quem chama a porta O adapter primário O núcleo
Exemplos de adapter Controller REST, CLI, consumer JPA, client HTTP, produtor de fila

No lado driving, o adapter chama a porta e o núcleo implementa. No lado driven, o núcleo chama a porta e o adapter implementa. É essa troca de papéis que gera a simetria do padrão.

Este é o conceito que mais confunde. São duas setas diferentes:

  • Fluxo de controle (runtime): Ator → Adapter primário → Núcleo → Adapter secundário → Recurso. A execução atravessa o hexágono da esquerda para a direita.
  • Direção da dependência (compile-time): tudo aponta para o núcleo. O adapter primário depende da driving port (que é do núcleo). O adapter secundário depende da driven port (que também é do núcleo). O núcleo não depende de ninguém externo.

No lado driven, essas duas setas apontam em sentidos opostos: o controle vai do núcleo para o adapter JPA, mas a dependência de código vai do adapter JPA para o núcleo. Esse “cruzamento” só é possível graças à driven port — a abstração que inverte a dependência (DIP).

graph LR
    A[Ator Externo] -->|1 controle| AP[Adapter Primario]
    AP -->|2 controle| DIN[Driving Port]
    DIN --> NUC[Nucleo]
    NUC -->|3 controle| DOUT[Driven Port]
    DOUT -->|4 controle| AS[Adapter Secundario]
    AS -->|5 controle| REC[Banco / Fila / API]

    AP -.dependencia.-> DIN
    AS -.dependencia.-> DOUT

    style NUC fill:#2d3b45,color:#fff
    style DIN fill:#3a5a40,color:#fff
    style DOUT fill:#5a3a40,color:#fff

As setas cheias são o fluxo de controle (esquerda → direita). As setas pontilhadas são a dependência de código, sempre apontando para dentro (para as portas do núcleo). No lado driven, controle e dependência vão em sentidos contrários.

  • Confundir “entrada/saída” com “topo/fundo”: pensar no lado driven como “camada mais baixa” reintroduz a hierarquia de camadas que o hexágono veio abolir.
  • Dependência apontando para fora: o núcleo importando o adapter JPA “para facilitar”. Isso quebra a inversão e amarra o domínio à tecnologia.
  • Tratar toda I/O como driven: um webhook que a aplicação recebe é driving (aciona o núcleo), mesmo sendo “rede”; o que classifica o lado é quem inicia, não se é entrada/saída de bytes.
  • Application service chamando controller: inverter o fluxo do lado driving, fazendo o núcleo conhecer quem o aciona.
  • Misturar papéis numa porta só: uma interface que ora é chamada de fora, ora chama para fora — sinal de que dois conceitos foram fundidos.

1. O que define se um ator está no lado driving ou driven?

Resposta

Quem toma a iniciativa. Se o ator aciona a aplicação, é driving (primário); se a aplicação o aciona, é driven (secundário). Não é sobre entrada/saída de bytes: um webhook recebido é driving porque inicia a interação.

2. Em que ponto o fluxo de controle e a direção da dependência divergem?

Resposta

No lado driven. O controle vai do núcleo para o adapter secundário (o núcleo chama), mas a dependência de código vai do adapter para o núcleo (o adapter implementa a porta do núcleo). As duas setas apontam em sentidos opostos.

3. Por que o núcleo pode “chamar” o adapter JPA sem depender dele?

Resposta

Porque ele chama através da driven port, uma interface que pertence ao próprio núcleo. Em tempo de compilação o núcleo só conhece a abstração; a implementação concreta (JPA) é injetada em runtime. A dependência de código continua apontando para dentro.

4. Por que pensar no lado driven como “camada inferior” é um erro conceitual?

Resposta

Porque reintroduz a hierarquia topo/fundo que Cockburn quis abolir ao escolher o hexágono. Driving e driven são papéis simétricos definidos por iniciativa, não níveis empilhados. Tratá-los como camadas costuma levar a dependências apontando para fora do núcleo.