Slide 1

Slide 1 text

Hexagonal Rails Luiz Costa gutomcosta@gmail.com @gutomcosta

Slide 2

Slide 2 text

Levar as melhores experiências em serviços de saúde para todo o Brasil. Temos vagas! beepsaude.gupy.io

Slide 3

Slide 3 text

hexágonos? ou ports and adapters

Slide 4

Slide 4 text

mas antes, layers… ou simplesmente camadas

Slide 5

Slide 5 text

Components within the layered architecture pattern are organized into horizontal layers, each layer performing a specific role within the application (e.g., presentation logic or business logic). Software Architecture Patterns, Mark Richards https://www.oreilly.com/library/view/software-architecture-patterns/9781491971437/

Slide 6

Slide 6 text

Na versão mais “restrita” deste pattern, as camadas superiores só acessam as inferiores passando pela camada seguinte.

Slide 7

Slide 7 text

Existem algumas variações, por exemplo, algumas camadas podem acessar diretamente outras camadas sem passar pela seguinte. Neste caso se diz que existem camadas “abertas”.

Slide 8

Slide 8 text

hexágonos? ou ports and adapters

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

Business

Slide 12

Slide 12 text

Business

Slide 13

Slide 13 text

entry / exit points

Slide 14

Slide 14 text

Business entry exit

Slide 15

Slide 15 text

Business entry exit

Slide 16

Slide 16 text

cada lado pode ter vários entry / exit points

Slide 17

Slide 17 text

Business entry exit … …

Slide 18

Slide 18 text

hexágonos finalmente!

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

Hexagonal Architecture, Alistair Cockburn https://bit.ly/2XBQHNx Allow an application to equally be driven by users, programs, automated test or batch scripts, and to be developed and tested in isolation from its eventual run- time devices and databases.

Slide 21

Slide 21 text

Outside ao invés de entry/exit points, agora inside/outside

Slide 22

Slide 22 text

ports and adapters

Slide 23

Slide 23 text

Ports and Adapters Architecture, Alistair Cockburn http://wiki.c2.com/?PortsAndAdaptersArchitecture Each face of the hexagon (port) represents some "reason" the application is trying to talk with the outside world. Events arrive from the outside world at a port. The adapter converts it into a usable procedure call or message and passes it to the application. The application is blissfully ignorant of the nature of the input device…

Slide 24

Slide 24 text

Ports and Adapters Architecture, Alistair Cockburn http://wiki.c2.com/?PortsAndAdaptersArchitecture Each face of the hexagon (port) represents some "reason" the application is trying to talk with the outside world. Events arrive from the outside world at a port. The adapter converts it into a usable procedure call or message and passes it to the application. The application is blissfully ignorant of the nature of the input device…

Slide 25

Slide 25 text

uma aplicação pode ter várias portas e isso não se limita ao número de lados do hexágono O adaptador converte a mensagem e delega para os objetos de domínio

Slide 26

Slide 26 text

algumas vantagens

Slide 27

Slide 27 text

Diminuir acoplamento Melhor para testar Adaptabilidade

Slide 28

Slide 28 text

clean architecture

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

sobre o quê?

Slide 32

Slide 32 text

sobre o quê?

Slide 33

Slide 33 text

como uma rails app se parece?

Slide 34

Slide 34 text

sobre o quê?

Slide 35

Slide 35 text

Screaming Architecture, Robert Martin https://blog.cleancoder.com/uncle-bob/2011/09/30Screaming-Architecture.html Architectures are not (or should not) be about frameworks. Architectures should not be supplied by frameworks. Frameworks are tools to be used, not architectures to be conformed to. If you architecture is based on frameworks, then it cannot be based on your use cases.

Slide 36

Slide 36 text

Screaming Architecture, Robert Martin https://blog.cleancoder.com/uncle-bob/2011/09/30Screaming-Architecture.html Architectures are not (or should not) be about frameworks. Architectures should not be supplied by frameworks. Frameworks are tools to be used, not architectures to be conformed to. If you architecture is based on frameworks, then it cannot be based on your use cases.

Slide 37

Slide 37 text

sobre o quê?

Slide 38

Slide 38 text

Screaming Architecture, Robert Martin https://blog.cleancoder.com/uncle-bob/2011/09/30Screaming-Architecture.html Your architectures should tell readers about the system, not about the frameworks you used in your system. If you are building a health-care system, then when new programmers look at the source repository, their first impression should be: “Oh, this is a heath-care system”.

Slide 39

Slide 39 text

architecture is about intent. Architecture the lost years, Robert Martin https://youtu.be/WpkDN78P884?t=704

Slide 40

Slide 40 text

rails is not your application http://blog.firsthand.ca/2011/10/rails-is-not-your-application.html it’s a web framework

Slide 41

Slide 41 text

the web is a delivery mechanism Architecture the lost years, Robert Martin https://youtu.be/WpkDN78P884?t=581

Slide 42

Slide 42 text

No content

Slide 43

Slide 43 text

No content

Slide 44

Slide 44 text

No content

Slide 45

Slide 45 text

como implementar com rails?

Slide 46

Slide 46 text

1. separar o código de negócio do framework

Slide 47

Slide 47 text

O código de negócio fica dentro da pasta application. Dentro da desta pasta, todo acesso ao framework é feito por adaptadores.

Slide 48

Slide 48 text

Código da aplicação web, escrita em rails fica dentro de web app. Esta pasta é a implementação de um delivery mechanism. O código negócio, que vive dentro de application, é acessado através de portas.

Slide 49

Slide 49 text

2. modularizar o código que vive dentro de application

Slide 50

Slide 50 text

alguns dos possíveis módulos de uma aplicação que no domínio de vacinação

Slide 51

Slide 51 text

o mesmo objeto de domínio em diferentes contextos ou módulos

Slide 52

Slide 52 text

Paciente Atendimento + qual nome, nascimento…? + qual dia do agendamento? + qual endereço de atendimento? Paciente Vacinação + como a caderneta de vacinação está organizada? + qual a próxima vacina? + qual vacina foi aplicada? Paciente Financeiro + qual custo das vacinas aplicadas? + alguma condição de desconto? + qual meio de pagamento utilizado? É responsabilidade de cada contexto modelar os dados da melhor maneira, de acordo com a as suas responsabilidades.

Slide 53

Slide 53 text

cada módulo é como se fosse uma implementação do padrão hexagonal

Slide 54

Slide 54 text

anatomia de um módulo

Slide 55

Slide 55 text

Application Domain Atendimento.Fila Infrastructure

Slide 56

Slide 56 text

show me the code! talk is cheap

Slide 57

Slide 57 text

implementação de um use case o fluxo de execução é simples e limpo As dependências são injetadas no construtor Usa um factory method* para manter o encapsulamento e diminuir o acoplamento com o objeto cliente * https://en.wikipedia.org/wiki/Factory_method_pattern application/src

Slide 58

Slide 58 text

como o delivery mechanism se conecta com a application?

Slide 59

Slide 59 text

conectando a web app com o application Aqui o factory method é usado para instanciar o use case. A interface pública do use case é usada como Port para acessar o código da application * https://en.wikipedia.org/wiki/Factory_method_pattern web-app/app/controllers

Slide 60

Slide 60 text

foco total no domain model domain model != model

Slide 61

Slide 61 text

objetos de domínio são escritos em código ruby puro (PORO*) Não existe nenhuma relação direta com o Active Record *http://blog.jayfields.com/2007/10/ruby-poro.html

Slide 62

Slide 62 text

e os models? Active Record?

Slide 63

Slide 63 text

Nas implementações padrão do rails, o model é uma subclasse de ApplicationRecord, isso faz com que o acoplamento com o banco de dados seja bem alto.

Slide 64

Slide 64 text

O domain object é separado do model e o seu ciclo de vida é controlado por um Repositório*. O repositório é responsável por executar as consultas (queries), e mapear os objetos de domínio. Para isso pode ter a colaboração de uma Factory*. O model tem a responsabilidade garantir a consistência dos dados, de acordo com o modelo relacional. Pode definir algumas queries e ter validações de dados O domain object é quem tem a implementação das lógicas de negócio. *https://martinfowler.com/eaaCatalog/repository.html

Slide 65

Slide 65 text

Um único Model pode dar origem a um modelo de domínio bem mais complexo. Neste caso, todos os dados do domain model são persistidos na mesma tabela (model) do banco de dados.

Slide 66

Slide 66 text

Aqui o model é usado para tirar vantagem do Active Record. Uma factory é usada para fazer a construção do objeto de domínio. .active_nurses é uma query que está encapsulada no Model. O save também delega para o Active Record. implementação de um repositório

Slide 67

Slide 67 text

onde estamos mesmo? e a história dos hexágonos?

Slide 68

Slide 68 text

a partir da representação original…

Slide 69

Slide 69 text

para uma proposta de implementação O controlador acessa os módulos através de uma porta que expõe a interface pública de um caso de uso. A implementação do caso de uso, atua como uma adaptador. O repositório encapsula o acesso aos models, funcionando como mais um adaptador.

Slide 70

Slide 70 text

para uma proposta de implementação O controlador acessa os módulos através de uma porta que expõe a interface pública de um caso de uso. A implementação do caso de uso, atua como uma adaptador. O repositório encapsula o acesso aos models, funcionando como mais um adaptador. Outside Inside Outside

Slide 71

Slide 71 text

Implementando uma User Story

Slide 72

Slide 72 text

Deve permitir o paciente agendar a aplicação de vacina. Ao fazer o agendamento deve-se efetuar o pagamento e reservar o estoque dos produtos agendados.

Slide 73

Slide 73 text

Deve permitir o paciente agendar a aplicação de vacina. Ao fazer o agendamento deve-se efetuar o pagamento e reservar o estoque dos produtos agendados.

Slide 74

Slide 74 text

Módulos

Slide 75

Slide 75 text

Módulos Bounded Contexts

Slide 76

Slide 76 text

Como um contexto executa uma ação em outro contexto?

Slide 77

Slide 77 text

Boundaries https:/ /martinfowler.com/bliki/ApplicationBoundary.html

Slide 78

Slide 78 text

O ideal é que um contexto só exponha objetos de fronteira. Ex: Use Cases, Services ou Repositories Se precisar retornar um conjunto de dados mais complexo, dê preferência para Hashs ou Tuplas Mantenha o domain model protegido dentro do contexto. O ideal é não deixar “vazar" do contexto os objetos de domínio

Slide 79

Slide 79 text

public class deve se reduzir o número de classes públicas para promover o encapsulamento

Slide 80

Slide 80 text

exemplo

Slide 81

Slide 81 text

Context Maps Open Host Service (OHS) Anti Corruption Layer (ACL) Event Publisher (EP)

Slide 82

Slide 82 text

1.

Slide 83

Slide 83 text

Gestão de Agendas Pagamentos Neste caso os contextos se falam através dos objetos de fronteira: Services e Casos de Uso

Slide 84

Slide 84 text

construa uma arquitetura que te permita atrasar as decisões https:/ /8thlight.com/blog/uncle-bob/2011/11/22/Clean-Architecture.html

Slide 85

Slide 85 text

No content

Slide 86

Slide 86 text

Indireção para o contexto de pagamento Injeção de Dependências

Slide 87

Slide 87 text

Único ponto de contato com contexto de pagamento Efetuar Agendamento

Slide 88

Slide 88 text

Efetuar Agendamento Tradução do modelo entre os dois contextos

Slide 89

Slide 89 text

2.

Slide 90

Slide 90 text

Gestão De Agendas Gestão de Estoque Os dois contextos se falam através de um domain event AgendamentoCriado

Slide 91

Slide 91 text

Publica o evento através da EP Contato com o contexto de gestão de estoque

Slide 92

Slide 92 text

Como tirar vantagem e extrair para um microsserviço?

Slide 93

Slide 93 text

Contexto de pagamento como microsserviço O único ponto de contato com o contexto de pagamento no agendamento, era o objeto de fronteira Pagamento. Este objeto vai precisar ser alterado, e ao invés de chamar o contexto diretamente, vamos introduzir uma service layer para implementar a chamada remota ao microserviço de pagamento O contexto de pagamento foi extraído e adicionado em uma nova aplicação rails. Foi necessário expor uma api para disponibilizar o acesso aos casos de uso. Neste caso, provavelmente os respositórios deverão ser alterados para conectar no banco de dados diferente.

Slide 94

Slide 94 text

O único ponto de contato com o contexto de pagamento no agendamento, era o objeto de fronteira Pagamento. Este objeto vai precisar ser alterado, e ao invés de chamar o contexto diretamente, vamos introduzir uma service layer para implementar a chamada remota ao microserviço de pagamento O contexto de pagamento foi extraído e adicionado em uma nova aplicação rails. Foi necessário expor uma api para disponibilizar o acesso aos casos de usos. Neste caso, provavelmente os respositórios deverão ser alterados para conectar no banco de dados diferente. Contexto de pagamento como microsserviço

Slide 95

Slide 95 text

Como extrair o contexto de Gestão de Estoque? Como lidar com o Domain Event AgendamentoCriado?

Slide 96

Slide 96 text

Publish/Subscribe ou Observers https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern https://en.wikipedia.org/wiki/Observer_pattern

Slide 97

Slide 97 text

Contexto de estoque como microsserviço O contexto de agendamento continua publicando o domain event AgendamentoCriado da mesma forma que antes, nada muda aqui. O Event Handler original é substituído por outro que public o evento em um Broker de mensagem. Ex: RabbitMQ, Kafka, ActveMQ No microserviço de estoque, é necessário adicionar na ACL, handlers que serão estimulados pelas mensagens entregues pelo broker. Estes handlers, delegam a execução para os caso de uso.

Slide 98

Slide 98 text

Contexto de estoque como microsserviço O contexto de agendamento continua publicando o domain event AgendamentoCriado da mesma forma que antes, nada muda aqui. O Event Handler original é substituído por outro que public o evento em um Broker de mensagem. Ex: RabbitMQ, Kafka, ActveMQ No microserviço de estoque, é necessário adicionar na ACL, handlers que serão estimulados pelas mensagens entregues pelo broker. Estes handlers, delegam a execução para os caso de uso.

Slide 99

Slide 99 text

Considerações Finais

Slide 100

Slide 100 text

Modelagem de domínio não é simples

Slide 101

Slide 101 text

O controle de acoplamento é extremamente importante

Slide 102

Slide 102 text

Mas lembre-se: https:/ /martinfowler.com/articles/dont-start-monolith.html

Slide 103

Slide 103 text

Obrigado! Luiz Costa gutomcosta@gmail.com @gutomcosta