Feeds:
Posts
Comments

Archive for the ‘Java’ Category

Proxy Pattern – Java e Python

Recentemente venho dedicando boa parte do meu tempo na implementação da minha dissertação de mestrado. O meu trabalho consiste em modelar/desenvolver um middleware para redes de sensores sem fio. Apesar de ser um pythonista de carteirinha não consegui achar nenhuma plataforma de sensores baseadas em python então a minha escolha para o mestrado ficou com o SunSPOT. Para os desavisados, o SunSPOT trabalha com j2me. Dessa forma, precisei deixar o python de lado e voltar a programar em “Java”.

O middleware que venho implementando tem como principal requisito ser extremamente flexível. O objetivo é tornar o middleware bastante customizável, permitindo que os interessados possam modificá-lo. Além disso, outra característica dele é permitir a troca on-the-fly de alguns componentes visando atender os requisitos da aplicação. No intuito de solucionar o problema da troca de componentes uma das escolhas realizadas foi a de utilizar o padrão proxy. Quando um componente é solicitado como requisito de outro componente, o middleware entrega um proxy para a  implementação real, assim um componente sempre tem uma referência opaca ao componente. Através da utilização de proxies, o middleware pode realizar a troca de componentes ajustando apenas a referencia do proxy e todos os objetos que fazem uso dele terão a referência ao novo componente automaticamente. Assim, o uso do padrão ajuda a controlar as referências para um determinado componente que precisa ser trocado.

No entanto, um “problema” da abordagem adotada é que eu necessito implementar um novo proxy para cada interface dos componentes. O middleware em questão possui vários componentes que podem ser modificados de acordo com a escolha da aplicação, por exemplo, gestores de bateria, roteamento e etc. Nesse cenário, para cada componente que é permitido a troca, é necessário ao programador desenvolver pelo menos 3 classes/interfaces. A interface do componente, a implementação real e o proxy.

Olhando a definição do padrão contida na wikipedia isso fica mais claro ao leitor. Podemos ver a definição da interface, da implementação real e do proxy.

import java.util.*;

interface Image {
    public void displayImage();
}

class RealImage implements Image {
    private String filename;
    public RealImage(String filename) {
        this.filename = filename;
        loadImageFromDisk();
    }

    private void loadImageFromDisk() {
        System.out.println("Loading   " + filename);
    }

    public void displayImage() {
        System.out.println("Displaying " + filename);
    }
}

class ProxyImage implements Image {
    private String filename;
    private Image image;

    public ProxyImage(String filename) {
        this.filename = filename;
    }
    public void displayImage() {
        if (image == null)
        {
           image = new RealImage(filename);
        }
        image.displayImage();
    }
}

Agora imagine que você tenha umas 15 interfaces para fazer isso ? Começa a ficar tedioso. Esse é o tipo de código em que um proxy em si não é código duplicado mas sua lógica sim, eles fazem sempre a mesma coisa, possuem uma referência ao objeto real e delegam todos os seus métodos para o objeto. Atualmente as IDEs for Java já permitem gerar esse tipo de código automaticamente, o que me facilitou muito o trabalho. Inicialmente eu passei mais tempo pedindo ao netbeans para produzir código do que de fato programando. Porém, apesar da IDE gerar o código, a sua manutenção ainda fica por conta do programador. O que acontece quando um método novo entra na interface? Outro precisa ser renomeado? Mudança de parâmetros e etc. Todos nós sabemos, mudanças na interface afetam todas as implementações, nesse caso os proxies também.

Como programador Python, pensei desde o princípio: "esse é o tipo de código que pode ser feito de forma muito mais inteligente em Python do que me Java". Em Python eu posso definir um único proxy para todas as interfaces. Ou seja, onde eu teria 15, 20 implementações eu passo a ter só uma. Isso é redução de código válida, não estamos falando de one-liners. Dessa forma é menos código para manter, um único ponto para consertar, refatorar, testar. Quanta mágica se precisa para definir esse proxy genérico em Python?

class Proxy(object):
    def __init__(self, obj):
        self.obj = obj
    def __getattr__(self, attr):
        return getattr(self.obj, attr)

Pronto, ai está nosso "incrível" "super" proxy. Isso teria me poupado mais de uma centena de linhas de código. Como esse código funciona? Simples, em python nós temos um método, denominado de __getattr__, o qual é invocado quando não é encontrado um determinado atributo na instância. O nosso Proxy implementa o __getattr__ na linha 4, e na 5 nós definimos que quando um atributo não for encontrado dentro do proxy deve ser procurado na referência que o mesmo detém. Pequeno e elegante. Outro detalhe é que não estamos amarrados a nenhuma interface e não precisamos escrever vários métodos apenas delegando tarefas.

Os programadores rails vão achar semelhante ao method_missing do ruby. A idéia é a mesma, porém funciona também para atributos. Não sei dizer se ruby possui isso para acesso a atributos também, acredito que sim.

Read Full Post »

Esse texto já esta na web há algum tempo, no entanto, muitos ainda não o leram. O texto fala sobre como os desenvolvedores Java costumam programar quando migram para a linguagem Python. O texto demonstra “erros” cometidos por esses programadores ao escrever uma aplicação, além disso contém várias dicas de como se evitar tais “erros” e tenta ensinar a pensar como programador Python. O texto original é em inglês mas recentemente foi traduzido e colocado a disposição no site do pythonbrasil.

De certa forma eu passei pela experiência de migrar do Java para a linguagem Python. Confesso que não gostava tanto de programar enquanto não conhecia essa nova linguagem. Desenvolver qualquer projeto pequeno para usufruir no meu próprio desktop em Java durava mais tempo que a minha empolgação.

O texto me foi bastante útil e por isso recomendo a leitura do mesmo. Minha experiência com Java veio por obrigação da faculdade, talvez se eu tivesse visto Python desde o começo do curso não tivesse achado as aulas tão enfadonhas. Migrar do Java pro Python, ao meu ver, é um caminho sem volta. A produtividade que se ganha é enorme, você vai conseguir terminar seus projetos antes do que você imaginava e isso vai lhe dar tempo para mais projetos ainda. Para ganhar tal produtividade é necessário que o programador deixe de pensar como fazia as coisas em Java e se pergunte como fazer essa mesma tarefa com os recursos do Python. Essa é a parte principal da migração para uma nova linguagem e do texto recomendado.

Read Full Post »

Follow

Get every new post delivered to your Inbox.