segunda-feira, janeiro 30, 2006

OffTopic: Filme bom pra caramba

Cinema nacional finalmente está saindo daquela utopia de "Cinema Arte" que só agrada aos cinéfilos. Principalmente daquele tipo que adora falar dos filmes usando termos como: "crítica da sociedade", "uma visão diferente", "belo" e por aí vai. "Se Eu Fosse Você" cai num tema muito batido (troca de corpos :D ), extremamente comercial, mas é MUITO BOM!!!! O filme é realmente divertido pra quem já levou (ou leva) uma vida a dois. Fazia tempo que eu não ria tanto com um filme. Não tem pornografia, não pretende ser "artístico", é leve, bem-humorado e tem até a característica "lição de moral" no finalzinho. :) Glória Pires nem convence tanto, mas manda bem. Agora o Tony Ramos tá MUITO perfeito e MUUUUUUITO engraçado. Eu não botava tanta fé no cara antes, mas depois desse filme, tenho que rever meus conceitos. Parece que dá até pra ver a Glória Pires dentro do cara. Assistam, eu recomendo.

sexta-feira, janeiro 27, 2006

Auto-crítica é uma droga mesmo

Já fui pior, estou melhorando, mas ainda não cheguei lá. http://www.hacknot.info/hacknot/action/showEntry?eid=81 Tem um pouco de vários, pode me chamar de Henry Kevin Zachary :p Inda chego a ser Quincy.

terça-feira, janeiro 24, 2006

Arrumando a casa

Poisé! Andei dando uma garibada no Blog. Cansei um pouco de ficar colocando minhas viagens aqui. De cara, mudei o modelo do blog (de novo), e agora vou começar a postar mais códigos e menos papo, basicamente, utilidades para Java e Ruby. Talvez eu comece a escrever em inglês, não sei alguém mais vai ler a bagaça, e com certeza vou perder umas piadas. Mas nunca fui bom piadista mesmo, nem em português nem em qualquer língua.

quinta-feira, janeiro 12, 2006

Duck Type em Java

Como o Java é uma linguagem boa e com excelentes APIs, mas muito tosca em algumas coisas básicas (como manipulação de Strings e Coleções), volta e meio fazemos alguns utilitários estúpidos pra facilitar a vida. Aqui vai um dos meus, um simples wrapper para facilitar a chamada de métodos dinâmicos.
package common;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Executes a method in an object dinamically. It's a wrapper to the java
 * reflection way of execute methods dinamically.
 */
public class DuckType {

  public static  T execute(Object object, String methodName, Object ... parameters) {

    if (object == null) return null;
    if (methodName == null || methodName.equals("")) return null;
    
    Class[] classes = extractClassesFromParameters(parameters);
    
    try {
      
      return (T) executeEasyWay(object, methodName, classes, parameters);

    } catch (NoSuchMethodException e) {
      
      return (T) executeHardWay(object, methodName, classes, parameters);
      
    } catch (SecurityException e) {
      return null;
    } catch (IllegalArgumentException e) {
      return null;
    } catch (IllegalAccessException e) {
      return null;
    } catch (InvocationTargetException e) {
      return null;
    }
  }

  private static Object executeEasyWay(Object object, String methodName, Class[] classes, Object... parameters) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
    
    Method method = object.getClass().getMethod(methodName, classes);
    return method.invoke(object, parameters);
  }

  private static Object executeHardWay(Object object, String methodName, Class[] classes, Object... parameters) {
    
    // it didn't find the method in the easy way, trying the hard way
    Method[] methods = object.getClass().getMethods();
    
    for (Method method : methods) {
      Class[] methodTypes = method.getParameterTypes();
      
      // Ignore methods with different names
      if (!methodName.equals(method.getName())) continue;
      
      // Ignore methods with different number of parameters 
      if (methodTypes.length != classes.length) continue;
      
      boolean isMethodExecutable = true;
      for (int i = 0; i < methodTypes.length; i++) {
        Class methodType = (Class) methodTypes[i];
        Class parameterType = classes[i];
        
        if (!methodType.isAssignableFrom(parameterType)) {
          isMethodExecutable = false;
          break;
        }
      }
      
      try {
        
        if (isMethodExecutable) return method.invoke(object, parameters);
        
      } catch (IllegalArgumentException e1) {
        return null;
      } catch (IllegalAccessException e1) {
        return null;
      } catch (InvocationTargetException e1) {
        return null;
      }
    }
    
    return null;
  }

  private static Class[] extractClassesFromParameters(Object[] parameters) {
    
    Class[] classes = new Class[parameters.length];
    
    for (int i = 0; i < parameters.length; i++) {
      Object parameter = parameters[i];
      classes[i] = parameter.getClass();        
    }
    
    return classes;
  }
}

quarta-feira, janeiro 11, 2006

Controle de versão para os dados

Quanto mais eu penso, mais acredito que preciso experimentar essa idéia o mais rapidamente possível. Outro dia estava mexendo com as "rules" do PostgreSQL (triggers) para fazer log de uma tabela essencial do sistema. Qualquer alteração criava um registro em uma tabela gêmea, com a data da alteração e o usuário. Comecei a pensar o que aconteceria se eu fizesse isso para TODAS as tabelas do sistema. Acho que ia virar uma espécie de controle de versão dos dados, e melhor ainda, acho que consigo criar toda essa estrutura, tabelas gêmeas e triggers, com um simples script. Ainda não pensei direito o efeito disso sobre as tabelas de relacionamento N-M, mas acho q também funciona. Talvez fiquem gigantes, mas não vejo problema nisso. E com certeza, as gêmeas não podem ter "constraints" como "unique" e coisas do tipo, mas também acho isso contornável. Resta o problema de manutenção, triggers sempre são complicadas. Mas como as tabelas gêmeas não fazem parte realmente do sistema e nenhuma delas vai ter triggers, acho que não vou ter problemas de atualizações em cascata que o pessoal tanto abomina nas triggers. Acho que dá pra fazer um Engine no Rails (ActiveRecord) pra isso. Já tem um plugin pra isso: acts_as_versioned Quem sabe? Só estou jogando idéias pra cima.

segunda-feira, janeiro 09, 2006

O que me imcomoda em Linguagens e APIs

Sabe, Tava organizando os pensamentos aqui e finalmente achei o motivo pelo qual não simpatizo muito de certas Linguagens e APIs. O que me torra o saco é quando os designers delas tem a genial idéia de proibir coisas na linguagem para evitar "más práticas". Só que más práticas dependem do contexto onde são usadas. Eu vejo frequentemente que o resultado disso cai em dois casos: - Programadores imbecis continuam fazendo imbecilidades de outras formas. ("É muito difícil fazer algo a prova de idiotas, eles são muito imaginativos") - Programadores menos imbecis tem que fazer imbecilidades para fazer o código funcionar como querem. Quantas vezes você já "hackeou" o Java porque ele não deixava você fazer o que queria de um jeito simples. A lição que eu tiro disso? Você não pode prever como seus usuário vão usar suas coisas, então é melhor não tentar. "AH! Mas os outros programadores são muito estúpidos, se eu não travar isso, vão fazer cagada" -- Típico pensamento arrogante que nós programadores temos. Devíamos ser mais humildes ou pelo menos não subestimar nossos pares. (Já ouvi um "Se você fizer algo achando que seus usuário são ignorantes, eles terão de ser ignorantes pra usar o que você fez") No fim das contas, se o outro programador fizer cagada com sua API/Linguagem, de quem é o problema? Do designer da API?! Isso só pode ser o cúmulo da arrogância, meio querer ser "oniscente e onipotente". Se o imbecil faz imbecilidades, sinceramente, problema dele, devia ter estudado mais antes de ser programador. Se não fizer, tanto melhor!!! Li em um blog outro dia uma coisa muito legal: "Fazer uma boa linguagem de programação 'segura' é como fazer uma faca afiada que nunca corte o dedo de quem usa". Mas sabe, eu estava no açougue outro dia e vi o açougueiro estripando a carne com fé e vontade. Fiquei pensando como é que ele não picava os dedos juntos, tal o empenho que ele estava em estripar a pobre peça de carne (acho que era uma costela, sei lá). Aí vi o motivo: ele estava usando uma luva de metal na mão que segurava a carne... Que isso tem a ver com programação? Que a faca tem que ser a mais afiada possível para você fazer um bom trabalho. E se não quiser cortar os dedos use a porcaria da luva! Imagino que nossas "luvas" sejam testes de unidade, mas não sei ao certo. Só garanto que se a linguagem é realmente afiada, use alguma proteção ao invés de querer fazer a linguagem "perder o fio".