domingo, 29 de agosto de 2010

Manuais, mentiras e telefonemas

O manual que eu escrevi, onde estará? O usuário não o leu, com certeza. Eu tento dar a dica:

-Isso está na segunda página do manual.

Mas a sutileza perde-se. Isso eu até suporto, mas não consigo entender por que o usuário mente para mim.

-Nunca fiz isso.

E o registro, brilhando na minha cara, indicando que fez. Ou ainda pior, diz que fez, mas nunca entrou no sistema.

Não se pode confiar no usuário. O primeiro passo de um atendimento é coletar todas as informações necessárias, porque nada do que ele diz é confiável. Nada mesmo. Ele pode dizer que usa IE, mas estar num Firefox. Pode dizer que usa XP, mas estar num Vista. Pode nem ser ele o usuário.

O usuário mente até no cadastro:

-Não recebi a senha.
-A senha foi para o email xyz@abc.com.
-Não uso esse email.
-Agora seria um bom momento para reativá-la, porque ainda não implementamos o subsistema de localização de emails secretos de usuários.

Está bem, não posso responder isso. Então, escrevo aqui. O usuário não tem senso de humor.

Atender por telefone é uma arte. Há um jogo muito sutil que precisa ser jogado. Tenho que fazer o usuário entender o que ele não quer entender (se quisesse, teria lido o manual). Quero que ele perceba que é um estorvo, mas não posso dizer diretamente. Minhas frases têm que continuar depois do ponto final. Lá no fim da frase mais polida, o usuário tem que perceber que paira no éter um "sua besta".

-De nada. Se quiseres trocar a senha outra vez, basta clicar no primeiro botão da primeira tela - aquele que diz "Trocar senha" - e seguir os passos que estão na terceira página do manual. É simples; são só três campos. Tenha uma boa semana.

Viste?

Todos os anos sai a triste estatística de quanto livros em média cada brasileiro lê. Eu adicionaria a estatística de quantos manuais o brasileiro não lê.

segunda-feira, 23 de agosto de 2010

Mais regressões lineares em SQL

Vasculhando o manual do Oracle, encontrei umas funções estatísticas e entre elas algumas funções para calcular regressões lineares. A função REGR_SLOPE() logo revelou-se a mais útil. Ela retorna a inclinação da reta que indica a tendência dos dados.

Para repetir o cálculo do artigo anterior, fiz o seguinte:

select min(idhm)+(2010-min(ano))*regr_slope(idhm, ano)
from indices_municipais
where municipio=130

Tenho a tendência de idhm sobre ano, então adiciono o menor valor de idhm ao produto da tendência pela diferença de anos e obtenho o resultado esperado para 2010 (a base tem dados de 1991 e 2000).

Depois, resolvi classificar os municípios pelo IDHM futuro:

select trunc(min(idhm)+(2010-min(ano))*regr_slope(idhm, ano),3), nome
from indices_municipais natural join municipio
group by nome
order by 1 desc

Essa consulta tem um join com a tabela de municpios, porque eu ainda não decorei todos os códigos. E adicionei um TRUNC(), porque resultados com 18 dígitos cansam os olhos.

A consulta é muito mais simples que a do primeiro artigo, mas será mais rápida? Reescrevi a consulta original para poder classificar todos os municípios.

select trunc(a+2010*b,3), nome from (
select (x2*y-xy*x)/(n*x2-x*x) a, (n*xy-x*y)/(n*x2-x*x) b, nome from (
select count(1) n, sum(ano) x, sum(ano*ano) x2,
sum(idhm) y, sum(idhm*idhm) y2, sum(ano*idhm) xy,
nome
from indices_municipais natural join municipio
group by nome
)
) order by 1 desc

Tabulei os tempos:
Consulta com REGR_SLOPEConsulta complicada
0,015s0,014s
0,015s0,014s
0,016s0,013s
0,014s0,017s
0,021s0,015s
0,013s0,014s
0,016s0,015s
0,023s0,015s
0,015s0,021s
0,015s0,014s

Então, a consulta complicada foi mais rápida em 8 das 10 execuções. Ambas produzem 467 linhas (o município campeão é Ibiaçá).

segunda-feira, 16 de agosto de 2010

Regressão linear em SQL

Uma das tarefas mais divertidas e inúteis para economistas amadores (como eu) passarem o tempo é procurar maneiras de prever o futuro. E uma das maneiras mais simples de se fazer isso é usando a regressão linear (finalmente uma entrada da Wikipédia cuja versão em português é melhor que a versão inglesa!).

O objetivo é simples: dada uma série, encontrar uma reta que descreva a tendência. Com essa reta, pode-se imaginar para que lado as medidas estão indo.

Decidi usar uma tabela de IDHs municipais para testar meu SQL. A tabela tem, entre outras colunas, ANO, IDHM (indíce de desenvolvimento municipal) e MUNICIPIO.

Conforme o artigo da Wikipédia, o objetivo é encontrar os termos a e b da equação y=a+bx. As equações para cada termo são trabalhosas, então decidi montar a consulta em 3 partes. Na primeira, calculo os pedaços das equações; na segunda calculo a e b; na última, prevejo o futuro.


select a+2010*b from (
select (x2*y-xy*x)/(n*x2-x*x) a, (n*xy-x*y)/(n*x2-x*x) b from (
select count(1) n, sum(ano) x, sum(ano*ano) x2,
sum(idhm) y, sum(idhm*idhm) y2, sum(ano*idhm) xy
from indices_municipais
where municipio=130
)
)

Eu tenho os dados de 1991 e 2001. Com essa pequena consulta, projeto a reta e descubro qual a tendência para 2010. Trocando o 2010 por 1991 e 2001 pude verificar que estava tudo certo; a consulta produziu os valores que já estavam na base. Como eu só tinha duas medidas, a reta tinha que passar exatamente por elas!

A consulta não é tão complicada e só o select mais de dentro muda, então resolvi escrever uma função parametrizada para poder repetir o experimento em outras tabelas com mais facilidade.


create or replace function regressao_linear (
valor number,
x varchar2,
y varchar2,
tabela varchar2,
restricao varchar2)
return number is
resultado number;
begin
execute immediate '
select a+'||valor||'*b from (
select (x2*y-xy*x)/(n*x2-x*x) a, (n*xy-x*y)/(n*x2-x*x) b from (
select count(1) n, sum('||x||') x, sum('||x||'*'||x||') x2,
sum('||y||') y, sum('||y||'*'||y||') y2, sum('||x||'*'||y||') xy
from '||tabela||'
where '||restricao||'
)
)
' into resultado;

return resultado;
end;


Os parâmetros x e y são os nomes das colunas; tabela não preciso explicar e restricao é tudo que vai na cláusula where. E valor é o x que se quer projetar além dos dados. A interpolação de strings no Oracle é mesmo pavorosa e essa multiplicação de x e y não ajuda. Mas agora posso usar a função e fazer de conta que é trivial; a sujeira foi toda para debaixo do tapete.

Para executar a consulta inicial usando a nova função, basta fazer o seguinte:

select regressao_linear(2010, 'ano', 'idhm',
'indices_municipais', 'municipio=130')
from dual


Esse município tem IDHs 0,746 e 0,822 para 1991 e 2001. O valor retornado pela função é 0,906. Quando sair o censo eu vou conferir e cobrar do prefeito se não estiver conforme o esperado.

quarta-feira, 11 de agosto de 2010

Truques com calculadoras

Um amigo de infância poucos dias lembrou de "quantas tardes jogando Elite nessa calculadora" passamos. A tal calculadora podia fazer, na melhor das hipóteses, uma adição de 8 bits em 2 ciclos (e em 6 na pior). Rodando a 2MHz, era possível, no máximo, 1 milhão de somas por segundo. Isto se o computador não tivesse mais nada para fazer.

Os computadores hoje estão nos gigahertz e agora os truques ficaram mais interessantes. Mesmo assim, o mecanismo básico é o mesmo: pegar um número, executar uma operação muito simples e guardar o resultado.

A primeira calculadora foi inventada por Pascal. O pai dele era coletor de impostos e o incumbiu de resolver uma papelada infindável. Para diminuir a carga e evitar que o tédio se prolongasse, ele inventou um aparelho mecânico que somava e subtraía. O primeiro processador foi inventado pela Intel para simplificar e baratear o projeto de uma calculadora e é, em essência, uma pequena calculadora programável.

Camadas e camadas de abstração mais tarde e temos comunicações, internet, som, vídeo e jogos rodando em cima de calculadoras. Calculadoras muito rápidas, mas calculadoras mesmo assim.

Por isso, não sei se o melhor nome para o curso seria Ciências da Computação. Nas outras ciências, as pessoas partem da observação da complexidade do mundo e tentam encontrar os princípios subjacentes. Na Computação, partimos de princípios básicos muito simples e rígidos e tentamos criar a maior complexidade possível. Acho que o curso deveria chamar-se Arte da Computação ou
Mágica com Números ou Truques com Calculadoras.

quinta-feira, 5 de agosto de 2010

IT nightmares

Um dos programas de TV mais divertidos dos últimos tempos é o Kitchen Nightmares, no qual o chef Gordon Ramsay visita restaurantes à beira do precipício e tenta retorná-los à lucratividade.

Invariavelmente, os problemas são causados pelo dono, pelo cozinheiro-chefe ou por ambos. Os temas mais comuns são a falta de higiene, a falta de coordenação entre os cozinheiros e pratos desnecessariamente complicados. Com freqüência, há um funcionário promissor sendo ofuscado pela teimosia dos líderes.

Eu sonho em ver um IT Nightmares! Um CIO experiente vai visitar CPDs e colocá-los no rumo. Haverá uma série de embates até o chefe convencer-se de que está complicando as coisas e impedindo sua talentosa equipe de brilhar.

O papel do cozinheiro-chefe teimoso e complicado vai ser preenchido pelo arquiteto multi-certificado e suas infinitas camadas, frameworks e arquivos de configuração.

O chef Ramsay insiste em criar pratos "simples e honestos" que, quase sempre, são mais baratos e, por isso, mais lucrativos. Pois, eu torço por soluções simples e honestas. Os sistemas não precisam resolver todos os problemas presentes e futuros; eles precisam resolver com eficiência os problemas de hoje. Quem sabe quais serão os problemas de amanhã?!

Na informática, já vi muitos finais desastrosos. Uma vez dentro de uma situação complicada, é difícil achar tempo e meios de resolvê-la com inteligência. Refletindo sobre projetos passados, pude ver claramente os erros, mas somente meses depois. Quem olha de fora, sem estresse e sem pressão, pode analisar melhor a situação.

Em alguns casos, teria sido ótimo ver o Gordon dar uns tabefes no chefe!