Este é o exemplo de código que eu, Jorge Feldmann, julgo o ideal para iniciar um projeto para aplicação Node.js. O código é baseado em refactoring de código para utilizar a API da Pagar.me
A idéia é entender o que o código original (docs/codigo-original) faz para então consertar e refatorar o que achar necessário. Desde que o código atenda a funcionalidade inicial (que é extremamente básica), sinta-se livre para adicionar ou remover o que quiser dele. Note que este código contém desde pequenos erros até questões extremamente importantes que estão faltando. O objetivo final é entregar um projeto completo, seguro, pronto para produção e de fácil manutenção.
Não fique preso a apenas refatorar o código, altere o que achar necessário para deixar o projeto em um estado pronto para produção, então escolha querer evoluir o quanto quiser, mas cuidado apenas com over engineering.
Sobre over engineering: quando se trata de um teste com foco em produção, creio que a prioridade seja demonstrar o máximo de conhecimento, focando em conceitos como DRY, KISS, separação de contextos, modularização, legibilidade, para demonstrar tais recursos.
A solução aqui proposta é um exemplo de scafolding que engloba conceitos de segurança, performance, escalabilidade e agilidade no desenvolvimento de novos recursos, bem como uso de wrappers para componentes.t
- Rotas: para a listagem e criação, a rota é a mesma (/pokemons), mas com os verbos GET e PUT (idempotente) respectivamente. Para o processo de compra (/pokemons/buy) o recurso de compra (/buy) foi transformado num nível abaixo do recurso principal, ao contrário da original (/buy-pokemons);
- Segurança: uso do middleware Helmet;
- Modularização das rotas (routes/routes.js) e dos recursos (/app/pokemons), ao invés de manter tudo isso atrelado;
- Performance: conversão de console.log (que afunila o processamento) para um chaveamento de logs em arquivo para produção ou console.log em dev, componente Bunyan
- Uso de steps e init() para mostrar o passo-a-passo das funções (leia o código de baixo para cima)
- Uso do Revealing Pattern, com composição, para criação de objetos (return _public), mantendo o "new" para denotar instanciação de objetos
- Uso do PM2: solução completa, open source e gratuita para monitoramento. Para DEV: recarregar alterações e acompanhamento de uso de recursos. Para PROD: uso de clusterização, recursos, API de healthcheck, escalonamento de instâncias, etc
- Promisses: ótimas para legibilidade, mas têm que se ter cuidado para tratativa de erros. Modifiquei os principais pontos em steps para legibilidade e melhor tratativa de erros
- Config.js: certas constantes de configuração (porta da API, nome, api_key, url de serviços) foram transferidos para um arquivo config/config.js, afim de evitar "chumbar" tais dados dentro da aplicação
- API Pagar.me: foi criado um wrapper (common/pagarme). A API_KEY está em config/config.js.
- Dados de mock do pagamento: ainda estão dentro do recurso pokemon
- Codificação literária: nomes de funções representam o que elas fazem. Ficam longas, mas evitam comentários
- Assinatura de funções e métodos possuem o tipo esperado (intQuantity, objResponse), baseado na notação de código húngara
- Design patterns de Node.js elementares e avançados
- Uso de features disponíveis do Node.js ES6
- Uso de debug com node-inspector
- Performance sistêmica: guia Node.js para profiling
- Performance de I/O HTTP: uso de stress test com siege -b -c100 -t 60S http://localhost:3000
- Testes de API baseados em testes funcionais da StrongLoop
- Integração contínua com Travis.CI
- Organização de pastas baseada em comportamentos
- Uso do NPM como ferramental de build, perfis, etc
- Transformação do modelo de dados baseado em Sequelize.js para um arquivo separado, baseado em componentes de model. Podemos usar Sequelize, Mongoose, Bookshelf, ou até mesmo Joi do Happi.js, apenas mudando o componente de factory de models
- Autenticação: usaria JWT (JSON Web Tokens) , Passport.js, com o Redis ou MemCache
- IDE: Sublime, com templates, snippets e meu gerador de código. Mas usaria um Web Storm com muita alegria ;)
- REST API tutorial
- Projetando uma API REST - octo.com
- Express.js best practices: security and performance
- Microservices pattern: Gateway
- Consultas sobre performance na comunidade de NodeBR, Quora e Reddit
- Referências de grandes players com stacks de microserviço, realtime e performáticos: Uber, Netflix, Spotify
- Promisses: patterns e HowToNode
- Padrões de codificação idiomáticos Node.js prevalecem sobre padrões JS (Douglas Crockford) e Google
- Node.js versão 6.0.0
- Instruções de instalação neste link
- Ao final, verificar a versão de ambos para confirmar:
node -v
npm -v
- Recomenda-se o uso de NVM para versionar diferentes versões do Node.js
- Instalação global do componente PM2 1.x
npm install -g pm2
pm2 -v
git clone https://github.com/jotafeldmann/node-gateway-payment
cd node-gateway-payment/src
npm install
Acessar a pasta com o código:
cd node-gateway-payment/src
Inicializa o PM2, com a aplicação como serviço, utilizando o máximo de núcleos disponíveis, observando mudanças e atualizando, reiniciando caso ocorram falhas
export NODE_ENV=production
cd node-gateway-payment/src
npm start
npm stop
Inicializa o PM2, com a aplicação como serviço, utilizando 1 núcleo, observando mudanças, parando a cada falha e lançando o log após a inicialização
npm run dev
npm run logs
Acessar a pasta com os testes:
cd node-gateway-payment/testes
- Instalação global do Mocha
npm install -g mocha
mocha --version
- Instalação das dependências locais dos testes
cd funcionais
npm install
cd node-gateway-payment/src
npm test
Após subir a aplicação, acessar http://localhost:3000 para verificar os recursos disponíveis.
MIT License © Jorge Feldmann (jotafeldmann)