• Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
No Downloads

Views

Total Views
1,654
On Slideshare
0
From Embeds
0
Number of Embeds
1

Actions

Shares
Downloads
0
Comments
2
Likes
2

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide
  • Falar do Desafio

Transcript

  • 1. Desmistificando o Cairngorm Eric Cavalcanti [email_address] @ericoc 06 de Fevereiro de 2010
  • 2. Sobre mim
    • Eric Cavalcanti
      • Engenheiro de Software Sênior do C.E.S.A.R (Centro de Estudos e Sistemas Avançados do Recife)
      • Mestre em Engenharia de Software pelo C.E.S.A.R
      • Certificado Scrum Master pela Scrum Alliance
    • Background
      • Trabalha com desenvolvimento de Software há mais de 10 anos .
      • Desenvolvedor Web/Mobile utilizando Java, .NET, PHP e Adobe Flex.
      • Instrutor Adobe Flex da Imedia Brasil.
      • Idealizador e principal desenvolvedor do projeto FireScrum : Ferramenta Open Source de Apoio à Gestão de Projetos utilizando Scrum (Flex e Java)
  • 3. O que é o Cairngorm?
    • Cairngorm é um framework arquitetural baseado no MVC para o desenvolvimento de aplicações em Adobe Flex
  • 4. História
    • Cairngorm foi um dos primeiros frameworks arquiteturais para Adobe Flex
    • Primeira versão foi desenvolvida para Flash, antes mesmo do Flex existir.
    • Foi desenvolvido pela interation::two , na qual foi adquirida pela Macromedia em 2005
    • Última versão estável (2.2.1) foi lançada em 30 de maio de 2007
    • Versão 3 Beta foi anunciada em 5 de outubro de 2009
  • 5. Pontos fortes
    • Fornece uma arquitetura bem definida e baseada em padrões
    • Padrões bem conhecidos como MVC, Singleton e Observer
    • Organização do código
    • Compartilha uma terminologia comum a todos da equipe
    • Encoraja desenvolvedores a identificar, organizar e separar o código baseado em papéis e responsabilidades
    • Facilidade de manutenção
    • Facilita a construção de aplicações desenvolvidas por equipe
    • Bem documentado
  • 6. Pontos fracos
    • O nome! “Cairn... O quê?”
    • É necessário escrever várias classes para um simples Use Case.
    • Curva de aprendizado alta
    • Nem sempre modificar a view pelo model é suficiente em todos os casos
  • 7. Vamos desmistificá-lo!
  • 8.
    • Model – Armazena dos dados e o estado da aplicação
    • View – "Renderiza" o model em uma forma específica para a interação, geralmente uma interface de usuário.
    • Controller – Controla o fluxo da sua aplicação invocando alterações no Model
  • 9. Fluxo Básico do Cairngorm
  • 10. Aplicação de exemplo
  • 11. VO (Value Object)
    • Objeto que armazena somente dados
    • [ Bindable ]
    • public class ContatoVO
    • {
      • public var id:int;
      • public var nome:String;
      • public var telefone:String;
      • public var email:String;
    • }
  • 12. Controller CairngormEvent FrontController Command
  • 13. CairngormEvent Olá! Eu sou o FrontController ! Chame um CairngormEvent sempre que precisar alterar o Model !
  • 14. CairngormEvent Eu sou o AdicionarContatoEvent ! É só me instanciar passando o ContatoVO que deverá ser adicionado e me lançar ! public class AdicionarContatoEvent extends CairngormEvent { public static const EVENT_ID :String = "ADICIONAR_CONTATO_EVENT" ; public var contato:ContatoVO ; public function AdicionarContatoEvent( contato:ContatoVO ) { super ( EVENT_ID ); this . contato = contato; } }
  • 15. CairngormEvent Vejam como é simples me utilizar!! // Cria um contato e atribui as informações var contato:ContatoVO = new ContatoVO(); contato.nome = txtNome.text; contato.telefone = txtTelefone.text; contato.email = txtEmail.text; // Cria um evento do tipo AdicionarContatoEvent informando o contato a ser adicionado var contatoEvent :AdicionarContatoEvent = new AdicionarContatoEvent(contato); // Lança o evento contatoEvent .dispatch();
  • 16. FrontController Eu capturo o evento e tenho um mapeamento que diz qual Command deverá ser chamado para cada evento !
  • 17. FrontController Por exemplo: para um AdicionarContatoEvent eu chamo o AdicionarContatoCommand !
  • 18. FrontController public class AgendaController extends FrontController { public function AgendaController() { addCommand( AdicionarContatoEvent.EVENT_ID, AdicionarContatoCommand ); addCommand( AtualizarContatoEvent.EVENT_ID, AtualizarContatoCommand ); addCommand( ExcluirContatoEvent.EVENT_ID, ExcluirContatoCommand); } } Vejam como eu faço o mapeamento entre um CairngormEvent e um Command !!
  • 19. Command Eu capturo os dados contidos no CairngormEvent que me chamou e altero o Model .
  • 20. Command Eu faço isso através do meu método execute .
    • public class AdicionarContatoCommand implements ICommand
    • {
    • public function execute(event:CairngormEvent): void
    • {
      • //Captura os dados do evento
      • //Atualiza o model
    • }
    • }
  • 21. Epa!! Você não pode dizer que vai atualizar o Model sem antes me apresentar! Eu sou o ModelLocator , o cara que centraliza e armazena as informações do Model . Então o Command deve alterar as informações que EU TENHO !
  • 22. ModelLocator package com.flexforkids.model { ... [ Bindable ] public class AgendaModelLocator { public var contatos:ArrayCollection = new ArrayCollection(); public var contatoAtual:ContatoVO; public static const TELA_PRINCIPAL : uint = 0; public static const TELA_FORM_USUARIO : uint = 1; public var applicationView:uint = TELA_PRINCIPAL; ... private static var _instance:AgendaModelLocator; public function AgendaModelLocator(param: ForceInstance ){} public static function getInstance() :AgendaModelLocator { if (_instance== null ) { _instance = new AgendaModelLocator( new ForceInstance()); } return _instance; } } } class ForceInstance { } Aqui estou eu!
  • 23. Atualizando o Model public class AdicionarContatoCommand implements ICommand { public function execute(event:CairngormEvent): void { var adicionarContatoEvent:AdicionarContatoEvent; adicionarContatoEvent = event as AdicionarContatoEvent; AgendaModelLocator.getInstance().contatos.addItem(adicionarContatoEvent.contato); } } Agora que nosso amigo se apresentou, vejam como eu o atualizo !
  • 24. Views e ModelLocator [ Bindable ] private var _model:AgendaModelLocator = AgendaModelLocator.getInstance(); <view:ContatosView contatos=&quot; { _model.contatos } &quot; > </view:ContatosView> [ Bindable ] public var contatos:ArrayCollection; <mx:DataGrid dataProvider=“ { contatos } &quot; > <mx:columns> <mx:DataGridColumn headerText=&quot; Nome &quot; dataField=&quot; nome ” /> <mx:DataGridColumn headerText=&quot; Telefone &quot; dataField=&quot; telefone &quot; /> <mx:DataGridColumn headerText=&quot; E-mail &quot; dataField=&quot; email “ /> </mx:columns> </mx:DataGrid> E como as views recebem referências aos dados do ModelLocator , elas são automaticamente atualizadas ! AgendaKids.mxml ContatosView.mxml
  • 25. MVC do Cairngorm
    • Model – ModelLocator
    • View – MXML e classes .as
    • Controller – FrontController
      • Command
      • CairngormEvent
  • 26. Revisão do Fluxo Básico do Cairngorm
  • 27. Ei!! Dessa forma que vocês mostraram os dados estão locais . E se esses dados precisarem representar informações vindas de um back-end ? Desenvolvedor
  • 28. Business Delegate Olá! Eu tenho uma proposta pra vocês! Me chamo Business Delegate ! Forneço serviços de back-end ! É só solicitar pra mim, que eu me encarrego de acessar o back-end !
  • 29. O acordo! Então de agora em diante sempre que eu precisar acessar o back-end eu chamo você?
  • 30. O acordo! Exato! Mas tem uma coisa, você precisa me dizer para quem devo responder quando eu trouxer os dados do back-end ! E sendo assim, quem for receber o resultado ( Responder) deverá atualizar o Model .
  • 31. O acordo! Ok! Não se preocupe, no caso, você responderá para mim mesmo. Ou seja, além de Command eu também serei um Responder .
  • 32. Command Turbinado!
    • public class AdicionarContatoCommand implements ICommand, IResponder
    • {
    • private var _model:AgendaModelLocator =
    • AgendaModelLocator.getInstance();
    • public function execute (event:CairngormEvent): void
    • {
      • var adicionarContatoEvent:AdicionarContatoEvent;
      • adicionarContatoEvent = event as AdicionarContatoEvent;
      • var delegate:ContatoDelegate = new ContatoDelegate( this );
      • delegate.salvarContato(adicionarContatoEvent.contato);
    • }
    • public function result (data:Object): void
    • {
      • _model.contatos.addItem(data.result);
      • _model.applicationView = AgendaModelLocator.TELA_PRINCIPAL;
    • }
    • public function fault (info:Object): void
    • {
      • _model.mensagemErro = &quot;Error &quot; + info.fault;
      • Alert.show(_model.mensagemErro);
    • }
    • }
    Aqui estou eu reformulado para utilizar o Business Delegate !
  • 33. Service Locator Pessoal, esse é o Service Locator que trabalha para mim! Ele é quem armazena os RemoteObject , WebService e HTTPService .
  • 34. Service Locator <?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?> <cairngorm:ServiceLocator xmlns:cairngorm=&quot; com.adobe.cairngorm.business.* &quot; xmlns:mx=&quot; http://www.adobe.com/2006/mxml &quot; > <mx:RemoteObject id=&quot; ro &quot; destination=&quot; zend &quot; endpoint=&quot; http://localhost/agendakids/server.php &quot; source=&quot; AgendaService &quot; /> </cairngorm:ServiceLocator> Nesse caso específico, eu tenho um RemoteObject que faz acesso ao PHP via Zend AMF !
  • 35. Business Delegate public class ContatoDelegate { private var _responder:IResponder; private var _service:Object; public function ContatoDelegate( responder:IResponder ) { this ._responder = responder; this ._service = ServiceLocator.getInstance().getRemoteObject( &quot;ro&quot; ); } public function salvarContato(contato:ContatoVO ): void { var token:AsyncToken = this ._service.salvarContato(contato); token.addResponder( this ._responder); } ... } Não vão contar para o Command ! Mas é assim que eu trabalho internamente!
  • 36. Fluxo Completo do Cairngorm
  • 37. Estrutura de Pastas e Arquivos
  • 38. Bem! Eu acho que agora comecei a entender de verdade esse Cairngorm. Mas a pergunta que não quer calar: “É possível reduzir a quantidade de classes necessárias?” Desenvolvedor
  • 39. SIM! Vamos ver uma das possibilidades!
  • 40. Imersão no CairngormEvent
  • 41. Front Controller
    • public class AgendaController extends FrontController
    • {
    • public static const ADICIONAR_CONTATO_EVENT : String = &quot;ADICIONAR_CONTATO_EVENT&quot; ;
    • public static const ATUALIZAR_CONTATO_EVENT : String = &quot;ATUALIZAR_CONTATO_EVENT&quot; ;
    • public static const CONSULTAR_CONTATOS_EVENT : String = &quot;CONSULTAR_CONTATOS_EVENT&quot; ;
    • public static const EXCLUIR_CONTATO_EVENT : String = &quot;EXCLUIR_CONTATO_EVENT&quot; ;
    • public static const EXIBIR_TELA_CONTATO_EVENT : String = &quot;EXIBIR_TELA_CONTATO_EVENT&quot; ;
    • public static const EXIBIR_TELA_PRINCIPAL_EVENT : String = &quot;EXIBIR_TELA_PRINCIPAL_EVENT&quot; ;
    • public static const SELECIONAR_CONTATO_EVENT : String = &quot;SELECIONAR_CONTATO_EVENT&quot; ;
    • public function AgendaController()
    • {
      • addCommand( ADICIONAR_CONTATO_EVENT, AdicionarContatoCommand );
      • addCommand( ATUALIZAR_CONTATO_EVENT, AtualizarContatoCommand );
      • addCommand( CONSULTAR_CONTATOS_EVENT, ConsultarContatosCommand );
      • addCommand( EXCLUIR_CONTATO_EVENT, ExcluirContatoCommand );
      • addCommand( EXIBIR_TELA_CONTATO_EVENT, ExibirTelaContatoCommand );
      • addCommand( EXIBIR_TELA_PRINCIPAL_EVENT, ExibirTelaPrincipalCommand );
      • addCommand( SELECIONAR_CONTATO_EVENT, SelecionarContatoCommand );
    • }
    • }
  • 42. Usando o data do CairngormEvent // Cria um contato e atribui as informações var contato:ContatoVO = new ContatoVO(); contato.nome = &quot;Eric Cavalcanti&quot; ; contato.email = &quot;ecavalcanti@gmail.com&quot; ; contato.telefone = &quot;99999999&quot; ; // Cria um evento do tipo AdicionarContatoEvent informando o contato a ser adicionado var contatoEvent :AdicionarContatoEvent = new AdicionarContatoEvent(contato); // Lança o evento contatoEvent .dispatch(); // Cria um contato e atribui as informações var contato:ContatoVO = new ContatoVO(); contato.nome = &quot;Eric Cavalcanti&quot; ; contato.email = &quot;ecavalcanti@gmail.com&quot; ; contato.telefone = &quot;99999999&quot; ; // Cria um evento do tipo CairngormEvent var contatoEvent :CairngormEvent = new CairngormEvent(AgendaController.ADICIONAR_CONTATO_EVENT); // Atribui o contato ao data do Evento contatoEvent .data = contato; // Lança o evento contatoEvent .dispatch();
  • 43. Usando o data no Command
    • public class AdicionarContatoCommand implements ICommand, IResponder
    • {
    • ...
    • public function execute(event:CairngormEvent): void
    • {
      • var adicionarContatoEvent:AdicionarContatoEvent;
      • adicionarContatoEvent = event as AdicionarContatoEvent;
      • var delegate:ContatoDelegate = new ContatoDelegate( this );
      • delegate.salvarContato(adicionarContatoEvent.contato);
    • }
    • ...
    • }
    • public class AdicionarContatoCommand implements ICommand, IResponder
    • {
    • ...
    • public function execute(event:CairngormEvent): void
    • {
      • var delegate:ContatoDelegate = new ContatoDelegate( this );
      • delegate.salvarContato(event.data as ContatoVO);
    • }
    • ...
    • }
  • 44. Comparando
  • 45. Links
    • Cairngorm - http://opensource.adobe.com/wiki/display/cairngorm/Cairngorm
    • Introducing Cairngorm - http://www.adobe.com/devnet/flex/articles/introducing_cairngorm.html
    • Developing Flex RIAs with Cairngorm microarchitecture - http://www.adobe.com/devnet/flex/articles/cairngorm_pt1.html
    • Getting Started with Cairngorm - http://www.davidtucker.net/category/cairngorm
    • Adobe Cairngorm Plugin - http://opensource.adobe.com/wiki/display/cairngorm/Plugin
    • Enterprise IDE Plugin - http://www.idefactory.com
    • FireScrum- http://www.firescrum.com
    • Bitstrips- http://www.bitstrips.com
  • 46. Obrigado! Eric Cavalcanti [email_address] @ericoc