segunda-feira, março 30, 2009

case-insensitive e accent-insensitive no PostgreSQL

Gosto muito do PostgreSQL. Pessoalmente é um dos bancos que menos me causa o efeito "WTF", quando estou trabalhando com ele, com uma notável exceção... não tem nenhum parâmetro nem coisa parecida para poder fazer pesquisas case-insensitive e accent-insensitive. E isso é um grande "WTF" pra qualquer um que possua acentos na língua. Procurando uma solução, encontrei esses posts aqui: http://www.laudatio.com/wordpress/2008/11/05/postgresql-83-to_ascii-utf8/ http://www.mail-archive.com/pgsql-general@postgresql.org/msg112591.html http://www.postgresonline.com/journal/index.php?/archives/9-How-to-create-an-index-based-on-a-function.html Como meu banco é UTF-8, combinei elas em uma única solução:
CREATE OR REPLACE FUNCTION to_ascii(bytea, name)
RETURNS text STRICT AS 'to_ascii_encname' LANGUAGE internal;

CREATE OR REPLACE FUNCTION norm(a_string text)
RETURNS text AS $$
  BEGIN
    RETURN lower(to_ascii(convert_to(a_string, 'latin1'), 'latin1'));
  END
$$ LANGUAGE plpgsql
E como quando fazemos isso sempre precisamos de índice, em tese podemos criar os índices assim:
CREATE INDEX norm_tabela_campo_idx
  ON tabela
  USING btree norm(campo);

domingo, março 29, 2009

Sugestões para programar

Aqui tem uma lista de sugestões que eu uso quando estou programando. Faço questão de colocar elas para mim mesmo de uma maneira um tanto... "enfática", digamos assim. Descobri que quando fico indignado eu lembro melhor das coisas. Por isso, perdoe minhas "ênfases". Sugestão 1 Nomes significativos: pelo amor de JC e sua gangue, pare um pouco e coloque um nome decente nas coisas que faz (variáveis, métodos e classes). Sempre vale a pena colocar um bom nome, mesmo que isso custe vários minutos pensando. A razão disso? Crie um programa com nomes bem ruins e pouco significativos e depois tente dar manutenção nele, você vai lembrar do que eu disse agora. Sugestão 2 Indireção: use e abuse. Crie métodos a rodo, crie dezenas de classes pequenas, jogue o que puder para uma classe pai, abstraia ao máximo. O efeito disso é criar naturalmente Template Methods e DSLs, sem falar em diminuir a duplicação. Aliás, já repararam como template methods se parecem com micro DSLs? Sugestão 3 Valide o que vai usar para o método que está escrevendo. Se vai usar parâmetros, alguns "ifs" para validar que não está vindo lixo sempre são bemvindos. Se vai usar atributos, teste para ver se estão do jeito que você esperava encontrá-los. Se estiver com muita preguiça, mas muita mesmo, valide ao menos os nulos. Ah... e antes que eu me esqueça... NÃO, isso NÃO vai fazer seu programa ficar lento. Sugestão 4 Estado: se você está programando orientado a objeto. USE A PORRA DO ESTADO! Comece a computação em um método, termine em outro, jogue todas as variáveis possíveis para atributos. Se ficar com atributos de computações diferentes em uma única classe, use a dica 2. Se essa classe for compartilhada por múltiplas threads, não use essa sugestão. Sugestão 5 Pais? Sim, use muito classes pais, evite delegação. Ela dá um trabalho danado (principalmente se sua linguagem do coração não tiver proxies dinâmicos) e o benefício é mais teórico que prático. Ahhmm... mas todo mundo diz que é melhor usar delegação do que herança. Poisé, e eu estou dizendo o contrário. Você está programando orientado a objeto ou não, afinal? Delegação é boa sim, onde fizer sentido, como por exemplo, em wrappers. Sugestão 6 Não use cegamente sugestões e boas práticas. Sempre, sempre, sempre (eu falei SEMPRE, caralho!) conheça os prós e principalmente os contras de toda técnica que você vai usar. Boa prática só é boa se você sabe quando não deve usá-la. Isso vale especialmente para as sugestões que acabei de listar. ;) Que sugestões você colocaria na lista? Ou modificaria?

quarta-feira, março 25, 2009

Flamings e Einstein

É muito comum ver por aí nos fóruns de tecnologias alguns tópicos que são "flamings". Fiquei imaginando o que causam esses flames e como é difícil distinguir idéias completamente furadas das idéias que realmente tem algo de bom. Acho que consegui chegar em uma pequena fórmula que deve resolver parte do problema, ao menos para mim. O raciocínio veio quando estava lembrando do que fez Albert Einstein. O cara foi tão ponto fora da curva que criou sua teoria da relatividade de cabeça, não por que ele quis assim, mas porque simplesmente não havia (e acho que ainda não há) experimentos possíveis para provar que a idéia é verdadeira ou não. Aliás, no meio acadêmico, isso é bastante comum. Como ele fez isso (e aliás, como os cientistas fazem isso, normalmente)? Ele partiu de um "pressuposto" e começou a raciocinar em cima dele. No caso, o pressuposto é de que a luz possui velocidade constante. Matutando e pensando, ele chegou a conclusões incríveis... desde que a velocidade da luz seja constante. O que tem isso de importante? Bom, se provarem que realmente é uma constante (se já não provaram), é grande a chance de que toda a teoria esteja correta. Se provarem que não é constante, então toda a teoria vai pro brejo. Aí nossa opinião sobre a teoria da relatividade se resume a analisar 2 coisas: 1 - Se concordamos com o pressuposto; 2 - Se achamos que o raciocínio do cara não tem falhas lógicas. Em software temos um problema similar ao que tinha o tio Einstein. Temos grandes dificuldades de provar nossas idéias e teorias sobre software. Acho que daí nascem os flamings e todas essas discussões que ficam parecendo mais discussões religiosas do que discussões sobre uma ciência exata. Como em software não temos quase limitação nenhuma, quase qualquer idéia dá certo com o esforço suficiente aplicado, mesmo as idéias muito idiotas. Essas idéias, idiotas ou não, também são criadas a partir de pressupostos. Não sei se todos, mas todos os softwares, apis, frameworks e posts de blog que consigo lembrar são baseados em alguns pressupostos. O problema é que nunca deixamos claros quais pressupostos são esses. Então nossas idéias são analisadas a partir dos pressupostos que cada pessoa escolhe. Depende do que ele escolhe como pressuposto, sua opinião vai ser favorável ou não a nossa idéia. A "pequena fórmula" para resolver o problema dos flamings, e também o problema para se detectar uma idéia boa de uma idéia idiota é simplesmente deixar bem claro os pressupostos que se tomou para a idéia. Não, não foi dessa vez que descobri a América ou inventei algo novo e inédito, pelo visto. Mas para mim é um coisa que vem dando certo quando tenho que analisar algumas coisas, como Frameworks e posts de blogs. :) Querem ver um pequeno exercício? Você pode concordar ou discordar de tudo isso que eu disse, mas se ela é uma boa idéia ou não é mais fácil analisar se eu colocar os pressupostos aqui. Aí vão eles: - É comum flaming nos fóruns de tecnologia; - O que causa o flaming é a dificuldade de se separar idéias boas das ruins; - É difícil separar as idéias porque é difícil prová-las; - É difícil prová-las porque quase qualquer idéia sobre software funciona se aplicarmos esforço suficiente; - As pessoas tendem a analisar as idéias pelos seus próprios pressupostos; - Podemos separar as idéias se conhecermos claramente os pressupostos em que foram baseadas; Parece uma linha de raciocínio, mas na verdade não é. Cada linha da lista acima pode ser contestada facilmente e não pode ser provada, são pressupostos. Se você concordar com todos eles, provavelmente vai concordar com a minha teoria como um todo. Se deixar de concordar com qualquer uma delas, provavelmente vai achar minha teoria um lixo. Se todos eles puderem ser provados com sucesso, então a teoria é verdadeira. Se qualquer um deles for provado em contrário, então ela é furada. Com tantos pressupostos (são ao menos seis, se não esqueci nada), dá pra ver que essa minha idéia é bem frágil. Bom, agora você conhece a teoria e conhece claramente no que me baseei para montá-la. Espero que fique fácil analisar se ela tem fundamento ou não para você e o porquê disso. E aí? Tem fundamento?

sexta-feira, fevereiro 06, 2009

Da série "notas mentais"

Não aconteceu comigo, mas com um amigo...

Quem efetivamente resolve o problema e faz acontecer não aparece em jornal. Quem aparece é o chefe, que é incapaz de gerar soluções e que mentiu o tempo todo para o cliente.

C'est la vie.

sexta-feira, janeiro 30, 2009

Fadado a ser estúpido

Tentei escrever um pequeno mecanismo para transações explícitas em Java. Na primeira versão, ou o programador faz "try catch" direitinho (e repetitivamente), ou a coisa não funciona.

Implementei depois usando uma classe anônima. Fica parecido com closure, e resolve esse problema, mas ficou desagradável e com aquele gosto de "gambiarra" na boca.

A solução mais estúpida pareceu melhor...

Tentei também um mecanismo simples de reflexão no banco para poder gravar tabelas simples sem precisar fazer "dança da chuva" toda hora. Consegui, mas ainda ficou um negócio meio repetitivo e com o mesmo gosto de "gambiarra".

A solução mais idiota, criar beans pra tudo, tinha uma aparência melhor.

Moral da história: Ou sou realmente estúpido e minhas soluções são idiotas, ou sou esperto e a linguagem me faz parecer um estúpido. Ou seja, de qualquer maneira, sou estúpido.

Veja, eu adoro Java, é uma linguagem excelente. Mas ela não presta para fazer coisas dinâmicas do mesmo jeito que Ruby não presta pra fazer concorrência.

quarta-feira, janeiro 28, 2009

Generalizando como o diabo...

Flash 1:
Estava aprendendo "clojure" (http://clojure.org) esses dias e o autor (Rich Hickey) fala sobre os problemas de variáveis mutáveis para multi-threading. Aí advoga sobre linguagens funcionais são melhores para multi-thread.

Flash 2:
Hoje, esbarrei com um código JSP e para tentar fazer uma besteirinha (colocar um valor padrão se um atributo não era fornecido) precisei de 5 linhas de "JSTL". Fiquei indignado e meti um operador ternário dentro da Expression Language.

Flash 3:
Estamos em um sistema que quase não possui regras de negócio. 90% são cadastros com simples validações (tem uma parte de GIS, mas essa é outra história). E temos dezenas de cadastros. Ao invés de criar um objeto "bean burro" para cada entidade e usar o hibernate como manda a cartilha, fizemos um objeto parecido com um Map que resolve pra todo mundo. O resultado é conseguimos fazer um CRUD simples com regras de validação em 4 minutos (mais ou menos), e esse tempo ainda vai cair...

O que esses 3 flashes me ensinam? Generalizações são extremamente perigosas. Se você não tem discernimento suficiente para saber quando quebrar um regra, tome cuidado ao segui-la. Você não sabe por que a está seguindo...

Adição: sempre existem regras que não sabemos quando quebrar.

Corolário: só respeitar a opinião de alguém se ele souber me dar um contra-exemplo.

segunda-feira, junho 02, 2008

Princípios de OO segundo Alan Knight (e Dilbert) (parte 2)

Essa é a segunda parte desse post aqui.

Evite responsabilidades

Objetos devem ser preguiçosos ao extremo. Evite responsabilidades, se tiver que aceitá-las, mantenha-as vagas e delegue o trabalho de verdade para outros. O efeito final é que cada método vai fazer um fragmento muito pequeno de trabalho. Segundo o próprio Alan Kay, em um sistema orientado a objetos bem feito, você não consegue saber onde o trabalho está sendo realmente feito, quando você vê, já foi. Apesar de um fluxo em específico ser mais difícil de seguir (experimenta debugar em Smalltalk q vc vai entender do que eu estou falando), os métodos todos são tão simples que você consegue entendê-los em segundos. A segunda parte da proposição: "mantenha a responsabilidade vaga", significa que você deve desconfiar de especificações do tipo "o objeto deve persistir em banco todas as entradas". Isso porque ele contém detalhes de implementação, na verdade, o que interessa para os outros objetos não é como a informação vai ser guardada, mas como ela vai ser recuperada. Uma especificação melhor seria "o objeto deve saber informar as entradas feitas". Se isso será feito em banco de dados, em arquivo texto, distribuído na rede ou por sinal de fumaça, não interessa, o que nos dá muito mais flexibilidade. No final a idéia é aumentar o reuso. Evitando responsabilidades e delegando o trabalho, na verdade estou procurando reutilizar o que outras classes já fazem. Mantendo as responsabilidades vagas estou escondendo como faço as coisas (encapsulamento).