Arquivo de testes - Blog do Fernando Jorge Mota https://fjorgemota.com/tag/testes-2/ Dicas e ferramentas para facilitar o seu dia-a-dia como desenvolvedor Sun, 30 Jun 2024 22:42:57 +0000 pt-BR hourly 1 https://wordpress.org/?v=6.9.1 71563333 Como melhorar a velocidade do phpcs e do phpcbf https://fjorgemota.com/2024/06/30/como-melhorar-a-velocidade-do-phpcs-e-do-phpcbf/ https://fjorgemota.com/2024/06/30/como-melhorar-a-velocidade-do-phpcs-e-do-phpcbf/#respond Sun, 30 Jun 2024 22:33:13 +0000 https://fjorgemota.com/?p=6871

Uma tarefa comum quando você está desenvolvendo um projeto é rodar um linter. Linters são ferramentas que analisam o código fonte do seu projeto e buscam detectar diferentes problemas no código, incluindo possíveis falhas na lógica e também questões relacionadas ao estilo do código. Porém, se tem uma coisa que incomoda MUITO é quando você está desenvolvendo, QUASE finalizando o software, e precisa ESPERAR para que ferramentas de verificação assim (que incluem tanto linters quanto testes, que são importantes para qualquer projeto) assim rodem.

Esse é o clássico problema que o XKCD retratou extremamente bem no post "Compiling":

Tirinha do XKCD que traduz livremente para: A desculpa número 1 dos programadores para procrastinar legitimamente: 'meu código está compilando'

E isso incomoda AINDA MAIS quando a ferramenta em questão é single-thread ou mal otimizada, pois o seu computador (que assumo ter um processador com múltiplos núcleos hoje em dia, certo?), fica mais ou menos assim:

Imagem de vários trabalhadores ao redor de uma obra, com só um dos trabalhadores de fato trabalhando em um buraco. Fazendo analogia ao uso de 100% de apenas um núcleo só na maior parte das atividades cotidianas em um computador.

Bom. Agora vamos ao tópico do post: Já que é bem difícil simplesmente paralelizar o trabalho de uma ferramenta de forma eficiente, vamos tentar tornar a sua atuação mais inteligente: Uma forma de deixar o trabalho de qualquer script - ou qualquer coisa, na verdade - mais eficiente, é fazer com que tal script (ou coisa) faça MENOS trabalho.

No caso de um linter, uma forma bem fácil de fazer MENOS trabalho é simplesmente... não ficar rechecando arquivos que não são necessários. Isso é MUITO mais eficiente do que simplesmente paralelizar o algoritmo, uma vez que mesmo o número de núcleos em um computador moderno é limitado.

Para exemplificar isso, considere um projeto que tenha, digamos, 5000 arquivos para serem analisados, cada um levando aí algo em torno de 0.04 segundos. Um linter rodando sequencialmente levaria, portanto, 200 segundos (ou 3 minutos e 20 segundos) para analisar tudo.

Se você tem um processador com 8 núcleos e 16 threads no seu computador, normalmente um algoritmo paralelo tentaria disparar 16 threads para processar cada arquivo. Digamos que essas 16 threads consigam acelerar em 16 vezes a velocidade de processamento (algo que nunca acontece pois há diversas limitações que impedem que algo assim aconteça). Em vez de demorar 200 segundos, ou 3 minutos e 20 segundos, tal algoritmo paralelo levaria cerca de 12 segundos para processar todos os 5000 arquivos.

Levar 12 segundos em vez de 3 minutos e 20 segundos é uma vitória tremenda, certo? Porém, considere que você NÃO vai modificar todos os 5000 arquivos a todo momento. Pelo contrário, você vai modificar ali 1, 3, 5 arquivos por vez, enquanto trabalha no seu projeto. E é aqui que mesmo a paralelização deixa de fazer sentido: Para que checar todos os arquivos, se apenas alguns poucos foram modificados? Se apenas 5 arquivos foram modificados, e o linter leva 0.04 segundos para processar um arquivo, apenas 0.04 * 5 = 0.2 segundos (ou MENOS de um segundo!) deveriam ser necessários para processar tudo, o que já é 60 vezes mais rápido que o algoritmo paralelo ou 1000 vezes mais rápido que o algoritmo sequencial.

E é aqui que entra o script que é o assunto desse post.

Esse é o script, em bash:

#!/bin/bash

set -e

SCRIPT_NAME=$(basename "$0");

find_script() {
    script_name="$1"
    current_dir=$(pwd)
    parent_dir=$(dirname "$current_dir")
    
    # Check if the path exists in the directory exists in the current directory
    script_path="$current_dir/vendor/bin/$script_name"
    if [ -x "$script_path" ]; then
        echo "$script_path"
        return
    fi
    
    # Traverse up the directory tree and check if the script exists in any parent directory
    while [ "$parent_dir" != "$current_dir" ]; do
        script_path="$parent_dir/vendor/bin/$script_name"
        if [ -x "$script_path" ]; then
            echo "$script_path"
            return
        fi
        
        current_dir="$parent_dir"
        parent_dir=$(dirname "$current_dir")
    done
    
    # Script not found
    echo "Script $SCRIPT_NAME not found." > /dev/stderr
    exit 1
}


SCRIPT_PATH=$(find_script "$SCRIPT_NAME");

MODIFIED_FILES=$(git status --porcelain=v2 . | awk '{print $NF}');

if [ -z "$MODIFIED_FILES" ]; then
  echo "No modified files found in the current directory."
  exit 0
fi

echo "Running $SCRIPT_PATH for the following list of files:";
echo "$MODIFIED_FILES" | xargs -i{} echo "- {}";

echo "$MODIFIED_FILES" | xargs "$SCRIPT_PATH";

O que o script faz? É bem simples, vou explicar:

  1. Primeiramente, rodamos set -e para fazer com que o bash imediatamente interrompa a execução caso qualquer comando retorne erro (com código de status de saída diferenet de 0)
  2. Definimos uma variável chamada SCRIPT_NAME contendo o nome do arquivo atual, já explico mais abaixo o motivo disso
  3. Definimos uma função find_script para procurar o script. Essa função busca encontrar o script de nome SCRIPT_NAME dentro da pasta vendor/bin, e busca tanto no diretório atual quanto em qualquer superior. Para exemplificar, se você rodar o arquivo dentro de uma pasta /home/usuario/projetos/MeuProjeto, ele procurará um arquivo executável com o nome do script salvo em SCRIPT_NAME (digamos que tal nome seja phpcs) nas seguintes pastas:
    • /home/usuario/projetos/MeuProjeto/vendor/bin/phpcs
    • /home/usuario/projetos/vendor/bin/phpcs
    • /home/usuario/vendor/bin/phpcs
    • /home/vendor/bin/phpcs
    • /vendor/bin/phpcs
  4. Definimos uma variável SCRIPT_PATH contendo o caminho para o script encontrado pela função find_script
  5. Computamos uma lista de arquivos modificados a partir do git. Apenas arquivos modificados cujas mudanças não foram comittados ainda aparecerão aqui
  6. Verificamos se a lista de arquivos modificados possui, de fato, arquivos modificados. Se não houver arquivos modificados mostramos uma mensagem e encerramos o script
  7. Mostramos a lista de arquivos modificados, e passamos essa lista de arquivos modificados para o script em questão, como parâmetros.

Para usar esse script em uma computador Linux, basta você

  1. Criar uma pasta bin na sua $HOME se você ainda não tiver, assim: mkdir -p $HOME/bin
  2. Adicionar essa pasta bin no seu environment, adicionando no arquivo de configuração do seu shell (digamos, .bashrc) algo como export PATH=$PATH:$HOME/bin
  3. Adicionar esse script nessa pasta bin, com o nome da ferramenta que você quer otimizar. Você pode nomeá-lo como phpcs ou phpcbf, por exemplo
  4. Em um projeto PHP com o phpcbf ou phpcs instalado via Composer, executar o comando correspondente SEM usar vendor/bin como prefixo
  5. Pronto!

O comando só rodará de fato a ferramenta em questão SE houver arquivos modificados e não comittados ainda no repositório Git.

Também não executará se a ferramenta em questão não estiver instalada usando Composer, que já apresentei me outro post.

Finalmente, se você não estiver usando Git, o script não executará, pois ele não tem como rastrear quais arquivos modificados. Se você ainda não usa Git, verifque o meu post sobre, também. ;)

E você, tem alguma outra dica para agilizar tarefas demoradas - mas necessárias - do seu dia-a-dia? Compartilhe nos comentários! E se ficou alguma dúvida, pode madnar nos comentários que vou tentar fazer o meu melhor para ajudar, também. :D

Valeu pela leitura!

]]>
Uma tarefa comum quando você está desenvolvendo um projeto é rodar um linter. Linters são ferramentas que analisam o código fonte do seu projeto e buscam detectar diferentes problemas no código, incluindo possíveis falhas na lógica e também questões relacionadas ao estilo do código. Porém, se tem uma coisa que incomoda MUITO é quando você está desenvolvendo, QUASE finalizando o software, e precisa ESPERAR para que ferramentas de verificação assim (que incluem tanto linters quanto testes, que são importantes para qualquer projeto) assim rodem.

Esse é o clássico problema que o XKCD retratou extremamente bem no post "Compiling":

Tirinha do XKCD que traduz livremente para: A desculpa número 1 dos programadores para procrastinar legitimamente: 'meu código está compilando'

E isso incomoda AINDA MAIS quando a ferramenta em questão é single-thread ou mal otimizada, pois o seu computador (que assumo ter um processador com múltiplos núcleos hoje em dia, certo?), fica mais ou menos assim:

Imagem de vários trabalhadores ao redor de uma obra, com só um dos trabalhadores de fato trabalhando em um buraco. Fazendo analogia ao uso de 100% de apenas um núcleo só na maior parte das atividades cotidianas em um computador.

Bom. Agora vamos ao tópico do post: Já que é bem difícil simplesmente paralelizar o trabalho de uma ferramenta de forma eficiente, vamos tentar tornar a sua atuação mais inteligente: Uma forma de deixar o trabalho de qualquer script - ou qualquer coisa, na verdade - mais eficiente, é fazer com que tal script (ou coisa) faça MENOS trabalho.

No caso de um linter, uma forma bem fácil de fazer MENOS trabalho é simplesmente... não ficar rechecando arquivos que não são necessários. Isso é MUITO mais eficiente do que simplesmente paralelizar o algoritmo, uma vez que mesmo o número de núcleos em um computador moderno é limitado.

Para exemplificar isso, considere um projeto que tenha, digamos, 5000 arquivos para serem analisados, cada um levando aí algo em torno de 0.04 segundos. Um linter rodando sequencialmente levaria, portanto, 200 segundos (ou 3 minutos e 20 segundos) para analisar tudo.

Se você tem um processador com 8 núcleos e 16 threads no seu computador, normalmente um algoritmo paralelo tentaria disparar 16 threads para processar cada arquivo. Digamos que essas 16 threads consigam acelerar em 16 vezes a velocidade de processamento (algo que nunca acontece pois há diversas limitações que impedem que algo assim aconteça). Em vez de demorar 200 segundos, ou 3 minutos e 20 segundos, tal algoritmo paralelo levaria cerca de 12 segundos para processar todos os 5000 arquivos.

Levar 12 segundos em vez de 3 minutos e 20 segundos é uma vitória tremenda, certo? Porém, considere que você NÃO vai modificar todos os 5000 arquivos a todo momento. Pelo contrário, você vai modificar ali 1, 3, 5 arquivos por vez, enquanto trabalha no seu projeto. E é aqui que mesmo a paralelização deixa de fazer sentido: Para que checar todos os arquivos, se apenas alguns poucos foram modificados? Se apenas 5 arquivos foram modificados, e o linter leva 0.04 segundos para processar um arquivo, apenas 0.04 * 5 = 0.2 segundos (ou MENOS de um segundo!) deveriam ser necessários para processar tudo, o que já é 60 vezes mais rápido que o algoritmo paralelo ou 1000 vezes mais rápido que o algoritmo sequencial.

E é aqui que entra o script que é o assunto desse post.

Esse é o script, em bash:

#!/bin/bash

set -e

SCRIPT_NAME=$(basename "$0");

find_script() {
    script_name="$1"
    current_dir=$(pwd)
    parent_dir=$(dirname "$current_dir")
    
    # Check if the path exists in the directory exists in the current directory
    script_path="$current_dir/vendor/bin/$script_name"
    if [ -x "$script_path" ]; then
        echo "$script_path"
        return
    fi
    
    # Traverse up the directory tree and check if the script exists in any parent directory
    while [ "$parent_dir" != "$current_dir" ]; do
        script_path="$parent_dir/vendor/bin/$script_name"
        if [ -x "$script_path" ]; then
            echo "$script_path"
            return
        fi
        
        current_dir="$parent_dir"
        parent_dir=$(dirname "$current_dir")
    done
    
    # Script not found
    echo "Script $SCRIPT_NAME not found." > /dev/stderr
    exit 1
}


SCRIPT_PATH=$(find_script "$SCRIPT_NAME");

MODIFIED_FILES=$(git status --porcelain=v2 . | awk '{print $NF}');

if [ -z "$MODIFIED_FILES" ]; then
  echo "No modified files found in the current directory."
  exit 0
fi

echo "Running $SCRIPT_PATH for the following list of files:";
echo "$MODIFIED_FILES" | xargs -i{} echo "- {}";

echo "$MODIFIED_FILES" | xargs "$SCRIPT_PATH";

O que o script faz? É bem simples, vou explicar:

  1. Primeiramente, rodamos set -e para fazer com que o bash imediatamente interrompa a execução caso qualquer comando retorne erro (com código de status de saída diferenet de 0)
  2. Definimos uma variável chamada SCRIPT_NAME contendo o nome do arquivo atual, já explico mais abaixo o motivo disso
  3. Definimos uma função find_script para procurar o script. Essa função busca encontrar o script de nome SCRIPT_NAME dentro da pasta vendor/bin, e busca tanto no diretório atual quanto em qualquer superior. Para exemplificar, se você rodar o arquivo dentro de uma pasta /home/usuario/projetos/MeuProjeto, ele procurará um arquivo executável com o nome do script salvo em SCRIPT_NAME (digamos que tal nome seja phpcs) nas seguintes pastas:
    • /home/usuario/projetos/MeuProjeto/vendor/bin/phpcs
    • /home/usuario/projetos/vendor/bin/phpcs
    • /home/usuario/vendor/bin/phpcs
    • /home/vendor/bin/phpcs
    • /vendor/bin/phpcs
  4. Definimos uma variável SCRIPT_PATH contendo o caminho para o script encontrado pela função find_script
  5. Computamos uma lista de arquivos modificados a partir do git. Apenas arquivos modificados cujas mudanças não foram comittados ainda aparecerão aqui
  6. Verificamos se a lista de arquivos modificados possui, de fato, arquivos modificados. Se não houver arquivos modificados mostramos uma mensagem e encerramos o script
  7. Mostramos a lista de arquivos modificados, e passamos essa lista de arquivos modificados para o script em questão, como parâmetros.

Para usar esse script em uma computador Linux, basta você

  1. Criar uma pasta bin na sua $HOME se você ainda não tiver, assim: mkdir -p $HOME/bin
  2. Adicionar essa pasta bin no seu environment, adicionando no arquivo de configuração do seu shell (digamos, .bashrc) algo como export PATH=$PATH:$HOME/bin
  3. Adicionar esse script nessa pasta bin, com o nome da ferramenta que você quer otimizar. Você pode nomeá-lo como phpcs ou phpcbf, por exemplo
  4. Em um projeto PHP com o phpcbf ou phpcs instalado via Composer, executar o comando correspondente SEM usar vendor/bin como prefixo
  5. Pronto!

O comando só rodará de fato a ferramenta em questão SE houver arquivos modificados e não comittados ainda no repositório Git.

Também não executará se a ferramenta em questão não estiver instalada usando Composer, que já apresentei me outro post.

Finalmente, se você não estiver usando Git, o script não executará, pois ele não tem como rastrear quais arquivos modificados. Se você ainda não usa Git, verifque o meu post sobre, também. 😉

E você, tem alguma outra dica para agilizar tarefas demoradas - mas necessárias - do seu dia-a-dia? Compartilhe nos comentários! E se ficou alguma dúvida, pode madnar nos comentários que vou tentar fazer o meu melhor para ajudar, também. 😀

Valeu pela leitura!

]]>
https://fjorgemota.com/2024/06/30/como-melhorar-a-velocidade-do-phpcs-e-do-phpcbf/feed/ 0 6871
SQLite - Um mecanismo de banco de dados incrivelmente versátil https://fjorgemota.com/2023/03/23/sqlite-um-mecanismo-de-banco-de-dados-incrivelmente-versatil/ https://fjorgemota.com/2023/03/23/sqlite-um-mecanismo-de-banco-de-dados-incrivelmente-versatil/#respond Fri, 24 Mar 2023 01:00:00 +0000 https://fjorgemota.com/?p=3951
Logo do SQLite
Logo do SQLite

Durante o desenvolvimento de uma aplicação, seja ela web, desktop ou mesmo mobile, sempre aparece algumas perguntas...complexas. Que linguagem de programação usar? Framework? Quais plataformas focar? E mais importante ainda: Onde armazenar os dados da aplicação?

Naturalmente, as resposta vão variar bastante de aplicação para aplicação. Não existe sequer uma aplicação em que eu trabalhei na vida em que a resposta foi simplesmente "evidentemente vai ser X, pois sim", embora com o passar dos anos a experiência e o conhecimento sobre diferentes soluções ajude na decisão por escolhas melhores e mais apropriadas para cada contexto.

E hoje, depois de anos sem escrever nada por aqui, eu vou falar um pouco sobre uma forma de armazenar e consultar dados que é bem interessante, mas quase nunca considerada no desenvolvimento de uma aplicação moderna, embora seja literalmente o mecanismo de banco de dados mais usado do mundo (sim, eu sei que isso é bastante contra intuitivo, mas eu já vou explicar mais sobre): o SQLite.

O que é

O SQLite é uma biblioteca desenvolvida na linguagem C por D. Richard Hipp lançada em 17 de agosto de 2000 enquanto Richard trabalhava para a General Dynamics em um contrato com a marinha dos Estados Unidos.

A ideia principal da biblioteca é bem simples: Prover uma forma de armazenar e consultar dados de forma confiável, com o uso de SQL, mas sem precisar dos complicados processos de instalação e manutenção que um sistema de gerenciamento de banco de dados (SGBDs) necessita, mas sem deixar a desejar muito em recursos, ao mesmo tempo que evita a necessidade de um administrador de banco de dados (ou DBA, como também é conhecido).

Apesar disso, e de conter uma série de recursos que normalmente são encontrados em SGBDs - como suporte a múltiplas tabelas, views, índices (até mesmo full-text!) e até mesmo triggers - o SQLite não compete contra esses sistemas gerenciadores de bancos de dados. Em vez disso, o SQLite compete com o....fopen(). Sim, a mesma chamada padrão que permite que você abra e crie arquivos.

Onde é usado

O SQLite é usado em praticamente...todo lugar. Seu navegador, esse que você provavelmente está usando agora para ler este post, usa SQLite. O seu sistema operacional, seja ele o Windows, Linux (nesse caso, muitas vezes, a nível de distribuição) ou Mac, usa SQLite.

Seu smartphone - e muitos dos aplicativos que você tem instalado nele - usam SQLite (o Android e o iOS chegam até mesmo a oferecer o SQLite de forma nativa). Além disso, muitos dispositivos inteligentes hoje, incluindo as Smart TVs e até muitas geladeiras inteligentes (daquelas super caras), chegam a usar SQLite.

Fora da sua casa, existem sistemas multimídias de carros e até mesmo aviões que usam SQLite, e muitas vezes ele é incluído nos ambientes nativos de linguagens de programação....populares, como PHP e Python. Legal, né?

Casos de Uso Úteis

Como você já pode perceber, o SQLite é um mecanismo de bancos de dados versátil, e na prática, você pode usá-lo em praticamente qualquer situação onde você deseja persistir dados.

Claro, isso não significa que seria uma decisão super inteligente fazer um mecanismo de busca com o objetivo de rastrear quase toda a internet como o Google faz apenas em cima de um banco de dados salvo pelo SQLite, ou então, criar um site que vá receber milhares de visitas por segundo, mas...veja: Em que momentos você precisa fazer isso, mesmo?

Por exemplo, quais aplicações precisam trabalhar com uma quantidade tão absurda de dados, enquanto as consulta tão frequentemente por dia? Pois é, não são muitas. Claro, não vou dizer que dá pra contar nos dedos, pois existem bastante situações em que a quantidade de dados é realmente grande, e a necessidade por fazer consultas frequentes também, mas, dá para dizer com tranquilidade que, para uma grande maior parte dos projetos por aí, o SQLite é sim uma opção bastante viável.

Com isso dito, na minha experiência, o SQLite se mostra especialmente valioso na criação de scripts, desses que são criados para processamento de dados. Isso porquê, com o SQLite, você consegue não só organizar os dados em uma estrutura conhecida, como também consultá-los de maneira eficiente. Chega num ponto em que fica tão interessante que você simplesmente consegue parar o script em dado ponto e rodar consultas para verificar se os dados estão sendo salvos da maneira como você esperava. É algo com MUITO potencial.

Uma outra situação em que o SQLite se destaca é no desenvolvimento de protótipos. Afinal, para quê usar um SGBD complexo rodando 24/7 somente para o desenvolvimento de um simples MVP que a principio vai rodar só na sua máquina, por exemplo? Para esses casos, a simplicidade do SQLite ajuda a economizar muito tempo que em outra situação seria gasto instalando e configurando um SGBD como o MySQL ou o PostgreSQL, por exemplo.

Outra situação no qual o SQLite se destaca bastante é para análise de dados, graças ao uso de ferramentas incríveis como o Datasette, que possui um ecossistema rico de plugins afim de ajudar na análise de diferentes tipos de dados e na criação de diferentes visualizações, como dashboards, só para citar um exemplo.

Por fim, uma outra situação no qual o SQLite é normalmente considerado é para o desenvolvimento de testes de integração - onde muitas aplicações acabam precisando se comunicar com o banco de dados afim de poder rodar suas consultas. Honestamente, eu não sugeriria fazer isso a menos que o seu SGBD principal já seja o SQLite, visto que muitas consultas podem acabar funcionando de forma diferente no SQLite vs. no seu SBGD principal. Apesar disso, é algo que ainda é bastante considerado e difundido na internet, logo fica aqui o aviso.

Para entender melhor em que situações vale considerar seu uso, vamos falar um pouco sobre suas vantagens e desvantagens.

Vantagens e Desvantagens

Apesar do fato do SQLite tentar competir mais com o fopen(), sua lista de vantagens e desvantagens na realidade é bem..interessante, em especial se você considerar quão pequeno o SQLite de fato é (a biblioteca compilada pesa menos de 1MB). Nessa seção, vou abordar alguns pontos que podem tanto motivar quanto desmotivar a escolha pelo SQLite.

Vantagens

Existem várias vantagens em usar o SQLite. Naturalmente, mesmo que alguma vantagem lhe pareça extremamente conveniente, isso não significa que ele será a solução absolutamente PERFEITA para o seu caso de uso. Afinal, vale dar uma olhada na lista de desvantagens também, afim de evitar eventuais problemas futuros. =)

Dito isso, vamos às vantagens:

Serverless (não precisa de servidor)

O SQLite é um SGBD que não necessita de configuração e inicialização de servidores. Basicamente, você importa/linka o SQLite no código do seu projeto, chama as funções da API pública para criar/abrir o banco de dados, rodar consultas e afins, e...é isso.

É basicamente como se, de repente, o driver que você usa para conectar ao banco de dados fosse de fato o banco de dados por si só, com latência basicamente zero, e sem a necessidade de fazer mais nada além do que você já está acostumado a fazer, que é chamar a API pública para abrir o banco de dados, rodar as migrações da sua aplicação para preparar a estrutura do banco de dados, e executar consultas.

Naturalmente, isso pode levar a alguns erros que não acho que aconteceriam tão facilmente no caso de um servidor de banco de dados. Se você passar a string ":memory:" como nome do banco de dados que você quer abrir, por exemplo, o SQLite vai abrir um banco de dados somente em memória, que portanto vai ser destruído no momento que a aplicação for encerrada. Da mesma forma, se você passar uma string vazia, o SQLite vai abrir um banco de dados em uma pasta temporária, que também será apagada ao final da execução do programa, mas que não é mais limitada pela quantidade de memória RAM disponível.

Portátil

Como é possível perceber, o SQLite opera manipulando diretamente arquivos locais de banco de dados. Isso significa que ele não exige nenhuma configuração e gerenciamento de portas nem nada do tipo, sendo, portanto, portátil. Se você desenvolve uma aplicação que usa SQLite e que salva o arquivo em um diretório na mesma pasta, por exemplo, você pode fazer operações no banco de dados mesmo de um pendrive, o que mostra o quão portátil é o SQLite enquanto banco de dados.

Confiável

O SQLite é extremamente confiável, ao ponto que consegue ser o mais resiliente possível mesmo para erros de sistema ou de memória. Além disso, também é resistente contra arquivos maliciosamente alterados, e é recomendado pela biblitoeca do congresso dos Estados Unidos para armazenamento de dados a longo prazo.

Inclusive, falando em longo prazo, o time do SQLite planeja suportar o projeto PELO MENOS até 2050. Dado a quantidade enorme e variada de casos de uso do projeto, eu pessoalmente acredito que irá facilmente além dessa marca, mas isso mostra o quão confiável é o SQLite no geral.

Possui amplo suporte à muitos dos recursos encontrados em outros SGBDs relacionais

O SQLite possui suporte à praticamente todos os recursos que você espera de um SGBD convencional:

  • Transações;
  • JOINs;
  • Window Functions - excelentes para analytics;
  • Suporte a variados tipos de Índices, incluindo aí índices geográficos e full-text;
  • Uma grande quantidade de funções para utilização nas consultas;
  • Tabelas virtuais;
  • Sub-Queries;
  • Um planejador de consultas (query planner) bastante avançado e inteligente;

E vários outros recursos dignos de SGBDs avançados, como o PostgreSQL e o MySQL.

Possui um extenso ecossistema

O SQLite possui uma comunidade muito grande, pelo fato de ser um projeto extremamente usado. Isso faz com que o projeto tenha, também, um rico ecossistema, capaz de suprir as mais variadas necessidades dos seus usuários, a partir do uso de projetos que foram criados justamente para...atender problemas de outros usuários.

Uma lista bastante completa dos projetos ao qual me refiro está presente no repositório awesome-sqlite, mas aqui segue alguns que definitivamente chamam minha atenção:

  • RQLite - Para usar o SQLIte com replicação entre diversos servidores, e também de forma mais tradicional, como um servidor à parte;
  • LiteStream - Também para replicação de diferentes bancos de dados, só que agora sem necessidade do uso de um servidor à parte;
  • Spatialite - Para estender o SQLite com habilidades geoespaciais, permitindo consultas capazes de lidar com dados geográficos de maneira muito eficiente;

Desvantagens

Como todo projeto e coisa nesse universo, o SQLite não é perfeito, e também tem sua lista de desvantagens própria, ou seja, não é uma solução que atende a todos os projetos de maneira absolutamente perfeita (se é que isso existe), e portanto é importante estar ciente de todos os possíveis problemas ao usar o projeto.

É mais dificil de escalar horizontalmente se usado em aplicações web

O SQLite, como já explicado nesse post, é basicamente uma biblioteca que se integra diretamente na aplicação, e que trabalha alterando diretamente um arquivo especificado, que é, nesse caso, o próprio arquivo do banco de dados (onde os dados e estruturas são efetivamente salvos).

Como pode-se imaginar, essa característica reduz significantemente a latência envolvida, pois a aplicação não precisa criar a consulta, mandar para um servidor, esperar o servidor processar e então receber a resposta para retornar para o usuário. Entretanto, essa abordagem também limita significantemente a capacidade de escalar horizontalmente de maneira fácil.

O que seria escalar horizontalmente, nesse caso? Simples! Imagine uma aplicação web, como um...blog, por exemplo. Numa arquitetura em que o SGBD é acessado usando o tradicional cliente-servidor, você pode ter vários clientes e um servidor. Ou seja, é possível ter 5, 10 máquinas distintas rodando o Apache/NGINX+PHP/Python/Go/qualquer outra linguagem, e apenas um banco de dados. Isso trás benefícios significativos quando os dados são apenas lidos do SGBD, e portanto é uma abordagem simples e muito utilizada para escalar aplicações web.

Entretanto, pela natureza do SQLite, isso...não se torna possível de maneira simples. Ou seja, você consegue, sim, escalar horizontalmente uma aplicação web usando SQLite (mesmo usando um dos projetos mencionados acima, como RQLite ou LiteStream), mas isso certamente será mais díficil do que em um SGBD cliente-servidor já pensado para atender esse tipo de situação.

Não possui suporte à concorrência em escritas

Outro problema característico do SQLite é a falta de suporte para atender grandes quantidades de usuários escrevendo simultaneamente no banco de dados. O que é uma grande quantidade, nesse contexto? Essa é uma boa pergunta! E a resposta para essa pergunta vai variar muito de acordo com a sua aplicação, as requisições feitas, e também a máquina no qual o código está rodando (por exemplo, se você salvar o arquivo do banco de dados em um HD, a performance vai ser MUITO pior do que se o arquivo estivesse em um SSD, naturalmente).

No geral, o que quero dizer aqui é que o SQLite acaba não sendo a opção mais adequada em um cenário com mais de uma operação de escrita sendo realizada em um dado momento. No modo padrão, por exemplo, o SQLite literalmente bloqueia todo e qualquer acesso ao banco de dados quando uma operação de escrita é realizada. Já no modo WAL (de Write-Ahead Logging, ou registro de gravação antecipada em tradução livre), o SQLite até permite que operações de leituras continuem sendo feitas, mas..adivinha? Demais operações de escritas ainda são bloqueadas.

Note que esses bloqueios acontecem mesmo em tabelas diferentes, e mesmo que as operações de escrita em questão não afetem ou sejam relacionados à outros registros no banco de dados. Por exemplo, se você tiver uma tabela simples de log, onde você só salva uma mensagem e a data do registro, a limitação ainda irá se aplicar.

Mas, isso dito, seria essa um problema que persistirá para sempre? Bom, não necessariamente. O próprio projeto do SQLite tem branches (similares às do GIT) onde os desenvolvedores do projeto estão estudando formas de solucionar esse problema e permitir mais de uma operação de escrita em um dado momento do tempo. Um grande exemplo de branch assim é a do BEGIN CONCURRENT, que basicamente implementa uma forma de permitir mais de uma transação de escrita ao mesmo tempo, ao procurar realizar bloqueios apenas quando duas operações manipulam exatamente o mesmo conjunto de dados.

Entretanto, HOJE, no momento em que escrevo esse post, essa branch ainda não foi mergeada na branch principal do projeto, e portanto, não há muitas alternativas para você, caro desenvolvedor, que quer escrever aplicações intensivas em escritas e que usem o SQLite, a não ser...solucionar o problema por conta própria.

Como? Bom, aí que as coisas ficam complicadas.. Você pode, por exemplo, implementtar em sua aplicação um sistema similar ao sharding de banco de dados, que consistiria, nesse caso, em ter vários arquivos de banco de dados, todos com a exata mesma estrutura, e fazer as operações de acordo com divisões que façam sentido para sua aplicação.

No exemplo do log, mencionado acima, você poderia criar um número arbitrário de arquivos de bancos de dados e, a cada operação de escrita, escrever em um dos arquivos de forma...aleatória (ou seja, se você tem 10 arquivos, você sorteia um e escreve nele). Está precisando de mais concorrência? Basta criar um número maior de arquivos, e aí o céu é o limite. =)

Ouuuu...você pode tomar a decisão lógica mais simples e.. optar por outro SGBD. Em um mundo em que temos SGBDs excelentes como o PostgreSQL à disposição, não tem muito motivo para você precisar fazer esse tipo de coisa na sua aplicação apenas por desejar usar o SQLite.

Conclusão

Como você pôde ver ao longo desse artigo, o SQLite é um SGBD extremamente versátil, portátil e fácil de usar. Claro, como toda e qualquer coisa por aí, o projeto tem seus pontos negativos, o que naturalmente pode ser um fator limitante para seu uso em tudo que é lugar.

Entretanto, é importante reconhecer o impacto que o projeto tem no mundo moderno, com o projeto sendo usado nos mais variados dispositivos e aplicações usados pelas pessoas, seja em um navegador de internet, seja em um sistema de um avião.

Deixe nos comentários o que você achou sobre esse artigo e também sugestões para os próximos! Eu pretendo voltar a escrever para o blog mais frequentemente - se tudo der certo - então ter ideias para cobrir aqui é legal e bem vindo! Valeu!

]]>
Logo do SQLite
Logo do SQLite

Durante o desenvolvimento de uma aplicação, seja ela web, desktop ou mesmo mobile, sempre aparece algumas perguntas...complexas. Que linguagem de programação usar? Framework? Quais plataformas focar? E mais importante ainda: Onde armazenar os dados da aplicação?

Naturalmente, as resposta vão variar bastante de aplicação para aplicação. Não existe sequer uma aplicação em que eu trabalhei na vida em que a resposta foi simplesmente "evidentemente vai ser X, pois sim", embora com o passar dos anos a experiência e o conhecimento sobre diferentes soluções ajude na decisão por escolhas melhores e mais apropriadas para cada contexto.

E hoje, depois de anos sem escrever nada por aqui, eu vou falar um pouco sobre uma forma de armazenar e consultar dados que é bem interessante, mas quase nunca considerada no desenvolvimento de uma aplicação moderna, embora seja literalmente o mecanismo de banco de dados mais usado do mundo (sim, eu sei que isso é bastante contra intuitivo, mas eu já vou explicar mais sobre): o SQLite.

O que é

O SQLite é uma biblioteca desenvolvida na linguagem C por D. Richard Hipp lançada em 17 de agosto de 2000 enquanto Richard trabalhava para a General Dynamics em um contrato com a marinha dos Estados Unidos.

A ideia principal da biblioteca é bem simples: Prover uma forma de armazenar e consultar dados de forma confiável, com o uso de SQL, mas sem precisar dos complicados processos de instalação e manutenção que um sistema de gerenciamento de banco de dados (SGBDs) necessita, mas sem deixar a desejar muito em recursos, ao mesmo tempo que evita a necessidade de um administrador de banco de dados (ou DBA, como também é conhecido).

Apesar disso, e de conter uma série de recursos que normalmente são encontrados em SGBDs - como suporte a múltiplas tabelas, views, índices (até mesmo full-text!) e até mesmo triggers - o SQLite não compete contra esses sistemas gerenciadores de bancos de dados. Em vez disso, o SQLite compete com o....fopen(). Sim, a mesma chamada padrão que permite que você abra e crie arquivos.

Onde é usado

O SQLite é usado em praticamente...todo lugar. Seu navegador, esse que você provavelmente está usando agora para ler este post, usa SQLite. O seu sistema operacional, seja ele o Windows, Linux (nesse caso, muitas vezes, a nível de distribuição) ou Mac, usa SQLite.

Seu smartphone - e muitos dos aplicativos que você tem instalado nele - usam SQLite (o Android e o iOS chegam até mesmo a oferecer o SQLite de forma nativa). Além disso, muitos dispositivos inteligentes hoje, incluindo as Smart TVs e até muitas geladeiras inteligentes (daquelas super caras), chegam a usar SQLite.

Fora da sua casa, existem sistemas multimídias de carros e até mesmo aviões que usam SQLite, e muitas vezes ele é incluído nos ambientes nativos de linguagens de programação....populares, como PHP e Python. Legal, né?

Casos de Uso Úteis

Como você já pode perceber, o SQLite é um mecanismo de bancos de dados versátil, e na prática, você pode usá-lo em praticamente qualquer situação onde você deseja persistir dados.

Claro, isso não significa que seria uma decisão super inteligente fazer um mecanismo de busca com o objetivo de rastrear quase toda a internet como o Google faz apenas em cima de um banco de dados salvo pelo SQLite, ou então, criar um site que vá receber milhares de visitas por segundo, mas...veja: Em que momentos você precisa fazer isso, mesmo?

Por exemplo, quais aplicações precisam trabalhar com uma quantidade tão absurda de dados, enquanto as consulta tão frequentemente por dia? Pois é, não são muitas. Claro, não vou dizer que dá pra contar nos dedos, pois existem bastante situações em que a quantidade de dados é realmente grande, e a necessidade por fazer consultas frequentes também, mas, dá para dizer com tranquilidade que, para uma grande maior parte dos projetos por aí, o SQLite é sim uma opção bastante viável.

Com isso dito, na minha experiência, o SQLite se mostra especialmente valioso na criação de scripts, desses que são criados para processamento de dados. Isso porquê, com o SQLite, você consegue não só organizar os dados em uma estrutura conhecida, como também consultá-los de maneira eficiente. Chega num ponto em que fica tão interessante que você simplesmente consegue parar o script em dado ponto e rodar consultas para verificar se os dados estão sendo salvos da maneira como você esperava. É algo com MUITO potencial.

Uma outra situação em que o SQLite se destaca é no desenvolvimento de protótipos. Afinal, para quê usar um SGBD complexo rodando 24/7 somente para o desenvolvimento de um simples MVP que a principio vai rodar só na sua máquina, por exemplo? Para esses casos, a simplicidade do SQLite ajuda a economizar muito tempo que em outra situação seria gasto instalando e configurando um SGBD como o MySQL ou o PostgreSQL, por exemplo.

Outra situação no qual o SQLite se destaca bastante é para análise de dados, graças ao uso de ferramentas incríveis como o Datasette, que possui um ecossistema rico de plugins afim de ajudar na análise de diferentes tipos de dados e na criação de diferentes visualizações, como dashboards, só para citar um exemplo.

Por fim, uma outra situação no qual o SQLite é normalmente considerado é para o desenvolvimento de testes de integração - onde muitas aplicações acabam precisando se comunicar com o banco de dados afim de poder rodar suas consultas. Honestamente, eu não sugeriria fazer isso a menos que o seu SGBD principal já seja o SQLite, visto que muitas consultas podem acabar funcionando de forma diferente no SQLite vs. no seu SBGD principal. Apesar disso, é algo que ainda é bastante considerado e difundido na internet, logo fica aqui o aviso.

Para entender melhor em que situações vale considerar seu uso, vamos falar um pouco sobre suas vantagens e desvantagens.

Vantagens e Desvantagens

Apesar do fato do SQLite tentar competir mais com o fopen(), sua lista de vantagens e desvantagens na realidade é bem..interessante, em especial se você considerar quão pequeno o SQLite de fato é (a biblioteca compilada pesa menos de 1MB). Nessa seção, vou abordar alguns pontos que podem tanto motivar quanto desmotivar a escolha pelo SQLite.

Vantagens

Existem várias vantagens em usar o SQLite. Naturalmente, mesmo que alguma vantagem lhe pareça extremamente conveniente, isso não significa que ele será a solução absolutamente PERFEITA para o seu caso de uso. Afinal, vale dar uma olhada na lista de desvantagens também, afim de evitar eventuais problemas futuros. =)

Dito isso, vamos às vantagens:

Serverless (não precisa de servidor)

O SQLite é um SGBD que não necessita de configuração e inicialização de servidores. Basicamente, você importa/linka o SQLite no código do seu projeto, chama as funções da API pública para criar/abrir o banco de dados, rodar consultas e afins, e...é isso.

É basicamente como se, de repente, o driver que você usa para conectar ao banco de dados fosse de fato o banco de dados por si só, com latência basicamente zero, e sem a necessidade de fazer mais nada além do que você já está acostumado a fazer, que é chamar a API pública para abrir o banco de dados, rodar as migrações da sua aplicação para preparar a estrutura do banco de dados, e executar consultas.

Naturalmente, isso pode levar a alguns erros que não acho que aconteceriam tão facilmente no caso de um servidor de banco de dados. Se você passar a string ":memory:" como nome do banco de dados que você quer abrir, por exemplo, o SQLite vai abrir um banco de dados somente em memória, que portanto vai ser destruído no momento que a aplicação for encerrada. Da mesma forma, se você passar uma string vazia, o SQLite vai abrir um banco de dados em uma pasta temporária, que também será apagada ao final da execução do programa, mas que não é mais limitada pela quantidade de memória RAM disponível.

Portátil

Como é possível perceber, o SQLite opera manipulando diretamente arquivos locais de banco de dados. Isso significa que ele não exige nenhuma configuração e gerenciamento de portas nem nada do tipo, sendo, portanto, portátil. Se você desenvolve uma aplicação que usa SQLite e que salva o arquivo em um diretório na mesma pasta, por exemplo, você pode fazer operações no banco de dados mesmo de um pendrive, o que mostra o quão portátil é o SQLite enquanto banco de dados.

Confiável

O SQLite é extremamente confiável, ao ponto que consegue ser o mais resiliente possível mesmo para erros de sistema ou de memória. Além disso, também é resistente contra arquivos maliciosamente alterados, e é recomendado pela biblitoeca do congresso dos Estados Unidos para armazenamento de dados a longo prazo.

Inclusive, falando em longo prazo, o time do SQLite planeja suportar o projeto PELO MENOS até 2050. Dado a quantidade enorme e variada de casos de uso do projeto, eu pessoalmente acredito que irá facilmente além dessa marca, mas isso mostra o quão confiável é o SQLite no geral.

Possui amplo suporte à muitos dos recursos encontrados em outros SGBDs relacionais

O SQLite possui suporte à praticamente todos os recursos que você espera de um SGBD convencional:

  • Transações;
  • JOINs;
  • Window Functions - excelentes para analytics;
  • Suporte a variados tipos de Índices, incluindo aí índices geográficos e full-text;
  • Uma grande quantidade de funções para utilização nas consultas;
  • Tabelas virtuais;
  • Sub-Queries;
  • Um planejador de consultas (query planner) bastante avançado e inteligente;

E vários outros recursos dignos de SGBDs avançados, como o PostgreSQL e o MySQL.

Possui um extenso ecossistema

O SQLite possui uma comunidade muito grande, pelo fato de ser um projeto extremamente usado. Isso faz com que o projeto tenha, também, um rico ecossistema, capaz de suprir as mais variadas necessidades dos seus usuários, a partir do uso de projetos que foram criados justamente para...atender problemas de outros usuários.

Uma lista bastante completa dos projetos ao qual me refiro está presente no repositório awesome-sqlite, mas aqui segue alguns que definitivamente chamam minha atenção:

  • RQLite - Para usar o SQLIte com replicação entre diversos servidores, e também de forma mais tradicional, como um servidor à parte;
  • LiteStream - Também para replicação de diferentes bancos de dados, só que agora sem necessidade do uso de um servidor à parte;
  • Spatialite - Para estender o SQLite com habilidades geoespaciais, permitindo consultas capazes de lidar com dados geográficos de maneira muito eficiente;

Desvantagens

Como todo projeto e coisa nesse universo, o SQLite não é perfeito, e também tem sua lista de desvantagens própria, ou seja, não é uma solução que atende a todos os projetos de maneira absolutamente perfeita (se é que isso existe), e portanto é importante estar ciente de todos os possíveis problemas ao usar o projeto.

É mais dificil de escalar horizontalmente se usado em aplicações web

O SQLite, como já explicado nesse post, é basicamente uma biblioteca que se integra diretamente na aplicação, e que trabalha alterando diretamente um arquivo especificado, que é, nesse caso, o próprio arquivo do banco de dados (onde os dados e estruturas são efetivamente salvos).

Como pode-se imaginar, essa característica reduz significantemente a latência envolvida, pois a aplicação não precisa criar a consulta, mandar para um servidor, esperar o servidor processar e então receber a resposta para retornar para o usuário. Entretanto, essa abordagem também limita significantemente a capacidade de escalar horizontalmente de maneira fácil.

O que seria escalar horizontalmente, nesse caso? Simples! Imagine uma aplicação web, como um...blog, por exemplo. Numa arquitetura em que o SGBD é acessado usando o tradicional cliente-servidor, você pode ter vários clientes e um servidor. Ou seja, é possível ter 5, 10 máquinas distintas rodando o Apache/NGINX+PHP/Python/Go/qualquer outra linguagem, e apenas um banco de dados. Isso trás benefícios significativos quando os dados são apenas lidos do SGBD, e portanto é uma abordagem simples e muito utilizada para escalar aplicações web.

Entretanto, pela natureza do SQLite, isso...não se torna possível de maneira simples. Ou seja, você consegue, sim, escalar horizontalmente uma aplicação web usando SQLite (mesmo usando um dos projetos mencionados acima, como RQLite ou LiteStream), mas isso certamente será mais díficil do que em um SGBD cliente-servidor já pensado para atender esse tipo de situação.

Não possui suporte à concorrência em escritas

Outro problema característico do SQLite é a falta de suporte para atender grandes quantidades de usuários escrevendo simultaneamente no banco de dados. O que é uma grande quantidade, nesse contexto? Essa é uma boa pergunta! E a resposta para essa pergunta vai variar muito de acordo com a sua aplicação, as requisições feitas, e também a máquina no qual o código está rodando (por exemplo, se você salvar o arquivo do banco de dados em um HD, a performance vai ser MUITO pior do que se o arquivo estivesse em um SSD, naturalmente).

No geral, o que quero dizer aqui é que o SQLite acaba não sendo a opção mais adequada em um cenário com mais de uma operação de escrita sendo realizada em um dado momento. No modo padrão, por exemplo, o SQLite literalmente bloqueia todo e qualquer acesso ao banco de dados quando uma operação de escrita é realizada. Já no modo WAL (de Write-Ahead Logging, ou registro de gravação antecipada em tradução livre), o SQLite até permite que operações de leituras continuem sendo feitas, mas..adivinha? Demais operações de escritas ainda são bloqueadas.

Note que esses bloqueios acontecem mesmo em tabelas diferentes, e mesmo que as operações de escrita em questão não afetem ou sejam relacionados à outros registros no banco de dados. Por exemplo, se você tiver uma tabela simples de log, onde você só salva uma mensagem e a data do registro, a limitação ainda irá se aplicar.

Mas, isso dito, seria essa um problema que persistirá para sempre? Bom, não necessariamente. O próprio projeto do SQLite tem branches (similares às do GIT) onde os desenvolvedores do projeto estão estudando formas de solucionar esse problema e permitir mais de uma operação de escrita em um dado momento do tempo. Um grande exemplo de branch assim é a do BEGIN CONCURRENT, que basicamente implementa uma forma de permitir mais de uma transação de escrita ao mesmo tempo, ao procurar realizar bloqueios apenas quando duas operações manipulam exatamente o mesmo conjunto de dados.

Entretanto, HOJE, no momento em que escrevo esse post, essa branch ainda não foi mergeada na branch principal do projeto, e portanto, não há muitas alternativas para você, caro desenvolvedor, que quer escrever aplicações intensivas em escritas e que usem o SQLite, a não ser...solucionar o problema por conta própria.

Como? Bom, aí que as coisas ficam complicadas.. Você pode, por exemplo, implementtar em sua aplicação um sistema similar ao sharding de banco de dados, que consistiria, nesse caso, em ter vários arquivos de banco de dados, todos com a exata mesma estrutura, e fazer as operações de acordo com divisões que façam sentido para sua aplicação.

No exemplo do log, mencionado acima, você poderia criar um número arbitrário de arquivos de bancos de dados e, a cada operação de escrita, escrever em um dos arquivos de forma...aleatória (ou seja, se você tem 10 arquivos, você sorteia um e escreve nele). Está precisando de mais concorrência? Basta criar um número maior de arquivos, e aí o céu é o limite. =)

Ouuuu...você pode tomar a decisão lógica mais simples e.. optar por outro SGBD. Em um mundo em que temos SGBDs excelentes como o PostgreSQL à disposição, não tem muito motivo para você precisar fazer esse tipo de coisa na sua aplicação apenas por desejar usar o SQLite.

Conclusão

Como você pôde ver ao longo desse artigo, o SQLite é um SGBD extremamente versátil, portátil e fácil de usar. Claro, como toda e qualquer coisa por aí, o projeto tem seus pontos negativos, o que naturalmente pode ser um fator limitante para seu uso em tudo que é lugar.

Entretanto, é importante reconhecer o impacto que o projeto tem no mundo moderno, com o projeto sendo usado nos mais variados dispositivos e aplicações usados pelas pessoas, seja em um navegador de internet, seja em um sistema de um avião.

Deixe nos comentários o que você achou sobre esse artigo e também sugestões para os próximos! Eu pretendo voltar a escrever para o blog mais frequentemente - se tudo der certo - então ter ideias para cobrir aqui é legal e bem vindo! Valeu!

]]>
https://fjorgemota.com/2023/03/23/sqlite-um-mecanismo-de-banco-de-dados-incrivelmente-versatil/feed/ 0 3951
Mailhog - Teste seus e-mails em desenvolvimento https://fjorgemota.com/2015/08/17/mailhog-teste-seus-e-mails-em-desenvolvimento/ https://fjorgemota.com/2015/08/17/mailhog-teste-seus-e-mails-em-desenvolvimento/#respond Mon, 17 Aug 2015 10:00:18 +0000 https://fjorgemota.com/?p=988 E a situação fica mais chata ainda quando você considera que, se você enviar um mesmo e-mail múltiplas vezes, seu e-mail pode cair na blacklist de SPAM, logo, fazer testes de e-mail com provedores reais normalmente não é algo que dá muito certo, e assim, é fácil concluir que depender da web para isso não é bem...interessante. Por isso que hoje vou falar do Mailhog. O Mailhog é um software de código aberto desenvolvido em Go que facilita e muito o teste de e-mails no ambiente de desenvolvimento. Funciona assim: Você baixa o binário do Mailhog, executa e....bem, é isso. O Mailhog inicia, em seu PC, um servidor de SMTP que não envia e-mails para absolutamente lugar nenhum. Os e-mails "enviados" a partir desse SMTP na verdade são capturados e colocados em memória, de forma que seja possível ver como eles ficam no browser e, caso você queira, mesmo enviá-lo para outro serviço de e-mail real, para ter certeza que está tudo certo e ver como o e-mail fica nesse outro serviço. Não bastasse ser uma tremenda mão na roda só com isso, o Mailhog também tem outra função que facilita pacas a vida do desenvolvedor: O Jim. O JIm é o que o Mailhog chama de "Macaco do Caos", pois sua intenção é unicamente...fazer bagunça. Segue a lista do que o Jim faz:
  • Recusa conexões;
  • Limita a velocidade das conexões;
  • Recusa autenticação;
  • Recusa destinatários;
  • Recusa remetentes;
Mas, se o Jim só faz bagunça, qual o motivo dele ser bom? Simples: Todos esses erros podem e não raramente acontecem em produção, seja por problemas no hardware, no software ou da área de ciências ocultas da computação. Com o Jim, você consegue ver como sua aplicação se comporta frente a esses erros, e consegue prevenir o que pode acontecer caso algum desses erros ocorram. Além disso tudo, o Mailhog tem também as seguintes características:
  • Aceita recebimento de e-mails com anexos;
  • Mostra e-mails no browser em tempo real conforme e-mails vão chegando;
  • Visualização de e-mail em modo texto e em modo HTML;
  • Portátil, não requer instalação;
  • Opção de salvar e-mails no MongoDB, para persistência;
Enfim, é isso. Se a aplicação no qual você trabalha envia e-mails, dedique alguns minutos do seu dia para testar o Mailhog. Vale bastante a pena e você não vai se arrepender. =) ]]>
Quando se desenvolve uma aplicação web, é normal que tal aplicação possua suporte a envio de e-mails. Seja para confirmar o e-mail do usuário, seja para mandar boas vindas a ele, seja para recuperar senha, enfim, são variados os e-mails a serem enviados pela aplicação e normalmente é bem chato de testar o envio em ambiente de desenvolvimento, pois o envio de e-mails exige configuração de algumas coisas bem chatas, como host SMTP, usuário, senha, criptografia, e por aí vai.

E a situação fica mais chata ainda quando você considera que, se você enviar um mesmo e-mail múltiplas vezes, seu e-mail pode cair na blacklist de SPAM, logo, fazer testes de e-mail com provedores reais normalmente não é algo que dá muito certo, e assim, é fácil concluir que depender da web para isso não é bem...interessante.

Por isso que hoje vou falar do Mailhog. O Mailhog é um software de código aberto desenvolvido em Go que facilita e muito o teste de e-mails no ambiente de desenvolvimento.

Funciona assim: Você baixa o binário do Mailhog, executa e....bem, é isso. O Mailhog inicia, em seu PC, um servidor de SMTP que não envia e-mails para absolutamente lugar nenhum. Os e-mails "enviados" a partir desse SMTP na verdade são capturados e colocados em memória, de forma que seja possível ver como eles ficam no browser e, caso você queira, mesmo enviá-lo para outro serviço de e-mail real, para ter certeza que está tudo certo e ver como o e-mail fica nesse outro serviço.

Não bastasse ser uma tremenda mão na roda só com isso, o Mailhog também tem outra função que facilita pacas a vida do desenvolvedor: O Jim. O JIm é o que o Mailhog chama de "Macaco do Caos", pois sua intenção é unicamente...fazer bagunça. Segue a lista do que o Jim faz:

  • Recusa conexões;
  • Limita a velocidade das conexões;
  • Recusa autenticação;
  • Recusa destinatários;
  • Recusa remetentes;

Mas, se o Jim só faz bagunça, qual o motivo dele ser bom? Simples: Todos esses erros podem e não raramente acontecem em produção, seja por problemas no hardware, no software ou da área de ciências ocultas da computação. Com o Jim, você consegue ver como sua aplicação se comporta frente a esses erros, e consegue prevenir o que pode acontecer caso algum desses erros ocorram.

Além disso tudo, o Mailhog tem também as seguintes características:

  • Aceita recebimento de e-mails com anexos;
  • Mostra e-mails no browser em tempo real conforme e-mails vão chegando;
  • Visualização de e-mail em modo texto e em modo HTML;
  • Portátil, não requer instalação;
  • Opção de salvar e-mails no MongoDB, para persistência;

Enfim, é isso. Se a aplicação no qual você trabalha envia e-mails, dedique alguns minutos do seu dia para testar o Mailhog. Vale bastante a pena e você não vai se arrepender. =)

]]>
https://fjorgemota.com/2015/08/17/mailhog-teste-seus-e-mails-em-desenvolvimento/feed/ 0 988
IEVMS - Instale o IE facilmente em seu Mac ou Linux https://fjorgemota.com/2014/09/22/ievms-instale-o-ie-facilmente-em-seu-mac-ou-linux/ https://fjorgemota.com/2014/09/22/ievms-instale-o-ie-facilmente-em-seu-mac-ou-linux/#respond Mon, 22 Sep 2014 12:00:37 +0000 https://fjorgemota.com/?p=159 developer, parece ser uma opção sensacional de sistema operacional a se usar. Entretanto, muitos ficam com receio nessa migração por falta de um excelente navegador que infelizmente ainda tem uma considerável porção de uso no mercado: O Internet Explorer. É por isso que hoje falarei sobre o IEVMS, um script desenvolvido em Bash e que tende a facilitar muito a instalação deste odiado navegador em outros sistemas operacionais além do Windows. O IEVMS é um script opensource que tem uma única função: Instalar, da melhor maneira possível, o Internet Explorer no seu computador. Como? Simples! Usando o Virtualbox, um software de virtualização gratuito mantido pela Oracle, e a imagem do Windows distribuída gratuitamente especificamente para os testes com Internet Explorer no modern.ie, que é uma iniciativa, veja só, da própria Microsoft! :) Mas...se a Microsoft oferece gratuitamente uma imagem do Windows para você conseguir testar os seus sites em diferentes versões do Internet Explorer, para que serviria o IEVMS? Simples! Para instalar TODAS as versões do IE servidas no modern.ie de forma eficiente e simples: Só com a execução de um simples comando no bash, e ainda com o salvamento automático de um snapshot para você reverter mudanças no Windows após os testes (ou após o período de expiração, também). Mas, para que instalar todas as versões do IE? Simples! Para poder verificar como o seu site funciona nessas versões, usando a versão adequada para isso! Afinal, em alguns casos, acreditem ou não, aquele simulador das ferramentas de desenvolvimento das últimas versões do IE podem não ter o mesmo comportamento das versões mais antigas do IE. E tem mais uma coisa: Se você não quiser instalar todas as versões do IE na sua máquina, é possível instalar apenas as que lhe convém. Assim, se você precisar das versões do IE à partir da 8,  poderá configurar o IEVMS para não instalar as versões 6 e 7, por exemplo. ]]> Faz alguns anos já que eu mudei para Linux. Para quem é developer, parece ser uma opção sensacional de sistema operacional a se usar. Entretanto, muitos ficam com receio nessa migração por falta de um excelente navegador que infelizmente ainda tem uma considerável porção de uso no mercado: O Internet Explorer. É por isso que hoje falarei sobre o IEVMS, um script desenvolvido em Bash e que tende a facilitar muito a instalação deste odiado navegador em outros sistemas operacionais além do Windows.

O IEVMS é um script opensource que tem uma única função: Instalar, da melhor maneira possível, o Internet Explorer no seu computador. Como? Simples! Usando o Virtualbox, um software de virtualização gratuito mantido pela Oracle, e a imagem do Windows distribuída gratuitamente especificamente para os testes com Internet Explorer no modern.ie, que é uma iniciativa, veja só, da própria Microsoft! 🙂

Mas...se a Microsoft oferece gratuitamente uma imagem do Windows para você conseguir testar os seus sites em diferentes versões do Internet Explorer, para que serviria o IEVMS? Simples! Para instalar TODAS as versões do IE servidas no modern.ie de forma eficiente e simples: Só com a execução de um simples comando no bash, e ainda com o salvamento automático de um snapshot para você reverter mudanças no Windows após os testes (ou após o período de expiração, também).

Mas, para que instalar todas as versões do IE? Simples! Para poder verificar como o seu site funciona nessas versões, usando a versão adequada para isso! Afinal, em alguns casos, acreditem ou não, aquele simulador das ferramentas de desenvolvimento das últimas versões do IE podem não ter o mesmo comportamento das versões mais antigas do IE.

E tem mais uma coisa: Se você não quiser instalar todas as versões do IE na sua máquina, é possível instalar apenas as que lhe convém. Assim, se você precisar das versões do IE à partir da 8,  poderá configurar o IEVMS para não instalar as versões 6 e 7, por exemplo.

]]>
https://fjorgemota.com/2014/09/22/ievms-instale-o-ie-facilmente-em-seu-mac-ou-linux/feed/ 0 159
Test’em – Execute testes Javascript com facilidade https://fjorgemota.com/2014/08/25/testem-execute-testes-javascript-com-facilidade/ https://fjorgemota.com/2014/08/25/testem-execute-testes-javascript-com-facilidade/#respond Mon, 25 Aug 2014 12:00:00 +0000 http://localhost/fjorgemota/?p=30 Mocha e o Jasmine, que são duas ferramentas íncriveis para facilitar a criação de testes. Entretanto, ficou faltando falar de opções para facilitar a execução dos testes. E sabe por qual motivo uma ferramenta para facilitar a execução de testes pode ajudar no desenvolvimento? Pelo simples motivo de que, quando você está escrevendo testes, pode simplesmente se tornar muito chato e ineficiente executá-los em vários browsers para verificar como eles estão se comportando. E é para isso que hoje apresentarem o Test’em, uma ferramenta que ajuda a tornar os testes em Javascript menos tediosos. Test’em é uma simples ferramenta de terminal desenvolvida em NodeJS e que é muito simples de instalar e usar. Com um simples arquivo de configuração, é possível definir coisas como framework a ser usado, comandos para build (para caso o projeto use Coffeescript, por exemplo) e arquivo HTML a ser carregado pelo servidor interno do Test'em. Após configurado, você tem acesso à coisa como:
  • Um servidor HTTP com auto-reload que recarrega os testes assim que eles são modificados;
  • Uma interface CLI prática para acompanhar os erros de forma remota (sem precisar acompanhá-los pelo browser);
  • Um modo "ci" para execução dos testes por um sistema de integração contínua, por exemplo;
  • E muito mais. =)
Segue um print-screen da interface CLI do Test’em caso você tenha ficado curioso sobre o segundo tópico: [caption id="attachment_146" align="aligncenter" width="300"]Interface gráfica do Test'em Afinal imagem de testes "dando certo" quase ninguém mostra, não é mesmo? :-)[/caption] ]]>
Já falamos aqui sobre o Mocha e o Jasmine, que são duas ferramentas íncriveis para facilitar a criação de testes. Entretanto, ficou faltando falar de opções para facilitar a execução dos testes. E sabe por qual motivo uma ferramenta para facilitar a execução de testes pode ajudar no desenvolvimento? Pelo simples motivo de que, quando você está escrevendo testes, pode simplesmente se tornar muito chato e ineficiente executá-los em vários browsers para verificar como eles estão se comportando. E é para isso que hoje apresentarem o Test’em, uma ferramenta que ajuda a tornar os testes em Javascript menos tediosos.

Test’em é uma simples ferramenta de terminal desenvolvida em NodeJS e que é muito simples de instalar e usar. Com um simples arquivo de configuração, é possível definir coisas como framework a ser usado, comandos para build (para caso o projeto use Coffeescript, por exemplo) e arquivo HTML a ser carregado pelo servidor interno do Test'em. Após configurado, você tem acesso à coisa como:

  • Um servidor HTTP com auto-reload que recarrega os testes assim que eles são modificados;
  • Uma interface CLI prática para acompanhar os erros de forma remota (sem precisar acompanhá-los pelo browser);
  • Um modo "ci" para execução dos testes por um sistema de integração contínua, por exemplo;
  • E muito mais. =)

Segue um print-screen da interface CLI do Test’em caso você tenha ficado curioso sobre o segundo tópico:

Interface gráfica do Test'em
Afinal imagem de testes "dando certo" quase ninguém mostra, não é mesmo? 🙂

]]>
https://fjorgemota.com/2014/08/25/testem-execute-testes-javascript-com-facilidade/feed/ 0 30