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):O 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:
Como 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?Dessa 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:DE 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:Como 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”.
Olá Robson, como vai?
Terias um exemplo prático, inclusive codificado?
Abs
CurtirCurtir
Olá, Fabiano
Posso providenciar nos próximos alguma coisa básica nesse sentido.
Aguarde.
[]s
CurtirCurtir
tiozão,
estava pensando hoje, estou esperando o dia que o senhor vai fazer um livro para gente hehehehehehe ou pelo menos um artigo relevante para algum lugar.
Att.
CurtirCurtir
Hahahah
Livro toma tempo hein…teria que tirar um ano pra isso… vai que rola um dia?! 🙂
Qto aos artigos, o máximo foi um pra revista “Engenharia de software” da DevMedia. Já fui convidado outras vezes para escrever para outras revistas da editora, mas os artigos devem ser maiores, precisam ser revisados, toma um tempão!
[]s
CurtirCurtir
Bacana a transição que fez entre os termos cebola, hexagono, e ports & adapters. Bem didático. Muito boa introdução.
CurtirCurtir
Obrigado, camarada!
[]s
CurtirCurtir
Parabéns pelo Post!
CurtirCurtir
Obrigado!
[]s
CurtirCurtir
Muito bom entrar aqui e rever seus textos.
Sempre tiram dúvidas e nos esclarecem mais e mais!
Parabéns!!!
CurtirCurtir
Obrigado, Paulo.
Estou à disposição (online ou lá na empresa) para trocarmos ideias sobre este e outros assuntos sempre que você puder.
[]s
CurtirCurtir
amigão, qual a referência que posso usar para me aprofundar mais sobre o assunto?
CurtirCurtir
E ai, João!
Recomendo a leitura dos artigos referenciados no texto e o artigo The Clean Architecture, do Uncle Bob.
Em se tratando de livros, recomendo estes:
– Patterns of the Enterprise Application Architecture (contem capitulos que falam sobre domain model e camada de serviço, por exemplo)
– Implementing Domain-Driven Design (fala muito de arquitetura, possui um capitulo inteiro sobre e um capitulo sobre a camada de aplicaçao).
Bom, esses são os bons conteúdos de que consegui me lembrar 🙂
[]s e bons estudos!
CurtirCurtir
Muito bom Robson!
Continue com esses artigos de arquitetura!
Abraços
CurtirCurtir
Obrigado!
Pode deixar.
[]s
CurtirCurtir
Esse artigo me lembra muito o principio SOLID, aplicando um total desacoplamento entre as camadas, a injeção de dependência e a inversão de controle são dois critérios exclusivos para um total desacoplamento, faço uso do Ninject ainda apanho com algumas injeções de dependência, atribuindo as interfaces as respectivas classes concretas…mas o artigo é muito bom, me passem um e-mail que acredito conseguir encaminhar um exemplo prático de aplicação ASP .net MVC , EF6, Code First , com injeção de dependência.
CurtirCurtir
Olá Robson, gostei do comparativo entre estes modelos arquiteturais, que no fim das contas possuem a mesma base com alguns detalhes a mais ou a menos, mas a sacada é sempre focar no domínio.
Você usa em seus projetos profissionais alguma destas arquiteturas?
CurtirCurtir
Olá, Kauan
Sim. Venho implementando esse estilo de arquitetura há pelo menos 1 década (claro, nos projetos onde tive a oportunidade de começar no green-field).
Qquer coisa, estamos aí!
[]s
CurtirCurtir