-
Notifications
You must be signed in to change notification settings - Fork 14
Layers
A aplicação Rastreador de Carga é organizada em camadas como a mostra a figura abaixo:
Como você pode ver, existem várias cadamas verticais: interfaces, application and domain, cada uma com um suporte específico da infraestrutura. Na aplicação, os nomes do pacote refletem estas camadas.
Esta camada manipula tudo que interage com o sistema (incluindo humanos 😄), coisas como serviços web REST, WebSocket endpoints, web UIs, external messaging end-points and batch processes. Ele manipula interpretação, valida entradas (input validation) e tradução de dados que chegam ao sistema. Essa camada também é responsável pela serialização de dados para saída externa, como HTML, JSON ou XML através do HTTP até os navegadoes ou web service clients, ou classes DTOs, e interfaces de fachada (facade) distribuídas para clientes remotos.
O pacote org.eclipse.cargotracker.interfaces guarda todas as classes de camada de interface da aplicação. Nós temos duas interfaces web UI - uma para booking e outra para tracking assim como uma REST interface e uma interface para um agendado de processamento de arquivos scheduled file processor para reportar handling events. A interface web é escrita em HTML/JavaScript/Jakarta Faces, a interface REST usa Jakarta REST enquanto o file processor usa @Scheduled/Jakarta Batch. Os frameworks web modernos naturalmente forçam a separação de interesses com MVC, então não existe muita carga que vocês precisa fazer. Além disso, você pode aplicar uma camada de fachada se necessário (por exemplo, sua equipe de UI está bem separada da equipe de services ou você deseja permanecer estritamente agnóstico da camada de UI). Caso contrário, você pode usar adapters para adaptar as classes de domínio à sua visão de UI. Nós demonstramos ambas as técnicas na aplicação usando padrões de projeto bem compreendidos, tais como Fachada, DTO, Assembler e Adapter (além do MVC, claro).
Além de Jakarta Faces, REST e Enterprise Beans, outras tecnologias de Jakarta EE tipicamente utilizadas na camada de interface são Jakarta EE Security, CDI, Bean Validation, JSON Processing/JSON Binding/XML Binding (para serialização), Batch, Messaging e WebSocket.
A camada de aplicação é responsável por conduzir o fluxo de trabalho (workflow) da aplicação, combinando com os casos de uso de negócio. Estas operações são independentes da interface e podem ser tanto síncronas quanto assíncronas. Esta camada é bem adequada para transações abrangentes (spanning), high-level logging, e segurança.
Observe que a camada de aplicação é muito fina em termos de lógica de domínio - ela simplesmente coordena os objetos da camada de domínio para realizar o trabalho real. Isto é muito diferente das arquiteturas tradicionais de camadas que tendem a parecer mais processuais com muita lógica de negócios na camada de aplicação.
O pacote org.eclpse.cargotracker.application contém todas as classes de Application. A camada de application é tipicamente implementada usando Enterprise Beans ou CDI Beans. Outras APIs de Jakarta EE que provavelmente serão usadas nesta camada são Jakarta EE Security, Interceptors, Transactions (em situações muito raras em que você mesmo gostaria de gerenciar transações) e Concurrency.
A camada de domínio é o coração do software, e é aqui que as coisas interessantes acontecem. Há um pacote por agregado e para cada agregado estão suas entidades, objetos de valor, eventos de domínio, uma interface de repositório e às vezes fábricas (veja a seção Caracterização para detalhes). As raízes do agregado (aggregate roots) são Cargo, HandlingEvent, Location e Voyage.
O núcleo da lógica de negócio, tal como determinar se um handlig event deve ser registrado e como a entrega de uma carga é afetada pelo handling, fica aqui. A estrutura e nomeação de agregados, classes e métodos na camada de domínio deve seguir o mundo real o mais próximo possível (Ubiquitous Language), e você deve ser capaz de explicar a um especialista no domínio do negócio como esta parte do software funciona, desenhando alguns diagramas simples e usando os nomes reais das classes e métodos do código fonte. Note que não é raro que algumas classes de domínio simplesmente modelem dados e não contenham nenhuma lógica de negócios.
A camada de domínio é geralmente implementada principalmente usando Jakarta Persistence, Bean Validation e CDI.
Além das três camadas verticais, há também a infra-estrutura. Como mostra a imagem no início, ela suporta todas as três camadas de maneiras diferentes, às vezes facilitando a comunicação entre as camadas. No caso mais comum, a camada de infra-estrutura consiste em implementações de Repository interagindo com um banco de dados. Em termos simples, a infra-estrutura consiste em tudo que existe independentemente de nossa aplicação: recursos externos/de terceiros, persistência/base de dados, back-ends de mensagens, sistemas legados e assim por diante.
Todas as classes de infra-estrutura estão no pacote org.eclipse.cargotracker.infrastructure. Utilizamos Jakarta Persistence, CDI, Messaging e a API REST Client nesta camada. A aplicação terá em sua maioria código de Jakarta Persistence nesta camada encapsulada com classes finas de Repositório de CDI Beans. Outras APIs do Jakarta EE comumente usadas nesta camada incluem clientes Jakarta Mail e XML Web Services.
Muito poucas coisas no DDD são obrigatórias, as camadas (layering) não é exceção. Você deve usar camadas se você acredita que elas agregam valor na manutenção de sua aplicação. De fato, mesmo se você optar por usar camadas, você não precisa usá-las em todos os lugares em sua aplicação como um requisito obrigatório. Se você olhar atentamente na aplicação, bem como a imagem de abertura nesta seção, não há problema em pular camadas por caso de uso. Por exemplo, é bastante comum que a camada de interface pule a camada da aplicação e se comunique diretamente com a camada de domínio. Em muitos outros casos, ter uma estratura de camadas clara agregará valor ao separar as preocupações/responsabilidades, melhorando a testabilidade, reduzindo o acoplamento e aumentando a clareza semântica. Um exemplo útil disto é a implementação BookingService.