Arquitetura de Bot's
Arquitetura de Bot's

Hoje resolvi dar dois dedos de prosa sobre o assunto. Programar bots é uma das coisas que mais me diverte, e durante algum tempo acumulei um bom conhecimento sobre a arquitetura deles.
Vamos abordar sobre:
- Strategy Pattern
- Bancos de Dados para Bots
- Resiliência
Strategy Pattern
Pelo amor de qualquer coisa que você acredite ou deixe de acreditar: NÃO COLOQUE TUDO EM UM SÓ ARQUIVO. Isso prejudica demais a manutenção do código, gera conflitos absurdos se você for trabalhar em equipe e torna praticamente impossível testar as funcionalidades de forma isolada.
Outra coisa que me deixa maluco é ver todos os comandos em um imenso if. Alguns mais moderninhos utilizam o switch case, mas ainda não é o ideal. Dá muito trabalho adicionar um comando novo. Ao invés disso, use o básico da orientação a objetos.
Veja a forma errada de fazer:
if (comando.equals("ping")) {
// Lógica do Ping
} else if (comando.equals("clear")) {
// Lógica do Clear
}
// ...
else {
// Comando não encontrado
}Logicamente, coloque as coisas em classes e pacotes separados (coloquei junto abaixo só para ilustrar o conceito). Um jeito muito mais decente, escalável e utilizando o poder da injeção de dependências do Spring:
package top.lmix.bot.commands;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
// 1. O Contrato (Interface)
public interface BotCommand {
String getCommandName();
void execute(String eventData); // Em um caso real, entraria o MessageReceivedEvent da API do Discord, por exemplo.
}
// 2. Os Comandos Isolados
@Component
public class PingCommand implements BotCommand {
@Override
public String getCommandName() {
return "ping";
}
@Override
public void execute(String eventData) {
// Lógica isolada do comando ping
System.out.println("Respondendo com: Pong!");
}
}
@Component
public class ClearCommand implements BotCommand {
@Override
public String getCommandName() {
return "clear";
}
@Override
public void execute(String eventData) {
// Lógica isolada para limpar mensagens (ótimo para moderação automágica)
System.out.println("Limpando as mensagens do canal...");
}
}
// 3. O Gerenciador (Dispatcher)
@Service
public class CommandDispatcher {
private final Map<String, BotCommand> commandMap;
// O Spring injeta automaticamente todas as classes que implementam BotCommand!
@Autowired
public CommandDispatcher(List<BotCommand> commands) {
this.commandMap = commands.stream()
.collect(Collectors.toMap(BotCommand::getCommandName, cmd -> cmd));
}
// O evento de mensagem recebida no Discord chama este método, sem nenhum IF gigante
public void handle(String commandName, String eventData) {
BotCommand command = commandMap.get(commandName.toLowerCase());
if (command != null) {
command.execute(eventData);
} else {
System.out.println("Comando desconhecido ou não encontrado.");
}
}
}Bancos de Dados
Aviso: Parece óbvio, mas o óbvio precisa ser dito: escolha o banco de dados correto para o que você irá fazer.
Não faz sentido você precisar de meia dúzia de dados (como salvar o prefixo customizado de um servidor ou o ID de um canal de logs) e instanciar um banco de dados super gordo e inflado. Use um simples SQLite. Ele resolve perfeitamente a maioria dos casos de bots iniciantes ou de escopo fechado.
O oposto também é verdade: se você está fazendo um scraper massivo de dados ou gerenciando um sistema complexo de economia para milhares de usuários simultâneos, você merece tomar na tarraqueta se quiser colocar em um SQLite e depois ficar com 200 gigas em um único arquivo, travando o disco da sua máquina. Nesses casos, parta para um PostgreSQL ou MySQL. Se o bot precisar consultar dados muito rápido para não sofrer com o rate limit da API, coloque um Redis para fazer cache.
Além disso, escolher o banco de dados correto afeta seu bolso. Imagina precisar de duas VPS só pra subir um banco que você não precisa, ou pagar muito mais caro em uma VPS parruda só pra conseguir rodar a aplicação e o banco juntos sem estourar a memória RAM.
Resiliência
O que significa ser resiliente?
Ser resiliente é a capacidade de adaptar-se positivamente, superar adversidades, resistir à pressão e aprender com situações difíceis, retornando ao equilíbrio emocional original.
Aplicando esse conceito em um bot, significa que, se cair a energia ou o servidor da VPS reiniciar, ele deve conseguir continuar exatamente de onde parou ao invés de começar do zero e perder todo o estado. Ele precisa iniciar sozinho junto ao sistema operacional, ter proteções (como blocos try-catch e controle de taxa de requisições) caso alguém fique tentando fazer lameragens floodando os comandos, e, acima de tudo, deve ser consistente e não crachar silenciosamente.
A melhor forma de garantir que o bot inicie com o sistema operacional no Linux e ressuscite caso dê algum erro fatal é criando um serviço nativo no systemd.
Você pode criar o arquivo de configuração de forma rápida usando o micro:
sudo micro /etc/systemd/system/meubot.serviceE adicionar a seguinte configuração completa:
[Unit]
Description=Serviço do Meu Bot em Java
After=network.target
[Service]
User=seu-usuario
WorkingDirectory=/opt/meubot
ExecStart=/usr/bin/java -jar /opt/meubot/bot.jar
SuccessExitStatus=143
# A mágica da resiliência acontece aqui:
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.targetDepois de salvar, basta ativar para iniciar com o boot (sudo systemctl enable meubot) e iniciar o processo (sudo systemctl start meubot). Se o bot sofrer uma falha crítica, o sistema operacional vai levantá-lo novamente de forma automática em 10 segundos.
Conclusão
Criar bots vai muito além de responder a um simples comando de "ping". Quando a brincadeira fica séria, a arquitetura do seu código e da sua infraestrutura cobra o preço. Organizar a base com padrões como o Strategy Pattern para facilitar a manutenção, escolher a persistência de dados adequada para não rasgar dinheiro com servidores à toa, e garantir que a aplicação seja à prova de quedas são os passos que separam um projetinho de final de semana de uma aplicação verdadeiramente profissional e estável.