20 de out. de 2011

Todo mundo quer uma API extensível

Como programador Java mas entusiasta de novas linguagens, acabo por sentir falta de alguns recursos que facilitam muito o trabalho, ou que pelo menos para mim fazem mais sentido usar.

Posso começar com um estudo de caso simples: dada uma String retornar o número de palavras.

É assim mesmo, simples assim, inclusive muito fácil de implementar em qualquer linguagem, mas a questão não é essa, como desenvolvedor eu quero usar orientação a objetos no projeto.

Vamos a uma implementação tosca em Java:
String frase = "Uma frase  de   exemplo";
System.out.println(frase.trim().split("\\s+").length);
Deu. Mostra 4. Entretanto eu quero reutilizar esta funcionalidade então em componentizo, bem, mas como?

Posso usar outro estudo de caso para dramatizar mais a história: verificar se uma String está em branco, ou seja, semelhante ao vazio só que ignorando espaços.

A implementação é medíocre:
String texto = "    ";
if (texto.trim().length() == 0) {
    System.out.println("vazio");
}
Não obstante, como no primeiro caso, eu quero componentizar.

No Java, é clássico fazer uma classe utilitária, algo como TipoUtils, neste caso, StringUtils:
public class StringUtils {
    public static int words(String str) {
        return str.trim().split("\\s+").length;
    }

    public static boolean isBlank(String str) {
        return str.trim().length() == 0;
    }
}
E uso assim:
String texto = "    ";
if (StringUtils.isBlank(texto)) {
    System.out.println("vazio");
}
Ainda posso usar um recurso introduzido no Java 5, o import estático.
import static meu.framework.utils.StringUtils.*;
// algumas linhas abaixo
String texto = "    ";
if (isBlank(texto)) {
    System.out.println("vazio");
}
Qual o problema com esta implementação? É que ela soa totalmente procedural em contraste ao modelo OO escolhido, em outras palavras eu queria fazer isso:
String texto = "    ";
// quero o próprio objeto me diga se está em branco
if (texto.isBlank()) {
    System.out.println("vazio");
} else {
     // quero que o próprio objeto me diga quantas palavras tem
    System.out.println("Existem " + texto.words() + " palavra(s)");
}
Em Java, impossível. No Java a classe String é final, ou seja, não pode ser estendida.

Para constar, uma extensão da API base do Java já existe e é distribuída pelo projeto commons do Apache e uma classe StringUtils já existe para estender as funcionalidades relacionadas a Strings e é muito bem escrita.

Mas isso não me deixa contente por que outras linguagens lidam muito melhor com esta situação, dando melhor suporte para estender a API base.

Vamos ao mesmo exemplo usando C#. No C# é possível, de certo modo, estender qualquer classe, mesmo as finais (sealed em C#), usando somente a API pública da classe, que já é suficiente para realizar muitas proezas:
public static class StringUtils {
 public static int Words(this string str) {
  return Regex.Split(str.Trim(), "\\s+").Length;
 }
 public static bool IsBlank(this string str) {
  return str.Trim().Length == 0;
 }
}
Implementações de classes estáticas no C# permitem estender a funcionalidade qualquer classe. Na verdade é um açúcar sintático no qual ele passa o conteúdo da variável para o método estático, ainda sendo procedural, mas de melhor leitura e mais elegante que em Java. Eu posso chamá-lo assim:
string texto = "    ";
if (texto.IsBlank()) {
    Console.WriteLine("vazio");
} else {
    Console.WriteLine("Existem " + texto.Words() + " palavra(s)");
}
Bem mais OO não acha? Pode ficar ainda melhor em Ruby, onde as classes são abertas. Em outras palavras, é possível estender a funcionalidade até mesmo das classes básicas como String e FixNum (inteiros). Claro que esta liberdade deve ser usada com parcimônia, é bem mais fácil fazer caca, mas com responsabilidade dá para fazer isso:
class String
    def words
        self.split.length
    end
    def blank?
        self.strip.length == 0
    end
end
Então eu posso usar estes métodos assim:
texto = "uma frase"
print texto.words
print "vazio" if texto.blank?
Sinceramente, sinto falta dessa flexibilidade em Java.

Acho exagerado a recomendação do Pragmatic Programmers de que todo programador deveria aprender uma linguagem por ano, por outro lado entendo o motivo que é propiciar novas visões, pontos de vista, ser mais crítico ao seu código, saber que há alternativas para fazer, melhor ou pior, aquilo que tu já faz todo o dia.

18 de out. de 2011

O operador 'Elvis'

O açúcar não deve ser consumido em excesso e nem deixar de ser consumido, assim como o sal, a gordura, etc.
Não, não virei nutricionista. É que este post é para falar de açúcar sintático, syntactic sugar em inglês, que é, em poucas palavras, o uso de operadores e construções da linguagem reduzem a escrita de um código maior e, assim como tudo, não pode deixar de existir na linguagens modernas e ao mesmo tempo não deve ser exagerado.

Nem sempre o açúcar sintático simplifica, pois às vezes tornam a leitura mais difícil, mas por outro lado economizam tempo -e tempo é dinheiro.

Vou citar um exemplo clássico, o operador ternário "? :"
Quem aqui né amigo não teve que escrever um código assim:
if (atraso > 10) {
    multa = 12.4;
} else {
    multa = 0.0;
}
Embora o código esteja em Java a construção é inerente a qualquer linguagem.

O mesmo código pode ser escrito usando o operador ternário, que é um açúcar sintático pois na prática ele compila, ou interpreta, para o código acima. Exemplo:
multa = atraso > 10 ? 12.4 : 0.0;
As linguagens estão cada vez mais adicionando açúcar sintático e uma que simpatizo muito é Ruby, entretanto como desenvolvedor Java sinto falta de um especialmente: o operador Elvis!

O "Elvis" -não me pergunte por que chamam assim, só sei o que dizem: "Elvis não morreu"- é uma simplificação do operador ternário para verificação de nulos. Por exemplo, imagine que desejes atribuir o valor de um parâmetro a uma variável, entretanto caso este parâmetro seja nulo é necessário atribuir um valor padrão. Vou propor um estudo de caso e uma implementação fictícia no código abaixo usando o clássico "if":
if (param.get("action") != null) {
    acao = param.get("action");
} else {
    acao = "listar";
}
O mesmo código poderia ser escrito assim:
acao = param.get("action") != null ? param.get("action") : "listar";

Esta sintaxe com operador ternário simplifica bastante porém ainda é possível simplificar ainda mais usando, bem, o Elvis! Abaixo uma implementação fictícia usando C#:
acao = param["action"] ?? "listar";
Bem melhor não concorda?
Java está meio atrasado nesta corrida por facilitação de sintaxe, o operador Elvis estava previsto para ser inserido no Java 7 e não rolou. A princípio ele teria a mesma sintaxe do Groovy, assim:
acao = param.get("action") ?: "listar";
Em Ruby ele é diferente sendo assim:
acao = param[:action] || "listar"
E pior, atualmente até o PHP tem, a partir da versão 5.3.

Enfim, o Java mostra sinais de idade e espero sinceramente que a Oracle com o Java 8 adicione mais liberdade a linguagem sem perder a elegância, a tipagem forte e robustez que o Java tem.

27 de ago. de 2011

Tchê Linux: Princípios de projeto e boas práticas de programação em Java

O evento do Tchê Linux Rio Grande - Furg estava muito legal. Tive a oportunidade de encontrar amigos, colegas, alunos e o prazer de ter contato com uma comunidade proativa e inovadora.


A minha palestra foi sobre Princípio de Projeto e Programação Java. No link abaixo é possível baixar o arquivo com os slides e o projeto:


http://mtiads.net/tchelinux/palestra-furg-2011.zip

Obs.: o projeto deve ser aberto no NetBeans ou importado no eclipse.



Qualquer dúvida não hesitem em perguntar. Abraço a todos.

14 de jul. de 2011

Enumerados em Java

Intro

Muitas pessoas não utilizam os tipos enumerados em Java, seja por não conhecerem por estar começando a programar em Java ou, no caso dos experientes, serem relutantes a mudanças (enums foram introduzidos no Java 5).

O fato é que enums quebram um galhão e, diferente como alguns pensam, não são apenas constantes (como é no C# por exemplo), eles podem ter atributos e métodos.

Para entender a utilidade de enums vamos aplicá-los em dois estudos de caso:
1: Uma refatoração de "obsessão primitiva" (um mau cheiro)
2: Introdução do Design Pattern Strategy (Padrão de Projeto Estratégia)

Neste post vou abordar o uso de enums em refatorações e no próximo post abordo o segundo caso, ok?



Usando enums em refatorações

Imagine a seguinte implementação:

public class Usuario {

    String nome;
    String login;
    String senha;
    int    perfil = 0;

}

Não fica claro o que perfil quer dizer, fica?

Então podemos adicionar um comentário! (a.k.a. desodorante!)

public class Usuario {

    String nome;
    String login;
    String senha;
    
    // perfil do usuário pode ser:
    // 0:visitante,
    // 1:usuário,
    // 2:funcionário,
    // 3:gerente,
    // 4:administrador
    
    int    perfil = 0;

}

Há ainda os que colocam caracteres de destaque no comentário (péssimo amigo):

// --------------------------------------------------------- //
// perfil do usuário pode ser:                               //
// 0:visitante,                                              //
// 1:usuário,                                                //
// 2:funcionário,                                            //
// 3:gerente,                                                //
// 4:administrador                                           //
// --------------------------------------------------------- //
    
int    perfil = 0;

Steve McConnel, respeitado Engenheiro de Software diz:
Bom código é sua melhor documentação. Sempre que você estiver por adicionar um comentário, pergunte a si mesmo: 'Como eu posso melhorar o código para que este comentário não seja necessário?'

Antes do Java 5 a opção era usar constantes, algo como:

public class Usuario {

    String nome;
    String login;
    String senha;
    int perfil = Perfil.VISITANTE;

    public abstract class Perfil {

        public static final int VISITANTE = 0;
        public static final int USUARIO = 1;
        public static final int FUNCIONARIO = 2;
        public static final int GERENTE = 3;
        public static final int ADMINISTRADOR = 4;
    }
}

O que já é bem mais profissional mesmo que não ofereça a segurança do enum. Digo isto por causa do benefício da tipagem forte, o que faz o Java uma opção para softwares robustos. Usando a implementação com constantes não há impedimento que alguém faça:

Usuario umUsuario = new Usuario();
umUsuario.perfil = 8;

Afinal, a variável perfil é do tipo inteiro. Claro que se encapsularmos a configuração do perfil em um setter (setPerfil(int perfil)) podemos tratar o número para que seja válido. Mas vamos um passo além, usaremos enums, como abaixo:

public class Usuario {

    String nome;
    String login;
    String senha;
    Perfil perfil = Perfil.VISITANTE;

    public enum Perfil {

        VISITANTE, USUARIO,
        FUNCIONARIO, GERENTE,
        ADMINISTRADOR;
    }
}

Agora, a variável perfil é do tipo Perfil. Apenas os valores enumerados são aceitos, além de nulo é claro, pois o enumerado é um tipo (classe).

Sempre é preferível implementar utilizando a tipagem forte, que é bem viva no Java. A tipagem forte permite ver possíveis erros ainda em tempo de compilação e benefícia o código coletivo já que a intenção é declarada e a quantidade de valores aceitos é limitada. Seria diferente se usássemos Strings por exemplo, que é aberto a qualquer coisa.

Os níveis numéricos ainda podem ser obtidos, como no exemplo:

Usuario umUsuario = new Usuario();
umUsuario.perfil = Usuario.Perfil.GERENTE;

// mostra o índice
System.out.println(umUsuario.perfil.ordinal());
// mostra o nome
System.out.println(umUsuario.perfil.toString());

Simples não?

Outro caso comum é na passagem de parâmetros. Imagine um funcionário que é recuperado de um banco de dados e tem seu salário calculado assim:

Funcionario func = ds.findFuncionarioById(1288);

double salario = func.calculaSalario(3, true);

O que é 3? E o true? É para calcular de verdade? hehehe

Bem, teríamos que ver a assinatura do método para entender. Digamos que seja isto:

public double calculaSalario(int mes, boolean liquido) {
    // implementação
}

Ah! O número é o mês e o true é para calcular liquido. False calcula o quê? Deve ser o salário bruto, eu acho.

Não preciso dizer que em programação não há espaço para achismo, então vamos implementar melhor este método usando o quê? usando o quê? ENUMS!

public class Funcionario {

    public enum Mes {
        JANEIRO, FEVEREIRO, MARCO,    ABRIL,   MAIO,     JUNHO,
        JULHO,   AGOSTO,    SETEMBRO, OUTUBRO, NOVEMBRO, DEZEMBRO;
    }
    
    public enum Valor {
        LIQUIDO, BRUTO;
    }

    public double calculaSalario(Mes mes, Valor valor) {
        // implementação
        return 0.0;
    }

}

Com esta implementação agora eu posso fazer:

Funcionario func = ds.findFuncionarioById(1288);

double salario = func.calculaSalario(Mes.MARCO, Valor.LIQUIDO);

Melhor?

Bem, mas digamos que ainda queira se manter a opção de passar o mês como inteiro. Note, usar tipos primitivos permitirá que seja passado qualquer valor, ou seja, algo como calculaSalario(15), bem propenso a erros. Também é o caso de querermos o número 1 para Janeiro, 2 para Fevereiro, etc, o que não é o caso quando chamamos ordinal() que começa com zero.

Então vamos preparar nosso enum para ser instanciado a partir de um inteiro para que faça a numeração correta:

public enum Mes {

    JANEIRO(1),  FEVEREIRO(2), MARCO(3),     ABRIL(4),
    MAIO(5),     JUNHO(6),     JULHO(7),     AGOSTO(8),
    SETEMBRO(9), OUTUBRO(10),  NOVEMBRO(11), DEZEMBRO(12);
    public int Numero;

    Mes(int n) {
        this.Numero = n;
    }

    public static Mes valueOf(int index) {
        for (Mes mes : EnumSet.allOf(Mes.class)) {
            if (mes.Numero == index) {
                return mes;
            }
        }
        return null;
    }
}

O valor entre parênteses nos enumerados definem o enum passando o número no construtor. Assim sendo, se eu chamar Mes.JULHO.Numero retorna 7.

O método valueOf(int) devolve o enumerado adequado conforme o número, ou nulo se não for encontrado.

A implementação da chamada do método calculaSalario usando inteiros fica assim:

double salario = func.calculaSalario(Mes.valueOf(3), Valor.LIQUIDO);


Conclusão

Java é uma linguagem fortemente tipada e os programadores devem tirar proveito deste recurso que, naturalmente, faz do Java uma linguagem robusta, confiável e preferida por empresas de grande porte.

1 de mai. de 2011

Primitive Obsession, Value object, Uniform Access Principle, Factory Method e Open/Close Principle

Salve,

Este tópico é para abordar um Code Smell (mau cheiro no código) chamado Primitive Obsession (obsessão primitiva). Este Code Smell é encontrado regularmente nas propriedades de classes e não é difícil identificá-lo. A refatoração comum é extrair uma classe, normalmente um Value Object (objeto de valor) imutável, criando um modelo mais rico, fazendo uso de princípios adequados de projeto orientado a objetos, como o UAP, Uniform Access Principle (Princípio do Acesso Uniforme) e OCP, Open/Close Principle (Princípio Aberto/Fechado).

Primitive Obsession

Imagine a situação onde seja necessário modelo um domínio de encomendas, tendo em mente que o valor cobrado no frente é relacionado com o peso da encomenda, pode ser? Naturalmente é comum modelarmos assim:

class Encomenda {
    int peso;
}

Obs.: deixei de lado Getter's e Setter's para favorecer a legibilidade do exemplo;

Mais tarde existirá a intenção de cobrar o frete por peso, por exemplo R$ 2,15 por Kilo. Mas o peso da encomenda usa qual unidade de medida? E se for necessário usar 0,5Kg? Pois então, o modelo deve ser refinado e talvez teremos um modelo assim:

class Encomenda {
    double pesoKilos;
}

Mais tarde é confirmado que a interface gráfica mostrará uma caixa de texto para entrar com o peso em kilos ou gramas. Se o usuário entrar com, por exemplo, 700 gramas, no evento será necessário converter estes 700 gramas para kilos, dividindo por 1000, para depois atribuir a encomenda. Então, após perceber a "gambi", talvez o modelo fique assim:

class Encomenda {
    double pesoKilos;
    int unidade; 
}

Como os outros colegas não entendem o que é essa tal de unidade em inteiro você decide então colocar um (desodorante) comentário:

class Encomenda {
    double pesoKilos;
    int unidade; // use 0 para kilo e 1 para gramas
}

Enfim, é muito comum querermos representar grupos de dados com tipos primitivos e isto é muito comum para quem vem de outras linguagens, a maioria procedural, as quais não proviam uma maneira uniforme e significativa de representar grupos ou estruturas de dados.

E como é a maneira OO de fazer? Ora, criando classes.

Aos que perguntam "bah, quantas classes vou criar?", digo: quantas forem necessárias. Programar em linguagens orientadas a objetos implica em criar classes (tipos), é fato.


Value Object (VO)

Objetos de valor são importantes para representar informações que não necessitam de uma identidade (exemplo, contrastando uma classe Compromisso com uma classe Data). Normalmente são imutáveis e fornecem métodos para tratar seu estado uniformemente. O caso do peso da encomenda é um forte candidato a ser um VO. Extraindo o peso para uma classe estaremos fazendo uma importante refatoração, para "curar" a nossa obsessão primitiva.

De início, poderíamos fazer algo mais ou menos assim:

class Encomenda {
    Peso peso;
}

class Peso {
    int valor;
}

Mas e agora, como vamos tratar esta representação de Peso. Bem, podemos fazer várias melhorias, como representar e converter facilmente unidades de medida, como Kilos, gramas e outros. O Kiko por exemplo, fez uma observação importante. Ele disse que poderíamos até mais tarde representar libras ou outra unidade estrangeira.

Primeiro temos de definir a unidade básica interna de armazenamento e depois fornecer acessores a este estado. Eu prefiro usar gramas, o que seria por exemplo, uma unidade mínima. A classe, agora completa para focar a solução, seria mais ou menos assim:

class Peso {
    private int gramas;

    public Peso(int gramas) {
        this.gramas = gramas;
    }

    public Peso(double kilos) {
        this.gramas =  (int) (1000 * kilos);
    }

    public int getGramas() {
        return gramas;
    }

    public double getKilos() {
        return gramas * 1000;
    }
    
}


Uniform Access Principle

Particularmente, ainda acho que esta classe deve ser refinada, mas ela já mostra a aplicação do Princípio do Acesso Uniforme. Este princípio baseia-se na premissa de que qualquer usuário da classe não precisa saber se a propriedade que está usando é um valor armazenado ou calculado. Se o método getKilos fosse converteEmKilos() estaríamos violando este princípio.

Do modo que está, o usuário da classe pode acessar o peso em gramas e em kilos uniformemente e transparentemente.

Eu não inclui métodos setGramas e setKilos, mas se o fizesse, o método setKilos converteria para gramas, como no construtor, e o usuário da classe ainda não teria conhecimento de como o peso internamente é armazenado (e nem é interessante). Incluir métodos set também implica em tornar o objeto mutável, a não ser que a cada set seja retornado um novo objeto Peso.


Factory Methods

Comentei que era possível fazer uma melhoria, penso que poderíamos substituir os construtores por métodos de fábrica (uma implementação simplificada do padrão de projeto Factory Method). Por quê? Imagine o caso:

Em uma instanciação da classe Peso como esta, como sabemos se é em gramas ou kilos?

Peso peso = new Peso(pesagem);

Pois é, apenas com essa linha não saberemos. Teremos que seguir a variável pesagem para saber se ela é do tipo int ou double para saber se a instância será em gramas ou kilos respectivamente.

Aplicando os métodos de fábrica, torna-se os construtores e privados e adiciona-se métodos estáticos com nomes amigáveis:

class Peso {
    private int gramas;

    private Peso(int gramas) { this.gramas = gramas; }
    
    private Peso(double kilos) { this.gramas =  (int) (1000 * kilos); }

    public static Peso comGramas(int gramas) { 
        return new Peso(gramas);
    }
    
    public static Peso comKilos(double kilos) {
        return new Peso(kilos);
    }
    
    public int getGramas() {
        return gramas;
    }

    public double getKilos() {
        return gramas / 1000;
    }
    
}

Então a chamada anterior ficaria assim:

Peso peso = Peso.comGramas(pesagem);

Desta maneira não é necessário seguir variáveis ou ler comentários para entender esta linha.



Open/Close Principle

Mas e se amanhã quisermos adicionar uma nova unidade de medida? Obviamente teremos que abrir a classe e implementar, a não ser que programemos com o princípio aberto/fechado em mente. O Princípio Aberto/Fechado diz que uma classe deve estar fechada para modificação mas deve estar aberta para extensão.

Existem vários modos de "abraçar" este princípio, um deles é usando o Design Pattern Strategy (padrão de projeto estratégia). Exemplo:


class Peso {
    private int gramas;

    private Peso(int gramas) { this.gramas = gramas; }

    private Peso(double kilos) { this.gramas =  (int) (1000 * kilos); }

    public static Peso comGramas(int gramas) {
        return new Peso(gramas);
    }

    public static Peso comKilos(double kilos) {
        return new Peso(kilos);
    }

    public static Peso comPeso(IConversorPeso conversor, double peso) {
        return new Peso(conversor.paraGramas(peso));
    }

    public int getGramas() {
        return gramas;
    }

    public double getKilos() {
        return gramas / 1000;
    }

    public double getPesoEm(IConversorPeso conversor) {
        return conversor.deGramas(gramas);
    }

    public interface IConversorPeso {

        public double deGramas(int gramas);
        public int paraGramas(double peso);

    }
    
}

Sabendo que 1 grama = 0,00220462262 libras, então poderíamos fazer isto:

class Libras implements IConversorPeso {

    public double deGramas(int gramas) { return gramas * 0.00220462262; }

    public int paraGramas(double peso) { return (int) (peso / 0.00220462262); }
}

Eu posso passar para Peso qualquer implementação de IConversorPeso e assim estender a funcionalidade da classe Peso sem alterá-la, aderindo ao Princípio Aberto/Fechado.


Caso de teste

Sabendo que 10 Kilogramas = 10000 gramas = 22,0462262 libras

Libras libras = new Libras();

System.out.println(libras.deGramas(10000));


Resultado Final

Obtendo o peso em Kilos instanciando com 500 libras:

Libras libras = new Libras();

Peso peso = Peso.comPeso(libras, 500);

System.out.println(peso.getKilos());


Conclusão

Minha implementação tem falhas de arredondamento (usa double para gramas atenuaria) mas acho que demonstra os temas. Espero que seja útil e que eu tenha me feito entender.

Abraços!

19 de abr. de 2011

Lei de Demeter, Train Wrecks e Tell, Don't Ask

Salve,

O objetivo deste tópico é abordar um princípio de OOD (Object-Oriented Design - Projeto Orientado a Objetos) chamado Lei de Demeter e junto aproveitar para falar do anti-padrão Train Wreck e sua possível cura, o princípio "Tell,Don't Ask" (Diga, não Peça).

Lei de Demeter

A Lei de Demeter é fácil de implementar e de entender, talvez o difícil de compreender seja o porquê, em outras palavras, compreender a motivação. A Lei de Demeter também é conhecida como Princípio do Menor Conhecimento.

De forma resumida, a Lei diz o seguinte: "Uma classe ou método deve ter um conhecimento limitado de outras classes e métodos, devendo comunicar-se apenas com as classes imediatamente mais próximas".

Formalmente diz que um método M de uma classe C só deve chamar métodos de:
C
Um objeto criado por M
Um objeto passado como parâmetro para M
Um objeto dentro de uma instância de C
Recentemente, em um projeto de exemplo usado em aula, dá para ilustrar bem a aplicação e a violação da Lei de Demeter. Por exemplo, temos uma classe GestorJanela, que tem internamente uma instância de JDesktopPane.

class GestorJanela {
    // ...

    public JDesktopPane getAreaTrabalho() {
        return areaTrabalho;
    }

}

A partir de uma ação ou método dentro de uma Janela eu posso trazer uma Janela para frente usando o seguinte código:

GestorJanela.getInstance().getAreaTrabalho().getDesktopManager().activateFrame(janela);

Este código viola a Lei de Demeter porque além de conhecer o GestorJanela, ele também conhece a implementação de JDesktopPane ao usar getAreaTrabalho, DesktopManager e do método activateFrame. Se qualquer parte deste código mudar todos os lugares onde é chamado também deverão mudar. Por exemplo, se o GestorJanela passar a usar outro Painel ao invés do JDesktopPane para embutir as janelas, todos os chamadores quebrarão.


Train Wreck

Este mesmo código também é um exemplo do anti-padrão Train Wreck. Ele é encontrado quando existem métodos getIsso().getAquilo().getAquiloOutro().facaAlgo()

O que fazer então? Delegar! Quem deve subir a Janela é o GestorJanela (o nome não é por acaso). A implementação ficaria assim:

class GestorJanela {
    // ...

    public void trazerJanelaParaFrente(JInternalFrame janela) {
        areaTrabalho.getDesktopManager().activateFrame(janela);

        // ainda viola o princípio aqui, mas não temos como 
        // alterar o comportamento de JDesktopPane
        // para não expor o DesktopManager, fazendo parte do Swing 
        // (em outras palavras, a culpa não é nossa)
    }

}

E os chamadores fariam assim:

GestorJanela.getInstance().trazerJanelaParaFrente(janela);

Dá para melhorar este código removendo o Train Wreck:

GestorJanela gestor = GestorJanela.getInstance();

gestor.trazerJanelaParaFrente(janela);

Um colega perguntou: "Vale a pena adicionar mais código executando a mesma funcionalidade?". A resposta é: "Vale". Para manutenções e revisões de código, a implementação deve tão simples quanto possível, permitindo entendê-la com uma passada de olhos. Se são necessárias duas ou mais passadas, então talvez esteja na hora de refatorar e dividir as funcionalidades/responsabilidades.


Tell, Don't Ask

O código de exemplo também é um bom exemplo do princípio Tell, don't Ask. Não seria Tell, don't Ask se fosse implementado assim:

GestorJanela.getInstance().setJanelaTopo(janela);

Métodos get e set são úteis para expor propriedades, não para definir comportamento. Logo, em geral, o hipotético código:

loginController.getUsuarioLogado().getPermissao().setHabilitado(false);

é melhor escrito assim:

loginController.desabilitaPermissao();

Diga, não peça.

Bibliografia:
Martin, Robert C. Código Limpo.
Wikipédia. Law of Demeter.

9 de fev. de 2011

Paradigmas, Coleções, Java, Programação Funcional, C# e Ruby

São vários os paradigmas de programação, entretanto os mais conhecidos e abordados são imperativo, estruturado, procedural e orientado a objetos (OOP). Os quais são suportados por muitas linguagens conhecidas como PHP, Java, Visual Basic, etc. Outros que tem destaque no desenvolvimento de aplicações são o funcional e orientado a aspectos (AOP).

Vou usar um estudo de caso simples nesse post para contrastar:
Imagine uma coleção de candidatos, com apenas dois atributos: nome e idade. Após obter esta lista, de um base de dados ou integração, é necessário subdividi-la em duas: candidatos maiores de idade e menores de idade. Preferencialmente deve ser uma solução reusável.

Abaixo fiz uma implementação em Java. Existem várias estratégias de implementação para obter os menores e maiores, qual seria a sua?

Arquivo Main.java
import java.util.*;

public class Main {

 public static void main(String[] args) {
  
  List<Candidato> candidatos = getCandidatosFromDataSource();
  
  //List<Candidato> menores = ??;
  //List<Candidato> maiores = ??;
  
 }
 
 
 public static List<Candidato> getCandidatosFromDataSource() {
  List<Candidato> candidatos = new ArrayList<Candidato>();
  
  candidatos.add(new Candidato("Alvaro", 23));
  candidatos.add(new Candidato("Vanessa", 13));
  candidatos.add(new Candidato("Paulo", 54));
  candidatos.add(new Candidato("André", 17));
  candidatos.add(new Candidato("Renata", 32));
  
  return candidatos;
 }
  
}

class Candidato {
 
 public String nome;
 
 public int idade; 
 
 public Candidato(String nome, int idade) {
  this.nome = nome; this.idade = idade;
 }

 @Override
 public String toString() {
  return "Candidato [nome=" + nome + ", idade=" + idade + "]";
 }
 
}



Para ilustrar vou extrair os menores de idade com algumas estratégias em Java e depois usando paradigma funcional em C#.


Java - exemplo 1 - usando lista temporária para adicionar os candidatos que aderem a regra:

public static void main(String[] args) {
 
 List<Candidato> candidatos = getCandidatosFromDataSource();
 
 List<Candidato> menores = menoresDeIdade(candidatos);  
 
 System.out.println(menores);
 
}

public static List<Candidato> menoresDeIdade(List<Candidato> candidatos) {
 List<Candidato> menores = new ArrayList<Candidato>();
 for (Candidato c : candidatos) 
  if (c.idade < 18)
   menores.add(c);
 return menores;
}

Este método funciona normalmente como uma implementação procedural. Java - exemplo 2 - usando lista temporária para remover os candidatos que não aderem a regra:

public static void main(String[] args) {
 
 List<Candidato> candidatos = getCandidatosFromDataSource();
 
 List<Candidato> menores = menoresDeIdade(candidatos);  
 
 System.out.println(menores);
 
}

public static List<Candidato> menoresDeIdade(List<Candidato> candidatos) {
 List<Candidato> menores = new ArrayList<Candidato>(candidatos);
 for (Candidato c : menores)
  if (c.idade > 18) menores.remove(c);
 return menores;
}

Esse método FALHA. Não é possível iterar e manipular uma lista simultaneamente. A seguinte exceção será lançada: Exception in thread "main" java.util.ConcurrentModificationException Na verdade, esse é um erro bem comum de programadores Java que não conhecem a API Collections. O método acima funciona se tu usares um ListIterator, que permite percorrer e manipular a lista. Exemplo corrigido:

public static List<Candidato> menoresDeIdade(List<Candidato> candidatos) {
 List<Candidato> menores = new ArrayList<Candidato>(candidatos);
 ListIterator<Candidato> iCandidato = menores.listIterator();
 while (iCandidato.hasNext()) {
  Candidato c = iCandidato.next();
  if (c.idade > 18) 
   iCandidato.remove();
 }  
 return menores;
}

Ok? Dúvidas, comentem.

 Java - exemplo 3 - especializando a coleção de Candidatos:

public static void main(String[] args) {
  
 Candidatos candidatos = new Candidatos(getCandidatosFromDataSource());
 
 System.out.println(candidatos.menoresDeIdade());
 
}


class Candidatos extends ArrayList<Candidato> {
 private static final long serialVersionUID = 0;

 public Candidatos() {
  super();
 }
 
 public Candidatos(Collection c) {
  super(c);
 }
  
 public Candidatos menoresDeIdade() {
  Candidatos menores = new Candidatos();
  for (Candidato c : this) 
   if (c.idade < 18)
    menores.add(c);
  return menores;
 }
}


Particularmente, acho essa solução mais elegante. Ela é orientada a objetos, bem diferente das outras, que chamavam um procedimento passando a lista de Candidatos (procedural). Alguns não gostam por que tem que criar classes, mas o que faz o programador de linguagens orientada a objetos senão modelar e criar classes?

 Dica: Não tenha medo de criar classes.

 O modo C# de fazer 

Assim como em outras linguagens, existem várias estratégias possíveis para fazer esta implementação. Os métodos utilizados em Java também podem ser usados em C#, mas existem duas formas particulares de fazer. Os exemplos a seguir são baseados no código abaixo: 

Arquivo Program.cs

using System;
using System.Collections.Generic;

class Program {

    static void Main(string[] args) {

        List<Candidato> candidatos = getCandidatosFromDataSource();

        // List<Candidato> menores = ??

    }

    public static List<Candidato> getCandidatosFromDataSource() {
        List<Candidato> Candidatos = new List<Candidato>();

        Candidatos.Add(new Candidato { Nome = "Alvaro", Idade = 23 });
        Candidatos.Add(new Candidato { Nome = "Vanessa", Idade = 13 });
        Candidatos.Add(new Candidato { Nome = "Paulo", Idade = 54 });
        Candidatos.Add(new Candidato { Nome = "André", Idade = 17 });
        Candidatos.Add(new Candidato { Nome = "Renata", Idade = 32 });

        return Candidatos;
    }

}

class Candidato {
    public string Nome { get; set; }
    public int Idade { get; set; }

    public override string ToString() {
        return "Candidato[Nome: " + Nome + ", Idade: " + Idade + "]";
    }
}

C# - exemplo 1 - usando yeld:

static void Main(string[] args) {

    List<Candidato> candidatos = getCandidatosFromDataSource();

    foreach(Candidato c in Menor(candidatos))
        Console.WriteLine(c);

}

public static IEnumerable<Candidato> Menor (List<Candidato> Candidatos) {
    foreach (Candidato p in Candidatos)
        if (p.Idade < 18) 
            yield return p;
}

Usando yeld return, é possível acumular os objetos em um IEnumerable, que mais tarde pode ser iterado exatamente como no exemplo.


C# - exemplo 2 - usando extension method, delegate e lambda: 

Tudo começa com esta classe de extensão:

static class Util {

    public static List<Candidato> SomenteSe(this List<Candidato> lista, Criterio crit) {
        List<Candidato> candidatos = new List<Candidato>();
        foreach (Candidato c in lista)
            if (crit(c)) 
                candidatos.Add(c);
        return candidatos;
    }

    public delegate bool Criterio(Candidato c);

}

Com ela posso retornar qualquer sublista de acordo com um Criterio, a definir. Melhor com um exemplo de uso:

static void Main(string[] args) {

    List<Candidato> candidatos = getCandidatosFromDataSource();

    foreach (Candidato c in candidatos.SomenteSe(c => c.Idade < 18))
        Console.WriteLine(c);

}

Neste exemplo o método SomenteSe é uma extensão de List<Candidato>. O parâmetro no parenteses é uma expressão lambda que representa o delegado que avalia o Criterio. É lida mais ou menos assim: para cada candidato c retorna verdadeiro se c.Idade for menor que 18. Essa é uma abordagem funcional, pois eu delego parte do processamento para uma função. 
<Candidato>

<Candidato> Na prática eu nem precisaria ter implementado por que o C# já tem uma API para lidar com coleções chamada LINQ. 
<Candidato>

<Candidato> C# - exemplo 3 - usando o LINQ: 
<Candidato>

 LINQ é o acrônimo de Language Integrated Query. O LINQ é usado para manipular coleções com vários tipos de implementações como: LINQ to Objects, LINQ to XML, LINQ to DataSet, LINQ to SQL, LINQ to Entities, e por aí vai. Cada biblioteca abstrai a manipulação de objetos, elementos ou nodos.

Para usar o LINQ para objetos é necessário declarar o namespace: using System.Linq;

A implementação fica assim:

static void Main(string[] args) {
    
    List<Candidato> candidatos = getCandidatosFromDataSource();

    foreach (Candidato c in candidatos.Where(c => c.Idade < 18))
        Console.WriteLine(c);

}


Se o critério será usado mais de uma vez basta declará-lo:


static void Main(string[] args) {
    
    List<Candidato> candidatos = getCandidatosFromDataSource();
    
    Func<Candidato, bool=""> menores = c => c.Idade < 18;
    
    foreach (Candidato c in candidatos.Where(menores))
        Console.WriteLine(c);

}


Outras linguagens 

 Só para constar, existem outras linguagens que usam o paradigma funcional como Ruby por exemplo. Para ilustrar colei abaixo a mesma funcionalidade feita com Ruby:

Arquivo candidatos.rb

def main
    candidatos = candidatos_from_data_source

    menores = candidatos.select { |c| c.idade < 18 }
    
    puts menores
end

def candidatos_from_data_source
    candidatos = [
        Candidato.new("Alvaro", 23),
        Candidato.new("Vanessa", 13),
        Candidato.new("Paulo", 54),
        Candidato.new("André", 17),
        Candidato.new("Renata", 32)
    ]
    candidatos
end

class Candidato

    attr_accessor :nome, :idade
    
    def initialize nome, idade
        @nome = nome
        @idade = idade
    end
    
    def to_s
        "Candidato[nome: #{@nome}, idade: #{@idade}]"
    end

end

main


Não é a toa que há demanda por programadores multiparadigma. Ainda conversava com o Leonardo esses dias sobre uma vaga em que pediam conhecimento de Haskell, que é uma linguagem puramente funcional. Posso falar mais em outro post/tópico, inclusive sobre Programação Orientada a Aspectos.

Qualquer dúvida, comentem.

1 de fev. de 2011

Strings no Java


Aproveitando a conversa com o Bruno sobre equals e == queria expor uma situação interessante. O modo como o Java lida com Strings tem sua particularidades que estão diretamente ligadas ao gerenciamento de memória. Por exemplo, no caso abaixo, a primeira assertiva é verdadeira, já que "aaa" é igual a "aaa", e a segunda assertiva é falsa, mesmo digitando "aaa" em "Outro texto". Se o operador == for substituído pelo método equals ambas assertivas retornam verdadeiro. Por quê?

public class Main {
    public static void main(String[] args) {

        String texto = "aaa";

        System.out.println("texto == aaa: " + (texto == "aaa") );

        System.out.print("Outro texto: ");

        String outroTexto = new Scanner(System.in).nextLine();

        System.out.println("texto == outroTexto: " + (texto == outroTexto) );

    }
}


O segredo está na arquitetura da memória no Java, embora existam algumas estratégias diferentes dependendo da implementação da máquina virtual, como a Java Hotspot, Oracle JRockit e o Apache Harmony.

Basicamente temos a memória divida como ...

  • ... uma pequena área chamada Stack (pilha), onde ficam as variáveis locais e chamadas de métodos (onde são empilhados). Por isso quando fazemos um encadeamento muito longo de chamadas, ou um processamento recursivo muito profundo, recebemos o erro: StackOverflowError. O Bruno teve um erro assim no C#;
  • ... um espaço maior, que é a memória disponível para os objetos, chamada Heap. Geralmente o Heap é divido em Young e Tenured (ver imagem abaixo), ou seja, objetos jovens ficam em parte de memória e se sobrevirem ao coletor de lixo são movidos para maduros (tenured), onde o intervalo de tempo para coleta é maior.
  • ... um espaço chamado Permanent Generation (geração permanente), onde ficam as informações carregadas que serão usadas durante todo o tempo de vida da aplicação, desde aberta até fechada. Nesta área ficam as classes por exemplo e outros dados estáticos, e também, e aí está o segredo, as String literais.


Toda String literal no programa, como o "aaa" no código, são instanciadas (new) e armazenadas no PermGen (não no Heap). Assim, quando novamente usamos "aaa", literalmente no código, ele utiliza aquela instância no PermGen. Isto é uma técnica para melhorar a performance e economizar memória, e foi por esse motivo que comparando "aaa" == "aaa" devolve verdadeiro, pois ambos apontam para a mesma String na memória. Agora no caso de usar new String("aaa") (como observou o Paulo), ou ler uma String de uma base de dados, console, parâmetro de uma requisição HTTP, enfim, tudo que não for literal, nós temos uma nova instância.

O resumo da ópera é, como disse o Leonardo, devemos usar o equals, que é implementado para comparar os atributos e não a posição na memória. No C#, é possível usar o operador == sempre, por que ele é sobrescrito na classe String para executar o método equals, ou seja, quando eu faço no C# "aaa" == "aaa", ele faz "aaa".equals("aaa").

Só mais um detalhe, se alguém aqui cria aplicações Web no Java e levanta no Tomcat, Glassfish, JBoss ou Jetty, já deve ter percebido que em desenvolvimento se for fazendo vários deploys, uma hora ou outra, tem que para o servidor e iniciar outra vez por que dá OutOfMemoryError: PermGen space. É por quê cada vez que a aplicação é implantada (deployada é horrível), as classes e Strings literais são novamente colocadas no PermGen e ele acaba estourando.

Algumas leituras sugeridas são:

The Structure of the Java Virtual Machine: http://java.sun.com/docs/books/jvms/second_edition/html/Overview.doc.html

Java HotSpot VM Options: http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html

Entendendo o NoSuchMethodError e o ClassLoader hell: http://www.arquiteturajava.com.br/livro/entendendo-nosuchmethoderror-e-classloader-hell.pdf

Começando com parâmetros e configurações da JVM: http://blog.caelum.com.br/comecando-com-parametros-e-configuracoes-da-jvm/

Mão sei se me fiz entender. Já passei por alguns problemas de performance e estabilidade com Java, por isso conheço um pouco dessa arquitetura.

Abraço a todos

20 de jan. de 2011

C# Extension Methods (e outros temas tranversais)

O problema

Quem aqui né amigo, não precisou de uma funcionalidade em um tipo básico e como não tinha acabou por criar classes com nome -tipo-Util.

Não entendeu? Bem, vou dar um exemplo. Imagine que no Java eu queira saber se uma String é um número (algo que seria útil no recebimento de parâmetros em requisições Web -que são todos string).

Não existe o método isNumber, isInteger, etc, em String. Existem métodos estáticos em Character, como isDigit.

Então, lá vem os TipoUtil's. Exemplo:

public class Main {
    public static void main(String[] args) {
        
        String parametro = "15.2";
        
        System.out.println(StringUtil.isInteger(parametro));    
    }
}

class StringUtil {
    
    public static boolean isInteger(String string) {        
        for (char c : string.toCharArray())
            if ( ! Character.isDigit(c)) return false;
        
        return true;        
    }
    
}

Neste caso, mostra: false.

Obs.: o método poderia ter sido implementado com expressões regulares.
Obs2.: Existem implementações de bibliotecas utilitárias por vários frameworks, como o Apache: http://commons.apache.org/lang/api-2.5/org/apache/commons/lang/StringUtils.html

E se eu chamar:
if ("641".isInteger()) System.out.println("É um Inteiro");

Não, embora pareça legível, não dá. Eu tenho que usar o método estático:
if (StringUtil.isInteger("641")) System.out.println("É um Inteiro");


Procedural vs Orientado a Objetos

Métodos Estáticos são implementações procedurais -sim, é possível programar proceduralmente em uma linguagem orientada a objetos.

O que denuncia isto é a passagem de um objeto para outro, o qual te dá informações sobre o primeiro. Em outras palavras, não é o próprio objeto que sabe de seu estado, eu tenho que passá-lo a outro para obter informações.

Algumas linguagens, mesmo adicionando orientação a objetos, tem aspectos procedurais. Por exemplo, não sei muito de PHP, mas pelo que conheço para saber o tamanho de um array devo chamar a função count (ou seu alias sizeof- corrijam-me se eu estiver errado):



Poderia ser assim:
echo $frutas.count(); // mas não é

Bem, o C#, assim como o Java, é uma linguagem com chamadas estáticas -o próprio Main é um caso. A implementação do isInteger, como foi feito no Java, a princípio não ficaria muito diferente, veja abaixo:

using System;

class Program {
    static void Main(string[] args) {

        string parametro = "123";
        Console.WriteLine(StringUtil.IsInteger(parametro));

    }
}

class StringUtil {
    public static bool IsInteger(string str) {
        foreach (char c in str.ToCharArray())
            if ( ! Char.IsDigit(c)) return false;
            return true;
    }
}

Quase a mesma coisa não é mesmo?

Então como alterar a classe String para que eu possa fazer "123".IsInteger()? Não tem jeito, a classe String é selada (sealed), ou seja, não é possível estendê-la.



Extension Methods

Entretanto, há um subterfúgio que pode deixar o código "menos feio", os Extension Methods, ou métodos de Extensão.

Exemplo:

using System;

class Program {
    static void Main(string[] args) {

        string parametro = "123";
        Console.WriteLine(parametro.IsInteger());

    }
}

static class StringUtil {
    public static bool IsInteger(this string str) {
        foreach (char c in str.ToCharArray())
            if ( ! Char.IsDigit(c)) return false;

        return true;
    }
}

É necessário adicionar a palavra-chave static na classe (uma classe estática só pode ter métodos estáticos) e a palavra-chave this no parâmetro.

Na prática, é um açúcar sintático, se por exemplo eu chamar: "9971".IsInteger()
O Runtime traduz para StringUtil.IsInteger("9971").

Legal, não? Existem várias implementações que são feitas com Extension Methods, inclusive nos Frameworks ORM da Microsoft, o Entity Framework ou o Linq to SQL.

Obs.: Algumas linguagens permitem que eu reabra qualquer tipo, mesmo os internos, como no Ruby. No Ruby eu posso adicionar qualquer método a qualquer classe em tempo de execução, como por exemplo um método para testar se é inteiro "123123".is_integer?. Abaixo a implementação usando o IRB:

class String
     def is_integer?
         self.to_i.to_s == self
     end
end

"23123".is_integer?
# devolve true
"231.23".is_integer?
# devolve false

Obs.: Na convenção de nomes do Ruby, métodos que retornam booleano terminam com ? (interrogação)


Cultura

Quando tu conheces mais de uma linguagem isto ajuda a mudar a visão, uma mudança de cultura. Por exemplo, em C# e Java, para transformar uma string em inteiro, normalmente chamamos um método estático (procedural) da classe Int32/Integer, como no exemplo:

C#:
int valor = int.Parse("12");

Java:
int valor = Integer.parseInt("12");

No Ruby, por exemplo, o método para converter uma string em inteiro está na própria classe string, exemplo:
"12".to_i

Então, como eu gosto dessa "forma" do Ruby, eu implemento em C# assim nos meus projetos:

public static class StringUtils {

    public static int ToInteger(this string text) {
        int number;
        return int.TryParse(text, out number) ? number : 0;
    }

}

Então eu posso fazer isso em C#:
"12".ToInteger();


Design com Exceções ou Não

Optei por fazer um design sem exceções, ou seja, se eu chamar "dsd".ToInteger() retorna 0. Se na implementação eu tivesse usado int.Parse poderia lançar uma exceção se a string não for válida.

O desenvolvedor sempre pode optar pode fazer o design de funcionalidades para exceção ou não, desde que seja elegante e de acordo com o contexto.

Por exemplo, em um sistema Web, se por exemplo for passado na URL o parâmetro domino/produtos?page=12, e a listagem tiver apenas 10 páginas, o que fazer? Mostrar uma tela de página inválida? Ou mostrar a última página (no caso 10)? Particularmente eu optaria por mostrar a última, e se a página fosse inválida (algo como page=dsfsd) eu mostraria a primeira.

Outro exemplo, se recebo na URL domino/cliente/action=excluir?id=200. O ID não existe, o que fazer? Eliminar o último ID? hehehehe, penso que não, este é um bom exemplo de lançar a exceção.

Cada caso é um caso. Não sei se me fiz entender.



Programação Funcional

O C# tem suporte ao paradigma de programação funcional. Ainda não abordei detalhes a respeito, mas adianto que é muito comum usar extension methods e delegados (ou lambdas).

Por exemplo, supondo que com frequência eu tenha que executar alguma tarefas certo número (finito) de vezes. Normalmente usamos um for com um contador, tipo, i = 0 e i < 20, certo? Bem, então eu posso criar um aspecto funcional, usando Extension Methods e Delegates (delegados) para fazer esse processamento, como no código abaixo:

public static class IntegerUtils {

    public delegate void Proc(int value);

    public static void Times(this int value, Proc proc) {
        for (int i = 0; i < value; i++) proc(i + 1);
    }
}

Para usar, um exemplo:
5.Times(delegate (int i) { Console.WriteLine("Iteração " + i); });

Ou, usando uma lambda:
5.Times(i => Console.WriteLine("Iteração " + i));


Obs.: O Ruby também tem suporte a programação funcional através de blocos e procs. Esta implementação que fiz no C# existe no Ruby e poderia ser feito assim:
5.times { |n| puts "Iteração #{n}" }


Acho que é isso. Se alguém testar e tiver algum erro poste aí, fiz os exemplo na correria.

Abraço a todos