EventService

3 views
Skip to first unread message

Magno Machado

unread,
Jan 26, 2009, 7:01:06 AM1/26/09
to Infra - Integrated Frameworks
Eu dei uma olhada no EventService do Infra, pelo que eu entendi você
se registra informando o tipo de evento sobre o qual você quer ser
notificado, não importando a origem do evento, é isso mesmo?
Se eu quiser ser notificado quand IInfraType especifico for
modificado, então isso não serviria?

Marcos Barreto

unread,
Jan 26, 2009, 9:25:01 AM1/26/09
to infra...@googlegroups.com
Magno existe 2 formas de subscrever para ouvir um evento:

Forma 1: Se registra informando o tipo de evento sobre o qual você quer ser
notificado, não importando a origem do evento;

EventService.Subscribe(TipoEvento, Ouvinte, Filter);

Onde:
  • Tipo de Evento = A interface do evento a ser ouvido;
  • Ouvinte = Objeto que está esperando ser notificado quando o evento acontecer;
  • Filter (opicional) = O objeto que é usado durante o disparo do evento para verificar se o ouvinte deve ou nao receber a notificação;

Forma2: Neste caso pode-se registra para ser notificado diretamente quando um evento ocorrer

Subscribe(TipoEvento, Ouvinte, MetodoInform, NomePropriedade, MetodoFiltro);

Onde:
  • Tipo de Evento = A interface do evento a ser ouvido
  • Ouvinte = Objeto que está esperando ser notificado quando o evento acontecer
  • MetodoInform = Método no ouvinte a ser chamado quando o Evento ocorrer;
  • NomePropriedade (opicional) = Nome da propriedade a ser lida
  • MetodoFilter (opicional) = Método no ouvinte que o event service usará para saber se deve ou não chamar o MetodoInform;
Usa-se NomePropriedade quando queremos garantir que a origem do evento foi uma propriedade de um objeto.

Bem, nem me lembrava mais desta parte, tem muito tempo que foi feita, mas olhando o código acabei percebendo que o TCallBackSubscription.Publish (segunda forma), só está verificando o MetodoFilter no Final em vez de no começo. Vou corrigir e isso já vai eliminar um overhead que deixei sem querer lá.

Bem Magno acho que em resumo, se vc quer tratar um objeto especifico, vc pode usar uma classe de filtro ou um metodo de filtro durante a subscrição. Isso nos dá uma flexibilidade tremenda na questão de notificação.

Abraços

Magno Machado

unread,
Jan 26, 2009, 1:29:52 PM1/26/09
to Infra - Integrated Frameworks
Ouvir o evento vindo de qualquer fonte e depois filtrar para pegar
apenas o que vier da fonte que eu quero, não vai gerar muito
processamento desnecessario?
Não seria possivel colocar algo assim diretamente em alguma classe
basica do Infra, para que eu possa fazer um objeto ser notificado de
eventos ocorridos em um determinado objeto (e somente nesse objeto)?


On 26 jan, 12:25, Marcos Barreto <mrbar2...@gmail.com> wrote:
> Magno existe 2 formas de subscrever para ouvir um evento:
>
> Forma 1: Se registra informando o tipo de evento sobre o qual você quer ser
> notificado, não importando a origem do evento;
>
> EventService.Subscribe(TipoEvento, Ouvinte, Filter);
>
> Onde:
>
>    - Tipo de Evento = A interface do evento a ser ouvido;
>    - Ouvinte = Objeto que está esperando ser notificado quando o evento
>    acontecer;
>    - Filter (opicional) = O objeto que é usado durante o disparo do evento
>    para verificar se o ouvinte deve ou nao receber a notificação;
>
> Forma2: Neste caso pode-se registra para ser notificado diretamente quando
> um evento ocorrer
>
> Subscribe(TipoEvento, Ouvinte, MetodoInform, NomePropriedade, MetodoFiltro);
>
> Onde:
>
>    - Tipo de Evento = A interface do evento a ser ouvido
>    - Ouvinte = Objeto que está esperando ser notificado quando o evento
>    acontecer
>    - MetodoInform = Método no ouvinte a ser chamado quando o Evento ocorrer;
>    - NomePropriedade (opicional) = Nome da propriedade a ser lida
>    - MetodoFilter (opicional) = Método no ouvinte que o event service usará

Solerman Kaplon

unread,
Jan 26, 2009, 2:20:51 PM1/26/09
to infra...@googlegroups.com
Magno Machado escreveu:

> Ouvir o evento vindo de qualquer fonte e depois filtrar para pegar
> apenas o que vier da fonte que eu quero, não vai gerar muito
> processamento desnecessario?
>

Só se precupa com processamento desnecessário quando isso for um
problema ou não. No momento não se sabe, então não se preocupa com isso =P
Na prática, se colocasse algo na parte base em qualquer ponto vai ter
que testar se há algo para notificar (pois não há como saber de
antemão), mesmo que não tivesse ninguém ouvindo nada (mesmo q seja um
boolean, tem q testar, vide notificações de datasets que são por
instância e não por tipo). Para melhorar isso, poderia ser convertido a
parte de notificação dos types base para usar AOP, de modo que só quando
houver o registro de que alguém quer ouvir um tipo de evento, se faz o
attach de um aspecto correspondente ao método e aí passa a disparar. Num
sistema grande, sempre vai haver alguém ouvindo um tipo de evento, entah
o código vai estar sempre ativado (salvo processo em batch ou servidor
de aplicação).

Solerman

Magno Machado

unread,
Jan 26, 2009, 2:26:46 PM1/26/09
to Infra - Integrated Frameworks
>Só se precupa com processamento desnecessário quando isso for um
>problema ou não. No momento não se sabe, então não se preocupa com isso =P
Essa de "só se preocupar com um problema quando o mesmo ocorrer", eu
acho válido, mas tem que ter muito cuidado para não levar ao pé da
letra... No caso, então deveriam ser feitos testes AGORA para avaliar
a performance de diferentes estratégias, e não depois que já estiver
tudo implementado, talvez com gente utilizando, pois aí o custo da
mudança será bem maior.

Magno Machado

unread,
Jan 26, 2009, 2:40:43 PM1/26/09
to Infra - Integrated Frameworks
Tem tambem o impacto na usabilidade..
Se eu adiciono um listener diretamente em um infratype, eu não preciso
ficar testando a origem do evento. Mas se o meu listener recebe
notificações do aplicativo inteiro, eu tenho sempre testar se o evento
que está vindo tem origem no objeto que me interessa.

Imagina se no Delphi em um evento OnClick você recebe notificações de
cliques vindos de TODOS os controles do sistema daí em cada
manipulador de evento você tem que testar "if Sender = xxx then"

Solerman Kaplon

unread,
Jan 26, 2009, 2:52:34 PM1/26/09
to infra...@googlegroups.com
Magno Machado escreveu:
Só se precupa com processamento desnecessário quando isso for um
problema ou não. No momento não se sabe, então não se preocupa com isso =P
    
Essa de "só se preocupar com um problema quando o mesmo ocorrer", eu
acho válido, mas tem que ter muito cuidado para não levar ao pé da
letra... No caso, então deveriam ser feitos testes AGORA para avaliar
a performance de diferentes estratégias, e não depois que já estiver
tudo implementado, talvez com gente utilizando, pois aí o custo da
mudança será bem maior.
  

Voluntários?

Solerman

Magno Machado

unread,
Jan 26, 2009, 5:56:33 PM1/26/09
to Infra - Integrated Frameworks
Fiz alguns testes aqui, de forma bem simplista, nem usei o Infra,
apenas tentei simular as duas situações.
Criei 1000 objetos de onde os eventos se originariam, e 100000 objetos
que receberão os eventos, cada um interessado em apenas um objeto de
origem (ou seja, 100 listeners para cada objeto de origem).
Meu teste consistiu em gerar um evento a partir de cada objeto de
origem e deixar os listeners receberem este evento.
Usando um "EventService" que entrega todos os eventos a todos os
listeners, cabendo a estes verificar se o evento está vindo do local
apropriado, o teste levou aproximadamente 2s

Deixando os listeners dentro dos objetos que eles querem escutar, o
teste levou ~ 13ms.

mrbar2000

unread,
Jan 26, 2009, 8:59:47 PM1/26/09
to Infra - Integrated Frameworks
Beleza Magno, entendi a situação e concordo contigo.
Não podemos esquecer que ser notificado de um evento independente da
origem e podendo filtrar isso é muito importante tambem e útil em
muitos casos.
Mas precisamos realmente de algo que dispare a notificação diretamente
para o objeto afim de reduzir o overhead nestes casos especificos
citados por você.

Hoje temos 2 tipos de Subscriptions (classes capazes de informar
ouvintes sobre o disparo de algum evento ocorrido em outros objetos),
são eles:

TClassicSubscription, cujo create é assim:
constructor Create(const Subscriber: ISubscriber; const Filter:
IInfraFilter);

e TCallBackSubscription, cujo create é assim:
constructor Create(const Subscriber: ISubscriber;
pInform: TSubscriberInform; const pPropertyName: string = '';
pFilter: TSubscriberFilter = nil);

Podemos criar um novo tipo de subscription, o TInjectSubscription,
este cara seria parecido com o TCallBackSubscription mas teria um
create assim:
constructor Create(const pSubscriber: ISubscriber; const
pPublisher IPublisher;
pInform: TSubscriberInform; const pPropertyName: string = '');

Precisaria de um novo método TInfraEventService.Subscribe com os
mesmos parametros do TInjectSubscription, neste método verificaria se
o Publisher já tem um ISubscriptionList injetado nele se nao tiver,
injeta, senão apenas adiciona o subscriber a esta lista.

Vai precisar testar no inicio do TInfraEventService.Publish se o
Event.Source suportar ISubscriptionList (por causa da injeção) então
ele chamaria o Publish de cada um dos Subscribers, senão ele faz o
processo atual.

Talvez para limpar a programação, seja melhor criar um método método
PublishAll(Event) em List_Subscription com a seguinte implementação:

var
vActualSubscription: Integer;
begin
vActualSubscription := 0;
while vActualSubscription < Subscriptions.Count do
begin
Subscriptions[ActualSubscription].Publish(pEvent);
Inc(vActualSubscription);
end;
end;

Pronto Magno, acho que com isso vc tem o que deseja e nós deixamos o
framework de notificação com as outras formas de notificação para os
outros casos.

Solerman Kaplon

unread,
Jan 27, 2009, 5:33:46 AM1/27/09
to infra...@googlegroups.com
Magno Machado escreveu:

> Fiz alguns testes aqui, de forma bem simplista, nem usei o Infra,
> apenas tentei simular as duas situações.
> Criei 1000 objetos de onde os eventos se originariam, e 100000 objetos
> que receberão os eventos, cada um interessado em apenas um objeto de
> origem (ou seja, 100 listeners para cada objeto de origem).
> Meu teste consistiu em gerar um evento a partir de cada objeto de
> origem e deixar os listeners receberem este evento.
> Usando um "EventService" que entrega todos os eventos a todos os
> listeners, cabendo a estes verificar se o evento está vindo do local
> apropriado, o teste levou aproximadamente 2s
>
> Deixando os listeners dentro dos objetos que eles querem escutar, o
> teste levou ~ 13ms.
>

Interessante, podemos dar uma olhada no código que você usou?
Não podemos esquecer também um dos motivos que levou a usar um sistema
de eventos independente de instância: setup de subscribers em objetos
que ficam sendo criados/destruídos algumas vezes sendo criados após o
setup dos subscribers. Ex: você tem um listview monitorando uma lista,
mas a view é criada antes da lista existir, tente fazer isso com um
sistema orientado a instância pra ver a dor de cabeça que é.

Solerman

Magno Machado

unread,
Jan 27, 2009, 7:45:06 AM1/27/09
to Infra - Integrated Frameworks
Se o listview precisa da lista, é de se esperar que quando o listview
for criado a lista já exista.

Bom, como eu disse pro mbar ontem, o event service hoje não está
ruim... ele é bom, mas para outras necessidades, não para monitorar
eventos com uma origem especifica.

Infelizmente não salvei o codigo que escrevi ontem, mas vou tentar
reproduzir hoje à noite para disponibilizar

Solerman Kaplon

unread,
Jan 27, 2009, 2:26:12 PM1/27/09
to infra...@googlegroups.com
Magno Machado escreveu:

> Se o listview precisa da lista, é de se esperar que quando o listview
> for criado a lista já exista.
>

Imagine uma tela com pesquisa onde a lista só é preenchida ao clicar no
pesquisar. Ou mesmo o caso onde a lista eh detalhe de algum outro objeto
(Nota Fiscal -> Itens) e toda a lista é substituída ao trocar de uma NF
para outra. Se só tiver suporte a notificação por instância, vai
precisar fazer unsubscribe da lista antiga e fazer subscribe na lista nova.

Acho que o suporte a instância pode ser feito em cima do suporte
genérico tal qual é feito para as propriedades (e acho q esse já é
suficiente, pois a propriedade é opcional). E tem também a sugestão de
AOP cuja performance precisaria ser testada em cima do Infra para ser
ter melhor idéia, mas em termos de código é muito mais benéfica. Eu
diria que o que se ganha em performance não compensa a diferença de
esforço em programação e manutenção do código em que os eventos são
disparados manualmente (pelo menos para mim, mas eu sou apenas um).

Solerman

Marcos Barreto

unread,
Jan 27, 2009, 6:17:59 PM1/27/09
to infra...@googlegroups.com
Solerman eu nao entendi, vc está dizendo que a sugestão que eu dei de colocar um novo método subscribe no eventservice que subscreve diretamente a um objeto resolveria ou está falando que não deveriamos fazer assim?

Solerman Kaplon

unread,
Jan 28, 2009, 5:14:29 AM1/28/09
to infra...@googlegroups.com
Marcos Barreto escreveu:

Pode ser colocado, o que quero dizer é que a infra-estrutura de eventos
atual permite montar isso sem ter que fazer uma forma especial de
infra-estrutura só para isso. Pelo menos se precisar otimizar depois é
possível, mas a performance inicial vai ser a mesma de antes.

Solerman

Magno Machado

unread,
Jan 28, 2009, 6:15:12 AM1/28/09
to Infra - Integrated Frameworks
Solerman, o problema com eventos orientados ao tipo é que sempre que
você precisar ouvir eventos apenas de uma fonte especifica, você vai
precisar ficar testando a origem do evento, ou ficar escrevendo
filtros... Alem de um possivel problema de performance, tem um outro
problema que merece tanto quanto ou até mais atenção: Isso é CHATO de
fazer. Não adianta ficarmos nos atendo a conceitos ou ideias legais e
esquecermos da praticidade, porque é apenas isso que interessa no dia-
a-dia.
Como eu disse antes, imagina se em todos os eventos da vcl você tiver
que testar o Sender para verificar se o evento vem de onde você quer
que venha.

Sobre o seu exemplo da lista:

>Imagine uma tela com pesquisa onde a lista só é preenchida ao clicar no
>pesquisar.
Bom, a lista existe mesmo antes de clicar no "pesquisar", certo? Então
anexa o listener na lista e pronto, ele vai continuar funcionando
quando a lista for populada.

>Ou mesmo o caso onde a lista eh detalhe de algum outro objeto
>(Nota Fiscal -> Itens) e toda a lista é substituída ao trocar de uma NF
>para outra
Nesse caso não tem jeito, tem que adicionar o listener na nova lista,
mas acredito que pior que isso seria se meu listener recebesse
notificações de toda e qualquer lista presente no sistema.

>e só tiver suporte a notificação por instância, vai
>precisar fazer unsubscribe da lista antiga e fazer subscribe na lista nova.
Veja que em momento algum isso foi proposto... Como eu disse pro
Marcos, o EventService com seu modelo de notificação por tipo é bom,
mas para outras necessidades, não para monitorar um objeto especifico.

Solerman Kaplon

unread,
Jan 29, 2009, 8:06:04 AM1/29/09
to infra...@googlegroups.com
Magno Machado escreveu:

> Solerman, o problema com eventos orientados ao tipo é que sempre que
> você precisar ouvir eventos apenas de uma fonte especifica, você vai
> precisar ficar testando a origem do evento, ou ficar escrevendo
> filtros... Alem de um possivel problema de performance, tem um outro
> problema que merece tanto quanto ou até mais atenção: Isso é CHATO de
> fazer.

Eu disse que um pode ser feito em cima do outro, não que não pode (ou
não seria) feito por instância. O sistema usado pelo MVP é por instância
E dinânico, prevendo ambos os casos que mencionei, e isso só é possível
de forma simples porquê a base não é por instância, mas para o usuário
parece que é, por vc amarra Pessoa.Nome a um edit e ele só vê eventos da
pessoa em questão. No final das contas você não fica trabalhando direto
por eventos.

Solerman


Reply all
Reply to author
Forward
0 new messages