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 deInterceptação, Signal Slots e finalmente Eventos, para então mostrar a arquitetura e as funcionalidades do Zend_EventManager.
Gerenciando aspectos e eventos com Zend Framework 2
1. 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.
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ó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.
4. 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.
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 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.
12. 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.
13. 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.
14. 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.
15. Solução: Observador de Sujeitos
Prós
Simples de entender
Interfaces SPL são bem
conhecidas (mas limitadas)
16. 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);
}
}
17. Solução: Observador de Sujeitos
<?php
public function measureTemperature()
{
if ($this->temperature > 40)
{
$this->notify();
}
}
public function setTemperature($temperature)
{
$this->temperature = $temperature;
}
}
18. Solução: Observador de Sujeitos
<?php
class Fireman implements SplObserver
{
public function update(Building $subject)
{
$subject->setTemperature(36);
}
}
19. 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.
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
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 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.
29. 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.
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);