O Backbone, na minha opinião, é maravilhoso. Você não precisa mudar a sua forma de pensar JavaScript e de brinde ganha uma arquitetura extremamente minimalista, produtiva e que não pretende mudar os paradigmas que você já conhece sobre o desenvolvimento front-end. Mas como nem tudo são flores, infelizmente, o Backbone possui um defeito: a sua camada de apresentaçãoview.
Na minha opinião, formada ao longo de dois anos de convívio com a tecnologia, ela apenas funciona e nada mais. Basicamente, ela cumpre o seu papel: consome dados e os exibe. E ponto.
Com o tempo, comecei a perceber que às vezes eu carregava as minhas views com alguma lógica — coisa que afeta diretamente a saúde de escalabilidade do aplicativo, afinal, vide o SRP, a ideia é que a camada de apresentação apenas sirva para exibir coisas, mas nunca jamais processar algum tipo de lógica.
Pois bem, aliando a minha paixão por modularização e desacoplamento, decidi, portanto, substituir a minha camada de apresentação nativa do Backbone por algo novo e que, ao que tudo indica, é superior: o React.
Quando se integra React com Backbone, muita gente ainda utiliza a camada de views para renderizar os componentes do React, o que, na minha opinião, é errado. O ideal é que você substitua, de cima para baixo, a camada de apresentação completamente. Em outras palavras, só e somente só React — esqueça Backbone para a apresentação.
Contudo, estudando bastante a interoperabilidade das duas tecnologias, acabei injetando muita responsabilidade para o mecanismo de rotas que o Backbone oferece. Afinal, por quê?
As teclas de um piano são emissoras de eventos!
No site do React, temos a seguinte chamada: JUST THE UI. Em português brasileiro sobre tradução livre, “Apenas a Interface do Usuário”. Isso significa que quando alguém pressionar um botão (o de enviar um formulário de cadastro, por exemplo), o responsável por fazer algo com os dados escritos pelo nosso cliente NÃO É O BOTÃO. A responsabilidade dele é uma só: avisar alguém que o usuário está submetendo aquele formulário.
Pois bem, eis o porquê da imagem do piano: as teclas em si não emitem os sons que ouvimos. Eles [os sons] são produtos de algum mecanismo emissor, desencadeado pela tecla.
Quando eu trouxe o React para o Backbone, abri minha cabeça e passei a trabalhar consistentemente com Event-Driven Progamming. Quando um botão é pressionado, um evento é engatilhado — e agregado! — através do Backbone.Events para que então ele possa ser escutado por uma entidade qualquer…
[…] entidade qualquer […]
Um amissíssimo meu e também adorador do Backbone, o Renan Carvalho, certa vez encontrou uma informação bem importante no Change Log do Backbone:
0.5.0 — July 1, 2011
[…] Controller was renamed to Router, for clarity. […]
Desde que ele me concedeu essa informação, passei a pensar melhor em como eu poderia aproveitar o mecanismo de rotas — e eis a entidade que estava se responsabilizando por ouvir os eventos emitidos por algum componente escrito sobre o React.
Passei a interpretar o “Router” do Backbone como sendo um Controller só que com um nome “alternativo”. Por isso, os listeners do meu Backbone.Events ficavam no método construtor do meu singular arquivo de roteamento — um simples router.js. Na prática, eu tinha isso:
initialize: function () {
Backbone.history.start({
pushState: true,
hashChange: false,
root: '/'
});
Backbone.Events.on('form:register:submit', function () {
// ...
});
Backbone.Events.on('form:register:clear', function () {
// ...
});
Backbone.Events.on('avatar:upload', function () {
// ...
});
}
E, entre nós, esta solução resolvia muito bem o meu problema. Até que eu tive um sonho…
Eu estava numa sala toda branca e ouvia à clássica Ode to Joy, do Beethoven. No sonho, comecei a cismar que a solução não era suficiente e então desacoplei de forma inerente a responsabilidade de listening do meu Router para módulos autônomos.
Mas uma vez que a plataforma que o Backbone me oferece consiste em Routing, Presenting e Modelling, quem seria o meu módulo autônomo então? Bom, ele não existe. Até agora…
Graças à parte criativa e funcional que habita o meu cérebro nos momentos de bom sono, a resposta era traduzida em um Controller. Eureca! Este é o meu módulo autônomo!
Quando acordei pela manhã de ontem, procurei no Google por um plug-in que eu já sabia que existia: o Backbone.Controller. Antes de sequer fazer o seu download para implementação, dei uma olhada nos seus recursos e posteriormente no código fonte.
Felizmente ou infelizmente, não me agradou. Uma bazuca para formigas: muita coisa desnecessária. Se eu o usasse, estaria contradizendo uma das razões que tenho para utilizar Backbone, que é o peso leve.
Então, decidi por mim mesmo criar o meu Controller. Criei um novo documento de texto e defini a sintaxe para JavaScript. Esse foi o resultado:
var Controller = {
extend: function (obj) {
return function (params) {
if (obj && obj.initialize)
obj.initialize(params);
};
}
};
module.exports = Controller;
Em suma, o script é simples. Criei um objeto chamado Controller e injetei nele um método chamado de extend, que retorna uma function.
A ideia do método extend é uma cópia do design das entidades do Backbone, onde initialize() é o método construtor e somente deve ser invocado caso o mesmo exista.
Para utilização, junto as pastas collections, models e components que compõem o meu aplicativo, eu trouxe à vida a famosa pasta controllers. Lá, criei um arquivo chamado Controller.js — com a primeira letra capitalizada pois, por convenção, o seu retorno é um object — e adicionei a ele o conteúdo acima.
Dentro da mesma pasta, tenho ainda um IndexController.js, que será instanciado quando o meu Router disser. A sua implementação:
var Controller = require ('./Controller')
, MyComponent = require ('../components/MyComponent')
, Popup = require ('../components/Popup');
module.exports = Controller.extend({
initialize: function () {
this.render();
Backbone.Events.on('popup:open', this.openPopup);
},
render: function () {
React.render(new MyComponent, $('.app').get(0));
},
openPopup: function () {
React.render(new Popup, $('.popup').get(0));
}
});
Algumas considerações:
- Para gerenciador de módulos, estou a utilizar o webpack com CommonJS;
- Estou utilizando .JSX para os componentes;
BackboneeReactsão bibliotecas pré-carregadas para todo/qualquer módulo da minha aplicação. Optei por isso pela recorrência de uso.
E por fim, o Router vai agora fazer literalmente jus ao seu nome:
var IndexController = require ('./controllers/IndexController');
module.exports = Backbone.Router.extend({
routes: {
'(/)': 'index'
},
initialize: function () {
Backbone.history.start({
pushState: true,
hashChange: false,
root: '/'
});
},
index: function () {
new IndexController;
}
});
Perceberam? Os eventos ficam por conta dos controladores e não mais do roteador. Agora cada controlador é responsável pela lógica dos seus componentes, desacoplando e modularizando ainda mais o aplicativo.
Para a nossa felicidade, o Controller que criamos vai além: a sua aplicabilidade transcende o seu uso por aqui.
Eu o nomeei como Controller, mas tecnicamente ele é abstrato. Isso significa que aquela pequena porção de código que torna o Controller um produto não é restrita. Você pode fazer daquele fragmento o que você quiser — ele é elástico; ele é a manifestação de uma ideia que pode assumir várias formas.
A implementação foi em JavaScript puro e o ganho foi na economia de uso: ele é somente o que precisa ser, sem tirar; sem colocar.
No mais, para desestressar e homenagear a quem participou do meu sonho que me trouxe tantos ganhos, Ode to Joy para vocês!





