quarta-feira, dezembro 23, 2009
Desenvolvimento de software é uma coisa irônica
Engraçado como o desenvolvimento de software tem uma tend?ncia a ser irônico e tirar um sarro dos seus esforços:
1 - Quanto mais flexível você tenta fazer o software, menos flexível ele fica.
2 - Quanto mais rápido você tenta contruí-lo, mas demora terminá-lo.
3 - Quanto mais simples você o faz, mais robusto ele fica.
4 - Mas quanto mais você tenta fazê-lo robusto e escalável, menos ele fica.
5 - Se você faz direito, demora menos tempo.
6 - Se você faz nas coxas pra ganhar tempo, você perde tempo.
7 - E quanto mais você estuda, mais aprende que nâo sabe o suficiente.
8 - Mas se não estuda, tem absoluta certeza que sabe tudo o que precisa.
Tem horas que acho que o negócio é pensar de ponta-cabeça =/
quinta-feira, outubro 29, 2009
O mito da "recuperação do atraso"
Não tem dessa de "recuperar o atraso" em um projeto de software...
Boa referência aqui também: What Is the Cost of a Requirement Error?
segunda-feira, outubro 26, 2009
Técnicas, não ferramentas
Acho que nós da área de desenvolvimento temos um grande problema onde focamos nossos estudos. Normalmente estudamos demais a coisa errada, e as coisas certas não estudamos o suficiente.
Também é difícil dizer qual é o foco "correto". Cada um vai ter uma opinião diferente e não há estudos pra basear nenhum dos nossos "achismos". (Hmmm... já reparou como quase todo desenvolvimento de software comercial/corporativo tem esse problema?)
Pessoalmente, depois de ficar perdendo muito tempo estudando frameworks, descobri que o que interessa são técnicas, não ferramentas. Tenho hoje a nítida percepção que a ferramenta vêm naturalmente se você tem a técnica.
O que seriam as técnicas?
- Idiomas das linguagens
- Patterns dos mais variados
- Modelos de arquitetura
- TDD/BDD
- Paradigmas de programação (OO / Funcional / Imperativo / Declarativo)
- DSLs ou Interfaces Fluentes
Ou seja, independente da linguagem, os conceitos serão úteis.
E as ferramentas?
- Qualquer linguagem (Ruby, Java, Haskell...)
- Qualquer framework (Rails, Spring...)
- Qualquer biblioteca ou API (REXML, JDOM...)
Hoje, eu foco o máximo na técnica e só estudo a ferramenta até o nível suficiente para o problema atual. O efeito que isso causa é bastante interessante, normalmente consigo responder se algo existe na ferramenta sem conhecê-la, porque, conceitualmente, a coisa deveria estar lá. :)
Estou certo? Sei lá. Pra mim funciona melhor do que antes, quando eu me matava pra ficar aprendendo ferramenta e a cada 3 anos vinha uma nova e todo o conhecimento era perdido. Agora o conhecimento acumula, e o que tenho que renovar é menor.
quinta-feira, outubro 01, 2009
Metaphone em português para Java
Custou um pouquinho para achar um banco com nomes para testar e acertar as rebarbas, mas finalmente está aí: codificação fonética em Metaphone para português (http://github.com/ruliana/MTFN) :)
Se você quiser saber do que estou falando:
http://en.wikipedia.org/wiki/Metaphone e http://www2.varzeapaulista.sp.gov.br/metaphone.
Muito simples de usar, muito simples de customizar e vem com um banco de dados de teste, cortesia do Marco "Kiko" Carnut (http://www.postcogito.org/) e seu trabalho sobre descobrir o sexo da pessoa somente pelo nome (http://www.postcogito.org/Kiko/PlanilhaMascFemPtBr.html, trabalho muito legal, vale a pena conferir!)
Só que, com a massa de testes e estudando um pouco melhor a fonética da língua portuguesa, deu pra perceber que a coisa pode ser melhorada. Como por exemplo, considerar "P" e "B" como equivalentes, assim como "M" e "N". Desconsiderar algumas consoantes nos finais dos nomes e assim por diante.
Optei primeiro por liberar um algoritmo bastante similar àquele que me baseei, que já é muito bom! Agora começo a refiná-lo com meus próprios "achismos". Vamos ver no que vai dar. ;)
domingo, setembro 27, 2009
Functors? Hmmm... nhammy
Ando estudando Haskell de farra ultimamente, confesso que ainda não entendi ainda qual é o barato dos monads, mas funções como cidadãos de primeira classe, combinação de funções e currying são conceitos bem legais.
Dei uma checada no que havia para Java (é... Java) e esbarrei com alguns projetos interessantes, mas todos muito trabalhosos para minha preguiça. Então, como todo bom nerd, se você não acha uma ferramenta que goste, você cria uma.
Então, com um pouco de Java Voodoo do Brabo, fiz o "Yo da Funkta!" pra satisfazer meu ego e minha preguiça. Acho que ficou bonzinho...
Agora... estou muito interessado em... Metaphone...
segunda-feira, junho 15, 2009
Sims ensina
Sou um jogador casual de "Sims", jogando ele acabei aprendendo algumas dicas boa para o dia a dia:
- Compre uma boa cama (com um excelente colchão), vale a pena!
- Não dá tempo de fazer tudo o que se quer.
- Gastar todo seu tempo livre com diversão não te leva a lugar nenhum, mas é preciso gastar algum tempo só com diversão.
- É possível aprender se divertindo, mas nem sempre dá pra se divertir aprendendo.
- Investir na carreira é ótimo, e tem que ser feito com intenção.
- Sozinho não se vai muito longe.
E por aí vai...
quarta-feira, junho 03, 2009
A difícil arte de explicar o abstrato
Tenho um problema básico de comunicação quando tratando com pessoal "não-nerd" como os gerentes (e a minha esposa). Toda vez que tenho que explicar "o código está ruim", eles me olham com aquela cara de tela azul do windows. Dá quase pra ouvir o somzinho no fundo: "pãm...!"
Aí comento que é difícil dar manutenção, que leva mais tempo, que para fazer algo precisamos arrumar um pouco a coisa, que as estimativas não são confiáveis.
"pãm...!?"
Torna explicar que mexer ali pode causar problemas em outros lugares, que pode quebrar o que funciona, etc... etc...
"pãm... pãm...!?"
Finalmente, achei um jeito bom de explicar quando digo "o código está nojento" e eles entenderem a encrenca que é mexer naquilo. As imagens abaixo (do post http://www.tvsnob.com/archives/016683.php ) ajudaram muito:
Primeiro, isso é um código bom:
E isso aqui é "código ruim:
Leia novamente as frases acima, mas observando as imagens... não fica óbvio?
Agora, sempre que vamos conversar, eu mantenho essa imagens por perto, hora que o pessoal começa a viajar muito, eles colocam o povo na terra. E tudo mundo entende o problema que temos nas mãos.
As imagens corretas valem por um milhão de palavras.
domingo, abril 26, 2009
É tarde da noite... passei horas incontáveis programando. Tomo um banho e tento dormir, não consigo. Linhas de código passam pela minha cabeça, penso em "if levantar", "sono -= 1", "sono += ler", blog, blog, coisas esquecidas...
Levanto, pego o Mac e abro. Fico olhando a tela azul, quando me dou conta, me loguei mas não consigo me lembrar quando digitei a senha.
O blog aparece, também não lembro de ter entrado aqui. Começo a digitar a esmo, as palavras vão saindo antes que eu consiga montar uma frase completa na cabeça. E agora, o que estou escrendo?
Continuo vendo linhas de código passando na minha frente, o Código chama. Não posso responder ao Código, preciso programar. Não posso, fiz isso por tempo demais. Preciso escrever, já estou, mas não me dei conta.
Queria poder escrever rápido como o Akita, programar como Kent Beck, arquiteturar como Fowler, ter a consciência do _Why. Pra quê? Não sei bem, mas imagino que deve ser divertido.
Abro o terminal, "ruby -v".
__"ruby 1.9.1p0 (2009-01-30 revision 21907) [i386-darwin9.6.0]" - a máquina responde feliz.
"irb", eu digo a ela.
Um prompt me saúda, o cursor pisca, perguntando o que eu quero.
text = <<TEXT
Colo o texto que escrevi
TEXT
words = text.split
words[rand(words.size)]
O prompt responde:
"dormir"
Sensato como Ronaldo Ferraz. Deveria, mas ainda náo consigo. Se eu rodar de novo, acho que ele responde "Deixa de frescura e vai pra cama". Direto e contundente como o TaQ. Fico com medo que ele responda isso mesmo e fecho o terminal.
Me dou por vencido.
Fecho o Mac, uma luzinha branca me lembra que ele ainda vigia. Desisto e fecho os olhos. Amanhã vou rir disso... acho.
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 plpgsqlE 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.
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.
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.
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.
Assinar:
Postagens (Atom)