-
Notifications
You must be signed in to change notification settings - Fork 0
MODULES
Para organizar as peças de sua aplicação sugerimos modularizá-la, ou seja, crie módulos. Construa pedaços úteis e relevantes isoladamente, depois conecte tudo para fazer sentido ao seu negócio.
Você pode saber mais sobre o padrão Module Pattern aqui, ou ainda nesse artigo aqui.
Quando optamos por modularizar estamos pensando nos seguintes objetivos:
A) Reaproveitamento
Ao invés de copiar e colar código por aí, escreva uma única vez, e quando precisar novamente simplesmente reutilize-o.
B) Segurança
Você não quer que o código de uma peça interfira em outra. Se em um módulo você tem uma variável x
, de modo algum ela deve interferir na variável x
de outro módulo. Quando nós garantimos essa premissa, estamos escrevendo código seguro.
C) Organização
É muito mais fácil você encontrar as coisas quando elas estão catalogadas, ou seja, a chance de você encontrar uma agulha espalhada em um palheiro é muito remota, por outro lado, se você tem uma caixa de agulhas as coisas já se tornam mais fáceis.
D) Simplificação
Se sua aplicação total tem 20.000 (vinte mil) linhas de código, e tudo está em um arquivo, quando você precisar encontrar e mudar alguma coisa, você precisará ter muito cuidado.
Porém, se essas mesmas 20.000 (vinte mil) linhas de código estão bem organizadas em módulos maiores, e submódulos menores, no final você terá cada funcionalidade em arquivos isolados bem menores (tipo umas 200 linhas de código). É muito mais fácil dar manutenção em um aquivo de 200 (duzentas) linhas de código do que em um de 20.000 (vinte mil), fica bem mais simples.
Construa sua aplicação em módulos e você alcançará todos esses objetivos.
Pra te ajudar nessa tarefa de modularizar sua aplicação, a biblioteca jQuery TOAD lhe dá algumas ferramentas que você vai conhecer agora.
Por questões didáticas, em todos os próximos exemplos vamos considerar que estamos trabalhando em uma aplicação chamada
E5R
(esse é meu jabá) e definimos nossa variável__TOAD__
com esse nome para que seja nosso módulo principal.
A primeira ferramenta é o utilitário namespace
. Com essa ferramenta você cria um espaço de nomes, e assim pode colocar o que quiser lá dentro, e depois poderá encontrá-lo para reutilização simplesmente importando esse nome de onde precisar.
/**
* @param {string} name - Nome do espaço de nomes
* @param {function} factory - Função que cria o espaço de nomes
*/
E5R.namespace = function(name, factory){};
Exemplo:
E5R.namespace('app/utils', function(){
/* seu código aqui */
});
Quando você garante que todo o seu código de aplicação está envolvido dentro de um namespace, você consegue garantir primeiramente a segurança de seu código, ou seja, todas as variáveis definidas aqui não irão vazar para fora do escopo.
Mas isso só é totalmente verdade se você estiver no modo estrito, por isso vamos acordar aqui que você sempre definirá um namespace assim:
E5R.namespace('app/utils', function(){
"use strict";
/* seu código aqui */
});
Porque isso é importante?
Esperimente executar o seguinte código:
E5R.namespace('app/utils', function(){
MINHA_VARIAVEL = "Meu valor";
});
Se você inspecionar no navegador seu objeto window
verá que existe lá a propriedade MINHA_VARIAVEL
, ou seja, essa variável vazou.
Agora se você executar esse código:
E5R.namespace('app/utils', function(){
"use strict";
MINHA_VARIAVEL = "Meu valor";
});
Perceberá que o navegador levantará uma exceção parecida com "Variável não definida no modo strict"
. O seu código falhará ao invés de tentar inferir o que você queria fazer.
Isso ocorreu porque o que queríamos era DEFINIR uma variável chamada MINHA_VARIAVEL
e ao mesmo tempo ATRIBUIR o valor "Meu valor"
a ela.
Só que o código de DEFINIÇÃO requer um var
antes do nome da variável.
var MINHA_VARIAVEL = "Meu valor";
PS: Aqui nós estaremos sempre tratando de ECMAScript5 e não o novo padrão ECMAScript6. Por isso não iremos falar de
let
ouconst
.
Já um código de ATRIBUIÇÃO não requer o var
, só requer uma variável já DEFINIDA.
Porém quando não estamos no modo estrito, podemos simplesmente ATRIBUIR uma variável, se ela ainda não foi DEFINIDA isso será feito automaticamente. Já com o modo estrito abrimos mão dessa "facilidade" para não cair em "armadilhas".
Voltando ao exemplo.
E5R.namespace('app/utils', function(){
"use strict";
/* seu código aqui */
});
Agora sim, com essa assinatura estamos escrevendo código seguro. Mas isso também poderia ser conseguido de outra forma que você talvez já conheça:
// Opção 1
(function(){
"use strict";
/* seu código aqui */
})();
// Opção 2
;function(){
"use strict";
/* seu código aqui */
}();
// Opção 3
+function(){
"use strict";
/* seu código aqui */
}();
// Opção 4
-function(){
"use strict";
/* seu código aqui */
}();
A vantagem de usar E5R.namespace
é que além do isolamento de escopo também criamos um espaço de nomes.
Criar um espaço de nomes não adianta muita coisa se você não puder colocar coisas nesse espaço, e também pegar coisas desse espaço quando precisar.
O simples fato de colocar seu código envolto a um E5R.namespace
não é suficiente. Você precisará dizer o que quer colocar dentro do namespace
, e isso é feito exportando objetos.
Para exportar um objeto basta "pendurá-lo" no único parâmetro da nossa função factory. Você não deve saber do que estamos falando porque omitimos o parâmetro no exemplo anterior. Então vamos finalizar aqui nossa assinatura de namespace de uma vez por todas:
E5R.namespace('app/utils', function(exports){
"use strict"; /* ^
|___( aqui ) */
/* seu código aqui */
});
Observe que agora nossa função factory tem um único parâmetro chamado exports
. Na verdade esse nome pode ser o que você preferir, o nome exports
só é bem sugestivo.
Então agora sempre que você precisar deixar algo no namespace
, basta exportá-lo assim:
E5R.namespace('app/utils', function(exports){
"use strict";
exports.DEFAULT_MESSAGE = 'Hello {name}!';
exports.showAlert = function(message) {
alert(message);
}
});
Agora você já tem um módulo de utilitários da aplicação no espaço de nomes app/utils
, e ele conta com uma variável DEFAULT_MESSAGE
e também um método showAlert
que exibe uma mensagem com o alert
padrão do navegador.
Agora que já conseguimos criar nossos módulos em espaços de nomes distintos, só precisamos aprender a reutilizar esses objetos que exportamos em outros lugares.
E é aí que entra a segunda ferramenta, o utilitário require
. Com essa ferramenta você carrega os objetos de um espaço de nomes para então poder usá-los.
/**
* @param {string} namespace - Nome do espaço de nomes
*/
E5R.require = function(namespace){};
Exemplo:
E5R.namespace('app/ui', function(exports){
"use strict";
var utils = E5R.require('app/utils'),
message = utils.DEFAULT_MESSAGE.replace('{name}', 'world');
utils.showAlert(message);
});
Ao executar esse código você verá a mensagem "Hello world!"
sendo exibida em seu navegador. E isso graças a reutilização de código e comunicação entre os seus dois módulos do sistema, app/utils
e app/ui
.
É importante ressaltar que o namespace
é a nossa forma de organizar as peças de nosso software. Ainda que você tenha código espalhado em vários arquivos, o que importa no fim é o namespace
.
Vamos supor que o nosso primeiro exemplo estava em um arquivo chamado show-message-util.js
e você também tem um outro arquivo que faz a mesma coisa só que ao invés de um alert
exibe a mensagem no console
, esse poderia ser o arquivo show-console-util.js
:
file:
show-message-util.js
E5R.namespace('app/utils', function(exports){
"use strict";
exports.DEFAULT_MESSAGE = 'Hello {name}!';
exports.showAlert = function(message) {
alert(message);
}
});
file:
show-console-util.js
E5R.namespace('app/utils', function(exports){
"use strict";
exports.showConsole = function(message) {
console.log(message);
}
});
Agora você tem 2 (dois) arquivos definindo cada um o seu próprio utilitário. Você não precisa saber da existência dos dois arquivos quando estiver lá no módulo app/ui
, bastará saber que tudo está no namespace app/utils
e isso será o suficiente para tirar proveito dos dois códigos:
E5R.namespace('app/ui', function(exports){
"use strict";
var utils = E5R.require('app/utils'),
message = utils.DEFAULT_MESSAGE.replace('{name}', 'world');
utils.showAlert(message);
utils.showConsole(message);
});
Observe que agora você terá a mensagem sendo exibida tanto no alert
do navegador, quanto no console
do mesmo, e isso ficou transparente para o uso no módulo app/ui
, porque no final o que requirea é o namespace
.
A biblioteca jQuery TOAD te ajuda com reaproveitamento, segurança, organização e simplificação do código com as ferramentas de modularização, a saber:
- namespace
- exports
- require
E como nossa proposta não é somente o código da biblioteca em si, mas também essa documentação, aproveitamos para recomendar mais duas coisas nessa seção de modularização:
1 - Use sempre o modo estrito.
2 - Nomeie seus espaços de nomes (namespace
) como se fossem diretórios lógicos.
Ex:
Imagine que você tem uma visão lógica da sua aplicação com módulos utilitários, financeiro e comercial. Se fosse dividir em um diretório seria algo como:
app/
utilitarios/
financeiro/
comercial/
Os seus módulos por sua vez poderiam ser: "app/utilitarios"
, "app/financeiro"
e "app/comercial"
.
Nada impede você de usar outra notação porque os nomes são livres, mas fica a nossa recomendação.
jQuery TOAD - O velho e querido jQuery - Um tributo ao jQuery