Este artigo ilustra um estilo de arquitetura focado no domínio do software, onde os detalhes (ex.: UI, acesso a dados) dependem do domínio e não o contrário.

Veremos toda a transição de um estilo de arquitetura em camadas mais acoplado para o estilo mais flexível (e alguns de seus nomes mais conhecidos).

A TRADICIONAL ARQUITETURA EM CAMADAS

Em uma arquitetura em camadas (Layered Architecture) tradicional, o fluxo de dependência de uma camada para outra segue do topo para baixo, onde no topo encontra-se a entrada de dados (normalmente, uma camada de interface com o usuário), no meio, o processamento (camada de negócio/domínio) e na base, a saída (normalmente, a camada de acesso a dados):layered-architectureO grande ponto a ser observado nesse desenho é que existe um acoplamento forte entre as camadas. Enquanto o acoplamento UI -> Business não é um problema, o segundo, Business -> Data Access torna o software inflexível (para substituir “Data Access” será preciso alterar “Business”).

INVERTENDO DEPENDÊNCIAS

Consideremos agora uma sutil inversão no desenho:
dip-layered-architectureComo podem notar, essa solução privilegia o domínio (business) do software, que é o propósito principal de sua existência. Afinal, um software corporativo nasce para atender necessidades de negócio!

CEBOLAS TEM CAMADAS

E se mudarmos um pouquinho a perspectiva do desenho, como ilustrado abaixo?onion-architectureDessa forma, fica ainda mais evidente que:

  • O foco é o domínio, parte central e mais estável do software. O domínio será evoluído ao longo do tempo sempre que surgirem mudanças no negócio, mas a tecnologia em si pode perdurar, uma vez que é código “puro” da linguagem dependendo apenas da plataforma (ex.: C#/.Net).
  • UI e acesso a dados são serviços periféricos, cujas tecnologias podem ser substituídas com muito mais frequência do que a linguagem/plataforma do software (ex.: trocar a tecnologia de persistência por outra mais nova.)

DEPENDÊNCIA ENTRE AS CAMADAS

No desenho anterior, batizado por Jeffrey Pallermo de “Onion Architecture” (Arquitetura-Cebola), uma camada é cliente dos serviços da camada imediatamente mais interna a ela, isto é, as dependências seguem sempre de fora para dentro.

No final das contas, o que fizemos foi simplesmente aplicar o “Princípio da Inversão de Dependência (DIP)”: a camada de acesso a dados (módulo de baixo nível) é que depende agora do domínio (módulo de alto nível). (Leia mais <aqui> para entender com detalhes como ficaria a aplicação do DIP neste cenário de persistência.)

UMA MELHORIA NO DESENHO

Ainda olhando para a “cebola”, vocês podem estranhar o fato de UI e acesso a dados terem sido colocados na mesma camada. Será que esses componentes podem depender entre si?

Como dito anteriormente, as dependências seguem de fora para dentro e NÃO É UMA BOA IDEIA fazer com que UI dependa da camada de acessos a dados ou vice-versa. Afinal, não queremos acoplar dois componentes com chance maior de substituição (lembram?) e também não queremos induzir o desenvolvimento a pular as regras do domínio!

Para deixar isso mais evidente, podemos fazer um leve ajuste no desenho:onion-architecture-v2DE CEBOLAS PARA HEXÁGONOS

Percebam nos desenhos anteriores como UI e acesso a dados ficaram em lados opostos (UI à esquerda e acesso a dados à direita). Esta separação foi proposital para fazer a devida associação a outro conceito: “Arquitetura Hexagonal” (Alistair Cockburn).

Vejamos como fica o desenho do hexágono:hexagonalComo podem notar, não há nada de diferente entre este desenho e o desenho anterior, exceto pelo fato de os círculos terem sido trocados por hexágonos!

Podemos dizer que “hexagonal” não é um nome muito claro para esta arquitetura. Poderiam ser 5 lados ou 4. O importante é ressaltar a simetria entre o lado esquerdo e o lado direito. No lado esquerdo são ilustrados os “atores primários”, ou seja, aqueles que estimulam a aplicação e, no lado direito, “os atores secundários”, aqueles que são dirigidos pela aplicação.

Dentro do hexágono maior estão os adaptadores, que fazem o meio de campo entre a aplicação (o hexágono menor) e as fronteiras do software (as portas, tanto de entrada quanto de saída). É por isso que essa arquitetura recebe também o nome de “Ports & Adapters”. (No desenho acima, um “Controller” de um framework web seria um exemplo de adapter em “UI” e um “Data Access Object (DAO)”, um exemplo de adapter em “Data Access”.)

E A TAL “CLEAN ARCHITECTURE” ?

“Clean Architecture”, termo cunhado e popularizado por Robert C. Martin (aka “Uncle Bob”), nada mais é do que um outro nome para o mesmo estilo arquitetural apresentado até aqui. Embora alguns detalhes possam variar (ele sugere, por ex, algumas camadas a mais, como a de “use cases”, que nada mais é do que a camada de aplicação), o propósito e suas principais características são exatamente os mesmos.

COMO COMPOR AS DEPENDÊNCIAS?

Voltando ao Princípio da Inversão de Dependência, é fato que em tempo de execução, um módulo de alto nível ainda depende do módulo de baixo nível. Sendo assim, precisamos, em algum ponto, “ensinar” ao software quais dependências concretas utilizar e nos entregar toda a composição de objetos prontinha. Isso normalmente acontece em um componente chamado de Composition Root. (Para saber mais, leia o artigo correspondente ou a série toda sobre DI.)

CONCLUSÃO

De modo geral, todas as representações mostradas neste artigo possuem os mesmos objetivos básicos:

» Separação de responsabilidades (SoC – separation of concerns).
» Isolar totalmente o domínio do software de detalhes técnicos e até de softwares/serviços externos, o que garante:

  • Testabilidade (ié, sem banco, disco, web service ou qualquer outro detalhe técnico).
  • Facilidade da troca desses detalhes técnicos no futuro (você pode mudar de ideia!).
  • E um dos pontos mais importantes: permitir adiar decisões técnicas até o último minuto responsável!

—————————————————————————–
ATUALIZADO EM 13/08/2018:
– Boa parte inicial do artigo foi reescrita, pois baseava-se em outro artigo (de terceiros), que não se encontra mais online.
– Troca de todas as imagens.
– Inclusão do tópico sobre “Clean Architecture”.
– Inclusão do tópico sobre o “Composition Root”.
– Pequenos ajustes e melhorias no texto todo.

CRÉDITOS:
A ideia de transição dos desenhos/estilos é totalmente baseada no artigo original de Mark Seemann, entitulado “Layers, Onions, Ports, Adapters: it’s all the same”.