Os eventos são usados ​​apenas para programação da GUI?

57

Os eventos são usados ​​apenas para programação da GUI?

Como você lida com a programação de back-end normal quando algo acontece com essa outra coisa?

user3093620
fonte
6
A propósito, Event Source é um conceito completamente ortogonal à Programação de Eventos. O conceito básico do Event Sourcing é que você armazene "eventos" ou "alterações" no seu sistema, em vez de armazenar o "estado" do seu sistema. Por exemplo, você pode modelar sua conta bancária como a) Seu saldo (STATE) ou b) Uma série de transações (EVENTSOURCE).
Artes
4
Dependendo do uso, um "evento" geralmente é apenas uma forma de retorno de chamada envolvida com açúcar. Os retornos de chamada são usados ​​em qualquer lugar - se você estiver interessado, provavelmente é uma boa palavra-chave para iniciar uma pesquisa.
J ...
10
Também apontarei que, mesmo que você tenha um nível tão baixo quanto um microcontrolador, você encontrará que o hardware interrompe um recurso útil e essencial. Ótimo para sistemas de controle ou IO básico como uma cafeteira. Essas interrupções de hardware realmente não são essencialmente diferentes dos eventos.
Dan
Não! Exemplo prático: eventos do
Nodejs
2
Você está no Windows? Confira o Visualizador de Eventos. Diverta-se.
Marc.2377

Respostas:

106

Não. Eles são realmente úteis para implementar Observadores e garantir que as classes sejam fechadas para modificação.

Digamos que temos um método que registra novos usuários.

public void Register(user) {
    db.Save(user);
}

Então alguém decide que um email deve ser enviado. Nós poderíamos fazer isso:

public void Register(user) {
    db.Save(user);
    emailClient.Send(new RegistrationEmail(user));
}

Mas acabamos de modificar uma classe que deveria estar fechada para modificação. Provavelmente é bom para esse pseudocódigo simples, mas provavelmente o caminho para a loucura no código de produção. Quanto tempo até esse método ter 30 linhas de código pouco relacionadas ao objetivo original de criar um novo usuário?

É muito mais agradável permitir que a classe execute sua funcionalidade principal e promover um evento informando quem está ouvindo que um usuário foi registrado, e eles podem tomar as medidas necessárias (como enviar um email).

public void Register(user) {
    db.Save(user);

    RaiseUserRegisteredEvent(user);
}

Isso mantém nosso código limpo e flexível. Uma das partes geralmente negligenciadas da OOP é que as classes enviam mensagens umas para as outras. Eventos são essas mensagens.

Pato de borracha
fonte
37
Li isso e penso em nosso código "criar reserva" e choro por um tempo e desejo um lugar melhor: '(
sara
11
+1, ótima resposta. Apenas uma pergunta tangencial (isso me incomodou um pouco): existe um motivo especial para você ter iniciado os nomes dos métodos (Registrar, Salvar e Enviar) com letras maiúsculas? É claro que isso não afeta a utilidade dessa resposta.
Pedro A
14
@ Hamsteriffic Sou principalmente um desenvolvedor de C # e essa é a convenção geralmente aceita. Nenhuma outra razão.
precisa
6
@ Hamsterifficas uma adição, o que você chama de lowerCase, mas contém uma maiúscula no meio, geralmente é chamado camelCase, porque tem corcovas no meio. Isso o diferencia de snake_case, onde as palavras em minúsculas são separadas por sublinhados, familiar ao python e à maioria das linguagens de shell, para citar alguns.
Aaron
5
Eventos são um tipo dessas mensagens, eu diria. As chamadas de método também devem ser consideradas como passagem de mensagens.
jpmc26
53

Não.

Um exemplo clássico de eventos usados ​​na lógica que não é da GUI são os gatilhos do banco de dados.

Triggers são códigos executados quando um determinado evento acontece (INSERT, DELETE, etc). Parece um evento para mim.

Esta é a definição de evento da Wikipedia:

Na computação, um evento é uma ação ou ocorrência reconhecida pelo software que pode ser manipulada pelo software. Eventos de computador podem ser gerados ou acionados pelo sistema, pelo usuário ou de outras maneiras. Normalmente, os eventos são manipulados de forma síncrona com o fluxo do programa, ou seja, o software pode ter um ou mais locais dedicados onde os eventos são manipulados, freqüentemente um loop de eventos. Uma fonte de eventos inclui o usuário, que pode interagir com o software por meio de, por exemplo, pressionamentos de tecla no teclado. Outra fonte é um dispositivo de hardware, como um timer. O software também pode acionar seu próprio conjunto de eventos no loop de eventos, por exemplo, para comunicar a conclusão de uma tarefa. Diz-se que o software que altera seu comportamento em resposta a eventos é orientado a eventos, geralmente com o objetivo de ser interativo.

Nem todos os eventos são gerados pelo usuário. Alguns são gerados por um timer como um crontab de um INSERT de banco de dados, como mencionei antes.

A definição também afirma que alguns programas ou sistemas são "orientados a eventos, geralmente com o objetivo de serem interativos" , dos quais se pode derivar que o objetivo ou a utilidade dos eventos não são apenas, mas frequentemente, fornecer interatividade (como GUIs) embora não necessariamente GUIs, pois os programas CLI também podem ser interativos).

Tulains Córdova
fonte
2
Eu sempre penso nisso quando eu ouvi sobre banco de dados dispara: thecodelesscode.com/case/42
Almo
Como um ex-desenvolvedor de DBA agora, eu me encolho toda vez que ouço as pessoas falarem sobre o uso de gatilhos sem considerar o desempenho mais amplo do DB.
Three Value Logic
27

Na verdade, a programação baseada em eventos também é usada para programação de servidores de alto desempenho.

Em uma carga de trabalho típica do servidor, na maioria das vezes o processamento de um resultado realmente vem de E / S. Por exemplo, retirar dados de uma unidade de disco rígido (7200 RPM) pode levar até 8,3 ms. Para um processador moderno de GHz, isso equivaleria a ~ 1 milhão de ciclos de clock. Se uma CPU esperasse os dados de cada vez (sem fazer nada), perderíamos MUITOS ciclos de clock.

As técnicas de programação tradicionais resolvem isso introduzindo vários threads . A CPU tenta executar centenas de threads simultaneamente. No entanto, o problema desse modelo é que, cada vez que uma CPU alterna o encadeamento, são necessários centenas de ciclos de clock para alternar o contexto . Uma troca de contexto ocorre quando a CPU copia a memória local do encadeamento nos registros da CPU e também armazena o registro / estado do encadeamento antigo na RAM.

Além disso, cada thread deve usar uma certa quantidade de memória para armazenar seu estado.

Hoje, houve um empurrão para os servidores que possuem um único encadeamento, executado em um loop. Em seguida, as peças de trabalho são enviadas para uma bomba de mensagens , que atua como uma fila para o encadeamento único (como em um encadeamento da interface do usuário). Em vez de esperar o trabalho terminar, a CPU define um evento de retorno de chamada, para coisas como acesso à unidade de disco rígido. O que reduz a alternância de contexto.

O melhor exemplo desse servidor é o Node.js , que demonstrou ser capaz de lidar com 1 milhão de conexões simultâneas com hardware modesto, enquanto um servidor Java / Tomcat enfrentaria alguns milhares.

ArTs
fonte
2
"Hardware modesto" é um pouco enganador. Você precisará de 8 GB ou mais para o Node, além do que o sistema operacional usar. E se você tem tanta memória, o Tomcat pode lidar facilmente com alguns milhares de conexões. Concedido, há uma grande diferença, mas não é 1000x.
Paul Draper
@PaulDraper não, não pode. E não, não. Você precisa de 8 GB + apenas para a pilha de 8000 threads. Essa é a grande diferença.
Artes
3
O @PaulDraper além de 8 GB é muito modesto para os padrões do servidor. Eu trabalhei em máquinas com 128 GB de RAM e essas nem sequer estão totalmente carregadas. As varas de ram custam mais do que toda a sua máquina.
Artes
depende do tamanho da sua pilha. O padrão Oracle / OpenJDK é de 1 MB na maioria das plataformas para 64 bits e 512K para 32 bits. Se você seguir os padrões, estará correto. Mas o padrão não é como você obtém as conexões do 1M Node;) De qualquer forma, 128K é suficiente; você pode se safar ainda menos. Seriam 1 GB de espaço na pilha para 8000 threads.
Paul Draper
6
Você está enganado. Mesmo com o tamanho padrão da pilha, você precisa apenas de 8 GiB de memória virtual . A memória é confirmada em tempo real, conforme necessário. Normalmente, você só precisa de uma única página por pilha, a menos que esteja realmente usando a memória extra. E, na prática, a maioria dos threads em um sistema desse tipo possui apenas aquelas (geralmente) pilhas de 64 kiB. O uso da memória virtual é importante no sistema operacional de 32 bits, mas não tanto no sistema de 64 bits. Você se depara com outros limites muito antes - como a exaustão da porta TCP, por exemplo :) E onde você acha que essas "pseudo-pilhas" de nós são armazenadas? Isso mesmo, na pilha.
precisa saber é
10

Os eventos também são muito usados ​​na programação de rede (por exemplo, Nginx) para evitar loops de espera ocupada e fornecer uma interface limpa para saber exatamente quando uma determinada operação está disponível (E / S, dados urgentes etc.). Essa também é uma solução para o problema do C10k .

A idéia básica é fornecer ao sistema operacional um conjunto de soquetes (ou seja, conexões de rede) para monitorar eventos, todos eles ou apenas alguns dos quais você está particularmente interessado (dados disponíveis para leitura, por exemplo); quando essa atividade é detectada pelo sistema operacional em um dos soquetes da lista, você recebe uma notificação do evento que estava procurando pela API, que precisará descobrir de onde vem e agir de acordo. .

Agora, essa é uma visão abstrata e de baixo nível, além de ser difícil de obter escala adequada. No entanto, existem muitas estruturas de nível superior que lidam com isso de maneira uniforme entre plataformas: Twisted for Python, Boost.Asio para C ++ ou libevent for C me vem à mente.

edmz
fonte
+1 "loops de espera ocupada caro": em outras palavras, é útil em qualquer processo paralelo que envolva alguma inatividade (em espera), bem como na sincronização entre esses processos (mensagens ou eventos). Grande parte do mundo real funciona.
fr13d
É interessante descobrir que os soquetes foram originalmente projetados como uma forma de IPC em uma única máquina, antes da existência da rede.
5

Os sistemas incorporados quase sempre são inerentemente orientados a eventos, mesmo que não sejam programados explicitamente como tal.

Esses eventos vêm de interrupções de hardware, pressionamentos de botão, leituras de período analógico-digital, expiração do temporizador etc.

Os sistemas embarcados de baixa potência são ainda mais propensos a serem orientados a eventos; eles passam a maior parte do tempo dormindo (CPU dormindo no modo de baixo consumo de energia), esperando que algo aconteça (que "algo" é um evento).

Uma das estruturas mais comuns e populares para sistemas embarcados controlados por eventos é a Quantum Platform (QP) (o QP também funciona no Linux, Windows e em qualquer sistema operacional semelhante ao unix.) As máquinas de estado são uma opção natural para a programação orientada a eventos, como o programa não é "seqüencial" no sentido típico, é um conjunto de "retornos de chamada" que são chamados, dependendo do estado do sistema e do evento atual.

Radiano
fonte
3

Mensagens de evento Gregor Hohpe.

Arquiteturas orientadas a eventos Gregor Hohpe.

Arquitetura SEDA , Galês, Culler, Brewer.

como você lida com a programação de back-end normal quando algo acontece faz essa outra coisa?

Máquina de estados finitos é uma abordagem comum

Given(State.A)
When(Event.B)
Then(State.C)
    .and(Consequences.D)
VoiceOfUnreason
fonte
2
1, essa não é realmente uma resposta coerente e 2, o FSM não são bons exemplos de uso de eventos.
Whatsisname
11
FSM. Tenho certeza de que a religião pastafarian observa uma série de eventos ;-)
fr13d
0

Nos sistemas incorporados, os eventos ocorrem durante as interrupções. Existem muitas fontes de interrupções, desde temporizadores até E / S.

Além disso, o RTOS também pode ter eventos. Um exemplo está aguardando uma mensagem de outra tarefa.

Thomas Matthews
fonte
0

Para sistemas não incorporados, mas algo que eu estava fazendo em C # era o sistema SCADA. Havia muitos eventos vinculados ao que estava acontecendo no armazém quando a carga foi descarregada, parte do evento gerado pelo sistema e outra parte estava gravando um novo estado no banco de dados. É claro que tínhamos algum cliente da GUI, mas era apenas para mostrar o estado do banco de dados que refletia o estado do armazém. Portanto, era um software de servidor back-end baseado em eventos e encadeamentos. Muito difícil de desenvolver.

https://en.wikipedia.org/wiki/SCADA

Mateusz
fonte