Mvc e o Javascript – Introducing Jails

Olá meus caros,

Há um tempo atrás havia começado uma discussão sobre como imaginava uma aplicação usando o design pattern MVC no javascript. Uma das coisas que havia comentado é que achava que o MVC no javascript não deveria ser tão complexo quanto é nas aplicações back-end e que para mim, o MVC no javascript deveria ser visto apenas como uma maneira de organização.

Mostrei como fazer uma simples aplicação back-end usando meu porco conhecimento em php, mostrando que não é necessário refazer um site, ou ter retrabalho para fazer uma aplicação que funcione com ou sem javascript.

Pensando nas coisas que havia comentado, comecei a pesquisar sobre como funcionavam os mais famosos frameworks do mercado, Cake, Rails, .NET MVC, CodeIgniter e alguns outros não tão conhecidos. Também pesquisei sobre os frameworks em javascript que também eram no esquema de Model, Views e Controllers.

Confesso que não gostei muitos dos frameworks javascript que pesquisei, muitos usavam uns esquemas de compilação de código, código em linha de comando para gerar um scaffold etc, tentativas de copiar a maneira como funciona o Rails. Outros tinham muita coisa a ser baixada, às vezes vinham com scripts de teste unitário e tudo mais… Para mim, é tudo uma tentativa de copiar as coisas que já existem em back-end para o front. Com isso a carga de arquivos necessários para fazer uma aplicação funcionar faz com que não compense montar sua aplicação em MVC principalmente se for um site simples.

Portanto, voltei novamente aos drafts passados, aqueles que eu havia postado e vi que para mim era aquele mesmo o caminho, deveria ser uma coisa bem simples, fácil de mexer, intuitivo e ao mesmo tempo escalável. Então montei algumas aplicações usando estes drafts e padronizei o código, construí métodos simples e úteis que eram sempre necessários e dentro desses padrões que sempre persistiam em se repetir montei o que eu acabei chamando de “Jails” . =D Taráaaaaaaaaaaaaa \o/

É claro que o nome Jails é uma brincadeira com o nome Rails porém tem a mesma intenção, colocar o Javascript na direção que considero certa. Portanto Jails significaria Javascript on Rails. Ele não é uma cópia do Rails, mas sofreu uma forte influência e inspiração. Usei alguns frameworks de diferentes linguagens e me baseei neles. O Jails é um grande objeto que pode ser incrementado com plugins e que já vem com alguns poucos plugins acoplados por padrão ou seja, uma aplicação escalável =).

Como o Jails enxerga sua aplicação?

Model : O que é json, dados que necessitam de alguma persistência.

View : Os elementos da tela, eventos, dom, tudo o que está no seu documento.

Controllers : Controladoras de requisições de ações que podem ou não influenciar sua Model, são como se fossem requisições como as que fazemos ao server, normalmente chamam os métodos da View.

– Rotas: Utiliza “Rotas” como os frameworks mais famosos costumam usar, no caso do Javascript, as rotas são usadas com hashs, ex: “#/home”.

Aos códigos então..

Nossa aplicação começa com uma variável global do nosso projeto, que carregará as Models, Views e Controllers. No meu exemplo vou chamar de App. Sempre começando com a Model.

/**
 * @class Model
 */

;(function(global){

	global.App = {};

	Jails.extend('Model', App.Model = {
		data   :{}
	});

})(window)

Aí eu inicío a aplicação como uma variável global, inicio o Model como uma propriedade da App e estendo a Model usando o Jails.
Depois a View:

;(function(Model){
    
    var 
	body,
	template = {
		message :'<h1><strong>@{message}</strong></h1>'
	};

	Jails.extend('View', App.View = {
		
		initialize :function(){
		    body = $('body');
		},
		
		print :function(msg){
		    var m = this.inject({ message :msg }, template.message);
		    body.html(m);
		},

		hello_world :function(param){
		   this.print('Hello World, My Jails Mvc Project!!! { ' +(param||'')+ ' }'); 
		}

	});

})(App.Model)

Passo na chamada do closure App.Model, lá embaixo do código, para poder usar a variável Model, mais sucinta. Toda View precisa de um método initialize que será chamado automaticamente e servirá para setar variáveis iniciais, como eu fiz.

Os outros métodos e o objeto template foram criados conforme minha necessidade. As Views quando estendidas recebem uma função bem útil chamada .inject(). Esse método pega um json como primeiro parâmetro e uma string como segundo parâmetro.

Ele vai pegar a chave do json procurar pela chave na string no padrão @{chave} e substituir pelo valor desta chave. Precisei deste método em TODAS as aplicações que usei o Jails.

E por último, a controller:

/**
 * @class Controller
 */
;(function(Model, View){
    
	Jails.extend('Controller', App.Controller = {

		index :function(param){
			View.hello_world( param );
		}

	});

})(App.Model, App.View)

Aqui, passo os dois objetos já existentes, a View e a Model para a controller como parâmetro e utilizo variáveis de mesmo nome mais sucintas nos parâmetros formais do nosso closure.

Novamente é estendido nosso objeto App, adicionando um novo objeto Controller. Aqui irão as actions que serão disparadas de acordo com nossas requisições. Apenas tenho uma action “Index” na aplicação e nela eu chamo o método hello_world da nossa view, passando um parâmetro como argumento, esse método da View vai pegar o parâmetro e substituir na string da variavel “template” (lá na nossa View).

Eu costumo deixar os três em arquivos separados, muito mais fácil a manutenção.

Beleza, mas agora quem decide qual action chamar ?

As actions são chamadas de acordo com a nossa url que possui um hash, portanto, isso será definido nas rotas:

/**
 * @singleton Routes
 */
;(function( namespace, App ){

	namespace.routes = [	
	
		{ '#!/:param' :function(param){
			App.Controller.index( param );
		}}

	]; 
		
})(Jails, App)

As rotas ficam direto no Jails, não no nosso App. Então passo dois parâmetros no nosso closure, Jails e App.

Elas são um vetor com rotas definidas para serem pegas da url cada vez que a url mudar, esse vetor tem como regra os itens de maior prioridade mais próximos do índice zero. Então a url mais importante deve ser a que estiver no topo.

A partir desta rota nós decidimos qual controller e qual action será chamada. No nosso exemplo acima, cada vez que acessarmos a url !#/:param, a Controller da nossa App dispará a action index passando aquele parâmetro como argumento.

:param não é uma palavra chave, nem na rota nem no parâmetro da função, você como programador decide qual nome chamar, desde que essa variável comece com “:”.

E por último, para decidir visitar essas url’s o Jails possui um objeto .url que contém métodos para nos direcionar às urls e actions que precisamos.

Se quiséssemos acessar a “home” fariámos:

Jails.url.redirect('home');

O método redirect é sobrecarregado, e podemos usá-lo também passando um objeto:

Jails.url.redirect( {home :'Pedro' })

Isso redirecionaria para a url : “/home/pedro”.

Poderíamos também usar string e objeto:

Jails.url.redirect('/sessao', {home :'Pedro'} )

Nos redirecionando para “/sessao/home/pedro”.
Isso é muito útil pois sempre estamos trabalhando com json no javascript, dependendo da ocasião, precisamos acessar a url dependendo de alguma propriedade de um objeto, esta forma quebra um galho, para que não precise iterar nada.

O Jails também possui a propriedade .params. Ela recupera os parâmetros usados na url, estes parâmetros são os que definimos nas rotas.

É…cansativa a leitura eu admito, o Jails pode fazer algumas outras coisas interessantes, mas para o começo cobri o necessário para explicar como utilizo o esquema MVC utilizando esse mini-framework. Após muitos testes muitas refatorações, o código ficou bem pequeno, o que era minha maior preocupação, deixá-lo bem leve e ao mesmo tempo poderoso suficiente para organizar e facilitar a codificação.

Esse post é o começo, nos próximos vou mostrar alguns métodos interessantes, alguma aplicações na vida real, pretendo também fazer um screencast para mostrar o quão fácil e intuitivo ficou programar as aplicações, principalmente que as que utilizam ajax.

Por enquanto, para quem não quiser esperar, pode baixar ou dar uma olhada no projeto, hospedado no svn do google: http://javiani-jails.googlecode.com/svn/trunk/site/index.htm

[update] A pedido do Maurício, para facilitar o compartilhamento do projeto, criei o github:
https://github.com/Javiani/Jails

A documentação utiliza o Jails, assim como a nova documentação do Validator. Gostei tanto da codificação do Jails, que padronizei usando essa plataforma para todas as documentações dos meus projetos. =D.

Fiquem à vontade para criticar, sugerir algo =). Prometo que os próximos posts serão melhores, principalmente o screencast.

Um grande abraço!

Anúncios

5 comentários sobre “Mvc e o Javascript – Introducing Jails

  1. Fala ai, tudo blz?

    Estou baixando o código para dar uma analisada melhor.
    Concordo plenamente com o que você expôs nos primeiros 4 parágrafos e já tinha chegado a mesma opinião.

    Vou acompanhar com muito interesse seus post e screencasts sobre o Jails.
    Uma sugestão inicial seria a troca de google code pelo github, pela praticidade e facilidades que o mesmo oferece.

    Abraços

    • Obrigado Maurício, que bom que pensa da mesma forma, pode ser um sinal para um caminho certo. =D
      Acompanhe sim, mesmo que não concorde com tudo, pode ser uma ajuda a desenvolver algo melhor ou mesmo sugerir algumas melhorias =).

      Tem toda razão, já estou preparando o github do projeto.

      []’s

  2. Parabéns pela iniciativa, até mesmo porque já venho há um tempo procurando essa especialidade para javascript, mas é bem complicado encontrar profissionais falando com clareza sobre isso. Estou acompanhando .

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s