Post on 26-May-2015
description
www.fgsl.eti.br - Livre para reprodução desde que citada a fonte - @fgsl.
Flávio Gomes da Silva Lisboa
Gerenciando Aspectos e Eventos com Zend Framework 2
www.fgsl.eti.br - Livre para reprodução desde que citada a fonte - @fgsl.
Quem sou eu
Autor
Instrutor
Arquiteto e DesenvolvedorCertificado
NOVO!
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.
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ísticaligada 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
www.fgsl.eti.br - Livre para reprodução desde que citada a fonte - @fgsl.
● 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.
Reuso limitado em POO
www.fgsl.eti.br - Livre para reprodução desde que citada a fonte - @fgsl.
● 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!
Reuso limitado em POO
www.fgsl.eti.br - Livre para reprodução desde que citada a fonte - @fgsl.
● 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
A Tirania da Decomposição Dominante
Solução: Observador de Sujeitos
Prós Simples de entender Interfaces SPL são bem
conhecidas (mas limitadas)
Solução: Observador de Sujeitos<?phpclass 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
<?phpclass 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!
Linka
Ma-Ti Kwame
Wheeler
Gi
Co m
bina
ção
de P
oder
es
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
use Zend\EventManager\EventManager;
$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 Zend\Loader\StandardAutoloader();$loader->register();
class EventManager implements EventManagerInterface
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