1
resposta

[Sugestão] Sobre o padrão de projeto Singleton

Problemas / armadilhas do seu singleton


import { Collection, MongoClient } from "mongodb";

export class MongoManager {
  public static instance: MongoManager;
  private client: MongoClient | null = null;
  private constructor() {}

  public static getInstance(): MongoManager {
    if (!MongoManager.instance) {
      MongoManager.instance = new MongoManager();
    }
    return MongoManager.instance;
  }

  public async connect(url: string): Promise<void> {
    if (!this.client) {
      this.client = await MongoClient.connect(url);
    }
  }

  public getCollection(name: string): Collection {
    if (!this.client) throw new Error("MongoClient is not connected");
    return this.client?.db().collection(name);
  }
}

1. Não é “global de verdade” em ambientes serverless

  • Cada execução fria cria um novo processo — e o seu instance só é “único” dentro do processo atual.
  • Se houver múltiplos processos, você pode acabar com várias conexões simultâneas ao MongoDB.

2. Não é thread-safe

Node.js é single-threaded, então normalmente não é problema. Mas se em algum momento você rodar em ambiente com Worker Threads, duas chamadas simultâneas a getInstance() podem criar duas instâncias.

Isso só vira problema em cenários raros, mas vale saber.

3. Estado global acoplado

O singleton mantém estado interno (this.client) que é compartilhado entre todos os consumidores.
Isso pode:

- Tornar testes mais difíceis (precisa limpar ou mockar estado entre testes).
- Criar efeitos colaterais inesperados se algum código fechar a conexão.

Em testes, pode-se injetar dependências em vez de depender de um singleton rígido.

4. Dificuldade de reutilização

Se amanhã você precisar de duas conexões diferentes (ex.: bancos distintos), esse singleton não serve sem modificações — porque ele está “preso” a uma única instância.


Quando o singleton é bom no caso do MongoDB

- Aplicações monolíticas ou API em Node.js que rodam num único processo.
- Você quer garantir uma conexão persistente ao MongoDB, sem abrir várias por requisição.
- O lifecycle da app é previsível (inicia, conecta, encerra).

Quando evitar

- Aplicações serverless com múltiplas execuções frias.
- Código que precisa de flexibilidade para múltiplas conexões.
- Cenários com testes unitários intensos, pois o singleton pode “vazar” estado entre testes.
1 resposta

Olá, Carlos! Como vai?

Obrigado por compartilhar suas observações sobre o padrão Singleton aplicado ao MongoManager. Você levantou pontos muito relevantes sobre os desafios e armadilhas do uso de Singletons, especialmente em ambientes como Node.js.

  1. Execuções em ambientes serverless: É verdade que em ambientes serverless, cada execução fria pode criar um novo processo, resultando em múltiplas instâncias do Singleton. Isso pode levar a várias conexões simultâneas ao MongoDB, o que não é ideal.

  2. Thread safety: Embora Node.js seja single-threaded, o uso de Worker Threads pode introduzir a possibilidade de criar múltiplas instâncias. Isso é algo que geralmente não afeta a maioria dos cenários, mas é importante estar ciente.

  3. Estado global acoplado: O estado compartilhado pode complicar testes e introduzir efeitos colaterais. Uma abordagem para mitigar isso é usar injeção de dependência, o que também facilita a substituição de componentes durante os testes.

  4. Reutilização e flexibilidade: Se houver necessidade de múltiplas conexões, a abordagem Singleton pode não ser adequada sem modificações significativas.

Quanto à sua dúvida sobre quando o Singleton pode ser benéfico, você está certo ao apontar que ele funciona bem em aplicações monolíticas ou APIs que rodam em um único processo e onde uma conexão persistente é desejável.

Espero que suas observações ajudem outros estudantes a entender melhor as nuances do padrão Singleton, especialmente no contexto do MongoDB.

Alura Conte com o apoio da comunidade Alura na sua jornada. Abraços e bons estudos!