Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

regra da dependência e dados que cruzam camadas.

Olá! Estou estudando a Clean Architecture, mas umas coisas me chamaram atenção:

  1. No exemplo construído em aula, as implementações concretas dos repository, que estão na camada de "infra" (interface adapters) na nomenclatura do uncle bob, dependem diretamente do domínio (entities/Enterprise business rules) , tanto que dão import nas classes da package aluno. A dependência está no sentido correto da regra, porém Uncle bob é explícito e claro ao dizer ( tanto no livro, quanto no artigo em seu blog que apresentou a Clean Architecture, n subtítulo "What data crosses the boundaries.") que os dados que cruzam fronteiras (ou seja, de uma camada a outra) são no máximo estruturas de dados simples, nunca ENTIDADES. Em outras palavras, deveria ser retornado (no máximo) um DTO e não a classe que contém as regras da entidade em si. Correto?
  2. Foi argumentado sobre o porque o repository fica na camada domínio. No entanto, além de eu não estar convencido conceitualmente de que persistência não é um conceito da aplicação, isso faz com que a dependência, apesar de no sentido correto, pule uma camada (a infra dependa diretamente da entidade, pulando a camada de aplicação). Isto é permitido/desejável? Em outras palavras, a clean architecture é uma arquitetura em camadas relaxada ou estrita? Eu não encontrei isto claro no livro, mas tenho uma pista de que Uncle bob pensou a interface do repository na camada de use cases. Trecho do livro (cap 23, pag 217):

"Entre os interagentes dos casos de uso e o banco de dados ficam os gatewais do banco de dados. Esses gateways são interfaces polimórficas(...). Lembre-se que não permitimos a presença de SQL na camada de casos de uso; em vez disso usamos interfaces de gateways com métodos adequados. Esses gateways são implementados por classes na camada da base de dados"

2 respostas

Olá! Vou deixar minha humilde opinião.. mas para efeito de reflexão.. hehe

No item 1, até entendo conceitualmente a "necessidade" de objetos DTOs sendo usado entre as camadas. Porém acho q na pratica isso torna-se um tanto impraticável (ou até onde vale a pena), dada a quantidade de classes DTOs que pode haver. Outra questão, se o usecase pode conhecer os domains assim como gateways (interfaces) também pode, não vejo uma necessidade de criar DTOs. Nos gateways e controllers crio mappers que controem dados em domains e domains em dados. Por aqui tem dado certo...

No item 2 eu prefiro criar um package gateway e ali as interfaces (com nome bem genérico). E suas implementações dentro de subpacotes de gateway.

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

solução!

Eu quase desisti desta pergunta, só não achei onde apagar hehe. Mas bom, eu procurei bastante sobre isso, Os exemplos práticos que encontrei por aí são coerentes com este, e, e mesmo sem ter certeza do que o uncle bob pensou, tenho conclusões pragmáticas:

  1. Até seria possível gateways de banco retornarem dto, mas tem pouca vantagem prática. O importante é em que camada essa interface é consumida e as entidades são manipuladas (use case ou entity). Considero a regra do bob importante quando se trata de views, controladores etc, estes devem ser desacoplados de entidades e conhecer apenas os use cases, e receber no máximo DTOs, ou seja, não conhecer nem as entidades nem o repository, do contrário se abre brecha para alguém implementar funcionalidades sem criar a respectiva use case. É justamente pra criar este desacoplamento que o bob propõe esta camada (além de diferenciar regras da aplicação das regras das entidades). De fato o import das entidades que precisa haver na implementação do gateway na camada de infra é excepcional.
  2. Pensando em alguns exemplos práticos pode ser mais fácil modelar algumas regras de entidade se elas tiverem uma interface do gateway disponível, por ex: evitar conflitos ao tentar marcar um evento em um calendário.

Adendo ao ponto 1: Ainda assim, sendo purista ao que o uncle bob propõe, é a princípio desaconselhável poluir as classes de entidades (regras de negócio centrais) com preocupações sobre persistência (por ex com anotações do hibernate etc). Portanto, caso se deseja fazer uso de um framework ORM e queiramos seguir o conselho do uncle bob de "não se casar com o framework" penso que faria sentido sim ter uma implementação de persistência que só conhece o DTO adaptado as necessidades do framework, e uma segunda classe que consome a primeira e converte em entidades (atuando como um adapter, e implementando a interface do repository que retorna entidades core). Esta última classe eu acho que não precisaria ficar na camada de infra, seria uma classe utilitária das use cases. De fato no livro há até um trecho dizendo que o que os ORMs retornam são meras estruturas de dados e não devem ser confundido com as entidades do core.