Sobre camadas, cebolas e hexágonos…

Olá, galera

Depois de um longo tempo, é hora de voltar à ativa falando um pouco sobre arquitetura de software. 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.

Apresentarei dois conceitos exatamente com este enfoque, conhecidos por “Onion Architecture” e “Hexagonal Architecture”, dando minhas considerações sobre eles.

Pela primeira vez, vou usar <outro artigo> como introdução ao meu, pois já ilustra bem o que eu queria dizer no início deste. Leia-o primeiro e retorne aqui pra continuarmos. É bem curtinho!

Artigo lido? Certeza? Então, vamos em frente…

SEM CAIXAS EMPILHADAS

No artigo acima chegamos a um desenho parecido com o mostrado a seguir. Apenas eliminei o tradicional formato de caixas empilhadas e deixei UI e dados nas extremidades. (Nota: deixarei o “Composition Root” para um próximo artigo.)

sobre_camadas_cebolas_hexagonos

Como podem notar, essa solução privilegia o domínio 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

Vamos avançar um pouco mais no desenho. Que tal vermos as camadas (layers) como camadas de uma cebola (*)?

(*) Ok, como só estou usando 2 camadas, está mais para um CD do que uma cebola, mas vocês vão entender mais à frente 🙂 .

Teríamos algo do tipo:

sobre_camadas_cebolas_hexagonos-2

Dessa forma, ao meu ver, 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. Por exemplo, trocar ASP.NET WebForms por ASP.NET MVC.

DEPENDÊNCIA ENTRE AS CAMADAS

No estilo anterior, batizado por Jeffrey Pallermo de “Onion Architecture” (Arquitetura-Cebola), a dependência continua orientada de fora para dentro, ou seja, uma camada é cliente dos serviços da camada imediatamente mais interna a ela (opção mais restrita) ou cliente dos serviços de qualquer camada mais interna a ela (opção mais relaxada). Reforçando: pode haver mais camadas (fatias) e, normalmente, é o que acontece.

Uma dúvida comum ao analisarmos esse estilo de arquitetura é: como persistir os dados se a dependência entre acesso a dados e domínio está invertida?

Na verdade, a resposta já foi entregue quando escrevi a palavra “invertida”. A solução está no Princípio da Inversão de Dependência (DIP). Aplicando o DIP, serviços de uma determinada camada dependem de abstrações, contidas na mesma camada, cujas implementações residem em camadas mais externas.

O “problema” da dependência entre acesso a dados e domínio é ilustrado no <<meu artigo sobre o princípio>>. Serviços de domínio dependem de uma abstração (em geral, o padrão Repository é usado) enquanto a implementação do repositório é feita na camada de acesso a dados.

No entanto, dado o total desconhecimento do domínio em relação a camada de acesso a dados, precisamos de uma forma de injetar a implementação correta do repositório em tempo de execução. Uma solução popularizada nos últimos anos é o uso de algum container de DI, como o Unity, o Ninject, entre dezenas de outros. Deixarei este assunto para uma próxima oportunidade.

UM PROBLEMA E UMA MELHORIA NO DESENHO

Ainda olhando para a cebola, vocês podem estar espantados pelo fato de UI e acesso a dados terem sido colocados na mesma camada. Não se assustem. Isso é uma forma de ilustrar que ambos são serviços periféricos de uso do software e pontos de acesso ao mundo externo (o usuário, a internet, o disco).

No entanto, o desenho sugere que todos os componentes da mesma camada possam depender sem problemas entre eles. Será verdade?

Fato é que NÃO É UMA BOA IDEIA fazer com que UI dependa do 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 caindo no anti-pattern Smart-UI.

Sendo assim, podemos fazer um leve ajuste no desenho:

sobre_camadas_cebolas_hexagonos-3

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:

sobre_camadas_cebolas_hexagonos-4

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.

No hexágono maior estão os “adaptadores” entre os atores (por ex, os componentes de UI são adaptadores entre o usuário e a aplicação) e no hexágono menor, a aplicação em si (use cases e domínio). As “portas”, que no desenho são os lados do hexágono menor, representam os componentes que ligam adaptadores e aplicação. É por isso que essa arquitetura recebe também o nome de “Ports & Adapters”.

CONCLUSÃO

No final das contas, 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. Esse isolamento garante, inclusive, testabilidade independente de banco, disco, web service ou qualquer outro detalhe técnico.
– Facilitar a troca desses detalhes técnicos.

Ou seja, vantagens excelentes para um software que deseja crescer e ter uma manutenibilidade sem maiores dores de cabeça.

Este artigo trouxe uma breve introdução ao assunto, o qual é extenso e gerador de muita discussão. Voltarei em artigos futuros com mais detalhes. Para adiantar, no meu próximo artigo sobre arquitetura, falarei sobre uma camada normalmente existente entre a camada mais externa e a camada de domínio, conhecida por “camada de aplicação” ou “camada de serviço”.

Aguardo vocês.
Comentem, perguntem, critiquem!
[]s

Créditos: embora não seja pura e simplesmente uma tradução, este artigo é totalmente baseado no original de Mark Seemann, entitulado “Layers, Onions, Ports, Adapters: it’s all the same”. Confira!

Anúncios

15 comentários em “Sobre camadas, cebolas e hexágonos…

    1. 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

  1. Muito bom entrar aqui e rever seus textos.
    Sempre tiram dúvidas e nos esclarecem mais e mais!
    Parabéns!!!

    1. 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!

  2. 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.

Participe! Vamos trocar uma ideia sobre desenvolvimento de software!

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s