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

module.exports função ou objeto

Ao longo das aulas eu vejo que foi exportando uma função no module.exports, só que eu vejo em vários lugares sendo exportado um objeto ai invés de uma função, meu arquivo DAO ficou assim e funciona:

const pgp = require('pg-promise')();

const cn = {
    user: 'postgres',
    password: 'admin',
    host: 'localhost',
    port: 5432,
    database: 'casadocodigo'
};

const db = pgp(cn);

function getLivros() {     
    return db.any('select * from livros')
        .catch(err => console.error(err));
}

module.exports = {
    getLivros
};

A seguinte chamada do router de produtos funciona perfeitamente:

module.exports = (app) => {
    const db = app.infra.dao;

    app.get('/produtos', (req, resp) => {
        db.getLivros()
            .then(result => resp.render('produtos', {title: 'Produtos', produtos: result}));
    });
};

Dessa forma dispensa a utilização do prototype na função, mas qual seria a convenção mais correta ou mais performática?

5 respostas

Oi Bruno, tudo bem? Em relação a performance eu não tenho nenhuma indicação, nem ao menos acho que essa deva ser uma preocupação, isso por que quando o node importa do outro lado, ele também faz um cache do modulo, isso já otimiza bastante coisa, mas também pode gerar problemas caso precise trabalhar com instâncias.

A questão de dispensar o prototype não está relacionada ao fato de como você exporta a função. E sim por que você não está usando orientação a objetos nesse trecho.

No geral, não tenho uma indicação de melhor forma, mas sim uma sugestão de boa prática. Se for exportar sempre objetos, ótimo, mas mantenha a consistência. Se for exportar funções, mantenha a consistência e tenha cuidado.

Para saber mais eu recomendo dar uma olhada na documentação: https://nodejs.org/api/modules.html#modules_module_exports

Opa Wanderson, bora lá.

Eu compreendi bem a questão da performance, e não me preocuparei tanto com isso, e eu até entendo quando você fala sobre sobre manter a consistência como uma boa prática, mas, confesso que fiquei meio dividido nessa questão.

Então, me arriscando a entra numa questão quase filosófica, mas levantarei uma questão aqui: A intuitividade do uso após a implementado, não deveria vir antes da consistência? Deixa eu explicar através de um exemplo:

Depois que eu postei o meu exemplo acima, eu refatorei o meu arquivo DAO pra criar o ConnectionFactory, como é feito das aulas, separado a lógica da instância do servido do database, e fiz da seguinte forma:

const pgp = require('pg-promise')();

const cn = {
  // configuração do servidor
};

const db = pgp(cn);

module.exports = db;

Nesse caso em especifico faz sentido retornar uma instância do database, já que para o uso fica só:

const db = require('./connectFactory');

function getLivros() {     
    return db.any('select * from livros')
        .catch(err => console.error(err));
}

Se eu retornasse uma função que retorna o db, ou um objeto com o db dentro, a chamada ficaria não intuitiva, da mesma forma que pode ser mais intuitivo retornar um função ou objeto, dependendo da situação, o que fugiria totalmente da ideia de consistência.

Mais uma vez, eu entendo a importância de manter a consistência, mas será que eventualmente não se acaba perdendo mais do que ganhando quando se engessa em um único paradigma, ou uma única convenção?

solução!

Entendo, parece fazer sentido sim neste cenário, mas veja lá, como o seu export já retorna a conexão, essa conexão será cacheada pelo node. Faz sentido manter um cache de uma conexão com um DB?

Se você precisar de conexões concorrentes, será que não terá problemas ali justamente por causa desse cache? Da forma que eu vejo, me parece que em algum ponto, sua conexão irá virar um gargalo. Vale a pena essa intuitividade?

Lembrando que, intuitividade é uma característica relativa para outras pessoas. O pessoal do Java por exemplo, está acostumado a usar métodos como getInstance quando se trata de Factory Classes, isso é intuitivo. Pedir uma instância de uma fábrica.

Consistência é algo mais fácil de seguir, quando o padrão é simples, é mais fácil de se tornar intuitivo o uso do código. Quando você quebra isso para um benefício que é subjetivo, você acaba tendo outros problemas, principalmente trabalhando em equipe.

Consistência você pode facilmente criar uma referência de consulta para uma equipe. Intuitividade nem tanto. Um é mais objetivo que o outro. Entende?

Entendo, o que você falou faz total sentido. o que é intuitivo para mim pode não ser intuitivo para outrem.

Nesse sentido, vale mais a pena ser um pouco mais verborrágico e escrever um pouco mais de código, para trazer mais consistência, e por consequência, integridade.

Como você mesmo explicou, no Java, por exemplo, essas convenções são bem mais estabelecidas, no javascript, pela própria natureza mais aberta da linguagem, alguns pontos podem ser um tanto quanto "tricky".

Mas valeu pela resposta, estou totalmente satisfeito com o desfecho da discussão.

Opa Bruno, fico feliz que tenha gostado, eu particularmente também achei bem interessante. Qualquer coisa, conta com a gente aê! : )