Mostrando postagens com marcador Programação. Mostrar todas as postagens
Mostrando postagens com marcador Programação. Mostrar todas as postagens

12 de dez. de 2012

Conversão de números em strings

Emergiu uma pequena dúvida, se é mais adequado converter números para string usando o "gambi mode":
int i = 4;
String s = i + "";
Ou usando a API do Java:
int i = 4;
String s = String.valueOf(i);
Bem, em outros tópicos já falei sobre o funcionamento de Strings no Java, e inclusive no meu blog, que anda desatualizado, publiquei um post sobre Strings: http://marciojrtorres.blogspot.com.br/2010/06/strings-no-java.html

A questão é que o primeiro modo resulta na criação de uma nova String resultando da operador + sobrecarregado, e a segundo a partir da estrutura interna de Strings e Integer para criar uma String a partir de um array de char, onde muitos são constantes de Integer, podem verificar o código-fonte.

Na prática, o segundo modo é mais rápido, podem usar o código a seguir para testes:
public static void main(String[] args) {
    converteInteiroStringGambi();
    converteInteiroStringJava();
}

private static void converteInteiroStringGambi() {
    long inicio = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++) {
        String s = i + "";
    }
    System.out.println("Tempo decorrido: " + (System.currentTimeMillis() - inicio) + "ms");
}

private static void converteInteiroStringJava() {
    long inicio = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++) {
        String s = String.valueOf(i);
    }
    System.out.println("Tempo decorrido: " + (System.currentTimeMillis() - inicio) + "ms");
}
Atenção, não estou fazendo apologia ao segundo modo, usando String.valueOf, na verdade, podem seguir usando o primeiro, mas com a consciência de que é mais lento. A diferença é ínfima em uma ou duas operações esporádicas, mas evidente quando é usando dentro de iterações, como no exemplo. Enfim, sabendo as regras, é só saber quando segui-las e quando quebrá-las, é uma prerrogativa de programar deliberadamente e não por coincidência.

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

24 de dez. de 2010

Programador e Desenvolvedor: enfim, qual a diferença?

Este assunto é bem polêmico, para uns, programar e desenvolver significam a mesma coisa, para outros (como eu), são atividades distintas.

Então, um conceito de programador:

Um programador é um profissional preocupado com a qualidade do código - por isto também é chamado de coder. Normalmente, conhece muito uma determinada linguagem e tem sólidos conhecimentos de lógica e matemática. A sua atividade geralmente começa quando lhe é entregue uma especificação e, a partir desta, escreve o código necessário para cumpri-la. O programador geralmente atua em partes específicas da aplicação.

E o conceito de um desenvolvedor:

Um profissional preocupado com a qualidade do software. Normalmente tem um conhecimento mais interdisciplinar, não só da linguagem, mas de plataforma, tecnologia, negócio, administração. Com um olhar mais crítico, consegue avaliar soluções diferentes para o mesmo problema e selecionar aquela que tem o melhor custo benefício para o domínio do problema. O desenvolvedor geralmente está preocupado com a big picture e esforça-se para pensar fora da caixa.

Pré-conceitos, conceitos e pós-conceitos, por aí ...

Neste blog, é argumentado que o trabalho realizado por programadores e desenvolvedores é fruto das mudanças de mercado. Compara o desenvolvimento de software a uma linha de montagem de uma fábrica e o programador àquele funcionário que executa uma determinada pequena tarefa.

Neste outro, achei interessante a abordagem sobre o aspecto social de programadores e desenvolvedores; embora não concorde em totalidade.

Alguns são mais contundentes, ao ponto de dizer "seja um desenvolvedor, não um programador". Também não acho que é por aí, penso que se alguém é feliz codificando, sem as dores de cabeça do desenho e arquitetura, que mal há?

Para descontrair: vida de programador/desenvolvedor ...




Tem certeza que deseja seguir nesta carreira?

21 de jan. de 2010

ActionScript por um programador Java: parte 2


Mais uma semana de desenvolvimento com Flex e ActionScript, mais algumas diferenças para o Java.

- Em ActionScript não é possível sobrecarregar um construtor ou um método, por exemplo, em Java posso fazer isso:

public void pagamento(Date dataPagamento, Double valor) { ... }
public void setPagamento(Double valor) { ... }

*Caso se o vencimento for omitido eu possa usar a data atual como data do pagamento.

Em ActionScript dá para fazer assim:

public function pagamento(valor:Number, data:Date=null) : void  { ... }

Nesta caso assumo a data com o valor padrão null, tornando o parâmetro opcional. Note, os parâmetros obrigatórios sempre tem que vir primeiro, como o valor. 

Agora posso chamar este método assim:  instancia.pagamento(100); ou assim: instancia.pagamento(100, new Date(2010, 1, 10));


- No ActionScript também existe algo semelhante ao varargs do Java, chamado de "rest". Posso declara o método como abaixo:

public function pagamento(valor:Number, ... outrosArgumentos) : void  { ... }

Neste caso, as reticências declaram um argumento "rest", que é um Array e pode ser iterado no corpo do método. Assim como no Java o argumento rest (varargs no Java) tem que ser o último argumento. No Java é assim:

public void pagamento(Double valor, Object ... outrosArgumentos) { ... }

ou 

public void pagamento(Double valor, Date ... datas) { ... }

Neste caso posso chamar este método definindo ou não o segundo argumento (terceiro, quarto...). Note que Java é tipado, ou seja, não há definição de tipo no Runtime como no ActionScript então ele deve fazer parte dos argumentos, diferente do AS.


- No ActionScript as funções são objetos e podem ser atribuídas a uma variável como abaixo:

var pagamento:Function = function (valor:Number) : void { ...}

Também podem ser passadas como parâmetros, como abaixo:

public function fazAlgo(metodo:Function) { ... }
Isto é especialmente útil para delegar ou fazer callbacks, caso dos retornos de chamadas no tratamento de Eventos, como abaixo:

btPagamento.addEventListener(MouseEvent.CLICK, pagamento);

Neste caso, pagamento é uma função. No C# é semelhante. Particularmente acho este método de tratamento de eventos muito melhor que no Java que usa o padrão Observer/Observable para implementar.

Bom, por enquanto é só, escrever ajuda a memorizar.

ActionScript por um programador Java



Já tive um pouco, pouco mesmo, de contato com ActionScript quando fazia testes 'domésticos' com Adobe Flex, mas nesta semana, graças a oportunidade de participar do Projeto da Vonpar, que é baseado em Back-end Java e Front-end Flex, comecei a observar as primeiras nuances, prós, contras, entre outros, claro, na minha perspectiva de desenvolvedor Java.

Todos que já leem esta lista e acompanham as minhas mensagens já devem saber que sou adepto do conceito: Não é a linguagem, mas o programador que faz um bom sistema.

ActionScript é uma linguagem orientada a objetos e como tal é muito semelhante a Java, C#, etc. Acredito que a principal barreira para um programador, como foi o meu caso que programa em linguagens procedurais, é entender OO.

Então, penso que para aprender uma nova linguagem baseada mesmo paradigma, a receita é:

1 - Prestar atenção na sintaxe:

   Várias vezes declarei um método assim:
   public void setValor(Double valor) {...}

   Quando deveria ser feito assim:

   public function setValor(valor:Number) : void 


{...}





   A diferença é auto-explicativa, apenas sintaxe e tipos.

2 -  Descobrir os recursos ausentes e usar outras estratégias (não confundir com Workarounds):

   Por exemplo, não tem Enumerado no ActionScript 3, então ...
   Usar os velhos campos estáticos constantes, como no Java 1.4  (enums vieram a partir do 5)

   Quase sempre é possível achar uma maneira elegante.

3 - Descobrir os recursos presentes na nova linguagem:

   Tchê, muito bom o recurso de declarar métodos de leitura e gravação (get e set) e ler como se fosse um atributo, basta fazer assim:



public function set valorConta(valor:Number) : void { /* lógica aqui */ }

   public function get valorConta() : Number { /* lógica aqui */ }

   Se a classe se chama Conta, eu posso acessar o valor de outra classe em uma instância da Conta assim:

   conta.valorConta    OU    conta.valorConta = 200;

   Pode parecer um atributo, mas é um get e set (acessores implícitos).

Uma dificuldade especial é trabalhar com a arquitetura assíncrona de requisição e resposta, mas para quem já uso JavaScript XML HTTP Request (Ajax no braço) é fácil se acostumar.

Estou de saída, e existem outros detalhes que deixarei para outro post.