MongoDB – Buscar termo em todos os campos

Ao desenvolver uma API, certamente você se deparou com a missão de ter que fazer uma busca genérica em todos os campos do seu banco.

A primeira vista, essa missão pode assustar, pois, você deve pensar, como eu vou fazer isso? E se eu tiver vários campos, vou ter que especificar tudo na query?

Nesse artigo eu te mostro uma forma bem tranquila de fazer isso e ainda te digo os prós e contras.

O problema

Você está desenvolvendo uma API para o seu aplicativo e quer fazer uma busca “simples”, onde o usuário tem apenas um campo “buscar por…” e ao digitar um termo qualquer, a sua API tem que “se virar” para encontrar os resultados, seja o nome do usuário, idade, sexo, etc. não importa o que o usuário tenha digitado.

Recebendo o termo de busca

Normalmente, em uma API REST você vai receber esse termo pela querystring.

Seria alguma coisa como isso:

GET https://api.seuapp.com.br/v1/endpoint?search=termo

Se você estiver usando express do Node.js para escrever sua API, você vaii obter esse valor da seguinte forma:

app.get('endpoint', (request, response) => {
   const searchTerm = request.query.search;
});

Bacana, agora você já sabe obter o termo para a pesquisa, mas antes de nós fazermos a pesquisa no banco, vou te mostrar o pulo do gato para que isso tudo funcione de uma forma simples.

Criando o índice Text Search

Para resolver esse problema, o MongoDB nos proporciona a funcionalidade Text Search.

O Text Search nada mais é do que um índice múltiplo que quando a gente fizer a busca por ele. Veremos isso em breve.

Para criar esse índice, devemos rodar o seguinte comando no terminal do MongoDB.

db.suacolecao.createIndex( { campo1: "text", campo2: "text" } )

Para acessar o terminal do MongoDB (Mongo Client) você precisa estar com o daemon do banco de dados iniciado e digitar “mongo” no terminal do seu computador.

Pronto! Dessa forma você configurou que quando você fizer sua busca genérica, você vai pesquisar o termo nos campos: “campo1” e “campo2”.

Fique atento!

Digamos que sua coleção tenha 4 campos e você configurou no índice apenas 2 deles, fique atento, pois o termo será procurado apenas nos 2 campos configurados.

Como fazer a query?

Com a confiugração do índice, você “disse” para o MongoDB onde ele deve pesquisar o termo quando for procurado no índice text e para fazer essa busca, você precisa usar esse código.

mongoClient.find({ $text: { $search: searchTerm }});

Bônus: Como melhorar a sua experiência com a busca em índices

É possível que você quera excluir algum termo da busca ou até mesmo pesquisar por um termo exato.

Você pode excluir termos da sua busca, apenas colocando um sinal de menos na frente do termo.

db.suaColecao.find( { $text: { $search: "gol fusca -brasilia" } } )

Essa busca retorna tudo que contenha gol, fusca e que não contenha brasilia.

Você também pode procurar por um termo específico.

db.stores.find( { $text: { $search: "\"brasilia amarela\"" } } )

Esse código vai trazer apenas os resultados que contenham “brasilia amarela”.

Você também pode ordenar os resultados conforme o score da sua busca. O score é uma espécie de pontuação na qual identifica o quanto o termo encontrado é parecido ou igual ao termo pesquisado.

db.suaColecao.find(
   { $text: { $search: "gol fusca puma" } },
   { score: { $meta: "textScore" } }
).sort( { score: { $meta: "textScore" } } )

Outra forma

Existe ainda um outra forma de fazer algo parecido com isso, talvez seja a forma mais comum, entretanto, crio que não é a forma mais performática.

Essa forma não cria um índice específico pra isso, apenas adiciona os valores que devem ser pesquisados em um único campo, exemplo:

db.latasVelhas.insert(
   [
     { _id: 1, name: "Fusca", color: "azul porrada", tags: "Fusca azul porrada" },
     { _id: 2, name: "Bianco", color: "vermelho montana", tags: "Bianco vermelho montana" },
     { _id: 3, name: "Puma", color: "verde", tags: "Puma verde" },
     { _id: 4, name: "Brasilia", color: "amarela", tags: "Brasilia amarela" },
     { _id: 5, name: "Rural", color: "azul e branca", tags: "Rural azul e branca" }
   ]
)

E a busca seria algo como:

db.latasVelhas.find({ tags: /Puma/ });

O que muda nessa coleção é que não temos um índice configurado para fazer o trabalho pra gente, nesse caso a gente faz o trabalho do índice manualmente colocando todos os termos relevantes em um campo dentro da coleção.

Apesar de eu achar que é uma “gambiarra”, funciona! Mas veremos a seguir os prós e contras de ambas as formas.

Prós Vs. Contras

Tudo na vida tem prós e contras e com essa funcionalidade não é diferente.

Se você optar por criar o índice Text Search, a cada vez que houver a necessidade de adicionar um novo campo à busca, você terá que recriar esse índice e isso pode ser bem custoso, entretanto, seu código fica mais limpo, você não precisa escrever nada a mais ao inserir ou editar um dado, isto é, a manutenção é bem menos custosa, fora a velocidade que um índice traz para a sua aplicação.

Se você optar por ter um campo de tags com os termos relevantes, você vai aumentar o tamanho da sua base de forma desnecessária, fora toda a manutenção que esse campo vai exigir quando você inserir, mas principalmente quando precisar editar esses dados. Também sabemos que os índices foram criados para melhorar a performance e nesse caso você não os tem.

Mas nem pense em criar o campo de tags e ainda colocar um índice nele. Essa seria sua pior opção, tendo em vista que a cada modificação você precisara recriar os índices.

Exemplos

Considere a coleção abaixo:

db.latasVelhas.insert(
   [
     { _id: 1, name: "Fusca", color: "azul porrada" },
     { _id: 2, name: "Bianco", color: "vermelho montana" },
     { _id: 3, name: "Puma", color: "verde" },
     { _id: 4, name: "Brasilia", color: "amarela" },
     { _id: 5, name: "Rural", color: "azul e branca" }
   ]
)

Configure o índice Text Search:

db.latasVelhas.createIndex({ name: "text", color: "text" });

Busque por algum termo

db.latasVelhas.find( { $text: { $search: "fusca amarela" } } )

Busque por um termo específico

db.latasVelhas.find( { $text: { $search: "\"Bianco\"" } } )

Referência

Esse artigo foi escrito baseado na documentação do MongoDB que pode ser consultada no link abaixo (em inglês).

https://docs.mongodb.com/manual/text-search/

Como listar os pacotes globais do NPM?

Você já deve ter se deparado com a necessidade de listar os pacotes instalados globalmente pelo NPM. Talvez você tenha tido a ideia de olhar os pacotes que estão na node_modules e acabou percebendo que isso fica quase impossível. Então esse comando vai te ajudar a fazer essa tarefa de uma forma bem melhor.

Apenas digite o comando no seu terminal.

npm list -g --depth 0

Espero ter te ajudado.

Grande abraço!

Como resolver problemas de migrações

Você está desenvolvendo uma aplicação na sua estação. Cria, modifica, remove tabelas, chaves (constraints) e colunas, gera um monte de migrações (migrations) com o seu ORM favorito para manipular uma base de dados relacional e na hora do deploy o sistema quebra porque as migrações estão uma bagunça querendo remover coisas que não existem mais ou criar cosias que já existem.

Isso acontece e eu vou te mostrar aqui algumas formas de resolver.

O problema…

Na hora do desenvolvimento é normal que a gente faça muita alteração, afinal de contas, é nessa hora que podemos testar hipóteses e errar bastante, mas isso gera um certo “lixo” nas migrações que podem e vão nos dar trabalho futuramente.

Esse tipo de problema acontece normalmente com quem usa geradores de migração ou com desenvolvedores que as escrevem de forma muito simplista, assim como os geradores fazem.

Vejamos um exemplo gerado pelo gerador de migrações do Typeorm.

import {MigrationInterface, QueryRunner} from "typeorm";

export class ModifySomething implements MigrationInterface {
    name = 'ModifySomething987982495702935873450987'

    public async up(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query("ALTER TABLE `syndicate` ADD CONSTRAINT `FK_sd9f8g7s8df6g89f6s87dfg` FOREIGN KEY (`addressId`) REFERENCES `address`(`id`) ON DELETE CASCADE ON UPDATE CASCADE");
        await queryRunner.query("ALTER TABLE `address` ADD CONSTRAINT `FK_c76sdf8g6sdf87g6s9g67` FOREIGN KEY (`companyId`) REFERENCES `company`(`id`) ON DELETE CASCADE ON UPDATE CASCADE");
    }

    public async down(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query("ALTER TABLE `address` DROP FOREIGN KEY `FK_c76sdf8g6sdf87g6s9g67`");
        await queryRunner.query("ALTER TABLE `syndicate` DROP FOREIGN KEY `FK_sd9f8g7s8df6g89f6s87dfg`");
    }

}

Notem que ele não faz nenhuma verificação se as chaves existem ou não e em caso de uma coluna, se tem algum dado lá dentro.

Ele simplesmente sai fazendo loucamente e é isso que normalmente geram erros ao rodar as migrações. Porque o sistema tenta adicionar algo que já existe ou remover algo que não existe mais.

Erro de migração
A imagem mostra a tela do editor de códigos com um erro de migração

Forma fácil, mas…

A forma mais fácil de resolver esse tipo de problema depois que ele já aconteceu é encontrar a última migração que foi executada com sucesso, remover todas as seguintes e depois gerar uma nova migração com todas as modificações compiladas nela mesma, mas… (sempre tem um mas) se você trabalha com mais desenvolvedores, pode ser que você complique as coisas já que no commit anterior haviam as migrations com problemas e o novo tem a solução… não necessariamente vai dar problema, mas pode dar!

Faça isso por sua conta e risco, combine com o seu time e antes disso, faça backups e etc. Lembre-se que migrations servem para versionar o banco de dados e é importante manter o histórico. Depois que tudo der certo, se livre dessas tranqueiras.

Forma mais trabalhosa, mas…

A forma mais “trabalhosa” é você criar as migrações você mesmo, ou usar o código gerado pelo ORM (Typeorm nesse caso) e refatorá-lo fazendo as verificações necessárias.

Normalmente, os ORM’s oferecem funções que ajudam nesse sentido, como no caso do Typeorm que tem uma API específica para isso.

Basta você utilizar QueryRunner como injeção de dependência no seus métodos up() e down() e chamar os métodos que quiser, tais como: createTable(), createIndex(), addColumn(), createForeignKey(), getTable(), etc.

Nesse caso, o método getTable() é um método muito importante, já que ele trás as informações da tabela e com ele saberemos se a coluna a ser criada existe, se a chave estrangeira já foi criada, etc.

Então, essa é a forma mais “trabalhosa”, mas (sempre tem um mas…) a mais elegante também (você achou que vinha alguma coisa ruim aqui, certo? heheh)

Previna-se

Lembre-se que você provavelmente só está nessa situação porque não fez um bom planejamento da funcionalidade ou porque você “comitou” o código sem revisar antes e levou um monte de bugs para o seu repositório remoto.

Para prevenir isso é fácil, é só fazer as revisões, usar testes e nunca “comitar” direto na sua branch master. Caso você trabalhe sozinho (como uma “euquipe”) redobre os cuidados, pois resolver problemas de desenvolvimento é custo e você precisa de lucro, estou certo? Caso você tenha uma equipe com mais desenvolvedores, crie uma pull request e solicite as revisões de código, aos seus colegas, discuta as melhores formas de resolver o problema antes de fazer o merge para a master e evite problemas.

Não deixe seu sistema quebrar…

Quando uma migração não acontece, o seu sistema quebra e isso é ruim, certo?

Imagine você que seu sistema está funcionando “bonitamente” e na sexta-feira você tem a brilhante ideia de fazer o deploy de uma release super massinha. Está tudo indo bem, mas no último segundo para o expediente acabar a sua migração quebra e a API do seu sistema vai pro saco…

Isso aconteceu comigo e eu não quero que aconteça com você 🙂

Docker Swarm Vs. Kubernates
Mostra os logos de Docker Swarm versus Kubernates

A melhor ideia para resolver esse problema é utilizar orquestradores de containers, como o Kubernates ou Docker Swarm por exemplo.

Eles fazem um monte de coisas e uma delas é manter a API em pé e só subir a nova realease quando tudo estiver certinho.

Isso pode salvar seu final de semana e evitar muitos cabelos brancos.

Por hoje é isso aí!

Esperto muito ter ajudado.

Não esqueça de deixar um comentário bem bacana contando suas experiências e como eu posso ajudar 🙂

Grande abraço!

Como clonar repositório privado do Github no Docker?

Clonar repositório privado do Github no Docker

O processo de deploy de uma aplicação pode ser feito de várias formas dependendo do ambiente escolhido tanto para o desenvolvimento quanto para a hospedagem final dele. Esse processo pode ser descomplicado com o simples fato de subir o código que está no seu Github direto na imagem docker e continuar com o processo de build e outras tarefas todas por lá, dessa forma tudo já fica bem mais encaminhado para usarmos CD/CI no futuro.

O problema…

Quando estamos lidando com repositórios públicos é bem simples de se fazer. Basta fazer o clone lá no Dockerfile da mesma forma que nós faríamos na nossa estação de desenvolvimento.

Algo como:

...
RUN git clone https://github.com/seu_usuario/seu_repositorio.git
...

Esse processo é simples porque o repositório é público e não precisa de nenhuma autenticação para clona-lo. O que obviamente não acontece no repositório privado.

Para fazer o clone do repositório privado nós precisamos estar autenticados e não seria interessante passarmos as informações de autenticação pela url, isso seria uma falha de segurança seríssima.

Então, para resolver esse problema vamos usar SSH para se autenticar de forma segura e mais elegante 🙂

Autenticando no Github por SSH

Para que o Github possa nos autorizar a fazer a clonagem do repositório na imagem Docker, nós vamos precisar gerar um par de chaves criptografadas na nossa estação de desenvolvimento. Você pode gerar as chaves em todas as máquinas que forem necessárias.

Se você não sabe o que é SSH, aqui vai um link bem completo que vai te ajudar, mas basicamente, usaremos um par de chaves assimétricos de criptografia, nas quais existem uma chave privada, que é sua (da sua máquina em questão) que vamos usar mais pra frente e uma chave pública que você vai configurar lá na sua conta no site do Github em seguida.

Uma coisa importante a saber é que cada par de chaves é único e a autorização é concedida quando a chave pública conseguir “entender” a chave privada que será passada à ela.

Feitas as apresentações, vamos ver como gerar nosso par de chaves SSH.

Verificando as chaves SSH

Antes de sair gerando as chaves, pode ser que você já as tenha gerado antes.

Vale lembrar que todos os procedimentos citados aqui podem ser utilizados em plataformas Microsoft Windows, GNU/Linux e MacOS. Nesse caso estou utilizando um GNU/Linux Ubuntu 20.04.1 LTS

Para verificar se você já possui um par de chaves SSH gerados, digite o seguinte comando no terminal do do seu sistema operacional  ls -al ~/.ssh para ver se existe alguma chave criada.

$ ls -al ~/.ssh
# Lista os arquivos do seu diretório .ssh, se eles existem

Por padrão os arquivos que nos interessam podem ter o nome de id_rsa e extensões .pub

Se você encontrou algum desses arquivos no seu diretório, é provável que possamos usá-los nos passos seguintes ao invés de criar um novo par de chaves.

Se você viu um par de chave pública e privada listado (por exemplo id_rsa.pub and id_rsa) e gostaria de usá-las para conectar com o Github, você pode adicionar sua chave SSH ao SSH-agent e pular o próximo passo da geração de chave do tutorial.

Se mesmo assim você quiser gerar um novo par de chaves não fará mal algum.

Como gerar o par de chaves SSH

Você vai precisar utilizar um pacote específico para gerar o par de chaves SSH. O mais conhecido é o openssh e ele tem versões para os sistemas operaacionais mais utilizados no mercado.

Para gerar o seu par de chaves, vá ao terminal do seu sistema operacional e digite ssh-keygen -t rsa -b 4096 -C “your_email@example.comsubstituindo o email pelo email da sua conta do Github.

$ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

Vai aparecer Enter a file in which to save the key no seu terminal. Você pode aceitar o caminho padrão (/home/seu_usuario/.ssh/id_rsa) pressionando enter ou digitar outro caminho para gerar suas chaves.

Enter a file in which to save the key (/home/you/.ssh/id_rsa): [Press enter]

Caso haja algum arquivo com o mesmo nome no diretório escolhido, será perguntado se você quer substituí-lo.

No próximo passo não informe nenhuma senha no arquivo, caso contrário teremos um erro de chave inválida (invalid key) quando gerarmos nossa imagem Docker.

Enter passphrase (empty for no passphrase): [Type a passphrase]
Enter same passphrase again: [Type passphrase again]

Depois disso seu par de chaves assimétricas será gerado. Vamos ver agora como adicioná-las ao seu agente.

Adicionado as chaves ao agente

Nessa etapa você pode adicionar as chaves já existentes ou adicionar as novas chaves geradas na etapa anterior.

Para adicionar as chaves no agente, vamos iniciá-lo em bacakground

$ eval "$(ssh-agent -s)"
Agent pid 43558

e agora adicione sua chave privada no agente. Se você alterou o nome e/ou o diretório da chave, substitua no comando.

$ ssh-add ~/.ssh/id_rsa

Esse procedimento deixa essa chave configurada e pronta para trabalhar em futuros commits e outros comandos, mas não necessariamente é obrigatório para gerarmos a imagem Docker, como vamos ver mais pra frente.

Adicionando a chave pública no Github

Lembra que para que a autenticação ocorra é preciso que as chaves pública e privada “conversem”? Nesse passo damos início á essa “conversa” configurando a chave pública na conta do Github. Para fazer isso, precisamos copiar o conteúdo da chave gerada no seu computador.

Você pode usar o xclip para fazer isso ou simplesmente copiar o arquivo gerado.

$ sudo apt-get install xclip
# Faz o download e instala o xclip. Se você não tem instalado o 'apt-get', você pode usar outro instalador (como o 'yum')$ xclip -sel clip < ~/.ssh/id_rsa.pub
# Copia o conteúdo da sua chave id_rsa.pub

Para usar o arquivo sem xclip

$ cat ~/.ssh/id_rsa.pub

Agora siga os passos para adicionar a chave na sua conta do Github.

  1. Acesse sua conta do Github
  2. Clique na sua foto de perfil no canto superior direito
  3. Clique em “Settings
  4. No menu à esquerda, clique em “SSH and GPG keys
  5. Clique em New SSH Key ou Add SSH key
  6. Adicione uma descrição para a nova chave (Ex.: note-dev)
  7. Cole a chave no campo Key
  8. Clique em Add SSH key
  9. Se for solicitado, confirme sua senha do Github.

Feito isso, vamos configurar nosso Dockerfile

Configurando o Dockerfile

Para configurar o dockerfile, vamos criar uma imagem intermediária para fazer o clone e depois elminá-lá, dando lugar apenas para a imagem definitiva.

# Choose and name our temporary image
FROM alpine as intermediate

# Add metadata identifying these images as our build containers (this will be useful later!)
LABEL stage=intermediate

# Take an SSH key as a build argument.
ARG SSH_PRIVATE_KEY

# Install dependencies required to git clone.
RUN apk update && \
    apk add --update git && \
    apk add --update openssh 

# 1. Create the SSH directory.
# 2. Populate the private key file.
# 3. Set the required permissions.
# 4. Add github to our list of known hosts for ssh.
RUN mkdir -p /root/.ssh/ && \
    echo "$SSH_PRIVATE_KEY" > /root/.ssh/id_rsa && \
    chmod -R 600 /root/.ssh/ && \
    ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts

# Clone a repository (my website in this case)
RUN git clone git@github.com:seu_usuario/seu_repositorio.git

# Choose the base image for our final imageFROM alpine
RUN apk update && \
    apk upgrade && \
    apk add --update nodejs npm && \
    npm install -g @angular/cli

# Copy across the files from our `intermediate` container
RUN mkdir app
COPY --from=intermediate /qualico/. /app/.

WORKDIR /app

Basicamente estamos dizendo apara o dockerfile que vamos informar uma variável $SSH_PRIVATE_KEY na hora de gerar a imagem. Queremos que ele crie uma instância intermediária só para fazer a clonagem do nosso repositório e depois elimine ela e aí sim nós configuramos a imagem definitiva.

Nesse ponto, já configuramos a chave pública na nossa conta do Github, agora chegou a hora de informar a chave privada para autenticação.

Para fazer isso, é preciso carregá-la em uma variável temporária no seu sistema operacional. Faça isso com o seguinte comando.

MY_KEY=$(cat ~/.ssh/id_rsa)

E agora já podemos fazer o build da imagem Docker

docker build --build-arg SSH_PRIVATE_KEY="$MY_KEY" --no-cache --tag clone-example .
…
Successfully tagged clone-example:latest

Nesse ponto já temos a imagem construída com sucesso e podemos fazer o nosso deploy para onde quisermos, mas se você ainda se preocupa com segurança e quer se livrar dos resquícios desse processo, siga em frente com mais alguns passos.

Limpando os vestígios

Mesmo utilizando uma imagem intermediária para dar mais segurança ao processo, se visualizamos os logs das operações, ainda podemos ver nossa chave privada por lá e não queremos isso, não é?

docker history clone-example
> IMAGE               CREATED             CREATED BY                                      SIZE
>b3dbbf389a73        2 minutes ago       /bin/sh -c #(nop) COPY file:90e3ecf812fe16bf…   254B
>39d11e01b3ad        2 minutes ago       /bin/sh -c mkdir files                          0B
>196d12cf6ab1        2 weeks ago         /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
><missing>           2 weeks ago         /bin/sh -c #(nop) ADD file:25c10b1d1b41d46a1…   4.41MB

Durante a configuração do Dockerfile utilizamos o comando LABEL onde especificamos o valor de intermediate. Fizemos isso justamente para identificar e facilitar a remoção dos dados sensíveis nessa etapa.

Onde apenas com um comando, vamos remover todos os vestígios da operação, não deixando a sua chave privada exposta.

Para isso, execute o comando:

docker rmi -f $(docker images -q --filter label=stage=intermediate)

Feito pessoas!

Agora seu processo de deploy está mais automatizado e seguro 🙂

Espero ter ajudado!

Grande abraço 🙂

Kaffeine – Como manter seu app sempre online no Heroku?

Logo do Kaffeine

E aí pessoas! Tudo numa boa?

Se você chegou até aqui, provavelmente você já conhece o Heroku e se essa for sua realidade, pode pular esse trecho 🙂

O que é o Heroku?

O Heroku é um serviço de hospedagem de conteúdo, seja um simples site estático ou até mesmo uma aplicação mais complexa, como uma API com acesso a banco de dados e outros recursos por exemplo.

O Heroku é conhecido por ter uma curva de aprendizagem extremamente curta, tornando o deploy da sua aplicação bem simples. Além disso conta com a possibilidade de um plano gratuito (apesar de você ter que deixar o seu cartão de crédito configurado por lá) e também de “incluir” addons para estender os recursos.

Alternativas ao Heroku

Outros players de mercado que concorrem com o Heroku são Amazon AWS, Microsoft Azure, Google Gloud Plataform, Digital Ocean… obviamente cada um tem o seu público-alvo e objetivos diferentes, mas dentre eles, o Heroku parece ser o mais “fácil” de fazer o trabalho com qualidade semelhante.

O problema

Mas, como nem tudo são flores a versão gratuita do Heroku “baixa” a aplicação quando ela não recebe uma requisição por um período de 30 minutos. Em outras palavras, se sua aplicação fica sem nenhum acesso por 30 minutos, ele desliga ela até que alguém a acesse novamente. Quando alguém acessar novamente, ele vai iniciar aplicação toda do zero novamente e o clico se repete. Essa inicialização normalmente é bem domorada e pode causar a percepção de que a sua aplicação é muito lenta aos usuários, quando na verdade é uma característica da sua hospedagem.

Ele faz isso por diversos motivos que a gente não tem certeza, mas talvez a principal delas seja de economizar recursos dos servidores 🙂

Como o Kaffeine resolve esse problema?

O Kaffeine e uma solução gratuita que resolve esse problema. Você simplesmente coloca o endereço da sua aplicação Heroku no site e recebe doses de Kaffeine a cada 30 minutos. Brincadeiras à parte, quando você coloca o endereço da sua aplicação nele, ele passa a fazer requisições a cada 30 minutos à sua aplicação, deixando ele no ar por uma maior parte de tempo.

Mas, como nem tudo são flores (de novo) outra característica da versão gratuita do Heroku é de que esses containers devem parar de funcionar por no mínimo 6 horas por dia e no Kaffeine, você consegue especifica o horário que isso vai acontecer, dessa forma podendo configurar o horário que a sua aplicação receberia menos requisições. Em uma aplicação corporativa por exemplo, provavelmente não haverá acesso fora do horário de expediente ou de madrugada, então você configura o Kaffeine para parar o container nesse período e o impacto nos usuários é menor.

Espero ter ajudado, grande abraço!

Como resolver SEFIP “Lacre do arquivo não confere com a informação de controle”?

SEFIP

Oi pessoas, tudo certo?

Para resolver o erro “Lacre do arquivo não confere com a informação de controle” que ocorre na SEFIP no Windows é preciso fazer download do software 7Zip File Manager. Depois de instalado, utilize ele ao invés do “Compactador de arquivos” do Windows. Para utilizar, basta clicar com o botão direito sobre o arquivo e ir em “Extrair aqui”.

Dica bem rápida dessa vez!

Abração!

Até que ponto automatizar tudo no desenvolvimento de software é interessante para o time de desenvolvimento?

Automatização de processo de desenvolvimento de software

Hoje mesmo recebi na newsletter do Medium com o título “Auto-Unsubscribing in Angular Components Like a Pro” e é obvio que eu fui correndo ler, mas depois de ler o artigo, me vieram algumas coisas na cabeça que eu quero compartilhar com vocês.

Dica

Aliás, se você não conhece o Medium eu recomendo que dê uma passadinha por lá. Tem artigo de tudo quanto que é coisa, você tem um limite de leitura e ele te joga uma mensagem dizendo “Você lê bastante Leo, para continuar lendo esse artigo manda uns pila pra cá”, não necessariamente com essas palavras… e também não para todos os artigos. Mas o que conta é que tem muito conteúdo de qualidade por lá e as newsletters fazem o papel. Diariamente recebo bastante emails do site, mas não chega a me incomodar, porque 99% deles tem algo de útil ou do meu interesse.

Feito o jabá gratuito para o Medium, vamos voltar ao assunto…

Até que ponto automatizar tudo no desenvolvimento de software é interessante para o time de desenvolvimento?

“TUDO” é uma palavra muito forte, mas tenho certeza que vocês vão acompanhar o meu raciocínio.

Quando eu iniciei no mundo do desenvolvimento de software e tinha uma aproximação maior da linguagem de desenvolvimento PHP havia uma grande vulnerabilidade que era a configuração de register_globals vir ativada por padrão nas configurações do PHP.

Isso ajudava muito no processo do desenvolvimento porque a gente não precisava ficar associando as variáveis que circundavam o ambiente ($_POST, $_GET, $_SESSION, etc). Se você recebia “bonitamente” o valor do formulário em $_POST['meu_campo'] era só você acessar a variável $meu_campo e seguir em frente.

Tudo certo até aí, né?! Mais ou menos, porque o PHP tem tipagem fraca e a gente pode simplesmente acessar essa mesma variável direto pela URL assim: http://meusiteinseguro.com/carrinho_de_compras.php?meu_campo=codigo_nocivo e dessa forma injetariamos o que quiséssemos na variável.

Depois disso, eu – muito espertalhão – comecei a usar a função extract() para extrair as variáveis dos mesmos arrays comentados anteriormente mas configurava o register_globals como off. Ora-ora espertalhão não mudou NADA… 🙂

O tempo passou, o PHP começou a trazer a register_globals configurada com off por padrão e eu comecei a carregar as minhas classes com o método mágico __autoload(), afinal de contas eram “mágicos”!

O que era uma mão-na-roda, mas talvez eu estivesse ganhando um pouco de tempo na importação das libs, mas perdendo o controle da minha aplicação.

Porque é interessante automatizar?

Não quero, de forma alguma, desmerecer a utilidade dessas opções e muito menos o PHP que eu curto muito, entretanto, quero ressaltar que eu as utilizava de uma forma um tanto quanto ingênua e egoísta (só pensava no meu tempo de desenvolvimento), então, é importante sim a automatização, isso que nem estou falando aqui a parte de DEVOPs que na minha época era só INFRA 🙂

Aproveitando a introdução com PHP, não vejo utilidade para register_globals estar ativada, mas a __autoload, hoje descontinuada, tinha seu valor. Eu a usava de forma adequada para carregar os módulos da minha aplicação quando desenvolvia meus próprios frameworks em MVC para meus projetos (quem faz isso hoje em dia né? Loucura…)

Não sou contra automatizações, mas acredito que a gente sempre tem que avaliar coisas como essa com bons olhos e isso eu vou escrever na próxima seção.

Porque não é interessante automatizar?

Seja pela introdução das minhas experiências passadas com PHP que comentei anteriormente ou pelo conteúdo do artigo do Medium mencionado, que aliás é um bait a artigo e sim, é um baita serviço que o cara desenvolveu por lá.

A questão aqui é que você provavelmente não desenvolve software sozinho e se prefere assim, tente desenvolver com um time, a experiência e o teu crescimento pessoal e profissional é incrível. Mas mesmo que desenvolva sozinho, se você ficar um mês sem ver o código, sem dúvidas quando vê-lo novamente vais ser um completo estranho e ainda se horrorizar com as gambiarras que o “Eu do passado” fez ou se impressionar com o código maravilhoso que esse mesmo cara fez…

As questões que me chamaram a atenção e me motivaram a escrever esse post foram duas:

  1. Automatizar pode te trazer problemas de segurança
  2. Automatizar pode te prejudicar no debug quando tu interfere no fluxo da aplicação

1. Automatizar pode te trazer problemas de segurança

Na minha opinião, ter regras claras e bem definidas com o time todo são melhores do que apenas a automatização da aplicação, DEVOP ou fluxo da aplicação.

É claro que qualquer automatização em qualquer nível vai ajudar muito no processo de desenvolvimento, mas além de normalmente dar um baita trabalho, deixa tudo ali prontinho para alguém, muitas vezes bem intencionado, fazer uma grande besteira em algum momento, mesmo sem querer.

Para complementar eu não preciso citar ainda as minhas peripécias na introdução desse texto, certo?

2. Automatizar pode te prejudicar no debug quando tu interfere no fluxo da aplicação

Essa seção tem total relação com o post do colega. Lá ele mostra como fazer para você automatizar o unsubscribe de um observer. Oberver é um padrão de projeto (design pattern) comportamental onde nós precisamos nos inscrever (subscribe) nele e assim ficar recebendo atualizações quando o objeto observer mudar de estado. Acontece que quando a gente está inscrito em um observer, o fluxo de dados está aberto e consumindo recursos da aplicação, portanto, seja por motivo de segurança ou performance é altamente recomendado que nós fechamos essa inscrição depois de executar o que a gente precisa, caso contrário fica ali aberto. É meio parecido com aquela conexão de banco de dados que eu e você “nunca” deixou aberta eternamente lá no MySQL, saca? 🙂

Mas isso é super interessante, não é? Automatizar esse processo burocrático é algo impressionante e “like a pro” como citado no título do artigo. Sim, pode ser pensado como algo fenomenal, mas não e isso que está em questão. O que me chamou a atenção é na dificuldade de troubleshooting na hora de debugar esse código, já que algo tão importante, como o fluxo da aplicação foi doutrinado pela automatização (forte isso hehehe).

Mas aí você pode me dizer que: “poots, mas é fácil resolver, afinal de contas eu fiz o código para automatizar a parada toda”.
E eu posso te responder que: “Toda a automatização nos leva à ignorar a questão automatizada e com isso esquece-la, além disso, o seu time para ser um time, necessariamente precisa de mais pessoas além de você que possam não ter o conhecimento desse código ninja like a boss que você fez. Mas o pior ainda é interferir no fluxo da aplicação…”

Resumindo

A automatização no desenvolvimento de software é importante quando bem definida, divulgada e estruturada.
Interferir no fluxo da aplicação pode trazer grandes problemas para soluções de problemas.
Acredito fortemente que apesar de nos preocupar com o tempo e conforto no desenvolvimento das nossas aplicações, não devemos priorizar esses fatores em detrimento da segurança, troubleshooting facilitado e do bom fluxo da aplicação.

É isso aí pessoas.
Comentem suas experiências e o que você acha disso… só não vale me xingar pelas peripécias com o PHP, eu estava começando e vocês também já erraram na vida que eu sei… heheheh

Grande abraço!

Como fazer favicon, splash screen e ícones de forma fácil e rápida?

Se você está criando um aplicativo, seja ele nativo ou uma PWA, certamente você já se deparou com a missão de fazer os ícones, tela de inicio e o famigerado favicon da aplicação.

Convenhamos que é uma tarefa um pouco chata de realizar, por que são muitas resoluções e formatos

Mas felizmente, vamos aprender aqui como a gente pode agilizar esse processo de forma indolor 🙂

Pré-requisitos

Antes de tudo você precisa ter a arte do seu ícone e a sua splash screen prontinhos e para que tudo fique certinho precisamos ficar atentos á essas regras:

Ícone

  • Pode ter background transparente
  • Tamanho de 1024 x 1024 px
  • PNG

Splash screen

  • Não pode ter fundo transparente
  • Tamanho de 4096 x 4096 px
  • Centralizar as informações importantes *

    * É importante centralizar porque a ferramenta não é “bala de prata” e não consegue manter as proporções corretas para todos os dispositivos, então ela centraliza o conteúdo e preenche com um background. Para um MVP resolve, mas se você vai usar em produção, eu aconselho a editar as imagens que ficarem “estranhas”.

Gerando os arquivos

Vamos usar a ferramenta Ape Tools através do link https://apetools.webprofusion.com/

No primeiro campo (Step 1) a gente precisa inserir o ícone no formato PNG e grandão mesmo…
e no segundo campo (Step 2) a gente insere a splash screen, também grandona.

Depois de inserir os arquivos, vai aparecer um botão “Kapow!” logo abaixo, clique sem medo. Se você quiser ver a prévia das imagens marque a caixa de seleção “Show previews”.

Agora você pode ainda escolher as plataformas que você quer trabalhar. Caso seja uma PWA, tem ferramentas melhores que geram inclusive o manifest.json e uma index.html com as tags necessárias, mas se precisar só das imagens a Ape Tools vai te ajudar.

Para fazer as imagens conforme as configurações dessas plataformas, basta clicar em “Include in bundle”.

O resultado de tudo isso é um arquivo .zip com todas as imagens necessárias.

Se você está usando em uma PWA, você ainda precisa criar o arquivo manifest.json e colocar algumas tags na sua index.html.

Mas, se o seu app é nativo, basta seguir as instruções que o próprio Ape Tools informa, dependendo da versão que você vai usar.

E aí, essa informação te ajudou?

Compartilha aí com teus amigos pra ver se ajuda eles também. Se não gostou, compartilha com os inimigos hiuahuiahuiah

E comenta aí se tu conheces uma forma melhor.

Grande abraço!

Onde encontrar datasets com dados brasileiros?

Muitos dados entrando em um computador

E aí galera! Tudo certo? Espero que sim!

Recentemente fiquei muito frustrado em não poder atingir um objetivo pessoal e profissional por não ter dados suficientes para treinar um modelo de inteligência artificial.

Esse projeto era muito importante porque estava totalmente e acordo com a minha atual filosofia de vida que é fazer com que as micro e pequenas empresas brasileiras perseverem e não se encerrem junto com os sonhos dos seus idealizadores.

Analisando os relatórios do censo das empresas brasileiras proposto pelo SEBRAE, pude observar que as micro e pequenas empresas tem uma grande representatividade na economia do país e isso é muito importante.

Muita gente sonha em ter um emprego em uma multinacional ou em trabalhar em uma empresa gigante. Ok! Isso é muito válido, mas os dados nos dizem que no final das contas, a maior representatividade na economia brasileira é dos pequenos empresários que lutam dia-a-dia deslealmente com palitos de dentes em punho contra gigantes com tanques de guerra.

E por esse motivo, tenho uma missão de empoderar esses guerreiros com ferramentas de acesso a informação e educação. É por esse motivo que sou sócio da ConnectBe Contabilidade Proativa, um escritório de contabilidade bem diferente e que tem uma proposta bem bacana para esse público.

Mas como empoderar esses empresários?

Você já ouviu falar que os “dados são o novo petróleo”, correto?

Os dados são o novo petróleo

Eu também acredito nisso e é dessa forma que pretendo realizar esse feito. Muitos empresários simplesmente seguem contato com a sorte e simplesmente administrando o seu negócio apenas com o feeling as vezes acreditando no que está fazendo e outras vezes torcendo para dar certo. Isso é muito ruim para a saúde do negócio (e do empreendedor também heheh)

Como a inteligência artificial pode ajudar?

A inteligência artificial não é nenhuma novidade nem algo de outro mundo, na verdade as pesquisas iniciais datam da década de 50 e sendo bem sucinto, trata-se apenas da interpretação matemática de dados através de estatística, gerando informação para solucionar alguma necessidade de negócio.

Mesmo sendo um estudo consideravelmente antigo, em um determinado tempo, além de falta de investimento e assuntos filosóficos, chegou-se a conclusão de que não haveriam dados suficientes para que os modelos propostos fossem treinados adequadamente. Esse período é conhecido como o inverno da inteligência artificial.

Entretanto, já faz um tempo em que vivemos em um mundo cheio de dados, na verdade que mede dados, porque eles sempre existiram, apenas nunca foram mensurados. Hoje, a sua geladeira pode te fornecer dados importantes sobre a sua alimentação, o seu carro sobre o seu consumo e até os brinquedos dos seus filhos podem te trazer alguma informação útil. Esse fenômeno é conhecido como big data, onde temos muitos dados disponíveis para fazermos coisas incríveis.

Beleza e os dados?

Os dados são a alma do negócio e toda essa introdução foi para compartilhar com vocês a necessidade que eles tem para todos nós, especificamente, para mim e nesse projeto, para os micro e pequenos empresários brasileiros.

Agora pare para pensar que se para fazer um bom treinamento de um modelo preditivo a gente precisa de milhões de exemplos e isso muitas vezes não é tão fácil nem para as gigantes do mercado, imagina como que eu vou fazer isso para o dono da padaria do bairro?

Essa foi a minha frustração, de certa forma quem está no “inverno da IA” agora, sou eu! Justamente por que esse mercado não gera dados suficientes para que eu coloque meus modelos em produção de forma confiável.

Tenho certeza que muita gente que trabalha com IA compartilha dos mesmos anseios, mas como encontrar datasets com informações importantes para darmos o primeiro passo?

Como encontrar os datasets?

No post anterior eu compartilhei uma busca de datasets oeferecida pelo Google, mas dando uma olhada no GitHub hoje, vi que meu amigo começou a seguir um repositório interessante e fui ver o que era.
Aí que a mágica aconteceu! Era um repositório do Felipe Deschamps com a iniciativa de criar um repositório com dados sobre o Brasil e tornar uma API aberta. Olha que maravilha!

Inicialmente ele está propondo a elaboração de uma API para CEP, para contornar um “problema” técnico na API atual dos Correios.

Mas a ideia do projeto é maravilinda e pretende abordar outros aspectos.

A comunidade inclusive já está adicionando várias dicas além de contribuir para o projeto, alias, foi dentro de uma das issues que eu encontrei também esses dois links https://brasil.io/home e https://catalogo.conecta.gov.br/store/apis/list fornecidos pela comunidade que dão uma mão na roda para treinarmos nossos modelos e resolver grandes problemas.

Você tem alguma experiência desse tipo para compartilhar com a gente?

Comenta aí em baixo pra gente trocar uma ideia.

Google disponibilizou mais de 25 milhões de datasets gratuitos

Tela de busca de datasets gratuitos do Google

Há muitos anos tivemos o apagão da inteligência artificial pela escassez de dados. Haviam os algoritmos, mas poucos dados para o treinamento dos modelos propostos. O tempo passou, desenvolvemos novos sensores e os incluímos em tudo (com IoT por exemplo), assim passando a gerar muitos dados em qualquer coisa que antes nem sequer pensávamos que poderia nos dar alguma ideia importante, como uma geladeira por exemplo que pode monitorar os produtos dentro dela e fazer as compras de forma automática para você.

De fato, vivemos em uma época maravilhosa de BIG DATA, entretanto, dados qualificados não fazem parte do cotidiano da vida de pequenas e médias empresas. Falo isso com propriedade porque possuo uma startup de contabilidade que atua com inteligência artificial para micro, pequenos e médios empresários e mesmo com um bom movimento em seus empreendimentos ainda não geram dados suficientes para um treinamento de um modelo de inteligência artificial.

Existem diversas outras possibilidades de uso e aplicação, mas de fato, datasets específicos e qualificados são ouro na mão da gente. Se vierem “limpos” melhor ainda.

Mas afinal o que são datasets

Se você chegou até aqui e ainda está meio perdido, datasets são conjuntos de dados, estruturados ou não, sobre assuntos específicos.

Para aplicação e treinamento de modelos de inteligência artificial, é necessária uma massa de dados consideravelmente grande para que você consiga os resultados esperados e quem tem esse dados para você validar seu modelo são os datasets.

Não desdenhe dos datasets, você só sabe o quanto são necessários quando precisar deles hehehe

Talk is cheap, show me the “code”

Não é um “code”, mas a citação é boa heheh

Você pode acessar os datasets através desse link https://datasetsearch.research.google.com/ e pasmem: é como se fosse uma busca do Google.

Explore a vontade! Busque o dataset pelo assunto que tens interesse, avalie as fontes, autor, licença e leia a descrição para saber de fato o que contém e divirta-se!

Muito obrigado por ler esse artigo e diga aí se você testou os datasets e como foi a sua experiência! Vai ser legal compartilharmos conhecimento.

Grande abraço e vamos fazer coisas incríveis!

Fonte

Essa dica foi passada pelo Miguel Neves que foi meu colega no MBA sobre Inteligência Artificial aqui na PUCRS. Valeu Miguel!!!

Link passado pelo Miguel https://towardsdatascience.com/google-just-published-25-million-free-datasets-d83940e24284