Pular para o conteúdo principal

Design Pattern Pub-Sub em C#

Agora que já vimos para que servem os Design Patterns, vamos entender como resolver aquele problema descrito no post anterior. Para resolver esse problema se definiu uma forma padronizada de criar objetos inspirado no caso de uso do "Observador" ou "Anunciante versus Inscritos".

O Publisher vs Subscriber ou Pub-Sub é um padrão de projeto comportamental que permite que você defina um mecanismo de assinatura para notificar múltiplos objetos sobre quaisquer eventos que aconteçam com o objeto que eles estão observando.

Na imagem acima temos uma atividade sendo executada enquanto outras atividades observam sua apresentação e aguardam a vez delas de executarem também. Temos nesse cenário uma regra de negócio resolvivel pelo padrão Pub-Sub. Na imagem abaixo é demonstrado o problema inicial na forma de um diagrama de atividades adaptado para o padrão Pub-Sub, da forma que o sistema realmente deve funcionar. Tem-se a Atividade 1 sendo executada e uma ramificação com diversas atividades esperando a vez delas de executar ao mesmo tempo. Compare esse diagrama com os diagramas anteriores e observe quais comportamentos diferentes existem neles.

Imagem criada pelo autor no editor UML Dia

No mundo real é muito comum criarmos um problema em que tenhamos de ficar checando a cada 1 ou mais segundos se determinada atividade encerrou para podermos executar as atividades que dependem dela. Com o Pub-Sub pretende-se chegar a solução onde assim que a atividade termina de executar todas as atividades que dependem dela são notificadas e começam a executar. Por isso, a ramificação. No cenário anterior tinha-se as Atividade B aguardando a Atividade A, e Atividade C aguardando a Atividade B. Não é o que se deseja.

Nessa figura temos dois cenários: um em que um determinado cliente fica indo na loja diversas vezes para conferir se um determinado produto já está no estoque; e outro em que a loja dispara uma notificação para todos os clientes informando a eles que o produto já está no estoque.

Mas, para compreensão correta desse cenário temos de analisar esse problema do ponto de vista da análise de sistemas. Na primeira figura temos um cliente aguardando a resposta da atividade "o produto está no estoque". E podemos perceber que esse cliente faz a verificação dessa atividade diversas vezes. A cada vez que esse cliente faz essa requisição ele é ocupa recursos do sistema (loja) impedindo que o logista consiga atender outros clientes. Já no cenário 2 da mesma figura nós temos uma situação em que a atividade o produto está no estoque assume a responsabilidade de notificar automaticamente todos os clientes que estão esperando o fim da atividade. Vejamos como ficaria a modelagem das classes:

Esse diagrama de classes nós temos um caso de uso em que a classe a Anunciante (Publisher) faz a excreção dos objetos daclasse Inscritos (Subscriber). Poderíamos também chama-los de Sujeito (Subject) e Ouvinte (Listener), respectivamente. O Anunciante é a Atividade 1, que será executada e os Inscritos são as demais atividades que dependem dela. Então a gente inscreve várias atividades em outra atividade para que elas fiquem aguardando a notificação de que é a primeira atividade encerrou, para que elas possam executar utilizando os dados da primeira atividade.

N código abaixo é definir uma interface para o inscrito ou assinante. Nessa interface tem o método update que será o método acionado pelo método notify do publisher (ou anunciante).

Na classe seguinte demos a implementação de uma classe escrito a que planeta a interface update cujo argumento recebe o anunciante. Nesse método estará a ação para qual o escrito existe. Esta ação poderá ser um envio de e-mail, escrita no log, ou outra especificada na análise do sistema.

 Em seguida temas a interface do anunciante com os seus métodos.


















Comentários

Postagens mais visitadas deste blog

UML e comunicação entre Componentes

(conteúdo gerado com I.A.) Antes de abordarmos o conceito de Componentes, vale a pena analisar como um programador iniciante costuma estruturar uma aplicação. Geralmente, a escolha é construir um monólito tradicional, agrupando todas as classes de domínio (como Categoria, Produto, Compra, Venda, Pagamento, etc.) em uma única pasta de Entidades. Da mesma forma, criam-se pacotes globais para Repositórios, Serviços e Controllers. O grande problema dessa abordagem é que ela gera um forte acoplamento entre as classes e as camadas do sistema. À medida que a aplicação cresce, isso desencadeia uma série de dificuldades: Manutenção e modelagem complexas: As responsabilidades se misturam. Rapidamente, o código passa a ter diversos trechos onde as classes assumem funções que não deveriam ter, tornando a evolução do sistema confusa. Escalabilidade ineficiente: Para escalar o backend, é necessário replicar a aplicação inteira e todo o banco de dados. Além de consumir mais recursos, isso traz o ri...

Quando escolher Flask ou Quart no Python

Atualmente , considerando o suporte assíncrono já presente no Flask, a escolha entre Flask e Quart para uma API Server depende de vários fatores técnicos. Vejamos alguns critérios: Fonte:  https://pt.stackoverflow.com/questions/51268/qual-a-diferen%C3%A7a-entre-comunica%C3%A7%C3%A3o-ass%C3%ADncrona-e-s%C3%ADncrona Suporte Assíncrono : Flask : O Flask oferece suporte assíncrono por meio de extensões de terceiros, como  flask[async] . No entanto, seu desempenho assíncrono é inferior aos frameworks nativamente assíncronos. Quart : O Quart é uma reimplantação do Flask baseada no padrão ASGI (Asynchronous Server Gateway Interface). Ele utiliza E/S assíncrona em todo o código e é mais adequado para bases de código predominantemente assíncronas. Desempenho : Flask : Como aplicação WSGI, o Flask usa um único worker para cada ciclo de solicitação/resposta. Quando uma solicitação chega a uma visualização assíncrona, o Flask inicia um loop de eventos em uma thread, executa a função da vi...

Metodo para criar relacionamento entre tabelas sem dar erro cíclico EFCore

Quando estamos modelando o banco de dados no Entity Framework Core (ou em qualquer outra ferramenta) é muito comum criarmos o erro cíclico. Este erro ocorre devido ao banco de dados não conseguir determinar onde o relacionamento termina, causando um erro de loop. Vejamos uma situação real onde foi gerado esse problema: Um Professor leciona em várias Turmas, Um Professor leciona uma ou mais Disciplinas, Um Professor leciona determinadas Disciplinas em determinadas Turmas, Uma Turma tem muitos Professores, Em todas as Turmas tem 9 Disciplinas. Em todas as turmas podem ter até 9 Professores. Só por essa descrição já é possível perceber que os relacionamentos podem ser complexos de entender. E tem-se também o problema da navegação em via dupla: Professor-Turmas, Turma-Professores. Então, como modelar essas tabelas sem que o banco entre em loop? Para resolver esse problema no Entity Framework Core e evitar o erro de "Multiple Cascade Paths" (caminhos múltiplos de cascata) comum n...