terça-feira, 22 de abril de 2014

Vi IMproved, mais conhecido como Vim!

Fala galera, tudo bom?

Há um tempo atrás prometi que iria falar a respeito do editor de texto Vim, e hoje o assunto é esse.
Para começar, que tal instalar o Vim no seu pc/mac?

Quem tem Linux ou MacOS como Sistema Operacional, muito provavelmente já vem instalado, só ir até terminal e digitar:
vim --version

Caso você não possua instalado é só baixar no link ao lado: vim.org.





O Vim (Vi IMproved) é uma versão melhorada do antigo VI, é um excelente e produtivo editor de texto modal, hoje conheceremos os 2 modos básicos:
Insert: O modo de inserção, onde podemos editar texto normalmente.
Command: No modo de comando temos algumas maneiras eficientes de navegação e edição de texto.

Agora vamos a prática, crie um novo arquivo e abra-o em seu terminal ou editor Vim para aprendermos.

A primeira coisa são os modos, assim que você abre o arquivo, está no modo command, como citado acima, pode navegar pelo documento e manipular textos.

Para começarmos a inserir texto digite i, entrará no modo de inserção, vamos fazer um hello-world.html:
  
    <html>
    <head>
      <title>Hello World</title>
    </head>
    <body>
      <h1>Hello World :)</h1>
    </body>
    </html>

Feito isso, vamos treinar algumas comandos no modo command, basicamente para navegação simples:
  • h: para navegar a esquerda.
  • j: para navegar para baixo.
  • k: para navegar para cima.
  • l: para navegar a direita.
Pratique esses movimentos, caminhe pelo nosso hello-world.html.
Próxima lista de comandos básicos:
  • G: para ir até a última linha do arquivo.
  • gg: para ir até a primeira linha do arquivo.
  • w: para navegar de palavra em palavra para frente.
  • b: para navegar de palavra em palavra para trás.
Pratique esses movimentos, navegue pelo nosso hello-world.html.
E aí, sentindo dificuldades? É só acostumar, depois fica tudo mais simples. Vamos para comandos de copiar, colar e deletar:
  • yy: você copia uma linha.
  • p: você cola uma linha.
  • dd: você recorta a linha.
Bom, agora vamos misturar as coisas, os comandos também aceitam uma quantidade específica de vezes que eles devem ser executados, como funciona?
( <repetição> <comando> )
  • 2h : para navegar 2 vezes para a esquerda.
  • 4k : para navegar 2 linhas acima.
  • gg yG : copiar todo o arquivo.
  • 3w : para navegar 3 palavras a direita.
  • 2b : para navegar 2 palavras a esquerda.
  • 10dd para recortar 10 linhas a partir da atual.
  • 8p para colar 8 linhas a partir da atual.
Bom, essa é a hora da sua imaginação fluir e ir tentando coisas novas e não se prenda aos poucos ensinamentos que passei hoje, busque muito mais.

E a boa de hoje?
Venho acompanhando o Drew Neil do VimCast e estou aprendendo milhares de coisas novas a cada vimcast. Esse site da UniRio também me ajudou muito no início e não deixe de acompanhar meu blog, prometo escrever mais a respeito do Vim.

Qualquer dúvida email-me abner.terribili@lambda3.com.br ou comente abaixo.


segunda-feira, 24 de março de 2014

Haskell: Operações Recursivas em Listas

Fala galera, tudo tranquilo?

Hoje o assunto é bem bacana, venho fazendo uma listinha de exercícios marotos em Scala, e estou aprendendendo muito. Hoje o assunto é recursividade, de novo esse assunto? Sim isso está mudando minha vida ou mesmo a forma como penso. (Exagerando rs)

Então, vamos fazer em Haskell?

A ideia é simples, quero deixar bem claro e simples as operações em listas imutáveis usando recursividade, já expliquei algo sobre listas imutáveis aqui.

Bom, vamos começar com um problema, que tal fazermos um map* em uma lista.

* = Para quem não sabe, mapear uma lista é transformar cada valor da lista atual, em um valor que passará através de uma determinada função.

Crie um novo arquivo, double.hs, como não falo há pouco de tempo de Haskell, nos meus primeiros posts, você consegue ver como instalar o interpretador Hugs.

Vamos ao double.hs:

double [] = []
double (head:tail) = head * 2 : double tail

Bom, isso aí já torna a compreensão pouco simples, mas vou explicar, entenda:  double [] = [] é a nossa guarda, ou seja, um ponto onde devemos parar a execução da função. Já falei muito a respeito em posts mais antigos.
Já na segunda linha, vemos algo novo, mas acredito ser bem expressivo, double (head:tail), ali estamos separando a cabeça da lista, de seu corpo, faremos uma operação na cabeça (head *2) e concatenaremos com o corpo, mas passando o corpo como argumento da função double, repetiremos esse processo novamente, isso é incrível e simples.

Para exercitar, primeiro vamos deixar nosso double mais genérico, pois podemos querer fazer outros tipos de map em lista, crie um arquivo mapear.hs:

mapear f [] = []
mapear f (x:xs) = (f x) : mapear f xs

Pronto, agora nossa função está apta a receber outras funções a serem aplicadas a lista, você pode testar no Hugs.

Vá ao seu terminal, caminhe até o diretório do arquivo e digite: hugs mapear.hs

Para construir listas em Haskell, você pode usar de duas formas:

[1,1,2,3,5,8]
1 : 1 : 2 : 3 : 5 : 8 : []

Agora é só passar os parâmetros para sua função: mapear (*2) (1 : 2 : 3 : [])

Use os parênteses para "separar" os argumentos. Tudo certo! (Ou deveria estar).

Vamos evoluir mais um pouco, outra das operações básicas que podem ser efetuadas com lista é o Filter, onde você filtra os elementos da lista e só extraí o que "passar pelo filtro". Basicamente vamos passar uma validação para cada elemento da lista, e como fazer? Crie um arquivo filtro.hs e vamos codar nele:

filtro :: (a -> Bool) -> [a] -> [a] 
filtro f [] = []
filtro f (x:xs) | f x = x : filtro f xs
                | otherwise = filtro f xs

Trabalhamos com quase a mesma forma de aplicar a função do mapear, porém fizemos uma verificação, onde:

  •  | é a nossa verificação;
  • caso f x retorne false:
    • devolvemos só  filtro f xs;
  •  caso f x retorne true:
    • concatenamos a cabeça x ao filtro f xs;


Ou seja, como vamos navegando na lista, cada hora a cabeça é o elemento posterior, isso é muito simples. Já falei de estruturas de verificação.

O desafio de hoje é meio trabalhoso, caso a preguiça domine vai ter que esperar eu fazer aqui também pra disponibilizar no Github. Você deve implementar um Flatten, ou seja, caso receba uma lista de listas, deve devolver uma lista contendo todos os elementos das listas internas.

É isso aí gente, qualquer dúvida comente abaixo ou email-me: abner.terribili@lambda3.com.br.



segunda-feira, 17 de março de 2014

Java, C#: Substituindo o Switch com Polimorfismo

Fala galera, tudo tranquilo? Passado o Carnaval, espero que tenham se divertido, eu estou há uma semana sem escrever e hoje, vou escrever algo não muito novo. O exemplo acontece em Java, mas é simples de replicar em C#, acredite.

Recebi um desafio na faculdade, de escrever uma estrutura de tomada de decisão, aquela famosa "coisa bizarra" chamada Switch.

Imagine o seguinte, nós temos 4 regiões, sendo elas: Sul, Norte, Leste e Oeste. E para cada valor setado, desejo retornar uma região diferente, por exemplo:

Região Valor
Sul 2
Norte 3
Leste 5
Oeste 7

Com essa tabela ficou mais claro, se eu passar como parâmetro o valor 2, quero receber a região Sul. Bom, escrevendo o teste, poderemos refatorar depois, certo?

Crie um projeto no Eclipse/Visual Studio, e dê o nome de SubstituindoSwitch, feito isso, crie um source folder de test e crie um pequeno teste de unidade, em seu interior:

public class SustituindoSwitchTest {

    @Test
    public void DeveBuscarRegiaoSul() {
        Assert.assertEquals("Sul", new SubstituindoSwitch().buscaRegiao(2));
    }

    @Test
    public void DeveBuscarRegiaoNorte() {
        Assert.assertEquals("Norte", new SubstituindoSwitch().buscaRegiao(3));
    }

    @Test
    public void DeveBuscarRegiaoLeste() {
        Assert.assertEquals("Leste", new SubstituindoSwitch().buscaRegiao(5));
    }

    @Test
    public void DeveBuscarRegiaoOeste() {
        Assert.assertEquals("Oeste", new SubstituindoSwitch().buscaRegiao(7));
    }

}

Agora vamos resolver da forma mais simples. E o Switch cai como uma luva certo? Olha ele aí:

public class SubstituindoSwitch {

    public String buscaRegiao(int valor) {

        switch (valor) {
        case 2:
            return "Sul";
        case 3:
            return "Norte";
        case 5:
            return "Leste";
        case 7:
            return "Oeste";
        default:
            return "Região não encontrada.";
        }
    }
}

Bom, resolvemos o problema certo? Sim! Mas se temos toda aquela história de orientação a objetos e polimorfismo, por que usamos essa estrutura forrada de responsabilidades e totalmente procedural?

Podemos começar a pensar apenas em dividir as responsabilidades, ali no switch ficou claro que nossa classe SubstituindoSwitch tem uma grande responsabilidade de avaliar e claro devolver o retorno esperado e isso não é nada vantajoso. Vamos tentar encontrar semelhanças na responsabilidade. Para todas as situações um determinado valor é avaliado e caso seja ele o correto, recebemos uma String. E aí identificamos uma responsabilidade, vamos construir uma interface para esses responsabilidade:

public interface Regiao {
    public boolean avalia(int valor);

    public String procedencia();
}

Pronto, já definimos a responsabilidade, agora precisamos delegar os respectivos comportamentos, sabemos que o quando o valor for 7, desejamos receber a string Oeste, ok?

public class Oeste implements Regiao {
    @Override
    public boolean avalia(int valor) {
        return valor == 7;
    }

    @Override
    public String procedencia() {
        return "Oeste";
    }
}

E podemos fazer isso para todas as outras três regiões esperadas(Sul, Norte e Leste), cada uma dessas regiões com a mesma responsabilidade mas diferentes comportamentos. Certo? Implemente as outras classes para podermos dar continuidade. Caso a preguiça domine, vá até meu Github.
Agora voltaremos a nossa classe SubstituindoSwitch, e faremos algumas pequenas modificações, a primeira de todas é apagar o devorador de responsabilidades switch:

public class SubstituindoSwitch {
    private List<Regiao> regioes;

    public SubstituindoSwitch() {
        regioes = new ArrayList<>();

        regioes.add(new Sul());
        regioes.add(new Norte());
        regioes.add(new Leste());
        regioes.add(new Oeste());

    }

    public String buscaRegiao(int valor) {

        for (Regiao regiao : regioes) {
            if (regiao.avalia(valor))
                return regiao.procedencia();
        }

        return "Região não encontrada.";
    }
}

Vou tentar ao máximo deixar claro o que está acontecendo no código acima, a primeira coisa que fizemos foi definir uma lista de regiões, ou seja, uma lista que armazenará todas as opções de regiões possíveis. Nosso método buscaRegiao continuou recebendo o parâmetro valor, mas ele não mais detém a responsabilidade de conter os valores das regiões, ele apenas delega a responsabilidade de acordo com uma avaliação também executada por cada responsável pelo valor, poxa, perdi até o fôlego. Detalhando:

if (regiao.avalia(valor)) return regiao.procedencia();

Esse if passa o valor para a região, a região detém o comportamento esperado e ela retorna o resultado desejado. Bom, só rodar os testes, e se maravilhar com o resultado. Bom, o próximo desafio é substituir o if, aí já envolve um pouco mais de estudo. :P

Qualquer dúvida, comente abaixo ou email-me: abner.terribili@lambda3.com.br.

Se surgir dúvidas, tem o exemplo lá no meu Github:
Para os Java: https://github.com/aterribili/SubstituindoSwitch
Para os C#: https://github.com/aterribili/SubstituindoSwitch-CSharp


Abraços!

segunda-feira, 10 de março de 2014

Java: Polimorfismo e suas diversas formas (Parte 2)

Fala galera, beleza?

Hoje vou dar continuidade ao assunto Polimorfismo e suas diversas formas, para que não leu Polimorfismo Parte 1.

E faremos algumas mutretas usando os poderes do Polimorfismo.

Imagine a situação onde você precisa categorizar 3 objetos diferentes que partilhem dos mesmos atributos, em um dos meus exercícios com o Jonas, na Lambda3, nós fizemos, com fins educacionais, um mini avaliador de endereços web, que retorna os corretos endereços.

Basicamente, vamos criar um novo projeto Java no Eclipse. Vamos manter o costume e escrever um teste básico:

@Test
public void deveRetornarDominioBuscape(){
   ProcessadorUrl processador = new ProcessadorUrl("buscape");

   Assert.assertEquals("http://www.buscape.com.br", processador.dominio());
}

@Test
public void deveRetornarParametroBuscape(){
   ProcessadorUrl processador = new ProcessadorUrl("buscape");

   Assert.assertEquals("p", processador.parametro());
}

@Test
public void deveRetornarCookie(){
   ProcessadorUrl processador = new ProcessadorUrl("buscape");

   Assert.assertEquals("bp", processador.cookie());
}

Definido nosso teste, podemos criar uma classe para satisfazer o teste:
public class ProcessadorUrl {
   private String dominio;

   public Dominio(String dominio){
      this.dominio = dominio;
   }

   public String dominio(){
      if(dominio=="buscape")
         return "http://www.buscape.com.br";
      if(dominio=="bondfaro")
         return "http://www.bondfaro.com.br";
      return "";
   }

   public String parametro(){
      if(dominio=="buscape")
         return "p";
      if(dominio=="bondfaro")
         return "b";
      return "";
   }  

   public String cookie(){
      if(dominio=="buscape")
         return "bp";
      if(dominio=="bondfaro")
         return "bf";
      return "";
   }
}

Pronto, conseguimos satisfazer nosso teste, mas espera aí, se o tema é Polimorfismo, por que estamos fazendo nessa forma procedimental?

Consegue ver que nossa classe ProcessadorUrl possui muitas responsabilidades? Ela é obrigada a avaliar o dominio, parametro e o cookie? Acho que para nossos "sites" temos características semelhantes, para todos os sites devemos ter metodos que busquem o domínio, parâmetro e cookie, certo? Então vamos para a Orientação a Objetos.

E como fazer bom uso do polimorfismo nesse caso? Antes de prosseguir, rode seus testes. Crie mais alguns para o bondfaro. Divida as responsabilidades, nossa classe ProcessadorUrl, deve apenas reconhecer o parâmetro String de dominio, e retornar o objeto correto. Creio ser uma boa forma de início.

ProcessadorUrl = deveria apenas avaliar dominio
Buscape = ter os atributos dominio, parametro e cookie
Bondfaro = igual Buscape

Vamos refatorar nossas classes:

De início vamos montar nossa classe ProcessadorUrl:

public class ProcessadorUrl{
   private String dominio;

   public Dominio(String dominio){
      this.dominio = dominio;
   }

   Site avaliaDominio(){
      if(dominio=="buscape")
         return new Buscape();
      if(dominio=="bondfaro")
     return new Bondfaro();
      throw new RuntimeException("Não foram encontrados registros");
   }
}

Já evitamos aquele retorno horrível de String vazia, dividimos mais a responsabilidade da nossa Classe ProcessadorUrl, agora vamos aos nossos "Sites". Podemos notar comportamentos semelhantes, como dito acima, sabendo disso que tal criar uma interface que delega as responsabilidades que os objetos devam implementar.

Crie uma Interface Site, onde teremos os seguintes métodos:

public interface Site(){

String Dominio();
String Parametro();
String Cookie();
}

Para completar podemos criar a classe Buscape, que implementará a interface Site:

public class Buscape implements Site {

    @Override
    public String dominio() {
        return "http://www.buscape.com.br";
    }

    @Override
    public String parametro() {
        return "p";
    }

    @Override
    public String cookie() {
        return "bp";
    }

}

Feito isso, rode seus testes! E aí o que rolou? Um problemão (rs), devemos refatorar nosso teste, agora ele também trabalha com objetos.

@Test
    public void deveRetornarDominioBuscape(){
       ProcessadorUrl processador= new ProcessadorUrl("buscape");

       Assert.assertEquals("http://www.buscape.com.br", processador.avaliaDominio().dominio());
    }

    @Test
    public void deveRetornarParametroBuscape(){
       ProcessadorUrl processador= new ProcessadorUrl("buscape");

       Assert.assertEquals("p", processador.avaliaDominio().parametro());
    }

    @Test
    public void deveRetornarCookie(){
       ProcessadorUrl processador = new ProcessadorUrl("buscape");

       Assert.assertEquals("bp", processador.avaliaDominio().cookie());
    }

O retorno do objeto não é muito explícito, mas nosso processador, possui o método avaliaDominio() que retorna um objeto do tipo Site, isso mesmo, assim podemos buscar os devidos comportamentos das devidas implementações da interface Site.

Legal né? Você então, usando Polimorfismo com uso de interfaces, pode fazer com que seus objetos partilhem os mesmas responsabilidades e direfentes comportamentos, evitando assim Heranças.

Aqui terminamos mais um exemplo do bom uso do Polimorfismo. Se surgir alguma dúvida, corre lá no meu Github

E a dica de hoje é, na verdade pergunta, já sabe usar o controlador de versões Git? Caso não e esteja afim de aprender, o Jonas tem feito um bom trabalho com uma mistura de prática e jogos: Git Game

Bom, por hoje é só galera. Qualquer coisa email-meabner.terribili@lambda3.com.br ou comente abaixo.

segunda-feira, 3 de março de 2014

C#: Um suporte a funções

Fala aí galera!

Seguindo os posts atuais sobre C#, em uma das minhas aulas com o Jonas, descobri uma das maravilhas de C# e seu "pequeno" suporte a programação funcional.

Hoje faremos algo bem prático. Vamos criar um exemplo genérico de um método que recebe três parametros, sendo eles: int, int, função.

Comecei hoje a leitura de um livro muito bacana: Código Limpo - Robert C. Martin. (Que já me proíbe a criação de uma função que recebe três parâmetros, mas vamos relevar isso rs) Parece muito bom, como o nome diz é um livro que através da pratica deliberada, nos "promete" o conhecimento para distinguir um bom código de um código ruim, digo isso como dica a todos vocês leitores, e que também é mais uma das minhas lições no desenvolvimento de software. (E o VIM galera, estão usando?)
Se ainda faltam alguns conceitos de paradigma funcional, dê uma lida nos meus posts anteriores, sempre estou com esse tema em pauta.

Vamos a prática.
Crie um projeto novo no seu Visual Studio e dê um nome bacana e objetivo.

Dei o nome de AprendendoFunc, na minha opinião, objetivo.

Segundo passo, vamos criar os Testes:

Cria uma nova Solution, dentro dela crie um projeto Class library e outro Projeto de Test Unit. Então a primeira coisa que vamos testar é uma possível soma entre dois números:

...
[TestMethod]
public void DeveSomarDoisNumeros()
{
    Func<int, int, int> funcaoSoma = (x, y) => x + y;

    Assert.AreEqual(120, new Calculadora().Calcula(60, 60, funcaoSoma));
}

Claro que nosso teste apresentará alguns erros, porém com ele já sabemos qual o nosso objetivo.

Nossa classe Calculadora, deve possuir um método que recebe 3 parâmetros. A função acima (funcaoSoma) é uma função que vem lá da matemática, entenda:

Func<parametro, parametro, tipoRetorno> nomeFuncao = (parametro, parametro) => funcao;

Ficou simples de entender, certo? Passamos dois números inteiros e recebemos o resultado da operação da função passada, isso é incrivel! Dizem as más linguas, ou boas, que o F# tem um pézinho aí!

Agora vamos implementar nossa classe Calculadora:
...
public class Calculadora()
{
    public int Calcula(int primeiroNumero, int segundoNumero, Func<int, int, int> funcao)
    {
        return funcao(primeiroNumero, segundoNumero);
    }   
}

Pronto, nossa Calculadora está pronta para receber os parâmetros corretos. Agora rode seus testes e assegure-se do resultado estar correto.

Feito isso, crie mais um método de teste que deve executar a multiplicação de dois números. É muito fácil né?

Bom, e se precisarmos fazer algum tipo de comparação? Um exemplo prático, ao tentar dividir o primeiroNumero pelo segundoNumero, poderemos encontrar um problema caso segundoNumero = 0, para evitar isso, podemos criar mais um método:

public class Calculadora(){
    ...
    public int VerificaECalcula(int primeiroNumero, int segundoNumero, Predicated<int> verificacao, Func<int, int, int> funcao)
    {
        if(verificacao(primeiroNumero, segundoNumero)
        return funcao(primeiroNumero, segundoNumero);
    return 0;
    }
}

Entenda: Predicated recebe apenas um parâmetro e retorna um booleano, é amplamente usado para verificações, acredite. Temos também o Action, que é void, mas não é útil no nosso exemplo.
Vamos ao teste?

...
[TestMethod]
public void DeveCalcularDivisaoComVerificacao()
{
    // Aqui podemos fazer as três etapas em uma só linha: Setup, Execução e Verificação
    Assert.AreEqual(0, new Calculadora().VerificaECalcula(100, 0, (y) => y > 0, (x, y) => x / y));
}

Pronto, assim podemos passar a função de verificação e ainda a função de execução, isso sim é incrível.

Bom galera, por hoje é só, qualquer dúvida email-me: abner.terribili@lambda3.com.br ou comente abaixo!


segunda-feira, 24 de fevereiro de 2014

C# : Polimorfismo nas suas diversas formas (Parte 1)

Fala aí galera.
Hoje o assunto é bem objetivo, vamos falar a respeito de Polimorfismo.

O que é Polimorfismo?
A primeira vista, parece algo como "Várias Formas", na verdade não é tudo isso. Encontrei uma definição bem interessante dada pelo Ivan Ricarte, da Unicamp, onde: "Polimorfismo é o princípio pelo qual duas ou mais classes derivadas de uma mesma superclasse podem invocar métodos que têm a mesma identificação (assinatura) mas comportamentos distintos, especializados para cada classe derivada, usando para tanto uma referência a um objeto do tipo da superclasse. A decisão sobre qual o método que deve ser selecionado, de acordo com o tipo da classe derivada, é tomada em tempo de execução, através do mecanismo de ligação tardia."

Bom e aí, será que ficou claro? Talvez com um exemplo mais simples, dê para entender.

Vou escrever em C#, é bem simples de replicar em Java.
Imagine que você tenha a necessidade de fazer com que Diferentes Classes possuam comportamentos semelhantes:

Em um dos meus exercícios aqui na Lambda3, tive que construir um "processador de URL's", algo que avalia o conteúdo de uma URL e de acordo faz determinada ação.

Nosso processador, não precisa encapsular diversos métodos, pois assim estaríamos dando muita responsabilidade para apenas uma classe, então basicamente o que nosso processador fará é Armazenar uma

Armazenará uma URL e a processará.

ProcessadorUrl:
class ProcessadorUrl
{
    private readonly String endereco;

    public ProcessadorUrl(String url) { this.endereco = url;}

    public String ProcessaUrl() { return endereco; }
}

Feito isso, da pra entender um pouco o que precisamos fazer. Basicamente, agora faremos as classes avaliadoras:
Farei apenas duas, para compreensão simples.

Primeira classe avaliadora:

class AvaliadorGoogle
{
    private readonly String endereco;
    
    public AvaliadorGoogle(String endereco) { this.endereco = endereco; }
    
    public bool Avalia() { return endereco.Contains("google"); }
        
    public string Executa() {
            return endereco.Replace("google", "bing"); }
}

Segunda classe avaliadora:

class AvaliadorAsdrubal
{
    private readonly String endereco;
    
    public AvaliadorAsdrubal(String endereco) { 
       this.endereco = endereco; }
    
    public bool Avalia() { 
       return endereco.Contains("asdrubal"); }
        
    public string Executa(){ 
       return endereco.Replace("asdrubal", "outro"); }
}

Agora nosso processador de URL pode fazer as comparações e retornar o necessário:

class ProcessadorUrl
{
    private readonly String endereco;
        
    public ProcessadorUrl(String url) { this.endereco = url; }
        
    public String ProcessaUrl()
    {
        if(new AvaliadorGoogle(endereco).Avalia())
               return new AvaliadorGoogle(endereco).Executa(); 
        if(new AvaliadorAsdrubal(endereco).Avalia())
               return new AvaliadorAsdrubal(endereco).Executa();
        return "";
    }
}

Então podemos notar que ambas classes, AvaliadorGoogle e AvaliadorAsdrubal, possuem comportamentos semelhantes, por que não fazer uso do Polimorfismo?

Crie uma nova Interface e de o nome de Avaliacao:

interface Avaliacao {
    bool Avalia();
    String Executa();
}

Agora os nossos Avaliadores implementarão essa interface:

class AvaliadorAsdrubal : Avaliacao
{
    private readonly String endereco;

    public AvaliadorAsdrubal(String endereco) { 
       this.endereco = endereco; }

    public bool Avalia() { 
       return endereco.Contains("asdrubal"); }
    
    public string Executa() { 
       return endereco.Replace("asdrubal", "outro"); }
}

Faça o mesmo para o avaliador Google e beleza! Vamos a classe que processa, podemos fazer bom uso do Polimorfismo:

public class ProcessadorUrl
  {
        private readonly String endereco;
        
        public ProcessadorUrl(String url)
        {
            this.endereco = url;
        }
        
        public String ProcessaUrl()
        {
           List<Avaliacao> lista = new List<Avaliacao>();
           lista.Add(new AvaliadorGoogle(endereco));
           lista.Add(new AvaliadorAsdrubal(endereco));
         
           for (var i = 0; i < lista.Count; i++){
               if(lista[i].Avalia()
                  lista[i].Executa();
           }
           return "";
        }
  }

Conseguiram compreender um bom uso do polimorfismo?

Criamos uma Lista de Objetos que implementam a interface Avaliação. Essa, como diz o Jonas, é a parte gostosa da "Herança" :).

Exemplos no meu Github:
https://github.com/aterribili/Mapeando
https://github.com/aterribili/AvaliacaoEnderecosWeb

Qualquer dúvida email-me: abner.terribili@lambda3.com.br ou comente abaixo.

Valeu galera!


segunda-feira, 17 de fevereiro de 2014

Java, C# : Imutabilidade

Fala galera, tudo tranquilo?

Você já teve interesse de conhecer como são as implementações de Listas ? (List do C#, Java)

Basicamente, as interfaces(List) definem os tipos de operações que podem ser realizadas nas Lista. Vou escrever algo bem bacana, faremos uma implementação de Lista Imutável.

Imutabilidade
Basicamente, é uma característica de um objeto permanecer o mesmo sempre. Quer saber mais sobre Imutabilidade: Bruno Nardini http://www.brunonardini.com.br/artigos/favoreca-a-imutabilidade-e-a-simplicidade

A classe String, tanto do Java quanto C# , encapsula alguns métodos de manipulação de String, como o toUpperCase() (C# = ToUpper()), que têm o objetivo de converter sua string para maiúsculo. Porém por baixo dos panos, o que acontece é você receberá uma nova instância, com o conteúdo de sua string antiga convertida para maiúsculo. (Você pode verificar isso nos links acima)

Já definido o que é Imutabilidade, vamos ao conceito básico de Listas Ligadas (Linked List). (http://www.caelum.com.br/apostila-java-estrutura-dados/listas-ligadas/#5-1-solucao-classica-de-lista-ligada)

Uma Lista Ligada é uma lista onde o elemento atual "aponta"(tem o endereço) para/do o seu próximo irmão, analisem a fotografia abaixo:



Um conceito simples, agora vamos a prática, assim podemos misturar os dois conceitos! (Imutabilidade e Linked List). No exemplo vai rolar um pouco Generics, se já sabe legal, caso não: http://en.wikipedia.org/wiki/Generic_programming#Generics_in_Java .

Primeiro, vamos criar uma interface para nossas listas, para isso, crie um projeto novo no Eclipse, dê um nome e vamos lá:

New -> Interface

public interface List {
    T cabeca();
    List cauda();
    List adicionaNoComeco(T elemento);
    T pegaPosicao(int position);
    List removePrimeiraPosicao();
}

Bom e o que é cabeça e cauda?
Cabeça é o elemento superior de nossa lista, ou seja a head da Lista.
Cauda é todo o restante da lista, é composta por sua cabeça e outra cauda, e assim respectivamente.

Nosso método adicionaNoComeco(T elemento) recebe um parâmetro e retorna uma nova Lista com o respectivo elemento adicionado. Bem parecido com o método removePrimeiraPosicao() que remove o primeiro elemento e retorna a cauda da lista.

Bom vamos as implementações, vamos criar uma nova classe, que podemos chamar de No, ou seja, serão os respectivos nós de nossa Lista:

public class No implements List {
    private final T cabeca;
    private final List cauda;

    public No(T cabeca, List cauda) {
        this.cabeca = cabeca;
        this.cauda = cauda;
    }
    @Override
    public T cabeca() {
        return cabeca;
    }
    @Override
    public List cauda() {
        return cauda;
    }
    @Override
    public List adicionaNoComeco(T elemento) {
        return new No(elemento, this);
    }
    @Override
    public T pegaPosicao(int position) {
        if (position == 0)
            return cabeca();

        return cauda.pegaPosicao(position - 1);
     }
    @Override
    public List removePrimeiraPosicao() {
    return cauda();
    }
}

Entenda:
Ao criar um No, nós receberemos a cabeça (elemento) e sua respectiva cauda (List). Fora o método pegaPosicao, o restante é bem trivial, por isso não entrarei em maiores detalhes.

pegaPosicao(T elemento)
Esse método faz uso recursivo de si próprio, ou seja, ele percorre a cauda, caso o posicao não seja 0, e recursivamente ele vai caminhando de cabeça em cabeça, das caudas, para encontrar o elemento desejado. Bem simples e objetivo.

Certo, feito isso, fica simples entender algumas coisas, a primeira de todas, como será o fim de nossa lista?
Temos que saber onde a Lista tem seu final e como o fazemos?

Faremos outra implementação de List, que agora chamaremos de Nil, será o fim de nossa lista.

public class Nil implements List {
    @Override
    public T cabeca() {
        throw new RuntimeException("Lista Vazia");
    }
    @Override
    public List cauda() {
        throw new RuntimeException("Lista Vazia");
    }
    @Override
    public List adicionaNoComeco(T elemento) {
        return new No(elemento, this);
    }
    @Override
    public T pegaPosicao(int position) {
        throw new RuntimeException("A lista não possui elementos");
    }
    @Override
    public List removePrimeiraPosicao() {
        throw new RuntimeException(
        "Impossível remover elementos de uma lista vazia");
    }
}

O Nil, que como dito acima, tem o objetivo de ser o fim da lista, a única coisa que podemos escrever interessante ao seu respeito é que a reescrita do método adicionaNoComeco vai retornar uma nova instância de No, ou seja, iniciaremos uma lista.

Feito isso, temos um Container, o List, que armazena valores e possui funções para alterar os dados internos, isso nos ajuda muito com a Imutabilidade, nos sentimos mais seguros e sabemos que nosso objeto não será um mutante, que pode perder/alterar seus valores em tempo de execução.

Bom galera, o conceito de hoje foi bem bacana e construtivo, é o que tenho mais feito no meu treinamento com o Jonas, aqui na Lambda3. Espero que tenha ficado claro.

Para os C# manjadores, no meu Github tem um exemplo parecido escrito em C#. Para os Javas, deixarei outro repositório no GitHub já com os testes implementados.

Qualquer dúvida ou sugestão email-me: abner.terribili@lambda3.com.br ou comente abaixo!

Valeu galera!