Gerenciando Aspectos e Eventos
   com Zend Framework 2
           Flávio Gomes da Silva Lisboa




 www.fgsl.eti.br - Livre para reprodução desde que citada a fonte - @fgsl.
Quem sou eu                                      NOVO!




  Autor


Arquiteto e Desenvolvedor
                                                          Certificado
                                    Instrutor


   www.fgsl.eti.br - Livre para reprodução desde que citada a fonte - @fgsl.
Especialista em história em
       quadrinhos http://perse.doneit.com.br
     romocavaleirodoespaco.blogspot.com




www.fgsl.eti.br - Livre para reprodução desde que citada a fonte - @fgsl.
Resumo
O objetivo desta palestra é apresentar o
componente Zend_EventManager, que manipula
tanto     programação      assíncrona     quanto
preocupações transversais em uma aplicação de
uma forma coesa. Será apresentado um resumo
sobre as abordagens de Aspectos, Filtros de
Interceptação, Signal Slots e finalmente Eventos,
para então mostrar a arquitetura e as
funcionalidades do Zend_EventManager.



    www.fgsl.eti.br - Livre para reprodução desde que citada a fonte - @fgsl.
EventManager
Problemas...

   Como nós introduzimos pontos de log/debug
    no código do framework?
   Como nós permitimos a introdução de caching
    sem necessidade de estender o código do
    framework?
   Como nós permitimos a introdução de
    validação, filtragem, verificações de controle de
    acesso, etc., sem necessariamente estender o
    código do framework?
Problemas...

   Como permitimos a manipulação da ordem na
    qual plugins, filtros de interceptação, eventos,
    etc., são disparados.
   ...
   Como resolver tudo isso?
Solução: Programação Orientada
          a Aspectos
   O código define vários “aspectos” que podem
    ser interessantes observar e/ou anexar a partir
    de um consumidor.




                                       www.fgsl.eti.br

                                         Palestras
Solução: Programação Orientada
          a Aspectos
“Um aspecto é uma característica
ligada a muitas partes de um
programa”


“Um aspecto é um interesse
transversal”
               FGSL
Interesses transversais


Interesses transversais geralmente são os
trechos de código espalhados pela
aplicação, como persistência, auditoria,
controle de exceções, e quaisquer
sequências que façam parte de métodos
mas que não consigam ser transformados
em métodos, ou que não possam ser
herdados por todos que precisam deles.
Interesses transversais




Classe A   Classe B   Classe C   Classe D
Reuso limitado em POO
●   A arma de reuso da orientação de objetos é a herança
    de classes.
●   Algumas linguagens limitam a herança (caso de PHP)
    de modo que uma classe filha tem apenas uma classe
    mãe.
●   A herança é total. Tudo o que for público e protegido é
    herdado.




        www.fgsl.eti.br - Livre para reprodução desde que citada a fonte - @fgsl.
Reuso limitado em POO
●   Mas existem trechos de código que se repetem, dentro
    de métodos diferentes.
●   Esses trechos de código ficam espalhados em vários
    métodos de várias classes.
●   Se não existe herança de método, quanto menos de
    trecho!




       www.fgsl.eti.br - Livre para reprodução desde que citada a fonte - @fgsl.
A Tirania da Decomposição
                  Dominante
●   O programa pode ser modularizado de uma forma
    somente a cada vez, e muitos tipos de interesses que
    não se alinham com essa modularização terminam
    espalhados por muitos módulos e emaranhados uns
    com os outros.
    ●   Sebastian Bergmann




         www.fgsl.eti.br - Livre para reprodução desde que citada a fonte - @fgsl.
Solução: Observador de Sujeitos

   Prós
       Simples de entender
       Interfaces SPL são bem
        conhecidas (mas limitadas)
Solução: Observador de Sujeitos
 <?php
 class Building implements SplSubject
 {
      private $observers;
      private $temperature;

     public function attach(SplObserver $observer)
    {
        $this->observers[$observer];
    }

     public function dettach(SplObserver $observer)
    {
         if (in_array($observer, $this->observers))
             unset($this->observers[$observer]);
    }

     public function notify()
    {
        foreach ($this->observers as $observer)
        {
            $observer->notify($this);
        }
    }
Solução: Observador de Sujeitos
   <?php

        public function measureTemperature()
       {
           if ($this->temperature > 40)
           {
               $this->notify();
           }
       }

        public function     setTemperature($temperature)
       {
           $this->temperature = $temperature;
       }

   }
Solução: Observador de Sujeitos



    <?php
    class Fireman implements SplObserver
    {
         public function update(Building $subject)
        {
            $subject->setTemperature(36);
        }
    }
Solução: Observador de Sujeitos

   Contras
       Tipicamente, não pode interromper
        a execução de observadores
        remanescentes
       Requer um sistema para cada
        componente e/ou classe
       Tipicamente, sem     habilidade     para   priorizar
        manipuladores.
Solução: Publicador/Sobrescritor
          de Eventos
   Prós
       Sobrescrita de notificações arbitrárias
       Tipicamente por componente + uso global; em
        muitas linguagens, um único agregador global
       Paradigma bem-conhecido na programação de
        interfaces com o usuário (pense em Javascript)
       Tende a ser um Turing completo
Solução: Publicador/Sobrescritor
     de Eventos (PubSub)
Solução: Publicador/Sobrescritor
      de Eventos (PubSub)
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Exemplo de evento</title>
    <script type="text/javascript" src="../dojotoolkit/dojo/dojo.js"></script>
    <script type="text/javascript" src="eventdojo02.js"></script>
</head>
<body>
    <select id="lista">
        <option>D'Artagnan</option>
        <option>Athos</option>
        <option>Porthos</option>
        <option>Aramis</option>
    </select>
    <button id="incluir">Incluir</button>
</body>
</html>
Solução: Publicador/Sobrescritor
     de Eventos (PubSub)
function identificarEvento(evt)

{

      window.alert("você disparou o evento " + evt.type + " de " + evt.target);

}



dojo.addOnLoad(function() {

dojo.subscribe("eventHandler", identificarEvento);



dojo.connect(dojo.byId("lista"), "change", function(evt){

      dojo.publish("eventHandler",evt);

});

dojo.connect(dojo.byId("incluir"), "click", function(evt){

      dojo.publish("eventHandler",evt);

});

});
Solução: Publicador/Sobrescritor
     de Eventos (PubSub)
   Contras
       Frequentemente, precisa testar o evento fornecido
        para garantir que você pode manipulá-lo.
       Uso global implica em agregação estática e/ou
        dependências estáticas.
       … mas o uso por componente implica em um
        boilerplate para compor em cada classe se ele for
        usado.
       Tipicamente, sem     habilidade   para   priorizar
        manipuladores.
O que é boilerplate?

   boilerplate é o termo usado para descrever
    seções de código que foram incluídas em
    muitos lugares com pouca ou nenhuma
    alteração.
Solução: SignalSlots

   Prós
       Conceito bem conhecido nos círculos de Ciência da
        Computação
       O código emite sinais, que são interceptados por
        slots (vulgos manipuladores)
       Tipicamente, compõe um gerenciador de sinais em
        uma classe, mas pode ser integrado com um
        gerenciador global também
       Geralmente tem algumas habilidades para priorizar
        manipuladores
Solução: SignalSlots

   Contras
       Esse palavreado não é bem conhecido entre
        programadores PHP.
       Argumentos irão variar entre sinais.
       Os mesmos problemas com composição por classe
        e uso estático como vemos em sistemas de
        eventos.
Solução: Filtros de Interceptação

   Prós
       Similar às soluções anteriores, exceto que cada
        manipulador recebe a cadeia de filtros como um
        argumento, e é responsável por chamar o próximo
        na cadeia.
       Frequentemente, o “trabalho” inteiro de um método
        é simplesmente executar um filtro.
       Dependendo do projeto, pode permitir acesso
        global/estático.
Solução: Filtros de Interceptação

   Contras
       Algumas vezes é difícil acompanhar fluxos de
        trabalho complexos.
       Os mesmos problemas com composição por classe
        e uso estático como vemos em sistemas de evento.
       É fácil esquecer de invocar o próximo filtro na
        cadeia.
       Tipicamente, sem habilidade de priorizar filtros.
Mas
 qual a
solução
 afinal?
Nenhuma!
Todas!
Combinação




                               de Poderes
                                            Linka
Wheeler




 Gi                    Ma-Ti                    Kwame
ZF2: EventManager Component

   A cereja do bolo de cada solução, Observer,
    SignalSlot, e Filtros de Interceptação, para
    prover uma solução compreensiva.
   Não pode resolver completamente          os
    problemas de composição/uso estático.
   Nós podemos resolver o problema          da
    composição no PHP 5.4 com traits.
   Há formas elegantes de manipular o uso
    estático.
Termos

   EventManager: objeto que mantém uma
    coleção de ouvintes para um ou mais eventos
    nomeados e que dispara eventos.
   Evento: uma     ação    disparada   por     um
    EventManager.
   Ouvinte: um objeto que reage a um evento.
Como criar
      class EventManager implements EventManagerInterface



 use ZendEventManagerEventManager;

 $eventManager = new EventManager();

 Não precisa criar uma aplicação Zend Framework...
set_include_path(realpath(__DIR__ .
'/../library/Zend') . PATH_SEPARATOR .
get_include_path());

require_once 'Zend/Loader/StandardAutoloader.php';
$loader = new ZendLoaderStandardAutoloader();
$loader->register();
Como adicionar ouvintes

              interface EventInterface




$eventName = 'begin';
$callback = function($event){
$class = get_class($event->getTarget());
echo "event {$event->getName()} triggered
by instance of {$class}";
};

$eventManager->attach($eventName,
$callback);
Como disparar eventos


$eventManager->trigger('begin', $this);
Obrigado

    www.fgsl.eti.br
flavio.lisboa@fgsl.eti.br
         @fgsl

Gerenciando aspectos e eventos com Zend Framework 2

  • 1.
    Gerenciando Aspectos eEventos com Zend Framework 2 Flávio Gomes da Silva Lisboa www.fgsl.eti.br - Livre para reprodução desde que citada a fonte - @fgsl.
  • 2.
    Quem sou eu NOVO! Autor Arquiteto e Desenvolvedor Certificado Instrutor www.fgsl.eti.br - Livre para reprodução desde que citada a fonte - @fgsl.
  • 3.
    Especialista em históriaem quadrinhos http://perse.doneit.com.br romocavaleirodoespaco.blogspot.com www.fgsl.eti.br - Livre para reprodução desde que citada a fonte - @fgsl.
  • 4.
    Resumo O objetivo destapalestra é apresentar o componente Zend_EventManager, que manipula tanto programação assíncrona quanto preocupações transversais em uma aplicação de uma forma coesa. Será apresentado um resumo sobre as abordagens de Aspectos, Filtros de Interceptação, Signal Slots e finalmente Eventos, para então mostrar a arquitetura e as funcionalidades do Zend_EventManager. www.fgsl.eti.br - Livre para reprodução desde que citada a fonte - @fgsl.
  • 5.
  • 6.
    Problemas...  Como nós introduzimos pontos de log/debug no código do framework?  Como nós permitimos a introdução de caching sem necessidade de estender o código do framework?  Como nós permitimos a introdução de validação, filtragem, verificações de controle de acesso, etc., sem necessariamente estender o código do framework?
  • 7.
    Problemas...  Como permitimos a manipulação da ordem na qual plugins, filtros de interceptação, eventos, etc., são disparados.  ...  Como resolver tudo isso?
  • 8.
    Solução: Programação Orientada a Aspectos  O código define vários “aspectos” que podem ser interessantes observar e/ou anexar a partir de um consumidor. www.fgsl.eti.br Palestras
  • 9.
    Solução: Programação Orientada a Aspectos “Um aspecto é uma característica ligada a muitas partes de um programa” “Um aspecto é um interesse transversal” FGSL
  • 10.
    Interesses transversais Interesses transversaisgeralmente são os trechos de código espalhados pela aplicação, como persistência, auditoria, controle de exceções, e quaisquer sequências que façam parte de métodos mas que não consigam ser transformados em métodos, ou que não possam ser herdados por todos que precisam deles.
  • 11.
    Interesses transversais Classe A Classe B Classe C Classe D
  • 12.
    Reuso limitado emPOO ● A arma de reuso da orientação de objetos é a herança de classes. ● Algumas linguagens limitam a herança (caso de PHP) de modo que uma classe filha tem apenas uma classe mãe. ● A herança é total. Tudo o que for público e protegido é herdado. www.fgsl.eti.br - Livre para reprodução desde que citada a fonte - @fgsl.
  • 13.
    Reuso limitado emPOO ● Mas existem trechos de código que se repetem, dentro de métodos diferentes. ● Esses trechos de código ficam espalhados em vários métodos de várias classes. ● Se não existe herança de método, quanto menos de trecho! www.fgsl.eti.br - Livre para reprodução desde que citada a fonte - @fgsl.
  • 14.
    A Tirania daDecomposição Dominante ● O programa pode ser modularizado de uma forma somente a cada vez, e muitos tipos de interesses que não se alinham com essa modularização terminam espalhados por muitos módulos e emaranhados uns com os outros. ● Sebastian Bergmann www.fgsl.eti.br - Livre para reprodução desde que citada a fonte - @fgsl.
  • 15.
    Solução: Observador deSujeitos  Prós  Simples de entender  Interfaces SPL são bem conhecidas (mas limitadas)
  • 16.
    Solução: Observador deSujeitos <?php class Building implements SplSubject { private $observers; private $temperature; public function attach(SplObserver $observer) { $this->observers[$observer]; } public function dettach(SplObserver $observer) { if (in_array($observer, $this->observers)) unset($this->observers[$observer]); } public function notify() { foreach ($this->observers as $observer) { $observer->notify($this); } }
  • 17.
    Solução: Observador deSujeitos <?php public function measureTemperature() { if ($this->temperature > 40) { $this->notify(); } } public function setTemperature($temperature) { $this->temperature = $temperature; } }
  • 18.
    Solução: Observador deSujeitos <?php class Fireman implements SplObserver { public function update(Building $subject) { $subject->setTemperature(36); } }
  • 19.
    Solução: Observador deSujeitos  Contras  Tipicamente, não pode interromper a execução de observadores remanescentes  Requer um sistema para cada componente e/ou classe  Tipicamente, sem habilidade para priorizar manipuladores.
  • 20.
    Solução: Publicador/Sobrescritor de Eventos  Prós  Sobrescrita de notificações arbitrárias  Tipicamente por componente + uso global; em muitas linguagens, um único agregador global  Paradigma bem-conhecido na programação de interfaces com o usuário (pense em Javascript)  Tende a ser um Turing completo
  • 21.
  • 22.
    Solução: Publicador/Sobrescritor de Eventos (PubSub) <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Exemplo de evento</title> <script type="text/javascript" src="../dojotoolkit/dojo/dojo.js"></script> <script type="text/javascript" src="eventdojo02.js"></script> </head> <body> <select id="lista"> <option>D'Artagnan</option> <option>Athos</option> <option>Porthos</option> <option>Aramis</option> </select> <button id="incluir">Incluir</button> </body> </html>
  • 23.
    Solução: Publicador/Sobrescritor de Eventos (PubSub) function identificarEvento(evt) { window.alert("você disparou o evento " + evt.type + " de " + evt.target); } dojo.addOnLoad(function() { dojo.subscribe("eventHandler", identificarEvento); dojo.connect(dojo.byId("lista"), "change", function(evt){ dojo.publish("eventHandler",evt); }); dojo.connect(dojo.byId("incluir"), "click", function(evt){ dojo.publish("eventHandler",evt); }); });
  • 24.
    Solução: Publicador/Sobrescritor de Eventos (PubSub)  Contras  Frequentemente, precisa testar o evento fornecido para garantir que você pode manipulá-lo.  Uso global implica em agregação estática e/ou dependências estáticas.  … mas o uso por componente implica em um boilerplate para compor em cada classe se ele for usado.  Tipicamente, sem habilidade para priorizar manipuladores.
  • 25.
    O que éboilerplate?  boilerplate é o termo usado para descrever seções de código que foram incluídas em muitos lugares com pouca ou nenhuma alteração.
  • 26.
    Solução: SignalSlots  Prós  Conceito bem conhecido nos círculos de Ciência da Computação  O código emite sinais, que são interceptados por slots (vulgos manipuladores)  Tipicamente, compõe um gerenciador de sinais em uma classe, mas pode ser integrado com um gerenciador global também  Geralmente tem algumas habilidades para priorizar manipuladores
  • 27.
    Solução: SignalSlots  Contras  Esse palavreado não é bem conhecido entre programadores PHP.  Argumentos irão variar entre sinais.  Os mesmos problemas com composição por classe e uso estático como vemos em sistemas de eventos.
  • 28.
    Solução: Filtros deInterceptação  Prós  Similar às soluções anteriores, exceto que cada manipulador recebe a cadeia de filtros como um argumento, e é responsável por chamar o próximo na cadeia.  Frequentemente, o “trabalho” inteiro de um método é simplesmente executar um filtro.  Dependendo do projeto, pode permitir acesso global/estático.
  • 29.
    Solução: Filtros deInterceptação  Contras  Algumas vezes é difícil acompanhar fluxos de trabalho complexos.  Os mesmos problemas com composição por classe e uso estático como vemos em sistemas de evento.  É fácil esquecer de invocar o próximo filtro na cadeia.  Tipicamente, sem habilidade de priorizar filtros.
  • 30.
  • 31.
  • 32.
  • 33.
    Combinação de Poderes Linka Wheeler Gi Ma-Ti Kwame
  • 34.
    ZF2: EventManager Component  A cereja do bolo de cada solução, Observer, SignalSlot, e Filtros de Interceptação, para prover uma solução compreensiva.  Não pode resolver completamente os problemas de composição/uso estático.  Nós podemos resolver o problema da composição no PHP 5.4 com traits.  Há formas elegantes de manipular o uso estático.
  • 35.
    Termos  EventManager: objeto que mantém uma coleção de ouvintes para um ou mais eventos nomeados e que dispara eventos.  Evento: uma ação disparada por um EventManager.  Ouvinte: um objeto que reage a um evento.
  • 36.
    Como criar class EventManager implements EventManagerInterface use ZendEventManagerEventManager; $eventManager = new EventManager(); Não precisa criar uma aplicação Zend Framework... set_include_path(realpath(__DIR__ . '/../library/Zend') . PATH_SEPARATOR . get_include_path()); require_once 'Zend/Loader/StandardAutoloader.php'; $loader = new ZendLoaderStandardAutoloader(); $loader->register();
  • 37.
    Como adicionar ouvintes interface EventInterface $eventName = 'begin'; $callback = function($event){ $class = get_class($event->getTarget()); echo "event {$event->getName()} triggered by instance of {$class}"; }; $eventManager->attach($eventName, $callback);
  • 38.
  • 39.
    Obrigado www.fgsl.eti.br flavio.lisboa@fgsl.eti.br @fgsl