sexta-feira, 22 de fevereiro de 2008

Flex, Cairngorm e desenvolvimento progressivo independente de Business / Delegate usando "FakeData Factory"

flex3_fx_124x120 Eu já estava para fazer esse post desde ontem quando passei a adotar essa metodologia que vou apresentar aqui para o devido propósito anunciado como título, mas no momento de pausa para me atualizar do conteúdo de outros blogs que leio, acabei, por pura coincidência, me deparanto com um artigo publicado pelo Ricardo Pettine no Blog da DClick com o título “A EVOLUÇÃO DO MOCK USANDO O CAIRNGORM”, o que me levou a antecipar e mudar um pouco o objetivo desta postagem.

Na verdade, se observarem os 3 comments que fiz no Blog da DClick, vão ver que eu tentei fazer o assunto progredir lá mesmo, mas acabei esbarrando no problema de caracteres do código de exemplo que tentei postar.

(que vergonha a minha... enferrujando no uso de blogs... acho que se eu tivesse colocado um <code>, resolveria talvez).

Bom, vamos lá...

A minha intenção com o que eu fiz e proponho usar, é permitir o desenvolvimento de toda a estrutura de front-end no Flex, usando Cairngorm, independente da parte de Business/Delegate que referem-se justamente à integração com o Back-end.

Não fiz isso baseado em nenhum modelo, nem ao menos pesquisei alternativas. Simplesmente adotei e apliquei para uma necessidade atual que tive em um projeto no qual estamos redefinindo todo um framework de backend (ColdFusion), mas que por já ter todos os dados e requisitos especificados, obviamente permitia o progresso individual do desenvolvimento do Front-end.

Então, são os requisitos para aplicar esse recurso:

  1. Utilizar o framework Cairngorm (embora possa ser aplicado em qualquer situação onde o MVC seja a base de desenvolvimento)
  2. Ter os ValueObjects (VO) ou DataTransferObjects (DTO) definidos.

Com os requisitos atendidos você imediatamente compreenderá que a implementação proposta será aplicada nos Commands, no caso da arquitetura do Cairngorm.

Meu exemplo se baseia em um EmailLoadAllCommand, que por sua vez instanciaria um EmailDelegate e então o método loadAll(). O Result nesse caso trabalharia com o recebimento de uma array de instancias de EmailVO.

Apenas para referência, o método execute() de EmailLoadAllCommand:

public function execute(event:CairngormEvent):void{
var delegate:EmailDelegate = new EmailDelegate(this);
delegate.loadAll();
}

A alteração seria feita exatamente aqui, eliminando neste momento o Delegate e consequentemente a implementação de Responders para tratar o resultado da atividade do Delegate. O código acima alterado para usar a solução proposta pela implementação da classe EmailFakeCollection.as que apresentarei logo após:

public function execute(event:CairngormEvent):void{
//var delegate:PessoaFisicaDelegate = new PessoaFisicaDelegate(this);
//delegate.loadAll();
EmailModel.getInstance().emailCollection = EmailFakeCollection.generate();
}

Repare que estamos no método execute(), alterando o Model diretamente, com o dado solicitado. Neste caso apenas antecipamos o que só ocorrería no result() do responder que sería especificado no instanciamento do Delegate.´

Considerando o exemplo acima, onde o Command teoricamente implementa mx.rpc.IResponder e portanto conterá o método result(), simplesmente mudamos a instrução de associação dos dados ao model de lugar.

A idéia então consiste em que a classe EmailFakeCollection (e todos os eventuais FakeCollections que o sistema necessitar) implementem um método estático generate() que por sua vez retorne um ArrayCollection simulando dados que seríam recebidos no result da classe apontada para ser o responder da aplicação.

Eu pessoalmente preferi implementar um parâmetro para o método estático generate() afim de que eu possa especificar um número de itens que desejo receber como retorno.

No caso do exemplo citado então, a proposta da classe EmailFakeCollection seria a mostrada abaixo, seguido da classe EmailVO para referência apenas:

package br.com.ir.pessoas.factory{
 
import br.com.ir.pessoas.vo.EmailVO;
 
import mx.collections.ArrayCollection;
 
public class EmailFakeCollection{
 
private static var fakeRawData:Array = [
{
id: 1,
email: "macieljr@gmail.com",
padrao: 1
},
{
id: 2,
email: "macieljr@interfacerica.com.br",
padrao: 0
},
{
id: 3,
email: "macieljr@ir.com.br",
padrao: 0
},
{
id: 4,
email: "owner@vpmjr.com",
padrao: 0
},
{
id: 5,
email: "publisher@teclandoalto.com.br",
padrao: 0
}
];
 
public function EmailFakeCollection(){}
 
public static function generate(_qty:int = 0):ArrayCollection{
 
var returnData:ArrayCollection = new ArrayCollection();
 
var totalItems:int = (_qty > 0 && _qty <= fakeRawData.length) ? _qty : fakeRawData.length;
 
for(var i:int = 0; i < totalItems; i++){
 
var email:EmailVO = new EmailVO(
fakeRawData[i].id,
fakeRawData[i].email,
fakeRawData[i].padrao
);
 
returnData.addItem(email);
 
}
 
return returnData;
 
}
 
}
 
}
package br.com.ir.pessoas.vo{
 
import com.adobe.cairngorm.vo.IValueObject;
 
[RemoteClass(alias="br.com.ir.pessoas.EmailVO")]
[Bindable] public class EmailVO implements IValueObject{
 
public var id:int;
public var usuario:String;
public var provedor:String;
public var padrao:uint;
 
public function set email(_email:String):void{
 
if(_email.length){
 
var emailParts:Array = _email.split("@");
this.usuario = emailParts[0];
this.provedor = emailParts[1];
 
}
 
}
 
public function get email():String{
 
return this.usuario + "@" + this.provedor;
 
}
 
public function EmailVO(_id:int = 0, _email:String = "", _padrao:uint = 0){
 
this.id = _id;
this.email = _email;
this.padrao = _padrao;
 
}
 
}
 
}

Eu acabei batizando isso de FakeDataFactory. Nem sei se o nome ja foi usado. Mas agora vou ficar de olho em temas como o abordado pelo Ricardo no blog da DClick para conhecer e aprender melhor formas alternativas de implementar isso.

Por enquanto esta forma me atende completamente. Inclusive, caso a aplicação especificasse a necessidade de criar um Factory (no padrão costumeiro da palavra mesmo) para o recebimento de dados no formato JSON, um XML ou qualquer outro tipo de serialização, eu simplesmente implementaría a classe normalmente e simularia dentro do meu FakeDataFactory o recebimento de dados e instanciamento através desse Factory de desserialização. Depois, na implementação final de integração com o Back-End, bastaría mover a chamada dessa implementação no seu local apropriado.

Qualquer dica à respeito do fundamento, outras formas de implementação e padrões já existentes é muito bem vinda!

Nenhum comentário: