Categorias
Crônicas Tecnologia

Machine Learning está arruinando as timelines

Machine Learning é incrível.

Hoje em dia temos máquinas aprendendo o tempo todo e os dados se tornaram o novo petróleo. Quem tem quantidades gigantescas de dados de usuários tem grande valor de mercado. Isso acontece porque quanto maior a quantidade de dados mais as máquinas podem aprender sobre qualquer coisa. O que você gosta, o que você quer comprar, quais são as suas inclinações políticas e sociais, por onde você costuma andar, etc.

As possibilidades que podem ser criadas a partir da análise dos dados de uso de um aplicativo são incríveis. A ideia geral é que isso ajude na personalização de qualquer serviço que você usa.

Dois bons exemplos do uso de Machine Learning em redes sociais para mim são a página inicial do YouTube e a parte de Explore do Instagram. Ambos se ajustam muito bem ao tipo de conteúdo que eu me interesso nesses serviços.

Algo que poderia incomodar algumas pessoas sobre o uso de Machine Learning atualmente é a questão da privacidade, que é um assunto muito discutido nesse conceito de uso dos dados alheios.

Mas o que me chamou atenção e me incomodou mais ultimamente sobre o assunto é uma coisa que pode parecer muito mais boba e simples. As timelines das redes sociais.

A timeline tem esse nome porque deveria ser uma linha do tempo. É comum gostarmos de saber o que está acontecendo de mais atual com nossos contatos sociais e também aqueles influenciadores que seguimos.

Entretanto, com o uso do machine learning na maioria das timelines de todas as redes sociais, não temos mais uma linha do tempo. Temos uma lista de conteúdos que a máquina resolveu que é o mais interessante para o seu perfil. Perfil esse criado através da análise dos seus dados de uso da rede.

Eu tenho usado pouco as redes sociais ultimamente, meu acesso não passa de um por dia durante os dias úteis para algumas redes e um por semana para outros, e essa descrição que vou dar sobre a experiência que tenho pode não condizer com a experiência de alguém que usa muito as redes, portanto se esse for o seu caso enquanto lê, por favor, deixe um comentário me falando como funciona para você.

Toda vez que acesso uma rede acontece a mesma coisa: recebo conteúdos que foram postados há um bom tempo atrás misturados com conteúdos recentes. Cheguei a receber alguns com mais de um mês de idade na minha timeline.

Como eu disse antes, pode parecer bobo, mas eu não tenho interesse em receber coisas tão antigas para os padrões da internet. Isso é um pequeno problema que venho enfrentando, mas existe um pior. Pessoas que simplesmente não dão as caras mais no meu feed.

Você pode pensar “Ah, mas elas nem devem postar mais”. Foi exatamente o que pensei sobre essas pessoas até acessar seus perfis nas redes. Lá estavam conteúdos que eu gostaria de ter visto, provavelmente teria interagido, mas que nunca tive a chance.

A máquina decidiu que eu não deveria me interessar por um conteúdo de uma pessoa talvez porque ela poste de forma mais esporádica. Mas a máquina errou.

Eu não quero que a máquina escolha quem deve aparecer ou não no feed do meu aplicativo. Eu quero ter a opção simples de acessar as configurações da minha rede e escolher que a máquina não monte o minha timeline e deixe de escolher qual conteúdo eu devo ou não devo interagir.

Uma opção simples de configuração, mas que pode afetar todo um modelo de negócio de uma empresa que se baseia em análise de dados de uso para vender certo serviço de publicidade.

Como isso afeta o modelo de negócios das redes sociais? Vamos ver um exemplo.

Uma amiga minha vende produtos pela internet e o Instagram costumava ser sua maior fonte de clientes. Bem, ela teve uma queda gigantesca nas vendas assim que a nova timeline com Machine Learning entrou no ar neste aplicativo. Graças à isso agora precisa comprar posts patrocinados da rede social se quiser continuar conseguindo leads pelo app de fotos.

Você pode me perguntar se eu acho errado que se venda um serviço baseado no acesso dos meus dados. Bem, eu aceitei aquele termo de uso e sei que nada vem de graça nesse mundo. O Facebook não gasta milhões de dólares em servidores e funcionários para que você possa curtir aquela foto da sua tia. Ele investe para obter lucro.

É por isso que resolvi fazer uma mudança na forma como consumo conteúdo e voltar para algo que se usava muito na internet do passado. Escolher blogs e sites e seguir suas postagens através de um agregador de conteúdo, o Feedly. Ele também deve aproveitar meus dados para alguma coisa, mas pelo menos eu escolho de onde meus conteúdos vem, não é mesmo.

As redes sociais não são a internet. A internet é descentralizada por natureza. É por isso que apesar de publicar com certa frequência na minha conta do Medium eu também costumo postar sempre aqui no meu próprio blog. Fica aqui o link para um texto do Luciano Ramalho sobre o porque ter seu próprio site na internet.

Aguardo sua opinião nos comentários.

Até a próxima!

Categorias
Tecnologia

Primeiros passos com o GIT

GIT é um software de controle de versão utilizado por muitos e muitos desenvolvedores e empresas no mercado de tecnologia.

Um controle de versão serve para manter o histórico do desenvolvimento do código e também para ajudar uma equipe de programadores trabalhando no mesmo código a não fazer besteira no meio do caminho.

Vamos à um exemplo bem simples.

João está fazendo alterações no arquivo index.html ao mesmo tempo em que Carlos. João altera as linhas 30 até 50 do arquivo e Carlos da 80 a 100. Em algum momento os dois precisam juntar esse código para ter a versão final do documento que vai para o site joaoecarlos.com.

Isso é bem fácil, basta que um dos dois pegue a parte do código que o outro alterou e cole na posição correta no arquivo index.html. Está pronto para subir para o servidor, certo? Certo.

Então para que eu preciso do Git para ajudar o João e o Carlos?

Bem, basta dizer que se o João estivesse alterando entre as linhas 80 e 100 do mesmo arquivo teríamos um conflito entre o que o João fez e o que o Carlos fez. Não bastaria colar as alterações do João sobre as do Carlos, seria preciso que se analisasse linha por linha do que cada um fez para ver qual deve entrar e qual deve sair. Basicamente os dois precisariam sentar juntos e reescrever o código. Trabalho dobrado.

Agora imagine que essa reescrita de código pudesse ser feita de forma automática? Não seria ótimo?! Sim. Seria.

Aí entra nosso querido software de controle de versão! No caso dessa publicação estamos falando de Git, mas ele não é o único.

Vamos rever o exemplo do site joaoecarlos.com agora utilizando o Git em todo o processo.

João modifica o arquivo em seu computador. Ele salva localmente suas alterações e faz o commit com o Git que salva no repositório local quais alterações foram feitas. No final do processo ele executa um push e essas alterações ficam salvas em no repositório remoto.

Carlos faz alterações no mesmo arquivo e executa seu commit localmente. Quando ele for executar o push para o repositório o Git vai avisá-lo que seu código local não está atualizado com o repositório. Então ele executa um pull e baixa as alterações que João fez e o Git se preocupa em reescrever seu código para escolher quais linhas devem ficar em quais posições. Depois disso, Carlos pode verificar se está tudo certo com seu novo código e mandá-lo para o repositório com mais um push.

Pronto. É assim que funciona o Git… da maneira mais básica o possível, é claro.

O Git é muito mais do que isso, mas primeiro é preciso entender o seu conceito básico para começar a trabalhar com ele.

Vamos ver o passo a passo do que o João e o Carlos fizeram.

Aviso: todos os exemplos vistos nesta publicação são comandos executados em um console/terminal de linha de comando de um sistema operacional com base em Unix (MacOS ou Linux, por exemplo). Eles consideram que o Git já está instalado no seu ambiente de trabalho. Para ver como instalar clique aqui.

Primeiro eles precisaram iniciar o repositório Git localmente no diretório em que seus códigos estavam. Acessando via linha de comando eles entraram na raiz do código.

cd /Project/joaoecarlos/

Foi lá que ele iniciaram seu novo repositório com o comando:

git init

Para verificar os arquivos que o Git vai rastrear eles usaram o comando git status e viram algo como o exemplo abaixo.

On branch master
Initial commit
Untracked files:
  (use "git add <file>..." to include in what will be committed)
index.html
nothing added to commit but untracked files present (use "git add" to track)

Eles notaram que está escrito Untracked files logo acima do nome do arquivo. Isso quer dizer que o Git não está “rastreando” esse arquivo.

Com o comando git add . eles adicionaram todos os arquivos do seu projeto na lista de arquivos a serem rastreados. O . representa todos os arquivos e diretórios presentes nesse diretório. Eles viram algo assim:

On branch master
Initial commit
Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
new file:   index.html

Agora eles tem um ambiente preparado para fazer o seu primeiro commit. Eles adicionaram o arquivo index.html à lista de arquivos que serão gravados nesse commit.

Com a execução do comando git commit -m "Primeiro commit" eles finalmente gravaram sua primeira “versão” do site joaoecarlos.com no seu repositório local.

[master (root-commit) d8cbc79] Primeiro commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 index.html

O atributo -m "Primeiro commit" é um encurtamento de uma parte do processo de commit que é muito importante: descrever o que foi alterado.

Todo commit precisa ter uma boa descrição do que foi feito. Isso facilita muito para o futuro, onde centenas ou milhares de commits foram executados em um repositório. Imagina se você precisa encontrar onde foi feita alguma alteração no passado?

Pode-se executar esse comando sem o atributo -m, mas em seguida o console irá abrir um editor de texto para que se escreva uma mensagem descrevendo o que foi alterado.

Bom, agora que nossos colegas do exemplo já tem um repositório local, precisam enviar isso para um repositório centralizado. Um exemplo de serviço muito bom (e bem conhecido) para criar um repositório é o GitHub.

Depois de criarem sua conta e seu repositório no Github, nossos desenvolvedores adicionaram esse repositório como remote nas suas configurações do Git.

git remote add origin https://github.com/user/repo.git

Esse origin que você vê no comando é um apelido que se dá para o repositório remoto em sua máquina. Por padrão estamos chamando de origin que é o mais comum que você vai encontrar por aí.

Adicionar o remote no seu repositório local serve para indicar de onde ele deve puxar o código atualizado e para onde ele deve enviar seus commits. É o repositório com o qual todos os desenvolvedores do projeto vão interagir e onde ficará registrado todas as informações sobre alterações e versões do código do seu projeto.

Agora nossos desenvolvedores de exemplo estão prontos para subir seus primeiros commits para o repositório no GitHub com o comando git push origin master.

git push origin master

Vamos analisar esse comando…

git push é a parte que diz que queremos enviar o que temos de commitsna nossa máquina para o repositório remoto, GitHub por exemplo.

origin master diz para onde enviar esses commits, como o apelido do repositório é origin isso significa que vamos enviar para o GitHub que adicionamos a pouco.

master significa o branch que estamos usando. Mais para frente vou falar sobre branch, mas por enquanto vamos assumir que estamos trabalhando apenas com o branch padrão, que é chamado de master. Ele já foi criado quando o João ou o Carlos executou o git init lá no começo.

voilá. O código dos nossos amigos está no repositório do GitHub.

Agora vamos dizer que o Carlos precise trazer as atualizações de lá. Ele executou os primeiros passos (git initgit remotegit add e git commit) na sua máquina local e agora quer atualizar o código com o que tem no repositório remoto.

git pull origin master

Assim como o git push nós estamos dizendo para o Git de onde queremos buscar as atualizações com o origin master.

Agora o Git já atualizou o código na máquina do Carlos.

Em outro momento vou falar sobre os conflitos, algo que pode acontecer nesse momento de sincronização (ou merge) quando se usa controle de versão.

Por enquanto é isso. Esses são os primeiríssimos passos para utilizar o Git como controle de versão em um projeto.

Esse texto foi produzido para quem nunca teve contato algum com controle de versão, para dar uma ideia geral de como é e para que serve.

Se você quer saber mais sobre Git, deixe um comentário que eu planejo mais publicações como essa, dando continuidade ao processo e explicando mais sobre outros fatores.

Postado originalmente no Medium.

Categorias
Tecnologia

Como utilizar Ajax no WordPress

Hoje vou dar uma dica de como utilizar ajax no WordPress.

Precisei fazer uma chamada assíncrona em uma página de template do WordPress em um projeto que estive trabalhando e fui pesquisar como funcionava. O WordPress tem seu jeitinho todo especial de executar requisições XHR.

O primeiro passo é escrever uma função (no arquivo functions.php) para executar o que você quiser que o backend faça nessa chamada Ajax. No caso do exemplo desta publicação estou enviando um email.

// Actions to send mail
add_action('wp_ajax_sendMyMail', 'sendMyMail');
add_action('wp_ajax_nopriv_sendMyMail', 'sendMyMail');

// Sending the email
function sendMyMail() {
  global $wpdb;

  $message = "Form data:\n\n Name: {$_POST['name']}";
  if (wp_mail('email@email.com', 
              'Title', 
              $message, 
              array('Cc:email@copy.com'), 
              array())) {
  	echo 'success';
  } else {
  	echo 'error';
  }

  die();
}

Linha por linha da função no functions.php

Usando o add_action do WordPress, registramos nossa função. No primeiro wp_ajax_sendMail estamos registrando a função para utilização no painel Admin do WordPress e com o wp_ajax_nopriv_sendMail registramos a função para utilização no frontend, onde o usuário não estará logado.

O formato desses dois tipos de actions específicas para ajax sempre devem começar com wp_ajax_(action) ou wp_ajax_nopriv_(action).

// Actions to send mail
add_action('wp_ajax_sendMyMail', 'sendMyMail'); 
add_action('wp_ajax_nopriv_sendMyMail', 'sendMyMail');

Depois vem a função em si, com as ações que você quiser. Como eu já disse, nesse exemplo é o envio de um email.

// Sending the email function 
sendMyMail() {
 global $wpdb;
 $message = "Form data:\n\n Name: {$_POST['name']}";

 if (wp_mail('email@email.com',
             'Title',
             $message,
             array('Cc:email@copy.com'),
             array())) {
  echo 'success';
 } else {
  echo 'error';
 }

No final usamos o die() do PHP para encerrar o processo.

 die();
}

A requisição Ajax

Agora vamos à chamada assíncrona no Javascript.

Fazemos uma chamada com o método $.ajax do jQuery normalmente, mas a diferença está na URL que utilizaremos nela e em um item que precisa ser adicionado nos dados enviados para o servidor.

$.ajax({
 type:"POST",
 url: "/wp-admin/admin-ajax.php",
 data: {
  action: 'sendMyMail',
  name: $('input[name=name]').val()  
 },  
 success: function(data){
  console.log(data)
 }
});

A URL deve ser sempre /wp-admin/admin-ajax.php e o nome da ação que você registrou no functions.php entra como um dado com o nome action junto com o resto dos dados que você irá mandar para o servidor.

url: "/wp-admin/admin-ajax.php",
data: {
 action: 'sendMyMail',
 name: $('input[name=name]').val() 
 }

E voilá!

Deixe suas dúvidas ou opiniões nos comentários abaixo.

Nos vemos na próxima.

Categorias
Tecnologia

Redirecionando posts para subdomínio no WordPress

Quando postagens já estão indexadas pelos mecanismos de busca, como Google e Bing, há algum tempo fica complicado mudar um blog do WordPress de domínio.

No meu caso eu precisava mudar apenas alguns posts de categorias específicas para um outro subdomínio do meu site. O objetivo era redirecionar os posts relacionados com artes para o meu novo blog sobre arte.

Depois de pesquisar um pouco acabei chegando em uma solução razoável.

Criei o novo blog com WordPress, importei o conteúdo das categorias específicas para o mesmo e coloquei em um novo subdomínio.

No meu blog atual, este que você está lendo agora, no arquivo functions.php do template adicionei o código abaixo.

add_action('template_redirect', 'redirect_category_posts');
function redirect_category_posts() {
 global $post;
 if (is_single($post->ID) && (
  in_category('ilustracoes', $post) || in_category('ilustracao-em-acao', $post) || 
  in_category('hqs', $post) || in_category('ecomic-hqs', $post) || 
  in_category('tailer-hqs', $post) || in_category('video', $post) || 
  in_category('quick-sketch', $post)
 )) {
  $new_url = str_replace('http://mbeck.com.br', 
                         'http://arte.mbeck.com.br',
                         get_permalink($post->ID));
  wp_redirect($new_url, 301);
  exit;
 }
}

Linha por Linha

A primeira linha adiciona uma nova ação ao template.

add_action('template_redirect', 'redirect_category_posts');

Em seguida eu crio a função e utilizo a global $post do WordPress. Nela teremos os dados da publicação.

function redirect_category_posts() { 
  global $post;

Adiciono uma condição para verificar se estamos em um post único através do $post->ID. Para verificar se encaixa em uma das categorias especificadas uso a função in_category do WordPress.

if (is_single($post->ID) && (
 in_category('ilustracoes', $post) || in_category('ilustracao-em-acao', $post) || 
 in_category('hqs', $post) || in_category('ecomic-hqs', $post) || 
 in_category('tailer-hqs', $post) || in_category('video', $post) || 
 in_category('quick-sketch', $post) 
)) {

Em seguida monto a URL que será utilizada para o redirecionamento substituindo o domínio antigo pelo novo com a função str_replace do PHP. Para pegar o link permanente do post eu uso a função get_permalink do WordPress.

  $new_url = str_replace('http://mbeck.com.br', 
                         'http://arte.mbeck.com.br', 
                         get_permalink($post->ID));

Lembrando que quando criei outro blog com o WordPress e importei o conteúdo do antigo eu utilizei exatamente o mesmo formato de URL (permalink) para os posts do novo blog que eu utilizava no antigo.

Para fechar, utilizo a função wp_redirect do WordPress, com um código 301 (código HTTP que significa movido permanentemente), e termino com um exit.

  wp_redirect($new_url, 301); 
  exit; 
 } 
}

E voilá! Está funcionando como o esperado.

Se ficou alguma dúvida comente abaixo.

Nos vemos na próxima.

Categorias
Tecnologia

Criando um bot super simples para o Slack

Em uma das reuniões dessa última semana na empresa onde trabalho surgiu uma necessidade simples de comunicação: Precisamos que toda a equipe saiba quando um novo release de algum dos nossos repositórios for criado no Github.

Como usamos o Slack como ferramenta de comunicação interna, na hora já pensei:

“Esta é a minha chance de criar um bot para o Slack!”

Sempre tive vontade de fazer algo para o Slack, mas não tinha conseguido achar um tempo e nem um motivo específico para isso. Eu já imaginava que para esse objetivo, avisar sobre um novo release, não seria algo complicado.

Realmente não foi. Em apenas algumas linhas deu pra criar um bot que conecta os webhooks do Github e do Slack utilizando o Flask como meio-campo.

Abaixo o código final da primeira versão.

# coding: utf-8
import os
import requests
from flask import Flask
from flask import request

app = Flask(__name__)

slack_webhook_url = os.getenv('SLACK_WEBHOOK_URL')

@app.route("/", methods=['POST', ])
def webhook():
 action = request.json['action']
 release = request.json['release']
 repository = request.json['repository']

slack_data = {
 "text": "A new release from *{repo_name}* was {action}!\n"
         "Click <{release_url}|Release {tag_name}> for more details".format(action=action,
           repo_name=repository['name'],
           release_url=release['url'],
           tag_name=release['tag_name'])
}

response = requests.post(slack_webhook_url, json=slack_data)

if response.status_code != 200:
 raise ValueError(
   'Request to slack returned an error {}, the response is:\n{}'.format(response.status_code, 
      response.text)
 )

return ""

Pelo pouco tempo que passei lendo sobre como fazer um bot para o Slack eu entendi que você cadastra um Incoming Webhook e eles geram uma URL a qual você irá executar um request do tipo POST enviando a mensagem que você quer que um canal específico receba.

É realmente muito simples, porque a própria URL já carrega os tokens que são gerados para você.

Existem diversas outras funcionalidades que podem ser criadas em um bot para o Slack e a documentação deles cobre tudo. Mas vou falar apenas desse pequeno release-alert que criei.

Explicando linha por linha

Antes de começar a escrever o código vou precisar do Flask e de alguns outros pacotes. Então começo ainda na linha de comando do shell.

$ pip install Flask
$ pip install requests

Depois eu coloco a URL que gerei no Incoming Webhooks do Slack em uma variável de ambiente que chamo de SLACK_WEBHOOK_URL. Depois basta importá-la para dentro do código.

$ export SLACK_WEBHOOK_URL=<aqui vai a url do webhook do slack>

Agora crio meu arquivo Python chamado bot.py. Como estou usando o Flask, só vou precisar desse arquivo e praticamente nada mais.

Nas primeiras linhas começo importando o que vou utilizar e criando o app do Flask.

import os
import requests
from flask import Flask
from flask import request

app = Flask(__name__)

Trago para dentro do código a variável de ambiente que criei antes.

slack_webhook_url = os.getenv('SLACK_WEBHOOK_URL')

Agora vou começar a montar o meu endpoint. Ele receberá um evento POST enviado pelo webhook do Github. Para que isso aconteça você precisa cadastrar uma URL de webhook no settings do seu projeto no Github.

No meu caso, eu cadastrei a webhook no settings da organização, já que queria que todos os projetos da empresa disparassem o aviso. Mas funciona do mesmo jeito em qualquer um dos casos.

Quando cadastrei o meu webhook no Github especifiquei que gostaria de receber apenas os eventos relacionados ao release dos projetos.

Para testar o código localmente eu utilizei o ngrok. Explico como usar o ngrok em outra publicação.

@app.route("/", methods=['POST', ])
def webhook():

As primeiras linhas do meu endpoint capturam as informações que eu preciso do corpo enviado pelo POST do webhook do Github.

 action = request.json['action']
 release = request.json['release']
 repository = request.json['repository']

O Flask facilita recuperar informações de um corpo de um request JSON com o seu objeto request nativo. Basta chamar request.json e ele retorna um dicionário.

Agora eu vou montar o corpo da mensagem que enviarei para o Slack. O formato pedido é muito simples: um JSON com um campo ‘text’.

slack_data = {
 "text": "A new release from *{repo_name}* was {action}!\n"
         "Click <{release_url}|Release {tag_name}> for more details".format(action=action,
            repo_name=repository['name'],
            release_url=release['url'],
            tag_name=release['tag_name'])
}

Esse dicionário será transformado em um JSON pela próxima linha. O pacote requests já resolve isso para mim através do argumento json.

response = requests.post(slack_webhook_url, json=slack_data)

if response.status_code != 200:
 raise ValueError(
   'Request to slack returned an error {}, the response is:\n{}'.format(response.status_code, 
       response.text)
 )

return ""

No final do arquivo estou apenas tratando algum possível erro. Caso o requests retorne um status_code diferente de 200 eu levanto uma exceção.

No final retorno uma string vazia, porque cada endpoint do Flask precisa retornar alguma coisa para não levantar erros.

Para que meu bot fique disponível o tempo todo, fiz um deploy na minha conta gratuita do Heroku. E voilá!

Categorias
Tecnologia

Essa nova tecnologia vai acabar com o que você usa hoje

Para entusiastas de martelo tudo é prego

Eu adoro ler sobre tecnologia e sua indústria pela internet a fora. É muito bom para descobrir algumas tendências e aprender sobre minha área de atuação.

Mas eu tenho notado um certo exagero em algumas publicações de nicho.

Alguns autores parecem querer reforçar que você precisa aprender essa ou aquela tecnologia porque é a única coisa que vai existir no futuro!

“Essa é a tecnologia que irá acabar com/substituir o que você usa hoje. Esteja pronto!”

Para ilustrar melhor o que quero dizer vou dar alguns exemplos.

Quando comecei a me informar sobre chatbots a primeira coisa que li nos textos do pessoal que já estava envolvido com isso é que os bots tomariam o lugar dos aplicativos mobile e até mesmo dos sites.

Afirmam isso com base em informações relevantes mesmo, como pesquisas que mostram que nos EUA as pessoas não estão mais baixando novos apps. Não é uma invenção, me parece apenas uma interpretação exagerada dessas informações.

Um tempo depois eu achei uma publicação que falava sobre arquitetura serverless. Lá o discurso era que em cinco anos ninguém mais estaria usando servidores.

Quando você faz parte de um nicho é muito fácil se deixar levar por opiniões exageradas em favor do que você está envolvido. Entretanto é preciso ser mais objetivo.

É claro que os chatbots podem assumir uma boa fatia de mercado dos aplicativos nativos (e vão, afinal eu sou um entusiasta ;D), mas não vão simplesmente acabar com eles do dia para a noite.

A mesma coisa para a arquitetura serverless… ninguém mais usando servidores em cinco anos? Um pouco exagerado, não acha?

Esses são apenas alguns exemplos, mas ainda podemos voltar um pouco no tempo e lembrar de algumas ondas que diziam que os aplicativos nativos seriam totalmente substituídos pelos híbridos e, já hoje em dia, substituídos pelos progressive webapps ou chatbots

Que tal voltar ainda mais, lá no começo da minha carreira nos grupos de Software Livre, onde achávamos que em breve os computadores com Windows seriam minoria perto dos usuários Linux… E quinze anos depois:

Market share de sistemas operacionais

Mesmo que a tecnologia seja muito rápida em sua evolução, dificilmente uma coisa mata outra tão rápido quanto as postagens que geram o hype afirmam.

Isso acontece porque cada negócio tem uma necessidade diferente, então cada tecnologia pode ser a melhor opção para cada tipo de necessidade. Uma não necessariamente mata outra. E não precisa matar!

Para que uma coisa seja boa ela não tem que destruir outra. Existe espaço, e até a necessidade, para tudo!

Eu escrevi o rascunho deste texto dentro de um Cabify, uso Uber com frequência e adivinha só: ainda existem muitos táxis por aí.

Se você gosta de algo e participa de um grupo sobre isso, como eu com chatbots por exemplo, seja um entusiasta sim! Discuta sobre, aposte nisso, mas mantenha os pés no chão. Entenda que o que você faz/gosta pode ser um ótimo martelo, mas nem tudo é prego.

Publicado originalmente no Medium.

Categorias
Tecnologia

Você não precisa de inteligência artificial para criar um chatbot

Nem Machine Learning e Processamento de Linguagem Natural

Todo mundo que trabalha com desenvolvimento de software sabe que, cada vez mais, existem as “expressões do momento” no mercado. É por isso que eu adoro o texto Hype Driven Development

Uma das mais faladas “expressões do momento” é a inteligência artificial. Ela está em todo lugar, em todas as matérias nas mídias e diversos artigos acadêmicos e começou a ficar extremamente popular no último ano.

Cuidado! Inteligência artificial vai roubar seu emprego!

Depois que o Facebook resolveu liberar os chatbots para sua plataforma de mensagens, chatbot também virou uma expressão do momento. Eu mesmo gostava do assunto antes, mas a partir do ano passado comecei a estudar e aprender ainda mais sobre esse tipo de software.

A partir daí todo lugar onde se vê a palavra chatbot também se vê inteligência artificial. É uma questão bem óbvia, afinal para um robô falar com um humano, ele precisa ter o mínimo de inteligência…

Mas será mesmo que preciso saber criar inteligência artificial para criar um chatbot?

Citando um ótimo texto do Caio Calado que explica o que são chatbots:

Chatbots são serviços baseados em regras e (às vezes) inteligência artificial, onde você pode conversar e interagir através de aplicações/aplicativos de mensagens.

A parte importante dessa citação são as palavras entre parênteses: às vezes.

Como ele explica no texto, existem dois tipos de chatbots. Os baseados em regras e os baseados em inteligência artificial. A maioria dos bots que encontramos por aí é puramente baseado em regras e eles não são ruins por causa disso.

As plataformas de mensagens oferecem diversas maneiras para que o usuário posso interagir com o bot. São botões, listas com links, webviews que abrem uma página externa, etc. Utilizando essas interações fica muito fácil saber o que o usuário quer fazer, sem necessidade de inteligência artificial.

Você não precisa fazer com que o bot tenha um entendimento profundo da lingua portuguesa e entenda cada detalhe de tudo que o usuário está falando para que ele cumpra o que propõe.

Um bot tem que ter uma naturalidade na interação, mas isso depende muito mais do design da conversação do que de inteligência artificial.

Um chatbot é um software. A tecnologia que você vai usar no seu desenvolvimento precisa ser compatível com as necessidades das funcionalidades dele.

Machine Learning, Processamento de Linguagem Natural (NLP) e Inteligência Artificial (AI) são importantes para os mais diversos tipos de aplicações, mas para aquelas que realmente necessitam dessas tecnologias.

Se o bot precisa aprender com dados e interações para melhor atender o usuário e cumprir o objetivo proposto, então Machine Learning é necessário. Se ele precisa classificar textos que o usuário venha a enviar, você vai precisar de NLP… e assim por diante.

Agora se ele fala informações sobre o clima, não precisa ser “inteligente” para bater papo com o usuário ou aprender com as interações. Afinal o objetivo dele é previsão do tempo! Ele só precisa saber onde o usuário está ou de onde ele quer saber a previsão.

Outro grande problema desse hype todo é que essas expressões técnicas assustam quem não conhece e podem acabar afastando pessoas interessadas na construção de chatbots por acharem que é um impeditivo não saber essas tecnologias.

O hype é algo que sempre existirá, mas não devemos nos guiar por ele. Pense no objetivo que o seu chatbot terá e nas funcionalidades que serão necessárias para atingí-lo. Se ele realmente precisar de Inteligência Artificial, então pare de ler e vá estudar matemática agora!

Publicado originalmente no Medium.

Categorias
Tecnologia

O que aprendi publicando um chatbot

A importância do feedback dos usuários

Um tempo atrás eu quis falar sobre chatbots na empresa onde trabalho. Temos um evento interno para compartilhar conhecimento, que começou há pouco tempo por aqui, e aproveitei a chance para mostrar para meus colegas como desenvolver e quais eram as ferramentas que o Messenger do Facebook oferece para a criação de um robô de conversa. Para meu lightning talk resolvi criar um chatbot experimental chamado Climão.

O Climão é um bot bem simples e apenas recebe a localização da pessoa e informa como está o clima no local.

Para isso eu usei um dos templates do Facebook Messenger que cria um botão para o usuário enviar a localização e fiz uma busca em uma API aberta de informações meteorológicas.

Publiquei o bot no Facebook Messenger e aproveitei o que apresentei na empresa para escrever um tutorial.

Após a publicação, algumas pessoas começaram a usá-lo, provavelmente porque leram o tutorial e resolveram testar o bot para ver como funcionava.

Foi aí que comecei a perceber que o Climão precisava de algumas melhorias…

Aprendendo com a experiência do usuário

A primeira pessoa que usou o meu chatbot acessou através de um link que enviei no WhatsApp. Esse link abriu o navegador no celular dela e a primeira coisa que ela me disse foi que o bot não estava funcionando.

Eu dei uma olhada no que ela estava fazendo e vi que ela não usou o botão de enviar localização e sim escreveu o nome da cidade. Pedi para que usasse o botão, mas ela reportou que ele não aparecia para ela.

Fiquei sem entender nada… mas pedi para que abrisse no aplicativo do Messenger e a partir daí tudo funcionou normalmente.

Acessando o histórico de mensagens da página do Climão percebi que mais algumas pessoas estavam tentando escrever o nome da cidade e não usando o botão de enviar localização. Isso era algo que eu não tinha previsto e portanto o bot não entendia e acabava reenviando o botão o tempo todo.

A primeira coisa que pensei foi que as pessoas não estão acostumadas a usar botões em chats, deve ser esse o problema.

Mas a realidade era outra.

Quando montei o bot para a apresentação, não dei atenção alguma para o texto que convidava o usuário à escolher a sua localização. Ele dizia: “De qual cidade você quer saber o clima?”. Isso fazia com que a pessoa pensasse que tinha que responder à pergunta.

Esse feedback veio da mesma pessoa que citei a cima. Algo que não havia me passado pela cabeça!

Isso podia mesmo ser um motivo, mas os dias passavam e eu via mais gente usando o Climão e escrevendo repetidamente o nome da cidade em vez de usar o botão.

Será mesmo que apenas a pergunta estava levando tanta gente à escrever a cidade? Por acaso, acabei descobrindo que não.

Lendo outro texto do Medium que falava sobre um chatbot, resolvi clicar no link para experimentá-lo. Foi então que o mistério se resolveu.

As pessoas estavam acessando o Climão pelo texto do Medium, assim como eu, provavelmente pelo celular, assim com eu, e estavam caindo direto no navegador, assim como eu.

Abrindo a página do Facebook pelo navegador do celular e clicando em “Enviar mensagem” você entra em uma página terrível de mensagem que não tem nenhuma das funcionalidades dos bots do Messenger. Nela você pode interagir com o bot apenas por texto!

No lado esquerdo a versão do navegador mobile e na direita o aplicativo do Facebook Messenger.

Isso poderia ser mais um motivo, além do “texto-pergunta”, que estava fazendo as pessoas digitarem ao invés de enviarem sua localização pelo botão.

Foi então que resolvi melhorar o bot, mesmo ele sendo apenas um experimento para um tutorial, achei que valia a pena a experiência de aprender com a interação de usuários.

Gastei um tempinho nele e fiz com que também aceitasse o nome da cidade escrita. Mudei a frase que pede a localização. Agora ele escolhe aleatoriamente entre algumas opções de texto que indicam ao usuário que pode digitar uma cidade ou apertar o botão de envio de localização.

Aproveitei para dar um tapa no visual da apresentação dos dados também. Ao invés de enviar apenas um texto, resolvi utilizar o template de lista que a API de envio do Messenger proporciona.

Interações “fora do contexto”

Um outro fato que me chamou a atenção quando analisei as mensagens enviadas pelos usuários foram as mensagens que estavam “fora do contexto” das funcionalidades do Climão.

Com “fora do contexto” eu quero dizer interações que eu não previ.

Coisas simples como um “Olá” e um “Obrigado” não eram tratadas, deixando o bot muito “robótico” e pouco natural na conversação. O Climão era antipático!

Dei uma atenção para o tratamento desse tipo de interação, mas não gastei muito tempo com isso ainda, afinal ele é apenas um experimento. Podemos dizer agora que ele não é muito simpático, mas pelo menos já é educado.

Algumas coisas ele responde, mas não chega a ser tão esperto assim…

Conclusão

Esse bot tem sido um experimento incrível. Além de ter aprendido muita coisa com um chatbot tão simples, ainda tenho ganhado uma experiência importante sobre como evoluí-lo para melhor se adaptar às interações com os usuários.

O feedback é a melhor maneira de se aprender. Saber onde você errou ou o que deixou passar depende muito dessa interação com diferentes pessoas. Por isso foi tão importante tirar esse bot do “desenvolvimento” e deixá-lo disponível para o público em geral.

Se você leitor tiver alguma sugestão para melhorar o Climão, deixe sua resposta abaixo. E se quiser ver o código-fonte, acesse o repositório no Github. Quer saber o clima atual em algum lugar? Mande uma mensagem pro Climão!

Publicado originalmente no Medium.

Categorias
Tecnologia

Como criar um chatbot para o Facebook Messenger

Passo a passo para começar um chatbot em Python

Este é um tutorial no estilo passo-a-passo para a criação de um chatbot simples para o Facebook Messenger. Ele foi escrito como conteúdo para uma pequena apresentação que farei em um evento interno de compartilhamento de conhecimento da TIKAL TECH, empresa em que trabalho.

Existem diversas maneiras de se criar um bot para o Messenger, mas neste tutorial eu utilizarei apenas o microframework para web escrito em Python chamado Flask e nada mais.

Esse tutorial resume algumas das coisas que aprendi durante o desenvolvimento de um outro projeto.

Passo 1

Criando um aplicativo e vinculando com uma fanpage

Acesse o dashboard do Facebook Developers e crie um aplicativo. No tipo de aplicativo escolha “Aplicativos para o Facebook Messenger”. Se você não tiver uma página para vincular o aplicativo, crie uma também.

Com a página criada, entre novamente no dashboard e gere um token para o aplicativo ser vinculado à página.

Passo 2

Começando a programar o backend

Vamos utilizar o microframework Flask para facilitar esse desenvolvimento, mas qualquer outro framework web pode ser utilizado.

Se você está acostumado a trabalhar com Python você pode pular alguns dos passos abaixo.

Vamos começar criando um ambiente virtual na linha de comando e instalando o Flask, o requests e o gunicorn. Precisaremos dos dois primeiros para nosso chatbot e o último será para o deploy.

Escolha o diretório que você vai utilizar e digite os seguintes comandos.

$ cd ~/projetos/chatbot/
$ mkvirtualenv chatbot
...

(chatbot)$ pip install Flask
(chatbot)$ pip install requests
(chatbot)$ pip install gunicorn
(chatbot)$ touch index.py

Agora temos um arquivo index.py no nosso diretório chatbot. É nele que faremos os próximos passos do nosso tutorial.

Começamos com o básico do Flask.

import os
from flask import Flask, request

token = os.environ.get('FB_ACCESS_TOKEN')
app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def webhook():
    return 'Nothing'

if __name__ == '__main__':
    app.run(debug=True)

Esse arquivo tem o básico do que precisamos para rodar um app no Flask.

O token que estamos pegando de uma variável de ambiente é o token que geramos no dashboard do Facebook.

Para adicioná-lo como variável de ambiente execute na linha de comando:

$ export FB_ACCESS_TOKEN=<cole o token gerado>

Passo 3

Configurando os Webhooks

Temos que configurar um webhook para que o Facebook saiba para onde enviar as requisições do chat.

Para isso utilizaremos o ngrok para “tunelar” nosso localhost. Para saber como funciona, veja esta publicação.

Vamos rodar nosso servidor local com o Flask. Na linha de comando com o virtualenv ativado, digite:

(chatbot)$ python index.py

Abra outra janela de terminal para iniciar o ngrok.

./ngrok http 5000

Agora temos um endereço web com HTTPS para cadastrar no dashboard do Facebook. Basta ir até o painel Webhooks e clicar em Configurar Webhooks.

Antes de cadastrar o endereço, é preciso adicionar uma parte a mais no nosso index.py. O bloco em negrito tem o que é preciso para que o Facebook aceite esse link como elegível para webhook.

def webhook():
    if request.method == 'POST':
        pass
    elif request.method == 'GET': # Para a verificação inicial
        if request.args.get('hub.verify_token') == os.environ.get('FB_VERIFY_TOKEN'):
            return request.args.get('hub.challenge')
        return "Wrong Verify Token"
    return "Nothing"

Coloque o endereço gerado pelo ngrok, por exemplo https://7f3o6bd7.ngrok.io, e crie uma frase de segurança. Essa frase colocamos na variável de ambiente FB_VERIFY_TOKEN que você pode ver no código acima.

(chatbot)$ export FB_VERIFY_TOKEN=<digite qualquer frase aqui>

Com isso já somos capazes de registrar nosso endereço do chatbot no Facebook.

Para finalizar, no mesmo painel de webhooks você deve “inscrever” sua página criada ao webhook adicionado. Essa parte é bem autoexplicativa.

Passo 4

Lendo a mensagem e respondendo

Agora vamos adicionar uma maneira de lermos o que o usuário nos enviou pelo Messenger. Isso é feito verificando os dados enviados na requisição que o chat nos envia via POST.

Então vamos adicionar ao nosso código o seguinte trecho:

import os
import requests
import traceback
import json

(...)

def webhook():
    if request.method == 'POST':
        try:
            data = json.loads(request.data.decode())
            text = data['entry'][0]['messaging'][0]['message']['text']
            sender = data['entry'][0]['messaging'][0]['sender']['id']
            payload = {'recipient': {'id': sender}, 'message': {'text': "Hello World"}}
            r = requests.post('https://graph.facebook.com/v2.6/me/messages/?access_token=' + token, json=payload)
        except Exception as e:
            print(traceback.format_exc())
    elif request.method == 'GET': # Para a verificação inicial
(...)

Explicando o que estamos fazendo. Adicionamos os imports necessários no topo do arquivo index.py e dentro do nosso método webhook verificamos se a requisição chegou como POST.

Com o data = json.loads(request.data.decode()) nós capturamos o corpo da mensagem que nos foi enviado pelo Messenger.

Com o trecho text = data['entry'][0]['messaging'][0]['message']['text']conseguimos pegar o texto que o usuário enviou via chat.

Pra saber quem enviou, usamos o trecho sender = data['entry'][0]['messaging'][0]['sender']['id']. Essa informação é necessária para que possamos enviar uma resposta para o usuário correto.

No trecho payload = {'recipient': {'id': sender}, 'message': {'text: "Hello World"}} nós montamos o corpo da nossa resposta ao usuário.

Para finalizar, respondemos enviando uma requisição para o endereço da API do Facebook Messenger com o corpo criado anteriormente. O trecho referente ao envio segue abaixo.

r = requests.post('https://graph.facebook.com/v2.6/me/messages/?access_token=' + token, json=payload)

Colocamos tudo isso dentro de um try/except para capturar um possível erro que imprimiremos no console. Isso fazemos com o trecho final do código que acabamos de adicionar.

except Exception as e:
    print(traceback.format_exc())

Com isso, respondemos um Hello World para cada entrada que o usuário nos enviar.

Passo 5

Tornando o chatbot em algo útil

Como responder Hello World para cada mensagem é algo totalmente inútil para um bot fazer, vamos colocar uma funcionalidade aproveitando a documentação do Messenger, que é bem completa.

Vamos pegar a localização do usuário e enviar informações sobre o clima atual em sua localidade.

Primeiro criamos uma função que monta um payload com formatoQuick Reply do Messenger. O formato que precisamos enviar para ter esse resultado é facilmente encontrado na documentação do Messenger. Nela definiremos que queremos um tipo location.

def location_quick_reply(sender):
    return {
        "recipient": {
            "id": sender
        },
        "message": {
            "text": "Compartilhe sua localização:",
            "quick_replies": [
                {
                    "content_type": "location",
                }
            ]
        }
    }

Agora, quando formos enviar uma mensagem para nosso usuário, utilizamos essa função no lugar do antigo payload.

payload = location_quick_reply(sender)

Isso vai enviar uma opção para o usuário nos enviar sua localização. Como mostra a imagem abaixo.

Vamos receber essa localização de maneira diferente do que um texto comum, ela virá como um anexo. Dessa forma mudamos nossa verificação de texto para o bloco abaixo.

if request.method == 'POST':
        try:
            data = json.loads(request.data.decode())
            print(data)
            message = data['entry'][0]['messaging'][0]['message']
            sender = data['entry'][0]['messaging'][0]['sender']['id'] # Sender ID

            if 'attachments' in message:
                if 'payload' in message['attachments'][0]:
                    if 'coordinates' in message['attachments'][0]['payload']:
                        location = message['attachments'][0]['payload']['coordinates']
                        latitude = location['lat']
                        longitude = location['long']
            else:
                text = message['text']
                payload = location_quick_reply(sender)
                r = requests.post('https://graph.facebook.com/v2.6/me/messages/?access_token=' + token,
                                  json=payload)

Nesse bloco verificamos se o corpo da requisição que o Messenger nos enviou possui uma chave attachments e se possui uma chave payload com as coordenadas da localização.

Se não vier nesse formato é porque ele enviou uma mensagem normal de texto, então reenviamos o botão que pede sua localização.

Agora que pegamos a latitude e longitude, podemos utilizar uma API aberta de clima para enviar as informações para nosso usuário.

Eu escolhi a OpenWeatherMap para isso. Basta se inscrever e gerar uma chave de API no site deles e você já pode começar a fazer requisições variadas para receber informações de clima do mundo inteiro.

Adicionei a chave de API deles numa variável de ambiente para utilizar nas requisições que farei dentro do código e pronto.

(chatbot)$ export WEATHER_API_KEY=<digite a api key>

Agora podemos acessar o endpoint que eles fornecem para current weathere pegar a temperatura e outros dados climáticos do local do usuário.

Logo após o trecho do código onde pegamos a latitude e longitude, adicionamos uma requisição para a API do OpenWeatherMap para montar a resposta que daremos ao nosso usuário.

api_key = os.environ.get('WEATHER_API_KEY')

(...)

url = 'http://api.openweathermap.org/data/2.5/weather?' \
      'lat={}&lon={}&appid={}&units={}&lang={}'.format(latitude, longitude, api_key, 'metric', 'pt')

r = requests.get(url)

description = r.json()['weather'][0]['description'].title()
icon = r.json()['weather'][0]['icon']
weather = r.json()['main']

text_res = '{}\n' \
           'Temperatura: {}\n' \
           'Pressão: {}\n' \
           'Humidade: {}\n' \
           'Máxima: {}\n' \
           'Mínima: {}'.format(description, weather['temp'], weather['pressure'], weather['humidity'], weather['temp_max'], weather['temp_min'])

payload = {'recipient': {'id': sender}, 'message': {'text': text_res}}

r = requests.post('https://graph.facebook.com/v2.6/me/messages/?access_token=' + token, json=payload)

Basicamente analisei a resposta da API do OpenWeatherMap e peguei as informações que gostaria de exibir ao usuário. Depois disso montei um bloco de texto simples exibindo algumas das informações.

Pronto! Agora temos uma funcionalidade para nosso bot experimental.

Passo 6

Fazendo o deploy

Vamos colocar nosso novo bot em um servidor para que ele fique disponível constantemente. Como eu falei anteriormente é preciso uma conexão segura (HTTPS) para que o Facebook aceite a URL do chatbot.

Com o Heroku é muito simples fazer o deploy. Basta que o seu código esteja no github, por exemplo, e com um clique ele fica online.

Para fazê-lo funcionar no Heroku é preciso adicionar dois novos arquivos ao nosso projeto. O Procfile e o runtime.txt. O primeiro configura o servidor web e o segundo define que estamos usando o Python 3.

Se você estiver utilizando a versão 2 do Python, o segundo arquivo é desnecessário.

O arquivo Procfile ficará assim:

web: gunicorn index:app

E o runtime.txt assim:

python-3.5.2

Criamos uma conta no Heroku e adicionamos um novo app. Em seguida vamos na aba Deploy e conectamos com o Github. Com isso basta escolher o seu repositório e clicar em Deploy Branch.

Abas do Dashboard do Heroku

Precisamos adicionar nossas variáveis de ambiente. Para isso devemos ir à aba Settings e adicionar manualmente por lá. É simples e autoexplicativo.

Agora testamos nossa URL, que será algo como https://<nome_do_app>.herokuapp.com.

Voltamos ao dashboard de developers do Facebook para mudar nosso webhook configurado. Lembra que fizemos isso com o endereço que o ngrok nos forneceu no passo três? Agora vamos mudar a URL para a nova que o Heroku nos forneceu.

Aprovação do Facebook

Com nosso bot funcional e online, agora temos que deixá-lo em aprovação no dashboard de developers do Facebook.

Basta preencher o que eles pedem por lá e aguardar até cinco dias para que seu bot possa ser usado por qualquer usuário do Facebook.

Conclusão

O Facebook aprovou rapidamente o chatbot que chamei de Climão. Isso porque utilizamos apenas a permissão de messages do Webhook, que é a mais simples.

Para utilizar esse bot acesse a Página do Facebook e envie uma mensagem para o Climão. =)

O código que criamos durante esse tutorial está disponível no Github.

Qualquer dúvida, entre em contato pelas respostas abaixo.

Publicado originalmente no Medium.

Categorias
Tecnologia

API Rest e os verbos HTTP

Arquitetura, padrões e boas práticas

Quando desenvolvemos um serviço web, que alimentará com dados algum cliente (aplicativos, webapps ou qualquer outro sistema), precisamos prestar muita atenção no modelo de interface que utilizaremos.

Isso é importante para que os desenvolvedores que utilizarem seu serviço web tenham fácil compreensão do que cada endpoint faz, de acordo com o verbo HTTP utilizado para a requisição.

A maneira mais comum para modelar uma interface como essas nos dias de hoje é a arquitetura REST.

Antes de continuar, vamos para algumas definições importantes para seguirmos o assunto sem que tudo fique incompreensível para quem não é familiarizado com as expressões utilizadas nos primeiros parágrafos.

O que é API?

Interface de Programação de Aplicação, cujo acrônimo API provém do Inglês Application Programming Interface, é um conjunto de rotinas e padrões estabelecidos por um software para a utilização das suas funcionalidades por aplicativos que não pretendem envolver-se em detalhes da implementação do software, mas apenas usar seus serviços. (fonte Wikipedia)

No caso desse texto estamos falando especificamente sobre as APIs de serviço web, ou web services APIs, que são interfaces de programação para troca de dados via web, utilizando protocolo HTTP.

Isso é feito através de endpoints.

Os endpoints são os endereços web que executam as ações e são acessados diretamente pelos clientes.

O que é REST?

Representational state transfer (REST) or RESTful web services são uma forma de proporcionar interoperabilidade entre sistemas de computadores na Internet. Os serviços da Web compatíveis com REST permitem que os sistemas solicitantes acessem e manipulem representações textuais de recursos da Web usando um conjunto uniforme e predefinido de operações sem estado (stateless). (fonte Wikipedia)

Quando a arquitetura REST é aplicada à APIs de serviços web, chamamos de RESTful APIs.

E os verbos HTTP?

O protocolo HTTP define métodos (às vezes referidos como verbos) para indicar a ação desejada a ser realizada no recurso identificado. O que este recurso representa, se são dados pré-existentes ou dados gerados dinamicamente, depende da implementação do servidor. Muitas vezes, o recurso corresponde a um arquivo ou a saída de um executável residente no servidor. (fonte Wikipedia)

Em resumo, os verbos HTTP são os métodos de requisição que utilizamos para acessar os endpoints de uma RESTful API.

Uma das primeiras coisas que deve ser feita ao iniciar um projeto de API é planejar os endpoints que existirão para o acesso aos dados e para as ações específicas.

Segue um exemplo bem simples desse planejamento feito em uma planilha qualquer.

Vendo esse exemplo fica bem explícito o que cada verbo HTTP significa, certo?

Qualquer um que conheça essa arquitetura vai saber que o endpoint /users tem, no mínimo, essas opções de ação. Por isso é tão importante respeitar os verbos para facilitar o entendimento da sua API.

Vamos detalhar melhor cada um deles.

POST

O verbo POST é mais frequentemente utilizado para criar novos recursos. Na criação bem-sucedida, retornar o status HTTP 201.

Ele não é um método seguro, pois altera o estado do recurso no servidor. Ele também não é idempotente, o que quer dizer que se ele for executado duas vezes de forma idêntica serão criados dois itens diferentes com o mesmo conjunto de dados.

GET

O método HTTP GET é usado para ler ou recuperar uma representação de um recurso. Em caso de sucesso, retorna uma representação em JSON e um código de resposta HTTP de 200 (OK). Em caso de erro, ele geralmente retorna um 404 (NOT FOUND) ou 400 (BAD REQUEST).

De acordo com o design da especificação HTTP, requisições GET (juntamente com HEAD) são usadas apenas para ler dados e jamais alterá-los. Portanto, quando usados dessa forma, são considerados seguros.

Além disso, GET (e HEAD) é idempotente, o que significa que fazer várias solicitações idênticas acaba tendo o mesmo resultado de uma única solicitação.

PUT

PUT é mais utilizado para substituir (ou atualizar) recursos, executando a requisição para uma URI de recurso conhecido, com o corpo da requisição contendo a representação recém-atualizada do recurso original.

Na atualização bem-sucedida, retorna 200 (ou 204 se não retornar qualquer conteúdo no corpo). Retornar os dados do recurso no corpo é opcional, lembrando que fazer isso causa maior consumo de banda.

PUT não é uma operação segura, pois modifica estado no servidor, mas é idempotente. Em outras palavras, se você atualizar um recurso usando PUT e, em seguida, fazer essa mesma chamada novamente, o recurso ainda está lá e ainda tem o mesmo estado.

Obs: Se, por exemplo, executar uma requisição PUT em um recurso incrementar um contador (dentro do recurso), a chamada não é mais idempotente. É recomendado manter as solicitações PUT idempotentes. Use o POST para solicitações não idempotentes.

PATCH

PATCH é usado para modificar parcialmente os recursos. A requisição só precisa conter as alterações específicas para o recurso, não o recurso completo.

Se parece com PUT, mas o corpo contém um conjunto de instruções descrevendo como um recurso no servidor deve ser modificado para produzir uma nova versão.

PATCH não é nem seguro, nem idempotente.

DELETE

DELETE é bastante fácil de entender. Ele é usado para excluir um recurso identificado por um URI.

Na exclusão bem-sucedida, devolve o status HTTP 200 (OK) ou o status HTTP 204 (NO CONTENT) sem corpo de resposta.

Operações DELETE são idempotentes.

Há uma advertência sobre idempotência no DELETE. Chamar DELETE em um recurso uma segunda vez geralmente retornará um 404 (NOT FOUND) já que ele já foi removido e, portanto, não é mais encontrável. Isso, por algumas opiniões, faz operações DELETE não mais idempotente, no entanto, o estado final do recurso é o mesmo. Retornar um 404 é aceitável e comunica com precisão o status da chamada.

Obs: Se a requisição DELETE decrementa um contador (dentro do recurso), a chamada DELETE não é mais idempotente. É recomendável usar o POST para solicitações de recursos não idempotentes.

Os códigos de resposta (status codes) HTTP

Nas descrições dos verbos HTTP foram citados diversas vezes os status code do protocolo HTTP.

Esse é outro item importante para a arquitetura de uma API REST, porque, da mesma maneira que acontece como os verbos HTTP, elas formam um padrão facilmente reconhecido por quem for consumir o web service.

Os principais códigos utilizados para as respostas de um endpoint são o 200 (OK), o 201 (CREATED), o 204 (NO CONTENT), o 404 (NOT FOUND) e o 400 (BAD REQUEST).

Todos os códigos tem nomes autoexplicativos, portanto é muito simples lembrar o que utilizar em cada situação.

Existe uma lista enorme de códigos de resposta do protocolo HTTP que podem ser utilizados, como o 301 (MOVED PERMANETLY) e o 304 (NOT MODIFIED). Sendo o segundo para conteúdos em cache, por exemplo.

Os códigos de sucesso tem o padrão 20x, os de redirecionamento 30x, os de erro do cliente 40x e os de erro de servidor 50x.

Lembrando mais uma vez, os padrões facilitam qualquer desenvolvedor de entender facilmente o que aconteceu com o retorno da requisição que ele executou.

No caso de erros, mesmo tendo esses padrões, é importante devolver ao cliente uma mensagem clara do que aconteceu com a requisição e qual o motivo do erro.

Para ver mais detalhes sobre os códigos HTTP e também a lista completa deles, acesse o link https://httpstatuses.com/.

Concluindo

Este foi uma publicação mais teórica sobre a arquitetura, os padrões e algumas boas práticas no desenvolvimento de uma RESTful API.

Ainda existem muitos assuntos a serem abordados para quem quer se aprofundar mais nesse tipo de desenvolvimento, mas essa publicação ajuda a dar os primeiros passos.

Mas a melhor maneira de aprender de verdade é passando pela experiência de desenvolver uma API que seja consumida por alguns clientes, ou até criar um cliente que consuma uma API pública já existente.

Publicado originalmente no Medium.