Solucionado (ver solução)
Solucionado
(ver solução)
4
respostas

NodeJS + Express + MongoDB

Gostaria que avaliassem o seguinte código, ele funciona mas não sei se é uma boa ideia, estou usando Node, Express e MongoDB:

rota.js:

const AuthDao = require('../infra/autenticacao-dao');

module.exports = (app) => {

    app.post('/autenticacao/registro', (requisicao, resposta) => {

        // Uso a clase AuthDao para validar os dados recebidos
        // e comunicar com o banco
        const authDao = new AuthDao();
        authDao.store(requisicao.body)
            .then(resultado => resposta.status(201).json(resultado))
            .catch(erro => resposta.status(401).json(erro));
    });
}

autenticacao-dao.js:

const BancoDados = require('./banco-dados');

class AuthDao {

    store(json) {

        return new Promise((resolve, reject) => {
            // validações e rejects omitidos...

            json.password = bcrypt.hashSync(json.password, saltRounds);

            // em vez de criar um arquivo com as configurações
            // criei uma classe que lida a conexão com o banco
            let bd = new BancoDados();
            bd.conecta(
                collection => collection.insertOne(json)
            );

            return resolve({
                success: true,
                message: "Usuário registrado com sucesso!"
            });
        });
    }
}

banco-dados.js:

const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');

class BancoDados {

   constructor() {

      this._url = 'mongodb://localhost:27017/';
      this._dbName = 'banco';
   }

   conecta(callback) {
      const client = new MongoClient(this._url, {
         useNewUrlParser: true
      });

      client.connect((err, client) => {
         assert.equal(null, err);
         const db = client.db(this._dbName);

    // minha dúvida é justamente nessa parte
    // está funcionando, mas não sei se é a forma correta
         callback(db.collection('collection'));

         client.close();
      });
   }
}

module.exports = BancoDados;
4 respostas

Boa tarde, Jefferson! Como vai?

O que eu estranhei no seu código e não é correto é o fato de o seu método conecta() ser responsável por coisas demais e ferir um princípio da programação chamado de princípio da responsabilidade única! Veja que ele é faz a conexão e tbm é executa um callback de ação que ele recebe.

Ao meu ver, esse método deveria apenas montar a conexão e retorná-la pra quem desejar usar ela. E, no seu caso, quem a usaria seria os seus DAOs.

Um outro ponto que me chamou a atenção, foi o fato de vc criar a instância da classe BancoDados dentro do método store() da classe AuthDao. É possível que esse DAO acabe crescendo e ganhando outros métodos que tbm precisem da conexão com o BD. Portanto, o ideal seria estabelecer essa conexão no construtor da classe AuthDao, dessa forma:

class AuthDao {

     constructor() {

          // crio uma propriedade "_conexao" para a classe
          // AuthDao que pode ser utilizada em qualquer
          // método fazendo apenas this._conexao.
          this._conexao = new BancoDados().conecta();
     }
}

Pegou a ideia? Qualquer coisa é só falar!

Grande abraço e bons estudos, meu aluno!

eu fiz algumas modificações com o que você falou, e modifiquei um monte de coisas...

estou com muita dificuldade em passar essa instancia do banco de dados (collection) para as minhas outras classes... a unica forma que consegui fazer dar certo foi usando esse callback. Passei a validação para um Helper e o fluxo ficou assim:

  1. A rota pega a requisição passa os dados recebidos para o Helper validar, caso seja válido, irá passar os dados para a AuthDao
  2. A AuthDao executa o método do banco (open) passando o callback (função que irá definir o que será feito com os dados no banco, inclusão, alteração ou exclusão de dados)
  3. A classe BancoDados irá abrir a conexão com o banco, executar o callback passando a instancia da collection e depois encerrar a conexão com o banco

quero deixar todas as classes o mais clean possível, estou aprendendo muito a cada dia e quero tornar isso fácil de receber atualizações...

Veja os códigos, estou achando algo esquisito...

Rota: autenticacao.js

const AutenticacaoDao = require('../infraestrutura/autenticacao-dao');
const ValidadorHelper = require('../ajudantes/valida-usuarios');
const autenticacaoDao = new AutenticacaoDao();
const validaUsuarios = new ValidadorHelper();

module.exports = (app) => {

    app.post('/autenticacao/registro', (requisicao, resposta) => {

        validaUsuarios.validaNovoUsuario(requisicao.body)
            .then(usuarioValidado => {
                let resultado = autenticacaoDao.register(usuarioValidado);
                resposta.status(201).json(resultado);
            })
            .catch(erro => resposta.status(400).json(erro));
    });
}

Classe autenticacao-dao.js

class AutenticacaoDao {

    constructor() {

        let Banco = require('./banco-de-dados');
        this._banco = new Banco();
    }

    store(usuario) {

        this._banco.open(
            collection => collection.insertOne(usuario)
        );

        return {
            success: true,
            message: "Usuário registrado com sucesso!"
        }
    }
}

module.exports = AutenticacaoDao;

banco-de-dados.js

class BancoDados {

   constructor() {

        this._MongoClient = require('mongodb').MongoClient;
        this._assert = require('assert');
        this._url = 'mongodb://localhost:27017/';
        this._dbName = 'naspservice';
      this._client = new this._MongoClient(this._url, {
         useNewUrlParser: true
      });
   }

   open(callback) {
      this._client.connect((err, client) => {
         this._assert.equal(null, err);
         const db = client.db(this._dbName);
         callback(db.collection('usuarios'));
         client.close();
      });
   }
}

module.exports = BancoDados;
solução!

Acabei optando pelo pacote express-mongo-db, não era bem o que queria, mas com umas 3 linhas de código foi possivel chamar o banco a cada requisição :

var app = require('express')();

var expressMongoDb = require('express-mongo-db');
app.use(expressMongoDb('mongodb://localhost/test'));

app.get('/', function (req, res, next) {
    req.db // => Db object
});

Opa, Jefferson! Como vai?

Excelente solução! E obrigado por compartilhar com a comunidade aqui da Alura! Assim todos nós crescemos juntos!

Sempre que tiver qualquer dúvida é só mandar aqui no fórum!

Grande abraço e bons estudos, meu aluno!