Init.js: Um Guia para o Porquê e Como da Stack Completa do JavaScript

View all articles

A história

Então, você e seu sócio tiveram esta ótima ideia para um negócio, certo?

Você tem adicionado funcionalidades ao sistema mentalmente.

Frequentemente você pergunta a potenciais clientes a opinião deles, e todos eles amam.

Ok, então as pessoas querem isso. Há até mesmo algum dinheiro para ser ganho. E a única razão deles não poderem ter é por que você não implementou—ainda.

Então finalmente você se senta um dia e diz: “Vamos fazer isso!”. Logo você está tentando descobrir como implementar a lógica de negócio da sua aplicação, o recurso matador que levará o produto adiante: você tem uma ideia de como fazer e você sabe que você pode fazer.

“Feito! Funciona!”, você diz. Sua prova de conceito é um sucesso! Tudo que falta é empacotar em uma aplicação web.

“Ok, vamos criar o site,” você diz.

E depois você percebe a verdade: você precisa escolher uma linguagem de programação; você precisa escolher uma plataforma (moderna); você precisa escolher alguns frameworks (modernos); você precisa comprar (e configurar) armazenamento, bancos de dados e provedores de hospedagem; você precisa de uma interface administrativa; você precisa de um sistema de permissões; você precisa de um gerenciador de conteúdo.

Você quer que seja leve, você quer ser ágil. Você quer usar tecnologias que o ajudarão a ter sucesso a curto e longo prazo. E elas nem sempre são fáceis de escolher.

Você tem dezenas e dezenas de decisões arquiteturais para tomar. E você quer tomar as decisões certas: você quer usar tecnologias que permitem desenvolvimento rápido, iteração constante, eficiência máxima, velocidade, robustez, e mais. Você quer que seja leve, você quer ser ágil. Você quer usar tecnologias que o ajudarão a ter sucesso a curto e longo prazo. E elas nem sempre são fáceis de escolher.

“Estou sobrecarregado”, você diz, sentindo-se de fato sobrecarregado. Sua energia não é mais a mesma. Você tenta juntar os pedaços, mas é trabalho demais.

Sua prova de conceito vagarosamente seca e morre.

A Proposta

Depois de eu mesmo abandonar inúmeras ideias, eu decidi por construir uma solução. Eu a chamo de projeto ‘Init’ (ou, init.js).

A parte central da ideia é ter um único projeto para começar todos eles, para permitir ao desenvolvedor ou fundador técnico tomar todas essas decisões essenciais de uma vez só, e receber um template inicial apropriado, baseado nestas decisões. Eu sei o que detratores dirão: “uma solução não pode ser aplicada para todo tipo de problema” (odiadores vão odiar). E eles podem estar certos. Mas nós podemos fazer nosso melhor para criar uma solução apropriada, e eu acho que o Init chega perto.

Para melhor atingir este objetivo, nós temos que manter algumas ideias em mente. Enquanto desenvolvendo o Init, eu considerei:

  • Componentes

    Componentização é uma característica chave de qualquer sistema já que permite o reuso de componentes de software em diferentes projetos — que é o principal objetivo do Init. Mas componentização também vem com um subproduto, “permutabilidade”, que será nosso melhor aliado em atacar vários problemas diferentes com “quase” a mesma solução.

  • Facilidade de Desenvolvimento

    Para algum problema, alguém tem uma solução melhor escrita em Brainf*ck. Mas implementar esta solução (em Brainfuck) será praticamente impossível de escrever, quanto mais ler. Lhe custará tempo e um tremendo esforço. Em geral, você deveria usar linguagens e plataformas que tornam o desenvolvimento mais fácil, não mais difícil para você (ou qualquer um que possa vir a trabalhar nele depois).

  • Comunidade

    Seja qual plataforma você escolher, certifique-se de que tem uma grande comunidade, e uma que possa lhe ajudar nos problemas mais comuns e incomuns. Lembre-se: jQuery pode não ser a biblioteca mais rápida, mais limpa,ou mais elegante — mas é uma vencedora simplesmente por causa da sua comunidade.

Mantendo estes objetivos em mente, irei lhe mostrar como eu tomei minhas decisões ao criar o Init.

No seu núcleo, o Init se aproveita do paradigma ‘full-stack JavaScript’ paradigm (algumas pessoas se referem a ele, ou um subconjunto dele, como o MEAN Stack). Ao trabalhar com tal stack, o Init é capaz de usar uma única linguagem enquanto criando um ambiente incrivelmente flexível e cheio de características para desenvolvimento de aplicações web. Em resumo, permite que você use JavaScript não somente para o desenvolvimento do cliente e servidor, mas também para construir, testar, criar templates, e mais.

Mas vamos desacelerar por um momento e nos perguntar: é realmente uma boa ideia usar JavaScript?

Por que eu escolhi JavaScript

Eu sou desenvolvedor web deste 1998. Lá atrás usávamos Perl para a maioria do desenvolvimento no lado servidor, mas mesmo desde então tínhamos JavaScript no lado cliente. Tecnologias para servidores web mudaram imensamente deste então: passamos onda após onda de linguagens e tecnologias tais como PHP, ASP, JSP, .NET, Ruby, Python, para nomear algumas. Desenvolvedores começaram a perceber que usar duas linguagens diferentes para os ambientes cliente e servidor estava complicando as coisas. As tentativas iniciais de unificar sob uma única linguagem tinham como objetivo criar componentes cliente no servidor e compilá-las para JavaScript. Isto não funcionou como esperado e a maioria dos projetos falhou (por exemplo: ASP MVC substituindo ASP.NET web forms, e GWT discutivelmente sendo substituída no futuro próximo pela Polymer). Mas foi uma ótima ideia: uma única linguagem no cliente e no servidor, permitindo a nós reutilizar componentes e recursos (esta é a palavra chave: recursos).

A resposta era simples: colocar JavaScript no servidor.

JavaScript na realidade [nasceu com o JavaScript Server Side] (http://www.infoworld.com/d/application-development/javascript-conquers-the-server-969) no Netscape Enterprise Server, mas a linguagem simplesmente não estava pronta naquela época. Depois de anos de tentativa e erro, o Node.js finalmente emergiu, o que não só colocou JavaScript no servidor, mas também promoveu a ideia de programação não-bloqueante, mudando para sempre a maneira como escrevemos um “fread” (I/O) leia aqui para saber mais).

Em uma frase: programação não-bloqueante objetiva colocar tarefas demoradas de lado, geralmente especificando o que deveria ser feito quando estas tarefas completarem, e permitindo ao processador tratar outras requisições enquanto isso não ocorre.

Mas estas ideias não eram novas — então por que elas se tornaram tão populares com o Node.js? Simples, programação não-bloqueante pode ser alcançada de diversas maneiras. Talvez a mais fácil seja usando callbacks e um loop de evento. Na maioria das linguagens, isso não é uma tarefa fácil: enquanto ‘callback’ é uma característica comum em outras linguagens, um loop de eventos não é, e você frequentemente se encontrará lutando com bibliotecas externas (por exemplo: Python, com Tornado). Mas em JavaScript, callbacks asão construídos dentro da linguagem, assim como os loops de eventos, e quase todo programador que tenha tocado em JavaScript é familiarizado com eles (ou pelo menos os utilizou, mesmo que não entenda bem o que um loop de evento seja). De repente cada startup na Terra poderia reusar desenvolvedores (isto é, recursos) tanto no lado cliente quanto no lado servidor, resolvendo o problema da oferta de emprego: “Buscamos Guru em Python”.

De repente cada startup na Terra poderia reutilizar desenvolvedores (isto é, recursos) tanto no lado cliente quanto no lado servidor, resolvendo o problema da oferta de emprego: "Buscamos Guru em Python”.

Então agora temos uma plataforma incrivelmente rápida (graças à programação não-bloqueante) com uma linguagem de programação que é incrivelmente fácil de usar (graças ao JavaScript). Mas isto é suficiente? Vai durar? Tenho certeza de que JavaScript terá um lugar importante no futuro. Deixe-me dizer-lhe por que:

  • Programação Funcional

    JavaScript foi a primeira linguagem de programação a trazer o paradigma de programação funcional para as massas (claro, Lisp veio primeiro, mas a maioria dos programadores nunca construíram aplicações para ambientes de produção usando Lisp). Lisp e Self, principais influências do Javascript, são cheias de ideias inovadoras. Estas ideias poderiam libertar nossas mentes para explorar novas técnicas, padrões e paradigmas. E todas elas levam o JavaScript. Dê uma olhada em monads, Church numbers, ou mesmo (para um exemplo mais real) as funções de coleções do Underscore.js, que podem lhe economizar linhas e linhas de código.

  • Objetos Dinâmicos e Herança Prototipal

    Programação Orientada a Objetos sem classes (e sem hierarquia de classes que não tenham fim) permite desenvolvimento rápido (criar objetos, adicionar métodos, e usá-los) mas, mais importante, reduz o tempo de refatoração durante tarefas de manutenção ao permitir ao programador modificar instâncias de objetos ao invés de classes. Esta velocidade e flexibilidade pavimenta o caminho para o desenvolvimento rápido.

  • JavaScript é a Internet

    JavaScript foi projetado para a Internet, iestá aqui desde o começo, e não irá embora. Todas as tentativas de destruí-lo falharam: veja, por exemplo, a queda dos Java Applets, a substituição do VBScript por Microsoft’s TypeScript (que compila para JavaScript), e a morte do Flash nas mãos do mercado móvel e HTML5. É impossível substituir JavaScript sem quebrar milhões de páginas web, então nossos objetivos deveriam ser em melhorá-lo. E não há ninguém melhor para o trabalho do que o Comitê Técnico 39 da ECMA.

    Ok, alternativas a JavaScript nascem todos os dias, tais como CoffeeScript, TypeScript e as milhões de linguagem que compilam para JavaScript. Estas alternativas podem ser úteis para estágios de desenvolvimento (via source maps), mas elas falharão em substituir JavaScript a longo prazo por duas razões: suas comunidades nunca serão maiores e suas melhores características serão adotadas pelo ECMA script (isto é, JavaScript). JavaScript não é uma linguagem de montagem: é uma linguagem de programação de alto nível com código fonte que você consegue entender—então você deveria entendê-la.

Agora graças ao projeto Esprima, você pode criar suas próprias ferramentas para brincar com o código fonte, modificá-lo, mudar seu estilo, adicionar componentes, instrumentar e todos os tipos de coisas que você pode imaginar, brincando com a Árvore Sintática Abstrata (AST - Abstract Syntax Tree, no inglês) de seu programa como se você estivesse trabalhando com uma árvore DOM.

JavaScript de ponta a ponta: Node.js e MongoDB

So, those are the reasons to use JavaScript. Now, I’ll use JavaScript as a reason to use Node.js and MongoDB.

  • Node.js

    Node.js é uma plataforma para construção rápida e escalável de aplicações de rede — isto é praticamente o que o site do Node.js diz. Mas Node.js é mais importante que isto: é o ambiente de runtime preferido para qualquer aplicação JavaScript com acesso a I/O. Mesmo que você não planeje escrever sua principal aplicação de servidor com Node.js, você pode usar ferramentas construídas em cima de Node.js para melhorar seu processo de desenvolvimento. Por exemplo: Mocha.js para teste unitário, Grunt.js para tarefas de build automatizado, ou mesmo Brackets para edição full-text de código.

    Então, se você for escrever aplicações JavaScript para o servidor ou cliente, você deveria se familiarizar com Node.js, por que você precisará usá-lo diariamente. Há algumas interessantes alternativas, mas nenhuma delas chega a sequer 10% da comunidade Node.js.

  • MongoDB

    MongoDB é um banco de dados NoSQL baseado em documentos que usa JavaScript como linguagem de consulta, permitindo a eu completar a plataforma com JavaScript de ponta a ponta.

    MongoDB é um banco de dados sem esquema que lhe permite persistir objetos de uma maneira flexível e portanto adaptar-se mais rapidamente a mudanças nos requisitos. E ainda mais, é altamente escalável e baseado em map-reduce, que o torna adequado para aplicações de big data. MongoDB é tão flexível que pode ser usado como um banco de dados sem esquema, como armazenamento relacional (apesar de não suportar transações), ou mesmo como um armazenamento chave-valor para fazer cache de respostas.

Componentização de Servidor com Express.js

Componentização no lado servidor nunca é fácil. Mas com Express.js (e Connect.js) veio a ideia de ‘middleware’. Na minha opinião, middleware é a melhor maneira de definir componentes no servidor. Se você quiser comparar com um padrão conhecido, é bem próximo de pipes e filtros.

A ideia básica é que seu componente é parte de um pipeline (uma tubulação). O pipeline processa uma requisição (entrada) e gera uma resposta (saída), mas seu componente não é responsável pela resposta toda. Ao invés disso, ele só modifica o que precisa e depois delega para a próxima peça do pipeline. Quando a última peça do pipeline termina o processamento a resposta é enviada de volta ao cliente.

Nos referimos a estes ‘pedaços do pipeline’ (pedaço de tubulação) como ‘middleware’. Claramente, nós podemos criar dois tipos de middleware:

  • Intermediários: aqueles que processam a requisição e a resposta, mas não são totalmente responsáveis pela resposta em si, então delegam para o próximo middleware.

  • Finais: aqueles com total responsibilidade sobre a resposta final. Eles processam e modificam a requisição e a resposta, mas não precisam delegar ao próximo middleware. Na prática, é recomendável que você delegue para um próximo middleware de qualquer maneira para permitir flexibilidade arquitetural (isto é, adicionar mais middleware depois), mesmo que este middleware não exista (portanto neste caso a resposta vai direto ao cliente).

Como exemplo concreto, considere um componente ‘usuário gerente’ no servidor. Em termos de middleware, teríamos tanto finais como intermediários. Para nossos finais, teríamos características tais como criar um usuário e listar usuários. Mas antes de conseguirmos realizar tais ações, nós precisamos de nossos intermediários para autenticação (já que não queremos requisições não-autenticadas entrando e criando usuários). Uma vez criados estes intermediários de autenticação, nós podemos simplesmente plugá-los onde quisermos para tornar uma funcionalidade antes não-autenticada em uma funcionalidade autenticada.

Aplicações de página única

TO projeto Init foca em criar aplicações de página única (SPA’s: Single Page Application). A maioria dos desenvolvedores web foram seduzidos a tentar usar SPAs. Eu construí diversas (a maioria proprietárias), e posso dizer com convicção que elas são simplesmente o futuro das aplicações web. Você já comparou uma SPA com uma aplicação web tradicional numa conexão móvel? A diferença no tempo de resposta está na ordem de dezenas de segundos.

Você já comparou uma SPA com uma aplicação web tradicional numa conexão móvel? A diferença no tempo de resposta está na ordem de dezenas de segundos.

SPAs são o futuro da web — então por que você construiria seu produto numa forma legada? Um argumento comum que ouço é que as pessoas estão preocupadas com SEO (otimização para sistemas de buscas, do inglês, Search Engine Optimization). Mas se você tratar as coisas direito isto não deve ser um problema: o próprio Google tem um tutorial muito bom em como fazê-lo e há alguns bons comentários aqui também.

MV* no lado cliente com Backbone.js, Marionette.js e Twitter Bootstrap

Muito tem sido dito sobre frameworks MVC* para SPA’s. É uma escolha difícil, mas eu diria que os 3 principais são Backbone.js, Ember.js, e Angular.js.

Todos os três são bem vistos. Mas qual deles é o melhor pra você?

Infezlimente, eu preciso admitir que eu tenho experiência muito limitada com Angular.js, então vou deixá-lo fora desta discussão. Agora, Ember.js e Backbone.js representam duas diferentes maneiras de atacar o mesmo problema.

Backbone.js é minimalista, simplista e oferece a você o suficiente para criar um SPA simples. Ember.js, por outro lado, é um framework completo e profissional para criação de SPAs. Tem mais atrativos, mas também uma curva de aprendizado maior.

Dependendo do tamanho de sua aplicação, a decisão pode ser tão fácil quando analisar a taxa de funcionalidades usadas versus funcionalidades disponíveis, que lhe dará uma boa ideia.

No caso do Init, eu quis cobrir a maioria dos cenários, então eu escolhi o Backbone.js para criação fácil de SPA, com Backbone.Marionette.View para componentização. Desta maneira, cada componente é uma aplicação simples e a aplicação final pode ser tão complexa quanto desejarmos.

Estilo é um desafio também, mas nós podemos novamente contar com frameworks para nos ajudar. Para CSS, não há nada melhor que Twitter Bootstrap, que oferece um conjunto completo de estilos prontos para usar e fáceis de personalizar.

Bootstrap foi criado usando a linguagem LESS e é software livre, então podemos modificá-lo caso precisemos. Ele vem com inúmeros controles para interface com usuário que são bem documentados no site do Bootstrap. PE ainda, há um modelo de personalização que permite a você criar seu próprio Bootstrap. É definitivamente o cara certo para o trabalho.

Melhores Práticas: Grunt.js, Mocha.js, Chai.js, RequireJS, e CoverJS

Finalmente, deveríamos definir algumas de nossas melhores práticas e ver como o Init pode ajudar você a implementá-las e mantê-las. Nossa solução é centrada em diversas ferramentas, que por sua vez são baseadas no Node.js.

  • Mocha.js e Chai.js:

    Estas ferramentas permitem que você melhore seu processo de desenvolvimento aplicando TDD ou BDD, provendo a infraestrutura para organizar seus testes unitários e um executor para executá-los automaticamente.

    milhares de frameworks para testes unitários para JavaScript. Então por que usar Mocha.js? Resposta curta: é flexível e completo.

    Resposta longa: tem duas características importantes (interfaces, reporters) e uma ausência significante: asserções. Deixe-me explicar.

    • Interfaces: talvez você esteja familiarizado com conceitos de TDD como suites e testes unitários, ou talvez você prefira ideias do BDD de especificação de comportamento com “describe” (descreva) e “it should” (deveria). Mocha.js permite a você usar ambas abordagens.

    • Reporters: executar seu teste irá gerar relatórios dos resultados, e você pode formatar estes resultados usando vários reporters. Por exemplo, se você precisar alimentar um servidor de Integração Contínua, você pode encontrar um reporter para fazer só isso.

    • Falta de uma biblioteca de asserções: longe de ser um problema, Mocha.js foi projetado para permitir a você usar a biblioteca de assertion de sua preferência, dando a você ainda mais flexibilidade. Há opções abundantes, mas é aqui que Chai.js entra em campo.

    Chai.js é uma flexível biblioteca de asserção que permite a você três estilos principais de asserções:

    • Assert: Estilo clássico de asserção ion do TDD tradicional. Exemplo:

        assert.equal(variavel, "valor");
      
    • Expect: Estilo de asserção encadeável, mais comumente usado em BDD. Exemplo:

        expect(variavel).to.equal ("valor");
      
    • Should: Também usado em BDD, mas eu prefiro Expect pois Should soa repetitivo com a especificação comportamental ‘it (“should do something..”)’. Exemplo:

        variavel.should.equal ("valor");
      

    Chai.js combina perfeitamente com Mocha.js. Usando apenas estas três bibliotecas, você pode escrever seus testes em TDD, BDD, ou qualquer estilo imaginável.

  • Grunt.js:

    Grunt.js permite a você automatizar tarefas de build, qualquer coisa desde um simples copiar-e-colar e concatenação de arquivos, até pré-compilação de template, compilação de linguagem de estilo (isto é, SASS e LESS), teste unitário (com mocha.js), linting e minificação de código (por exemplo, com UglifyJS ou Closure Compiler). Você pode adicionar sua própria tarefa automatizada ao Grunt, ou procurar no Grunt registry, , onde há centenas e centenas de plugins disponíveis (relembro: usar ferramentas com grandes comunidades por trás compensa). Grunt também pode monitorar seus arquivos e disparar ações quando eles são modificados.

  • RequireJS:

    RequireJS pode soar como apenas outra maneira de carregar módulos com AMD, mas eu posso lhe garantir que é muito mais do que isto. Para entender por que, nós precisamos primeiro mencionar a ideia de namespacing de módulos (por exemplo, demo.views.hello), que evita poluir o namespace global ao envolver cada módulo no seu próprio namespace. O problema é que estes módulos não são reutilizáveis: se você modificar o namespace de uma ‘instance’, você está modificando o namespace de todas as ‘instances’. Em contraste a isto, RequireJS lhe permite definir módulos reutilizáveis desde o começo. Adicionalmente, lhe ajudará a adotar Injeção de Dependência para evitar ter seus módulos acessando variáveis globais.)

  • CoverJS:

    Cobertura de código é uma métrica para avaliar seus testes. Como o nome sugere, isto lhe diz quanto do seu código está coberto pelo conjunto de testes atual. CoverJS mede a cobertura de código dos seus testes instrumentando declarações (ao invés de linhas de código como o JSCoverage) no seu código e gerando uma versão instrumentada de seu código. Também pode gerar relatórios para alimentar ao seu servidor de Integração Contínua.

Usando Branches para escolher funcionalidades

Quando eu comecei o Init, eu precisava de uma maneira para usuários ativarem e desativarem várias funcionalidades que eles pudessem querer em seus projetos. Eu decidi tomar a medida radical de usar o sistema de branches do git para implementar esta funcionalidade.

Essencialmente, cada branch representa uma característica ou funcionalidade que um usuário pode querer incluir. Se você estiver começando um projeto do zero, comece na branch mínima que você precisa e depois adicione outras tecnologias fazendo merge com as branches desejadas. Por exemplo, digamos que você queira começar seu projeto com Backbone.js e Marionette.js. Bem, você pode começar com a branch Backbone.js e fazer merge dela com a branch Marionette, continuando assim para cada pedaço de funcionalidade que você quiser adicionar.

Por enquanto esta ideia de fazer merge para adicionar funcionalidades só pode ser usada para templates de tecnologias (por exemplo: Backbone, Node, Express). Mas no futuro você poderá alternar entre implementações de back-end (por exemplo, do MongoDB ao Postgres) e cliente.

Iniciar um projeto com Init e implantar a Heroku Hoje

Nunca houve maneira mais fácil de começar um projeto. Simplesmente vá ao repositório no GitHub, verifique a branch com os últimos commits (neste momento é a usermanager, embora possa mudar no futuro) e depois:

  1. Crie o diretório para seu projeto (ou use um existente).
  2. Crie seu repositório com “git init” (ou use um repositório existente).
  3. Adicione um remote com o init

     git remote add init git://github.com/picanteverde/init.git
    
  4. Baixe o arquivo de processo do Heroku

     git pull init usermanager
    
  5. Com o Heroku Toolbelt instalado, crie uma aplicação Heroku

     git pull init heroku-webprocess
    
  6. Com o Heroku Toolbelt instalado, crie uma aplicação Heroku

     heroku create
    
  7. Faça push da sua branch master para o Heroku

     git push heroku master
    
  8. Visite sua aplicação rodando no Heroku!

Agora você pode começar a desenvolver sua característica matadora com apenas algumas linhas de código. Não só isso, mas você estará desenvolvendo com as mais atuais e eficientes tecnologias numa suíte de desenvolvimento que é tão automatizada quanto poderia ser.

Espero que você possa usar Init para começar sua próxima grande ideia. Lembre-se de verificar o repositório Init para novas correções e funcionalidades — seu desenvolvimento está bastante ativo e eu aguardo seus comentários.


Conteúdo traduzido por Eduardo Kienetz, membro do TransBrunko, um mercado para traduções técnicas.

About the author

Alejandro Hernandez, Argentina
member since August 30, 2012
Alejandro got his Bachelor's in software engineering eleven years ago, and since then has been working for software companies of all sizes from all around the globe as a freelancer. Currently, he enjoys working as the technical lead on JavaScript projects, where his deep understanding of architecture and theory is most impactful. [click to continue...]
Hiring? Meet the Top 10 Freelance JavaScript Developers for Hire in December 2016

Comments

Kirmayr roberto
Muito bom o post. Parabéns
comments powered by Disqus
Subscribe
The #1 Blog for Engineers
Get the latest content first.
No spam. Just great engineering and design posts.
The #1 Blog for Engineers
Get the latest content first.
Thank you for subscribing!
You can edit your subscription preferences here.
Trending articles
Relevant technologies
About the author
Alejandro Hernandez
JavaScript Developer
Alejandro got his Bachelor's in software engineering eleven years ago, and since then has been working for software companies of all sizes from all around the globe as a freelancer. Currently, he enjoys working as the technical lead on JavaScript projects, where his deep understanding of architecture and theory is most impactful.