3 de janeiro de 2022

Feliz 2022!

Este ano as coisas parecem estar um pouco melhores do que nos anos anteriores, temos um pouco mais de perspectiva no que tange a nossa saúde, ficamos um pouco mais tranquilos e um pouco mais seguros, e isso é bom.

Depois de muitas postagens no ano passado neste blog em torno de dezembro eu confesso que fiquei um tanto quanto sem assuntos, as coisas estavam corridas e a cabeça precisava de um refresco, isso aconteceu e agora temos um ano inteiro pela frente. Passei por uma mudança de emprego que trás muitas coisas novas para a minha caminhada e com certeza irão agregar muito para mim e para este pequeno blog, então vamos fazer as coisas se movimentarem por aqui.

Para não dizer que este não foi um post técnico (e não foi, mas fica a recomendação), essa semana em aprendi um pouco mais sobre covariância, contravariância e invariância e isso foi sensacional. Esbarrei no assunto estudando Scala (é uma das linguagens que na minha opnião levam a tipagem como um assunto prioritário, como Rust). Vou deixar aqui os materiais que li para aprender mais sobre o assunto:

Em Python (inglês): https://blog.magrathealabs.com/pythons-covariance-and-contravariance-b422c63f57ac

C# (inglês): https://www.pluralsight.com/guides/covariance-and-contravariance-csharp

Scala (Em Português 🇧🇷): https://codeoutputstream.wordpress.com/2013/11/15/scala-invariancia-covariancia-e-contravariancia/

Pretendo retomar esse assunto quando eu tiver uma base formal mais forte e fazer um post aqui.

Um ótimo ano de 2022!

6 de dezembro de 2021

Usando o operador de módulo para criar ciclos

Em alguns momento é possível que precisamos criar ciclos numéricos, por exemplo, vamos supor que desejamos contar de 0 até 5 e após isso retornar ao zero. Uma solução simples seria algo como:

Este tipo de código funciona muito bem e é simples de entender, porém podemos usar a nosso favor a matemática e utilizando o operador módulo, que traz o resto da divisão, conseguimos o mesmo efeito:

Uma vantagem do operador módulo sobre o if é que ele também funciona para quando seguimos para a direção contrária, como  podemos ver abaixo:

Uma vantagem dessa abordagem é que ela pode ser mais rápida pois evita saltos de código ao utilizar um operador matemático.

22 de novembro de 2021

Fazendo queries em JSON com jq

O jq é uma ferramenta de linha de comando que permite fazer queries e transformações em arquivos JSON. Ela é muito interessante e útil quando queremos buscar dados diversos em arquivos muito grandes. Para utilizar ela é muito simples, após instalada você já pode fazer a query. Vamos usar de exemplo este JSON.

A primeira coisa que podemos fazer é utilizar ele apenas para formatar, para isso basta executarmos o comando cat exemplo.json | jq:


O que temos aqui é uma lista de objetos, vamos então listar o nome de todas as pessoas dessa lista cat exemplo.json | jq .[].name:
Como podemos ver é muito simples, usamos o . (ponto) para indicar que estamos operando na raiz, os colchetes são para operações em lista, podemos especificar o índice passando algo como [1], ou até inicio e fim com [2:4]. Outra operação que podemos fazer é saber o tamanho de array usando o length cat exemplo.json | jq "length":
Podemos inclusive criar condicionais utilizando o jq, por exemplo baseado na operação de tamanho que fizemos anteriormente cat exemplo.json | jq 'if .[].name == "Tanya Villarreal" then "Achou" else "Não Achou" end':

Podemos interpolar strings cat exemplo.json | jq '"O nome é \(.[].name)"':

Além dessas possibilidades o jq permite fazer diversas outras operações, como operações matemáticas, pipelines, maps e muito mais. Um lugar para aprender a usa-lo e treinar pode ser o jq play, uma versão online que permite treinar e até usar o jq sem instalar.]

Há também implementações do jq dentro de linguagens, mas pode ser algo não tem performático do que usar as próprias estruturas de dados inerentes a própria linguagem.

15 de novembro de 2021

Criando um bot no Telegram

Alguns anos atrás fiz um bot no Telegram e me surpreendi como é simples e rápido fazer utilizando Python. O Telegram fornece uma API para seus bots e há varias bibliotecas em diversas linguagens para interagir de maneira simples com esta API. A primeira coisa que precisamos fazer é acessar o @BotFather e solicitar a criação de um novo bot.

Após seguirmos as instruções e configurarmos o nosso bot receberemos um token que será utilizado por nós mais a frente.

Para interagirmos com a API de bots do Telegram usaremos a biblioteca python-telegram-bot. Após instalar a biblioteca podemos fazer um simples script que é equivalente ao "Hello World!" dos bots do Telegram:

O script é simples, lemos o token de uma variável de ambiente (você também poderia colocar direto no código, mas não recomendo fazer isso) e criamos os objetos do Telegram para subir o nosso bot. Na linha 15 fazemos o registro da função que irá responder um comando ao bot, nossa função é bem simples e apenas  faz o envio de uma mensagem de texto. Após a configuração do bot iniciamos o polling, ou seja, o script fica ouvindo se há mensagens novas para responder. Assim entramos em nosso bot, enviamos o start e já recebemos a mensagem:

Como podemos ver acima, recebemos o retorno conforme esperado. Como o handler é uma simples função Python nós podemos agora fazer algo mais complexo. Vamos expandir criando um novo handler para buscar o nome da rua dado um determinado CEP, utilizando a biblioteca requests que já utilizamos antes em outros posts:

Para usar a nova funcionalidade do bot basta enviar o comando /cep CEP e ele irá retornar o CEP buscado na API do ViaCEP. 

No manual da biblioteca e também no BotFather é possível encontrar muitos outros recursos que podem ser definidos para o bot, vale apena a leitura caso esteja pensando em fazer algo mais avançado.

8 de novembro de 2021

Enviando SMS via Amazon Web Services SNS com Python

O Amazon Web Services SNS é um serviço que permite a notificação de diversas formas, desde conexões com as finas SQS do SMS até o envio de mensagens SMS. É muito comum o serviço ser utilizado por empresas para mandar notificações para seus clientes e é muito simples de ser utilizado.

A primeira coisa necessária para fazer o envio de SMS é a criação de usuário com permissões de acesso ao SNS na Amazon. Com o usuário criado basta instalar a biblioteca boto3 e assim podemos criar o script necessário. Primeiro é necessário criar um cliente que acessa o serviço do SNS:

Com isso é possível agora de maneira muito simples fazer o envio de SMS, basta utilizarmos o método publish passando o número de telefone (como o serviço é mundial é necessário especificar o código do país com o "+" na frente):

Assim já será possível enviar mensagens utilizando o serviço. O número exibido para quem recebe a mensagem costuma ser o de 5 dígitos iniciando em "2", mas podendo variar.

1 de novembro de 2021

Gerando código que gera código

Alguns anos atrás lendo o Programador Pragmático eu esbarrei em um conceito muito interessante, geração de código. O caso de uso era simples: em alguns momentos você precisava produzir diversas estruturas de código, as vezes em mais de uma linguagem, que seguiam os mesmos padrões e para evitar o trabalho manual era interessante fazer um gerador de código.

O caso do livro era a geração de algumas estruturas de dados em diversas linguagens e aproveitando o aprendizado eu decidi estender o conceito para a geração de classes (projeto aqui), para isso era lido um código simples dizendo o nome da classe, seus atributos e também os modificadores de acesso, como abaixo:

B + Pessoa 
A - nome:String
A - teste1:int
A # teste:char[10]
A # teste:teste[56]
A + desprotegido:float
A - teste:float[34543]
E 

Como podemos ver temos a definição de cada linha pela primeira letra, depois o modificador do atributo seguido de seu nome e tipo. É algo muito simples, mas lembro que foi neste exemplo a primeira vez que eu ouvi falar de expressões regulares, afinal o gerador de código era feito em Perl e expressões regulares para Perl são algo intrínseco da linguagem. Um exemplo das classes geradas em Java, C++ e PHP a partir da especificação acima é o abaixo:

O conceito é poderoso, apesar de simples, afinal isso mostrou que a partir de uma especificação eu poderia gerar código, ou se quisermos ir um pouco além, significava que a partir de uma linguagem em poderia gerar código em outras linguagens.

Com este aprendizado fiz alguns outros geradores de código, principalmente geração de comandos a partir de alguma lista de dados. O que mais usei foi um script para geração de comandos de macro para o TeraTerm (programa de terminal) permitindo automatizar diversas tarefas.

Voltando para o conceito inicial do Programador Pragmático, o principal motivo de utilizar um gerador de código era evitar a duplicidade de código, o que é confuso, pois no final do meu exemplo acima o código estava triplicado, o que é verdade, mas nem tanto. Como a geração destas classes estava atrelada a um único arquivo de especificação a regra estava centralizada e o código gerado era praticamente um asset do meu projeto.

Este conceito de geração de código inclusive pode ser uma sementinha inicial para outras coisas mais profundas, como criação de linguagens de script, compiladores e afins. No livro Crafting Intepreters que já citei aqui no blog mais de uma vez, além da geração de código "óbvia" que a construção de um compilador faz, o autor se aproveita do conceito mais simples de script de geração de código para gerar a árvore de sintaxe abstrada, permitindo assim após ter o script de geração ampliar a sintaxe apenas mudando algumas especificações. 

Provavelmente você faz ou já fez uso de alguma ferramenta de geração de código e também poderia se aproveitar do conceito em algum momento para economizar tempo e diminuir a quantidade de erros gerados pelo fardo da repetição.

25 de outubro de 2021

Criando tarefas peródicas com o Celery Beat

Como vimos neste artigo postado anteriormente aqui no blog, o Celery é uma ferramenta que permite executar tarefas de maneira assíncrona através de mensageria. Isso por si só já traz diversos benefícios, mas também é possível imaginarmos criando tarefas que seriam executadas dados certos intervalos de tempo (por exemplo o disparo de processos serem executados de madrugada) ou durante horários específicos. Este trabalho pode ser feito manualmente, basta criarmos um programa em Python que analisa todos os parâmetros temporais cadastrados e dispare as tarefas na hora adequada invocando a função através do método .delay().

Apesar de ser interessante desenvolver algo assim a ideia não é tão nova e o próprio pessoal que desenvolve o Celery se adiantou no assunto e criou o Celery Beat, uma aplicação que permite invocar tarefas do Celery conforme o tempo cadastrado.

Primeiro criamos e configuramos a nossa task, por fins de simplicidade iremos usar um Redis rodando localmente como broker (no post anterior usamos o SQS, porém como é mais complexo de configurar, o Redis já nos atende bem):

Após isso podemos fazer a invocação manualmente para testarmos. A saída será a invocação das funções:

Agora iremos para a parte mais importante deste artigo, como realizar o agendamento de tasks e a maneira mais simples é dentro do próprio arquivo de tasks definirmos a configuração. Para o nosso teste vamos chamar a task que criamos a cada 10 segundos (apenas para não termos que esperar muito tempo):

E executamos: celery -A tasks beat

Após um pequeno intervalo de tempo vemos a execução da nossa task como se tivéssemos chamados manualmente.

Para melhorar a nossa estrutura podemos separar a configuração do projeto, as tasks e o startup. Para isso basta separarmos alguns objetos em mais módulos e alterar algumas coisas simples:

Com isso temos uma estrutura de tarefas agendadas que pode ir para produção. A estrutura de componentes pode ser vista abaixo, expandindo o exemplo que fizemos no post anterior: