Otimização de performance prematura: não faça!

Otimização de performance é uma preocupação comum para quem está começando em programação, e muitas vezes mesmo programadores experientes tem dúvidas sobre esse assunto, o que é normal uma vez que o assunto é mesmo complexo. Não vou explicar nesse post tudo o que você precisa saber sobre performance, mas pretendo dizer o mais importante: quando você precisa se preocupar. Isso mesmo, porque um erro muito comum é ver os programadores se preocupar demais com performance, na hora errada.

Então vamos lá: nossos computadores são muito potentes hoje em dia. Muito. Dificilmente mudar a lógica de um cálculo, criar uma variável a menos, otimizar um loop, ou até concatenar menos strings vai fazer algum diferença sensível. Então, não pré-otimize, não otimize antes de medir.

Vamos mostrar um exemplo. Fiz em Python só porque eu gosto, mas a mesma coisa vale para sua linguagem favorita. Escrevi os dois arquivos a seguir:

strings1.py

tamanho=20
a='a'
for i in range(tamanho):
    a*=2
print(len(a))

strings2.py

tamanho=20
a='a' * (2**tamanho)
print(len(a))

São duas maneiras bem diferentes de se criar uma grande string. A segunda é muito mais eficiente que a primeira. Bom, veja os resultados da execução aqui na minha máquina:

$ time python strings1.py
1048576
real 0m0.023s
user 0m0.013s
sys 0m0.008s
$ time python strings2.py
1048576
real 0m0.021s
user 0m0.012s
sys 0m0.008s

Nenhuma diferença prática, certo? Aumentei a variável tamanho para 30, agora notamos diferença:

$ time python strings1.py
1073741824
real 0m1.375s
user 0m0.671s
sys  0m0.691s
$ time python strings2.py
1073741824
real 0m0.586s
user 0m0.235s
sys  0m0.344s

Agora a diferença é absurda, certo? Mas quando foi a última vez que você precisou concatenar strings de um bilhão de caracteres? O caso é: se suas strings vão chegar a esse tamanho, você provavelmente vai saber disso antes. Por exemplo, se você está fazendo um software de tratamento de imagens, parece óbvio que processamento pode ser um problema, certo? Se não, gastar seu tempo e esforço com otimização de performance provavelmente não vale a pena.

Aviso: o código do exemplo 1 é muito ruim, além de dar mais trabalho para escrever. Eu não estou sugerindo que você escreva código ruim de propósito, tá? Apenas que você não se preocupe demais com performance e não gaste seu tempo resolvendo problemas imaginários.

Há, porém, algumas situações em que tudo o que eu disse acima não vale. Nossos processadores são muito rápidos, nossas memórias também. Discos já não são tão rápidos assim. Bancos de dados, mais ou menos. A internet, bom, quem pode confiar na internet, né?

Então, se você vai consumir um webservice, e pode mudar seu algoritmo para fazer dez chamados ao invés de vinte, faça isso. Se vai escrever muito no disco, e puder reduzir em 20% as operações de escrita de arquivos, faça isso. Se escrevendo uma consulta SQL mais complexa você consegue fazer muito menos consultas ao banco de dados e usar mais índices, faça isso.

Eu faço mais ou menos assim em relação a performance:

  1. Vamos usar a internet? Otimize sempre.
  2. Vamos gravar grandes arquivos, ou fazer uso intensivo de disco? Otimize sempre.
  3. Cálculo científico, tratamento de imagens e outras operações de processamento massivo? Otimize sempre.
  4. Bancos de dados com milhões de registros e uso intenso? Otimize sempre.
  5. Uso comum de arquivos e bancos de dados? Cuide de não escrever nada muito ruim, e otimize se der problema.
  6. O resto todo? Escreva pensando em legibilidade, encapsulamento e reuso. Só otimize se tiver problemas.

Publiquei um vídeo sobre isso há um tempo, se você quiser dar uma olhada: Não pré-otimize.

Média de lista em Python, como calcular

Às vezes a gente tem a tendência de complicar as coisas. Semana passada, um amigo me perguntou se há alguma forma de calcular a média de uma lista em Python. Assim como há funções para calcular a soma dos elementos ou o maior elemento, ele esperava que houvesse uma para calcular a média.

Afinal, calcular a média de uma lista é uma necessidade comum, certo? Deve haver no Python algum jeito fácil de fazer, então. Quando eu disse que não, meu amigo gastou alguns segundos pesquisando e chegou nessa solução:

import numpy
l = [ 2, 5, 6.8, 9, 7]
avg = numpy.mean(l)

Funciona. Não é muito código. Mas tem alguns problemas:

  1. Cria uma dependência extra: será preciso ter o numpy instalado para que a aplicação funcione
  2. Complica um pouco mais o código: nem todo mundo sabe o que faz o método .mean(), fazendo com que outros programadores tenham que gastar um tempinho pesquisando
  3. Tem uma performance pior: ou, pelo menos, para os tamanhos de lista mais comum. A função de média do numpy é otimizada. Deveria portanto, ser mais rápida. Se você tiver que calcular centenas de médias de listas gigantescas, numpy vai fazer diferença. Mas não é o caso da maioria das aplicações. Se você for usar pouco a função mean() o custo de importá-la é maior que o de fazer o cálculo você mesmo.

E como fica esse cálculo? O jeito como eu recomendo calcular a média de uma lista em Python é esse:

l = [ 2, 5, 6.8, 9, 7]
avg = sum(l)/len(l)

A dica é: antes de procurar ou construir um módulo com a solução do seu problema, pense se não é um problema simples demais para isso. Se você fizer esse exercício, vai evitar escrever código como esse:

import calculations
x = calculations.sum(2, 7)

Ao invés de:

x = 2 + 7

E não, não tem filosofia, técnica ou estratégia que você posa usar para tentar me convencer de que o primeiro jeito é melhor do que o segundo.

Recursos “escondidos” do Python

Resposta que eu dei à pergunta: Quais são alguns dos recursos ocultos do Python? no Quora.


1. Atribuição múltipla (com tuple unpacking)

a, b, c = 1, 2, 3

2. Com isso dá para trocar o valor de variáveis

a, b = b, a

3. Encadeamento de comparadores

x = 3
print(1 < x < 5) # True

4. Generators

def fib(max):
    n1, n2 = 0, 1
    for i in range(max):
        yield n1
        n1, n2 = n2, n1 + n2
f = fib(20)
for i in f:
    print(i)

5. If em uma linha

aliquota = 0.05 if valor < 1000 else 0.07

6. List comprehension

# Quadrados dos números de 0 a 99
[i ** 2 for i in range(100)]

# Quadrados dos números de 0 a 99, apenas
# se o resultado não contém o dígito "4"
[i ** 2 for i in range(100) if not '4' in str(i**2)]

7. Invertendo uma string

a = a[::-1]

8. enumerate

for i, l in enumerate('palavra'):
    print (i, l, end=' / ')
# 0 p / 1 a / 2 l / 3 a / 4 v / 5 r / 6 a /

9. Unpacking estendido (só Python 3)

a, *b, c = "unpacking"
print(a, b, c)
# u ['n', 'p', 'a', 'c', 'k', 'i', 'n'] g

10. Dict comprehension

d = {i: i**2 for i in range(10)}
print(d)
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36}

11. String formatting

dados={'nome': 'Joaquim', 'email': 'jsilva@fbi.gov'}
print('%(nome)s <%(email)s>' % dados)
# Joaquim <jsilva@fbi.gov>
print('{nome} <{email}>'.format(**dados))
# Joaquim <jsilva@fbi.gov>

12. zip

list(zip([1, 2, 3], [4, 5, 6]))
[(1, 4), (2, 5), (3, 6)]

Módulos Úteis

1. collections

import collections
print(collections.Counter('banana'))
# Counter({'a': 3, 'n': 2, 'b': 1})
d = collections.defaultdict(lambda:'...')
d['nome'] = 'Teste'
print(d['nome']) # Teste
print(d['idade']) # ...

2. pprint

from pprint import pprint
pprint(['a' * i for i in range(20)])
# ['',
#  'a',
#  'aa',
#  'aaa',
#  'aaaa',
#  'aaaaa',
#  'aaaaaa',
#  'aaaaaaa',
#  'aaaaaaaa',
#  'aaaaaaaaa',
#  'aaaaaaaaaa',
#  'aaaaaaaaaaa',
#  'aaaaaaaaaaaa',
#  'aaaaaaaaaaaaa',
#  'aaaaaaaaaaaaaa',
#  'aaaaaaaaaaaaaaa',
#  'aaaaaaaaaaaaaaaa',
#  'aaaaaaaaaaaaaaaaa',
#  'aaaaaaaaaaaaaaaaaa',
#  'aaaaaaaaaaaaaaaaaaa']

3. itertools

import itertools
for i in itertools.permutations("123"):
    print("".join(i), end=", ")
# 123, 132, 213, 231, 312, 321,
for i in itertools.product("01", repeat=3):
    print("".join(i), end=", ")
# 000, 001, 010, 011, 100, 101, 110, 111,

4. SimpleHTTPServer

➜  ~ python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...

5. webbrowser

import webbrowser
webbrowser.open('https://campus.visie.com.br/')

6. atexit

➜  ~ python3 -q
>>> def teste():
...     print('Bye!')
...
>>> import atexit
>>> atexit.register(teste)
<function teste at 0x10973a620>
>>> ^D
Bye!
➜  ~ _

7. base64

import base64
print(base64.b64encode(b'Teste'))
# b'VGVzdGU='

8. gzip

import gzip
print(gzip.open('teste.txt.gz').read())

Easter Eggs

Tente aí:

>> import this
>> import hello
>> import antigravity
>> from __future__ import braces

Software desejável

Um dos processos mais eficientes para melhorar a performance e o valor de um software é a análise de funil.

Isso é, você procura pelos “gargalos” de performance, aqueles pontos onde, se você melhorar as coisas, tudo vai fluir melhor.

Bem, software é feito para ser usado por pessoas. E aí está, geralmente, o gargalo mais óbvio para que um software dê o retorno que se espera dele.

Nós não somos racionais como gostamos de achar que somos. A maior parte de nossas motivações é emocional e intuitiva.

Por isso, se você construir software que as pessoas gostem de usar, isso pode com facilidade dobrar ou triplicar os retornos que seu software gera para seu cliente.

Isso inclui fatores objetivos, como responder rápido, ser fácil de usar, automatizar tarefas repetitivas e exigir menos passos para completar tarefas.

Mas inclui fatores subjetivos. Coisas que fazem as pessoas gostarem de um software.

Por exemplo, não basta que ele seja fácil de usar, precisa parecer fácil de usar. Não basta ser produtivo, precisa parecer produtivo.

Estou falando do valor de um bom design. O pessoal que desenvolve sites já descobriu isso há uns vinte anos.

Mas muita gente no mercado de software ainda está desperdiçando essa oportunidade. Você já reparou como são feios e complicados os ERPs, por exemplo?

Aprenda os fundamentos: cores no CSS

Quando você se deparar com algum tipo de código, tenha a curiosidade de decifrá-lo.

Me impressiono com a quantidade de programadores que precisam escrever CSS com regularidade e nunca pararam para entender o significado dos código de cores.

É simples: uma cor RGB é composta de três números, representando as cores vermelho (R), verde (G) e azul (B). Cada um desses números pode ir de 0 a 255 (1 byte).

Então o vermelho vivo é:

rgb(255, 0, 0)

Que também pode ser escrito como:

rgb(100%, 0, 0)

Ou, em hexadecimal (255 = FF):

#FF0000

As cores que podem ser “arredondadas” para duplas de letras iguais, como essa, podem também ser escritas assim:

#F00

E é isso. Da próxima vez que você escrever uma cor, vai saber o que significa. Agora pesquisa sobre RGBA, você via ver como fica fácil entender.

Mas não é só sobre cores. Faça isso sempre que se deparar com qualquer tipo de código, tente entender o que ele significa, você vai gastar um pouquinho de tempo no início, mas a vida vai ficar muito mais fácil depois.

Você está no negócio do conhecimento

Joel Spolsky diz que um bom programador pode ser 5 ou 10 vezes mais produtivo que um programador medíocre.

Esses números, postos desse jeito, talvez não dêem a dimensão do que isso significa. Você preferiria trabalhar com alguém porque ele é 10% mais produtivo? Que tal 20%? Com certeza!

Não estamos falando de um ganho de 10% ou 20%, estamos falando de um ganho de 400% a 900%!

Você quer ser esse programador? Então vai estudar, filhão!

Eu sei que tem assuntos demais para ser estudados, que é difícil escolher qual linguagem, framework, ferramenta ou técnica aprender em seguida. Mas não use isso como desculpa! Larga um pouco o Free Fire e investe na sua carreira.

Faço uma aposta com você: meia hora por dia, por seis meses. Daqui a seis meses você pede um aumento, ou arruma um emprego melhor. Duvido que não funcione.

Não seja escravo das suas ferramentas

Muita gente que, como eu, tem um blog, usa o plugin Yoast SEO para WordPress. É muito bom, uma escolha óbvia. Ele praticamente lê seu texto e te diz o que você tem que fazer para melhorar a indexação.

O problema? Muitas vezes, otimizar seu texto para uma determinada palavra-chave o torna chato de ler. Seu texto fica mais ou menos assim:

… Ao usar um plugin de SEO para WordPress, você corre o risco de escrever um texto mecânico. É verdade que plugins de SEO para WordPress são uma coisa boa, mas você precisa tomar cuidado para não deixar seu plugin de SEO para WordPress mandar em você…

Você quer apenas ser encontrado? Tem um monte de sites por aí tão cheios de publicidade que tornam quase impossível ler o que está escrito. O objetivo é ser encontrado e gerar um clique patrocinado, apenas isso. Se é isso o que você está construindo, vá em frente, siga as regras do plugin e você vai poupar um bocado de tempo.

Mas se seu objetivo é que as pessoas encontrem, leiam e entendam o que você está escrevendo, então seguir cegamente as regras não é a melhor decisão.

Escreve para pessoas, depois faça o que for possível para agradar os robôs.

Há um tempo que eu tenho usado o Pylint em alguns projetos. Ele me avisa se eu deixo de seguir algum padrão de código. Ele até dá uma nota para o meu código!

Mas o recurso mais legal do Pylint é poder fazer isso:

import config # pylint: disable = relative-import

Ou seja, não preciso seguir as regras cegamente.

Você também pode decidir quando quebrar as regras. Escolha com cuidado.

Não é sobre quantas linhas de código você escreve

Parece haver uma certa fixação entre os programadores, principalmente os menos experientes, em quantas linhas de código são necessárias para resolver determinado problema.

Às vezes isso é bom. Veja como ler um arquivo texto em Java:

import java.io.*; 
public class ReadingFromFile 
{ 
    public static void main(String[] args) throws Exception 
    { 
	FileReader fr = 
	new FileReader("arquivo.txt"); 

	int i; 
	while ((i=fr.read()) != -1) 
	    System.out.print((char) i); 
    } 
} 

Agora compare com a mesma coisa em Python:

print(open('arquivo.txt').read())

Nesse caso, parece óbvio que a resposta em Python é muito melhor, não? Agora olhe esse código em JavaScript:

urlscore = url.indexOf('http') ? -1 : (url.indexOf('https://')+1)*5 + 
                                      (url.split('/')[2].indexOf('www')?1:0)*2 + 
                                      (url.split('/')[1].indexOf('@')>-1?-1:1)*3

Uau! O sujeito reduziu a função inteira a uma única expressão! Parece uma boa ideia pra você? Coitado de quem tiver que dar manutenção nisso!

Seu inimigo não é a quantidade de código, é a complexidade. É difícil dar uma boa definição técnica de complexidade, mas você a reconhece quando vê.

Salvando diff em HTML

Comece instalando as ferramentas:

sudo apt-get install colordiff kbtin

Agora você pode:

diff arquivo1.txt arquivo2.txt | colordiff | ansi2html > diff.html

Ou, com git:

git diff | colordiff | ansi2html > gitdiff.html

Você também pode salvar a saída de qualquer comando que retorne ANSI colorido:

ls -lha --color | ansi2html > ls.html

Faça o Google falar por você

Ah, a internet! Você, usuário de Linux, comece pela preparação:

sudo apt-get install curl mpg123

Depois crie o script falador:

#!/bin/bash
l=pt-BR
if [ "$1" == "-l" ];then
  shift
  l=$1
  shift
fi
curl -A "Falador" translate\.google\.com/translate_tts -d "tl=$l&ie=UTF-8&q=$@" |mpg123 -;

Dê permissão de execução:

chmod +x falador

E divirta-se:

./falador "Onde está o futuro que nos prometeram?"
./falador -l en "Luke, I am your father."

Dúvida: URLs de categoria amigáveis

Um amigo me escreveu:

Ola Elcio,

vc tem algum tutorial de como reescrever a url para deixar mais amigável?

no momento eu tenho isso
http://www.meusite.com.br/index.php/category/produtos/produtos-especiais/

quero deixar assim:
http://www.meusite.com.br/produtos-especiais/

Muito bem, vamos lá. O primeiro passo é, se você não quer que as categorias apareçam uma dentro da outra, não usá-las de forma hierárquica no cadastro. Edite a categoria “produtos-especiais” e faça com que ela não seja mais filha de “produtos”. Isso deve deixar a URL dela assim:

http://www.meusite.com.br/index.php/category/produtos-especiais/

O passo seguinte é ir em “Configurações -> Links Permanentes” e configurar corretamente a estrutura de links permanentes, para retirar o “index.php” da URL. Escolha o formato que mais lhe agradar lá. Você vai precisar:

  1. Estar rodando Apache. Essa dica não vai funcionar em outro servidor web, a não ser que você acrescente uma boa dose de hacking.
  2. Ter o mod_rewrite habilitado no seu Apache.
  3. Que o PHP tenha permissão de escrita no arquivo .htaccess.

Tendo feito isso, a URL vai ficar:

http://www.meusite.com.br/category/produtos-especiais/

Por fim, você pode usar esse plugin: Top Level Categories. Ele consegue retirar aquele /category/ da URL, deixando o formato final da URL do jeito que você quer.

Boa sorte!

 

Mini-curso dominando o terminal do linux

É hoje à noite

DURAÇÃO: 2h

Aprenda os fundamentos do terminal do Linux, domine os comandos mais comuns mas, além disso, aprenda um novo jeito de pensar. Automatize tarefas e coloque seu computador para trabalhar por você.

Por que estamos oferecendo esse curso?

Durante os últimos anos eu tenho ensinado milhares de técnicos, programadores e webdesigners a ser mais produtivos. Treinei equipes inteiras de empresas como iG, Terra, Yahoo!, Locaweb, Magazine Luíza e Editora Abril. Além disso, tenho sido chamado para palestrar em grandes eventos técnicos em todas as regiões do Brasil.

Mas sinto que o Brasil (e provavelmente o mundo) tem uma carência enorme de conhecimento em computação. E essa carência não poderá ser preenchida apenas ensinando mais a quem já é especialista no assunto. Por isso, fiquei muito feliz quando o Maudy, do Ubuntu Dicas, me convidou para ensinar os segredos do terminal do Linux a iniciantes. E o resultado disso é esse curso que você poderá assistir hoje, quinta-feira, dia 30, às 20h.

Temos sentido, tanto na comunidade Ubuntu Dicas quanto no mercado em geral, um grande interesse dos usuários iniciantes em aprender os segredos do terminal do Linux. É uma ferramenta fantástica de automatização de tarefas, capaz de fazer seu computador trabalhar por você. E também é a porta de entrada para uma série de novos conhecimentos e, inclusive, para um novo jeito de pensar.

Por que você deve dominar o terminal?

Eu comecei minha carreira como programador Windows. Como todo usuário experiente de Windows, eu dominava uma porção de truques avançados do próprio Windows e de seus programas. Foi nessa época que comecei a estudar Linux. Um dia meu chefe na época apareceu com uma tarefa desafiadora para mim. Todos os dias chegava, no mesmo horário, um CD com imagens vindas das filiais. Sim, em CD, naquela época fazer esse tipo de coisa pela Internet ainda era muito lento. E essas imagens deviam ser preparadas para publicação no site. Não era uma tarefa complexa, precisava basicamente redimensionar as imagens e copiá-las para a pasta certa através de um programa de FTP.

Eu resolvi o problema usando um recurso do Photoshop para processamento em lote, chamado “batch” na versão em inglês. Criei uma action no Photoshop para ser executada com o recurso de batch e, todos os dias, quando o CD chegava, eu copiava o conteúdo para uma determinada pasta, abria o Photoshop, executava o processamento em lote e aguardava o Photoshop terminar. Ao final, abria um programa de FTP e copiava os arquivos para o servidor do site.

Era uma tarefa enfadonha, repetitiva e aquilo começou a me deixar desanimado. Eu passava as tardes me sentindo mal, antecipando o momento em que eu teria que parar meu trabalho para copiar as imagens e ficar olhando o Photoshop trabalhar.

Felizmente, foi nessa época que eu comecei a aprender Linux. E com um bocado de estudo e um pouco de esforço cheguei a uma sequência de comandos que resolvia o problema:

cd imagens_filiais/entrada
for i in *.jpg;do  
  convert -thumbnail 300x300 $i $i
done
mv entrada `date +%Y%m%d`
cd ..
rsync -razv . servidor:imagens_filiais/

Uma simples sequência de sete linhas. Claro, você pode achar esses comandos assustadores, e pensar que dá mais trabalho digitar isso tudo do que simplesmente copiar a pasta, renomear, executar a action no Photoshop, abrir o programa de FTP e copiar os arquivos. Acontece que só foi necessário digitar esses comandos uma vez. Criei um arquivo com essa sequência de comandos e, cada vez que o CD de imagens chegava, eu copiava as imagens para a pasta entrada e executava um único comando. Consegue imaginar meu alívio e alegria ao conseguir me livrar dessa tarefa repetitiva, colocando o computador para trabalhar para mim?

Não se assuste com os comandos. Eu também tinha medo deles e não entendia nada quando os vi pela primeira vez. Mas eles são simples, acredite. Muito simples. Se você entender os conceitos fundamentais, vai entender esses comandos e qualquer outro com que tiver que lidar, com facilidade. E é fácil entender, você vai ver.

Você vai gastar duas horas estudando hoje e com certeza, vai economizar muito mais do que duas horas na primeira tarefa repetitiva que chegar às suas mãos. E vai parar de ter medo do terminal.

Por que você deveria se inscrever para esse curso agora?

Por que o curso, com interação ao vivo, vai estar disponível apenas hoje, dia 30/01. Além disso quem se inscrever até lá vai receber também a apostila do treinamento e um bônus especial, preparado com carinho para quem quer avançar na automatização de tarefas. Esta é então uma chance única, uma oferta que não estará disponível depois de quinta-feira. Depois disso você poderá adquirir apenas o acesso à gravação do curso. A apostila estará disponível exclusivamente para quem adquirir o acesso até às 20h.

Nós temos tanta certeza que você vai gostar do curso que, para que você tenha certeza ao se inscrever, oferecemos a exclusiva garantia completa: se você assistir o treinamento ao vivo e, por qualquer motivo, não estiver satisfeito com o que aprendeu, você pode simplesmente escrever para a gente e obter seu dinheiro de volta. Todo o seu dinheiro de volta, sem letras miúdas, sem perguntas, basta mandar um e-mail.

Para quem é esse curso?

Se seu trabalho envolve lidar com arquivos em um computador e realizar tarefas que podem ser automatizadas, esse curso é para você. Se você apenas navega na internet, escreve textos e planilhas, por favor, não se inscreva. Mas se você precisa lidar com tarefas como capturar dados da internet, lidar com arquivos em grandes volumes, tratar texto, imagens, vídeos ou áudio, administrar servidores ou qualquer outra tarefa repetitiva que possa ser automatizada, você PRECISA fazer esse curso.
Eu tenho certeza que, se você trabalha assim com um computador, vai recuperar o tempo investido em estudar em no máximo uma semana.

Inscreva-se

Elcio Ferreira é sócio-diretor da Visie Padrões Web, empresa especializada no desenvolvimento de sites, sistemas web e aplicativos móveis. Já treinou e auxiliou equipes de desenvolvimento de centenas de equipes em empresas como Globo.com, Editora Abril, iG e Terra. Trabalhando com web há mais de quinze anos, Elcio é nome de referência no Brasil em padrões web e tecnologias abertas para a internet, sendo membro do grupo de trabalho de acessibilidade do W3C. Durante o ano de 2011, ministrou os treinamentos oficiais de HTML5 na sede do W3C Brasil.

Fazendo o comando rm enviar arquivos para a Lixeira

Talvez você tenha um pouco de medo de usar o comando rm, porque ele exclui definitivamente os arquivos. Não há “lixeira”, e todos os métodos disponíveis para desfazer a deleção, como o ext2undel, não passam de boas tentativas com uma razoável chance de insucesso.

Você sabia que pode enviar um arquivo para a lixeira a partir do terminal, ao invés de apagá-lo? Para isso, você precisa instalar o pacote trash-cli. No Ubuntu, faça:

sudo apt-get install trash-cli

Em seguida você pode usar, no lugar do comando rm, o comando trash:

trash arquivo_a_apagar.txt

Você também pode manipular a lixeira com os comandos trash-list, restore-trash e trash-empty.

Substituindo o comando rm

E se quiser você evitar usar o comando rm por engano, insira no final de seu .bashrc:

alias rm=trash

Assim, cada vez que você digitar o comando rm, será na verdade executado o comando trash. E se você deliberadamente quiser excluir um arquivo, sempre poderá chamar o comando rm digitando uma contrabarra, assim:

\rm arquivo_a_apagar.txt

Mas você tem certeza que vai substituir o comando rm?

Na página do trash-cli o autor trata dessa questão. Ele diz que, embora você possa substituir o comando  rm pelo trash, você não deveria, porque os argumentos dos dois comandos são diferentes. Por exemplo, o comando rm exige o argumento -R para remover diretórios, o trash não. Então ele sugere que não o faça.

Mas, se você tem medo de apagar arquivos por engano, ele sugere uma outra abordagem. Crie um alias para o comando rm em seu .bashrc assim:

alias rm='echo "Este não é o comando que você quer executar."; false'

E pronto, você não vai mais executar o comando rm por engano, mas, do mesmo modo que no primeiro exemplo, sempre poderá executá-lo deliberadamente, começando com uma contrabarra.

PS1: o trash-cli é feito em Python, e muito bem escrito. Estudar o código dele pode ser muito instrutivo.

PS2: estou prestes a lançar, junto com o Ubuntu Dicas, uma novidade para quem quer aprender a usar o terminal. Se você é iniciante no terminal do Linux e gostaria de aprender os segredos para dominar o terminal, você precisa assinar a lista do Ubuntu Dicas.

Porque você deveria aprender várias linguagens de programação

tpp_xlargecover
O programador pragmático não está preso a nenhuma tecnologia.

Há um tempo eu li “The Pragmatic Programmer“, uma espécie de livro de auto-ajuda para programadores. Não é um livro técnico, não vai te ensinar técnicas ou tecnologias, mas fala de um jeito de pensar e traz uma coleção de conselhos daquele tipo que parece óbvio mas ninguém nunca faz.

Um desses conselhos era aprender novas linguagens de programação. Os autores recomendam que você se torne proficiente em uma nova linguagem de programação por ano. O que, eu sei, é muito difícil. Eu não tenho conseguido aprender uma nova linguagem por ano. Mas isso não invalida o conselho de que você deve aprender novas linguagens de programação.

Por que aprender linguagens de programação novas?

Cada linguagem de programação traz consigo um jeito de pensar, um conjunto de soluções e uma comunidade com cultura diferente. E isso enriquece você. O bom programador tem uma visão ampla e não está “preso” a uma única tecnologia.

Por exemplo, digamos que você esteja desenvolvendo um sistema em PHP e precise, de tempos em tempos, fazer parsing de feeds RSS cuja URL foi cadastrada pelos usuários. Digamos que você queira fazer o parsing em segundo plano, a cada meia hora. Claro, você pode usar SimplePie, mas ele não é tão “Simple” assim. Dê uma olhada na documentação. SimplePie é muito poderoso, tem uma porção de recursos, mas vai dar algum trabalho para instalar direito, montar seu script, testar e automatizar.

E se você procurar soluções em outras linguagens de programação? Quanto trabalho vai ter? Vamos ver o que Python tem para nós, usando o excelente módulo feedparser. O módulo feedparser está disponível no gerenciador de pacotes do Ubuntu, e também para instalação via PIP.

import feedparser
print feedparser.parse('https://elcio.com.br/feed')

Mais uma meia dúzia de linhas para ler as URLs e salvar os resultados no banco de dados e pronto, temos um arquivo simples com excelente performance para ser colocado no cron. Bom, falando em performance, esse é o típico processamento que vai rodar muito mais rápido se feito em paralelo. Processamento em paralelo com PHP é um parto, certo? Com Python você pode usar o módulo multiprocessing e fazer isso quase que em uma linha só.

Além de ferramentas, linguagens de programação carregam jeitos de pensar

Uma vez que você já tenha resolvido um problema em uma linguagem de programação, você consegue resolver o mesmo problema em qualquer outra, certo? Bom, quando você aprende uma linguagem nova, você acaba tendo que ler um bocado de código de outras pessoas. E isso te ensina novas soluções para os seus velhos problemas.

Isso é diferente de se aprofundar no estudo de sua linguagem atual. O aprofundamento vai fazer você ler mais códigos das mesmas pessoas, da mesma comunidade, da mesma cultura. Aprender uma linguagem nova faz você ler códigos de gente nova, com outra cultura. Na prática, aprender Python vai fazer você melhor programador PHP, aprender Smalltalk vai fazer você melhor programador Java, etc.

Porque Python

De todas as linguagens de programação que você poderia escolher para começar a aprender algo novo hoje, eu recomendo que, se você ainda não sabe Python, comece por ela. Python roda no Google App Engine, no AWS Elastic Beanstalk e é a linguagem de programação por trás da maioria das ferramentas de administração do Ubuntu. Se você quer construir pequenos scripts para automatizar tarefas em seu servidor, ou quer construir grandes aplicações web para rodar em Cloud, ou se quer criar ferramentas de processamento paralelo massivo, ou interfaces gráficas multiplataforma, Python vai servir.

E é, ao mesmo tempo, uma linguagem que possui recurso fantásticos e vai te ensinar coisas incríveis, e uma das linguagens mais fáceis de aprender que eu conheço.

Que tal começar agora? Leia o excelente “Dive Into Python“, faça os exercícios, depois tente desenvolver alguma coisa na linguagem. E veja se você não vai se tornar mais eficiente em sua linguagem atual.

“Jabá”: Python é a linguagem que escolhemos para a aula de integração multi-linguagem do DevOps Heroes, treinamento da Visie que acontece a partir do dia 27 em São Paulo. Quem estiver lá vai ver isso tudo funcionando na prática. As vagas estão se esgotando.

Pare de usar FTP

Há mais de dez anos que meus processos de deploy, isto é, colocar um site ou sistema em produção, não usam FTP. Qualquer bom provedor, nacional ou internacional, oferece ferramentas muito mais eficientes para o deploy de sites e sistemas. E isso inclui desde pequenos sites em WordPress ou HTML estático até portais com milhares de acesso por hora e grandes sistemas rodando em estruturas de cloud computing elástico.

Por que você não deveria usar FTP

FTP é um protocolo muito simples de troca de arquivos, que pode ser útil para uma porção de coisas. Mas não possui os recursos necessários para o deploy e controle eficiente de aplicações web. Entre os problemas com o protocolo FTP, podemos citar:

  1. Falta de integração com controle de versão: você está fazendo uma manutenção num site, cujo diretório tem 5MB de dados. Você alterou não mais que uma dúzia de arquivos, em pastas diferentes. Arquivos texto cujos tamanhos, somados, não passam de 200KB. Como você faz o deploy por FTP? Ou sobe o site todo, “por via das dúvidas”, ou precisa pinçar os arquivos que precisa subir, um a um, certo? Algumas ferramentas de transferência, como o Filezilla, conseguem “sincronizar” as pastas, mas eles fazem isso varrendo as pastas uma por uma e comparando as datas e tamanhos dos arquivos. Leva um tempão e, se algum outro programador alterou os arquivos antes de você isso certamente vai dar problemas. O que nos leva a um segundo ponto:
  2. Falta de recursos de “auditoria” e controle de deploys: não há como obter um log ou lista de quem fez deploy, quando e o que foi feito. Um problema recorrente em ambientes em que uma equipe trabalha com FTP é a sobrescrita de alterações já publicadas. Na pior das hipóteses, gerando perda de trabalho. Mas mesmo que a equipe tenha um ambiente interno de controle de versões e a sobrescrita no FTP seja fácil de resolver, pense na dor de cabeça de ter que explicar para o cliente que o defeito que foi corrigido ontem voltou ao ar hoje, mas já estamos resolvendo.
  3. Falta de automatização: deploy por FTP é feito à mão. Um homo sapiens navega nas pastas de seu computador e do servidor e arrasta o que deve ser atualizado de um lado para outro. Num processo chato e delicado. Se ele arrasta as coisas para a pasta errada, pode ser muito difícil consertar o problema. Pode ser difícil até entender o problema. E se você coloca um homo sapiens para repetir uma mesma tarefa vinte ou trinta vezes, ele certamente vai errar alguma.
  4. Falta de recursos para rollback automatizado: você subiu a alteração. Em seguida abriu o site e viu um “erro de conexão ao banco de dados”. Percebe então que subiu a versão errada, ou no lugar errado. Como voltar atrás? Voltar atrás com FTP é um processo ainda mais manual e trabalhoso do que subir o site. Já vi casos, e não foram poucos, em que foi preciso pedir ao provedor para restaurar o backup diário. E esperar por isso, claro.

O que você deveria usar então?

SSH e Git. Há uma série de ferramentas para deploy automático, como o Capistrano ou o Jenkins. Esqueça isso tudo no começo. Aprenda SSH e Git, e construa seu processo de deploy com isso. Você vai ganhar:

  1. Deploy realmente automático. Com um único comando.
  2. Integração real com o controle de versão. Isso significa que sempre será possível rastrear cada alteração. Também significa rollback automático, o que é maravilhoso.
  3. Controle simplificado de múltiplos ambientes. Precisa fazer deploy em um ambiente de homologação, para mostrar as novidades ao cliente? Um comando. Ele aprovou as novidades, e agora é hora de fazer deploy em produção da versão que foi homologada ontem? Um comando.
  4. Preparação para o futuro. O site cresceu e você precisa agora migrar para um serviço como o AWS Elastic Beanstalk, que oferece escalabilidade “elástica” sob demanda dentro da estrutura de serviços da Amazon. O processo vai ser praticamente indolor. O cliente precisa agora de deploys com zero de indisponibilidade, e você resolveu usar a estratégia Blue Green. Já tem tudo o que precisa.

Por isso, não se conforme em usar FTP. Se precisa estudar SSH e Git, estude, vai valer a pena. Se já sabe, está esperando o quê?

“Jabá”: uma boa maneira de aprender como mudar seus processos de deploy, e muito mais, é o treinamento DevOps Heroes da Visie, que acontece daqui a duas semanas.

 

SQL Executioner

Olha que útil: SQL Executioner, um plugin WordPress que te dá uma tela no painel para a execução de SQL, substituindo para muita coisa o phpMyAdmin ou ferramentas semelhantes:

wordpress-sql-executioner-screenshot

Acabou de salvar um cliente da Visie que hospeda o site num provedor que não nos dá facilidades como acesso SSH ou um bom painel de controle.

Claro, use com cuidado, e desinstale depois de usar.

Pequena dica de Python: módulo webbrowser

O módulo webbrowser permite abrir uma URL no navegador do usuário. Só isso, simples assim. Por exemplo:

import webbrowser
webbrowser.open("http://visie.com.br")

E o site da Visie será aberto no navegador do usuário. Muito útil se você está fazendo um programa para desktop ou mesmo um script para o terminal. No caso de scripts para terminal, se o usuário estiver rodando o script sob uma interface gráfica o site será aberto no navegador padrão dele, já se estiver rodando via ssh ou num outro terminal sem interface gráfica, será usado um navegador de CLI (como o Lynx) se estiver disponível.

API gratuita de consulta de CEP

Nosso presente de natal para os desenvolvedores do Brasil: API gratuita de consulta de CEP.

A Visie é parceira de tecnologia da Aviso Brasil. Nós fornecemos tecnologia para o Correio Control, e como parte do negócio, precisamos ter a base de endereços sempre atualizada e sincronizada com o Diretório Nacional de Endereços.

Vimos que muita gente oferece aquele cômodo recurso de auto completar o endereço pelo CEP, mas usando bases de dados desatualizadas. Existem até uns serviços pagos que oferecem esses dados.

Por isso, decidimos oferecer um serviço gratuito de consulta de endereços pelo CEP, para que você possa usar em sua aplicação. Os resultados podem ser retornados usando o modelo JSONp, de modo que o próprio navegador do usuário requisite diretamente o endereço de nossos servidores.

Aproveite!

Em tempo: se você faz software que de alguma maneira envia e controla encomendas, você precisa conhecer o Correio Control. É um software de baixo custo para usuários corporativos dos Correios que oferece o controle de faixas de registro, geração de etiquetas e AR, monitoramento e rastreamento estendido, solicitação automatizada de pedidos de informação e indenização, relatórios de status e muito mais.

 

Pequena dica de Python: as classes são dinâmicas

Veja:

>>> class Class:
...   def um(self):
...     return 1
... 
>>> c=Class()
>>> c.um()
1
>>> def dois(self):
...   return 2
... 
>>> Class.dois=dois
>>> c.dois()
2
>>> Class.tres=lambda self:3
>>> c.tres()
3
>>> Class.um=lambda self:'Um modificado.'
>>> c.um()
'Um modificado.'

As classes em Python são completamente dinâmicas. Você pode acrescentar métodos quando quiser e isso se refletirá em todos os objetos criados com aquela classe (mais ou menos como o que você faz em Javascript com prototype.)