Archive

Posts Tagged ‘Design Patterns’

[tradução] Iniciando com o Cairngorm, parte 2

May 22nd, 2008 Ved 3 comments
Créditos: esta série sobre o Cairngorm foi originalmente escrita por David Tucker (www.davidtucker.net), a quem dou todos os créditos. Esta é uma livre tradução do original que pode ser encontrado aqui

Recapitulando: Na Parte 1, discuti a implementação básica e o uso do padrão Model Locator. Este padrão é um dos muitos padrões de projeto contidos no Cairngorm (micro-arquitetura). O Model Locator será usado também na Parte 2, então, assumo que você está familiarizado com os conceitos apresentados na Parte 1 deste tutorial. Neste momento, não trabalharemos ainda com uma completa aplicação do Cairngorm, o que será feito na parte 3.

Parte 2 – Usando o Model Locator para gerenciar a camada View

No tutorial anterior você aprendeu as vantagens da utilização do Model Locator para gerenciar dados na aplicação, contudo, a vantagem do ModelLocator vai além do gerenciamento de dados. Pode também gerenciar a camada view de uma aplicação. Para entender como o gerenciamento da view se comporta no Cairngorm, você precisa primeiro criar um projeto chamado ViewManager e nomear a aplicação principal como Main.mxml. Para este projeto, você também precisará adiciona o swc do Cairngorm (Cairngorm.swc) no seu BuildPath (como descrito na Parte 1). Também será necessário criar duas pastas dentro da pasta src: view e model. Quando estiver completo, seu projeto se parecerá com a imagem 1, abaixo:

Em seguida, precisaremos pegar o código do ModelLocator do tutorial anterior e colocar na aplicação. O código está abaixo para sua conveniência.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package model {
	import com.adobe.cairngorm.model.IModelLocator;
	[Bindable]
	public class ViewModelLocator implements IModelLocator {
		// Single Instance of Our ModelLocator
		private static var instance:ViewModelLocator;
		public function ViewModelLocator(enforcer:SingletonEnforcer) {
		if (enforcer == null) {
				throw new Error( "You Can Only Have One ViewModelLocator" );
			}
		}
		// Returns the Single Instance
		public static function getInstance() : ViewModelLocator {
			if (instance == null) {
				instance = new ViewModelLocator( new SingletonEnforcer );
			}
			return instance;
		}
		//DEFINE YOUR VARIABLES HERE
	}
}
// Utility Class to Deny Access to Constructor
class SingletonEnforcer {}

Exemplo 1 – O ModelLocator da Parte 1

Se você precisar de informações sobre o ModelLocator, por favor retorne à Parte 1 deste tutorial.

O único item a ser modificado no ModelLocator é o Package. Para este projeto, você colocará o ModelLocator na pasta model, então, o caminho do package apenas precisa ser model (package.model, o que já foi feito acima). Também será necessário adicionar uma variável ao ModelLocator. Esta variável se chamará worflowstate e será do tipo uint. A declaração será assim:

1
public var workflowState:uint = 0;

Exemplo 2 - Definindo a variável workflowState

Esta variável será usada para controlar a camada view da sua aplicação. A forma mais comum de aplicar este método é usar um ViewStack. Se você não é familiarizado com o ViewStack, leia antes esta informação. Um ViewStack possui uma propriedade chamada selectedIndex. Este valor numerico define qual filho é visível dentro do ViewStack. Considere o seguinte código:

1
2
3
4
5
6
7
8
9
10
11
<mx:ViewStack id="myViewStack">
  <mx:HBox id="box1">
	<mx:Label text="I am Box 1" />
  </mx:HBox>
  <mx:HBox id="box2">
	<mx:Label text="I am Box 2" />
  </mx:HBox>
  <mx:HBox id="box3">
	<mx:Label text="I am Box 3" />
  </mx:HBox>
</mx:ViewStack>

Exemplo 3 – Um exemplo básico de ViewStack

Inicialmente o valor do selectedIndex é 0 (zero). Com isso, o box1 deve ser visível mas não os demais. Se você inserir o seguinte comando:

1
myViewStack.selectedIndex = 1;

Exemplo 4 – Setando manualmente o selectedIndex

então o box chamado box2 será visível. Contudo, se você aplicar o ModelLocator a este conceito, você deverá usar a variável workflowState para setar a propriedade selectedIndex. Associando o selectedIndex ao valor de workflowState, você terá controle completo sobre o que será visível dentro do ViewStack, a partir do seu ModelLocator.

1
2
3
<mx:ViewStack id="myViewStack" selectedIndex="{modelLocator.workflowState}">
  ...
</mx:ViewStack>

Exemplo 5: Associando o selectedIndex à variável workflowState

Definindo constantes para uma melhor codificação

É muito simples manipular a camada view usando este método, contudo, seria um código potencialmente confuso. Por exemplo, pense que você tem o seguinte:

- Um ViewStack com dois filhos: uma tela de Login e uma tela de Boas Vindas
- O selectedIndex do ViewStack está associado à variável workflowState
- Um botão de login que dispara a ação mostrada no Exemplo 4

Isso pode funcionar perfeitamente, mas não considera nenhuma modificação, Se outro filho for adicionado ao ViewStack, pode bagunçar a ordem. Necessitamos então uma maneira melhor de setar o selectedIndex. Para implementar, é necessário apenas definir constantes dentro do ModelLocator.

1
2
3
4
5
//DEFINE YOUR VARIABLES HERE
public var workflowState:uint = 0;
// DEFINE VIEW CONSTANTS
public static const LOGIN_SCREEN = 0;
public static const WELCOME_SCREEN = 1;

Exemplo 6 - Definindo constantes View no ModelLocator

Utilizando este método, você tem apenas que modificar o valor em um local se o número do filho ou a posição dos filhos forem modificadas no ViewStack. Agora, você pode associar ao botão de login a seguinte ação ao evento click:

1
myViewStack.selectedIndex = ViewModelLocator.WELCOME_SCREEN;

Exemplo 7: modificando a view com uma constante definida

Utilizando este método você não somente proteje sua aplicação contra futuras mudanças, como deixa seu código muito mais lógico e didático. Outro desenvolvedor poderá olhar o código e entender o processo.

Screencast deste tutorial em breve!

[tradução] Iniciando com o Cairngorm – Parte 1

May 18th, 2008 Ved 4 comments
Créditos: esta série sobre o Cairngorm foi originalmente escrita por David Tucker (www.davidtucker.net), a quem dou todos os créditos. Esta é uma livre tradução do original que pode ser encontrado aqui

Falei sobre o Cairngorm 2.2 no Flex Bootcamp na Max da semana passada. Muitas pessoas estavam interessadas no Cairngorm, mas só tive 10 minutos para explicar o básico. Acho que a forma mais fácil de ajudar as pessoas é fazer uma rápida série de posts falando sobre os benefícios do Cairngorm. Esta série combinará artigos e videos.

Nota do tradutor: os videos não serão traduzidos. Você pode baixá-los e assisti-los em inglês, no link. De qualquer forma, tentarei fazer um ou outro screencast para mostrar o código escrito em funcionamento.

Importante: não me considero “o expert” em Cairngorm – estou longe disso. Entretanto, tenho usado Cairngorm em muitos projetos grandes (tanto na Georgia Tech quanto em meus próprios negócios). Estou aberto a correções se você achar que eu cometi um erro neste projeto. Se você quer aprender com “os experts”, verifique: Steven Webster, Alistair McLeod, Alex Uhlmann e Peter Martin.

Nota: o pessoal da Adobe Consulting (que desenvolveu o Cairngorm) está analisando o framework como um todo. É possível (atualmente provável) que algumas coisas mudem no futuro. Uma das áreas que especificamente poderão ser mudadas é o Model Locator.

Parte 1 – Iniciando com o Model Locator

O padrão Model Locator é usado no Cairngorm, mas você não precisa de uma implementação completa para usar este padrão. Primeiro vamos falar sobre os benefícios de usar um Model Locator.

Um Model Locator é um repositório centralizado para todos os dados que são necessários por toda sua aplicação. Seus dados existirão dento de uma classe Singleton. Esta classe pode ser instanciada apenas uma vez. Mas porque isso é tão importante? Deixe-me exemplificar.

Tenho no trabalho mini-blocos de notas que uso para escrever alguns dados enquanto eu trabalho. Algumas vezes eu perco um destes blocos de notas – pego um novo mas encontro o antigo, que havia perdido. Depois de um tempo usando muito ambos os blocos de notas, é muito difícil saber em qual bloco está contida determinada informação, que escrevi a uma semana atrás. Este é um exemplo simples – mas imagine se eu tiver 20 blocos de notas? Isso me deixaria louco!

Da mesma forma você pode ter uma classe que é instanciada 20 vezes dentro de sua aplicação (mesmo que você não queira). A maneira mais fácil de eliminar o problema é usar um “singleton”. Uma classe singleton é uma classe que nunca é criada da forma tradicional (nt: ou seja, new Classe()). Ela possui uma regra principal: não pode existir mais de uma vez em qualquer ponto na sua aplicação. Mas como fazer isso? Mostrarei no exemplo Model Locator.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package net.davidtucker.CairngormSample.model {
	import com.adobe.Cairngorm.model.IModelLocator;
	[Bindable]
	public class ModelLocator implements IModelLocator {
		// Unica instancia do ModelLocator
		private static var instance:ModelLocator;
		public function ModelLocator(enforcer:SingletonEnforcer) {
		if (enforcer == null) {
				throw new Error( "Você pode ter apenas um ModelLocator" );
			}
		}
		// Retorna a instância singleton
		public static function getInstance() : ModelLocator {
			if (instance == null) {
				instance = new ModelLocator( new SingletonEnforcer );
			}
			return instance;
		}
		//DEFINA SUAS VARIÁVEIS AQUI
	}
}
// Classe utilitária para proibir o acesso à classe construtora
class SingletonEnforcer {}

Este código pode parecer um tanto assustador no início, mas acredite: não é tão difícil quanto pode parecer. Primeiro, temos nossa declaração de pacote (package) e importamos algumas classes. Neste momento sabemos que iremos precisar da interface IModelLocator. Para usá-la você precisará do SWC do Cairngorm, que pode ser encontrado aqui: Cairngorm. Note também que você pode construir um Model Locator sem o Cairngorm e eu faço isso frequentemente em pequenos projetos (simplesmente deixando de fora o ‘implements IModelLocator’ e ‘import com.adobe.Cairngorm.IModelLocator’ da minhas classe Model Locator).

1
2
3
4
[Bindable]
public class ModelLocator implements IModelLocator {
	 // Unica instancia do ModelLocator
	 private static var instance:ModelLocator;

Em seguida temos nossa definição da classe. É muito importante usar a metatag Bindable exatamente antes da definição da classe. Isso tornará possível que todas as variáveis definidas dentro do ModelLocator sejam usadas para “bindar”. Seguiremos em frente e criaremos uma variável. Ela será chamada de “instance” e será do tipo ModelLocator. Essa será a variável onde vamos guardar nossa única instância da classe. Também será marcada como estática (static). Se você não sabe o que é static, não se preocupe: será discutido na próxima lição.

1
2
3
4
5
public function ModelLocator(enforcer:SingletonEnforcer) {
	 if (enforcer == null) {
		  throw new Error( "Você pode ter apenas um ModelLocator" );
	 }
}

O próximo passo é o contrutor. Ele recebe apenas um argumento – enforcer. Você vai ver que tem como tipo SingletonEnforcer que é definido exatamente após a nossa classe. Aqui está a lógica por trás da técnica:

- Em Actionscript, quando se declara uma classe abaixo da classe principal, esta estará disponível apenas para aquela classe (a principal). Muitas pessoas chamam esta técnica de Classes Utilitárias (mas outras pessoas utilizam o termo para definir um escopo muito maior).
- Se o método construtor requer este argumento, então a classe principal pode criar apenas uma instância dela mesma, porque não temos acesso direto à classe SingletonEnforcer. Apenas a classe principal tem acesso.
- Não acessaremos nossa classe da maneira tradicional, usando o new porque não podemos chamar o construtor. Mostrarei em instantes como fazer.

Uma vez que estamos dentro do método construtor, temos umas poucas linhas que fazem as coisas funcionar como planejado. O if verifica se temos um enforcer válido passado como parâmetro. Caso não exista, dispara uma exceção informando que “Você pode ter apenas um ModelLocator”.

1
2
3
4
5
6
7
// retorna a instância singleton
public static function getInstance() : ModelLocator {
	 if (instance == null) {
		  instance = new ModelLocator( new SingletonEnforcer );
	 }
	 return instance;
}

A função “getInstance” é como acessamos nosso ModelLocator a partir de nossa aplicação. Essa função simplesmente retorna a instância da classe. Se ainda não existe, ela é criada. Podemos então acessar nosso ModelLocator usando o seguinte código:

1
var model:ModelLocator = ModelLocator.getInstance();

Baixe aqui o código da aplicação

Veja aqui o screencast para este artigo