Durante uma discussão lá no .Net Architects sobre a necessidade de faculdade mencionou-se que você aprende BubbleSort na faculdade, e fora dela talvez seja mais difícil. Pois bem, já há um artigo na Wikipedia (em inglês e em português) para quem quiser aprender, além de um monte de outras fontes. Fiquei com vontade de implementá-lo, e foi divertido. Daí tive a idéia de apresentar um kata, e como não participo de nenhum grupo de coding dojo, nada melhor do que gravar e colocar aqui no blog.

Pois bem, nesse não há musica de fundo como no outro que fiz, que foi sobre fatoriais primos. Fui fazendo e explicando. Até por isso levou um pouco mais de tempo.

Como os katas sempre são feitos com TDD, é uma boa oportunidade de ver TDD funcionando na prática também.

Fiz o vídeo em um take só, de primeira, após ter executado o algoritmo 4 vezes, então a execução está bem realista. Tive pouquíssimos esquecimentos ou errinhos ao longo do kata. Vejam o que acham, se gostarem vou seguir fazendo. Estou pensando em fazer o HeapSort também, que é um pouco mais complicado, mas talvez demore um pouco.

 

Aqui o link do vídeo:

BubbleSort Kata

Aqui o código final:

[TestFixture]
public class Dado_Um_Ordenador
{
    [Test]
    public void Quando_Eu_Ordeno_Uma_Lista_Vazia_Recebo_Outra_Lista_Vazia()
    {
        Assert.AreElementsEqual(new int[] { }, new int[] { }.Ordenar());
    }

    [Test]
    public void Quando_Eu_Ordeno_Uma_Lista_Com_1_Recebo_Os_mesmos_Elementos()
    {
        Assert.AreElementsEqual(new [] { 1 }, new [] { 1 }.Ordenar());
    }
    
    [Test]
    public void Quando_Eu_Ordeno_Uma_Lista_Com_1_2_Recebo_Os_mesmos_Elementos()
    {
        Assert.AreElementsEqual(new [] { 1, 2 }, new [] { 1, 2 }.Ordenar());
    }
    
    [Test]
    public void Consigo_Ordenar_Uma_Lista_Com_2_1()
    {
        Assert.AreElementsEqual(new [] { 1, 2 }, new [] { 2, 1 }.Ordenar());
    }

    [Test]
    public void Consigo_Ordenar_Uma_Lista_Com_3_2_1()
    {
        Assert.AreElementsEqual(new [] { 1, 2, 3 }, new [] { 3, 2, 1 }.Ordenar());
    }

    [Test]
    public void Consigo_Ordenar_Uma_Lista_Com_4_3_2_1()
    {
        Assert.AreElementsEqual(new [] { 1, 2, 3, 4 }, new [] { 4, 3, 2, 1 }.Ordenar());
    }

    [Test]
    public void Consigo_Ordenar_Uma_Lista_Com_5_4_3_2_1()
    {
        Assert.AreElementsEqual(new[] { 1, 2, 3, 4, 5 }, new[] { 5, 4, 3, 2, 1 }.Ordenar());
    }

    [Test]
    public void Consigo_Ordenar_Uma_Lista_Com_30_a_1()
    {
        Assert.AreElementsEqual(1.Ate(30), 30.Ate(1).Ordenar());
    }

    [Test]
    public void Consigo_Ordenar_Uma_Lista_Com_1_a_30_E_Passa_Uma_Vez_So()
    {
        Assert.AreElementsEqual(1.Ate(30), 1.Ate(30).Ordenar());
        Assert.AreEqual(1, Ordenador.Passadas);
    }
}

public static class ExtensoesDeTeste
{
    public static int[] Ate(this int numero, int ate)
    {
        var numeros = new List<int>();
        if (ate > numero)
            for (int i = numero; i <= ate; i++)
                numeros.Add(i);
        else if (ate < numero)
            for (int i = numero; i >= ate; i--)
                numeros.Add(i);

        return numeros.ToArray();
    }
}

public static class Ordenador
{
    public static int[] Ordenar(this int[] numeros)
    {
        var length = numeros.Length;
        while (true)
        {
            var inverteu = false;
            for (int i = 0; i < length - 1; i++)
            {
                if (numeros[i] > numeros[i + 1])
                {
                    numeros.Inverter(i, i + 1);
                    inverteu = true;
                }
            }
            Passadas++;
            if (!inverteu) break;
            length--;
        }
        return numeros;
    }
    
    public static void Inverter(this int[] numeros, int zero, int um)
    {
        Console.Write("Invertendo numero {0} (posição {1} com numero {2} (posição {3}. Array: {4}).",
            numeros[zero], zero, numeros[um], um, numeros.EscreverNumeros());
        var numeroParaInverter = numeros[um];
        numeros[um] = numeros[zero];
        numeros[zero] = numeroParaInverter;
        
        Console.WriteLine("Array após inverter: {0})", numeros.EscreverNumeros());
    }

    public static string EscreverNumeros(this int[] numeros)
    {
        var numerosTexto = "{";
        foreach (var i in numeros)
        {
            numerosTexto += i + ", ";
        }
        numerosTexto = numerosTexto.Substring(0, numerosTexto.Length - 2) + "}";
        return numerosTexto;
    }

    public static int Passadas { get; set; }

}

Feedbacks são bem vindos, como sempre.


Postado na(s) categoria(s) Kata pelo Giovanni Bassi em 7 de dezembro de 2009 às 02:03 | Tags: , , ,

Seguindo a idéia do Kata do Uncle Bob de números primos, fiz o mesmo Kata em C# e gravei o vídeo. Treinei um pouco, e foi um exercício interessante, fiquei bom o suficiente pra bater o Kata em dez minutos. Uma das coisas mais interessantes é praticar o TDD, com uma grande ajuda do Resharper e do TestDriven.Net. Usei o framework de testes Gallio (MbUnit), porque o MSTest não possui um método de Assert que compare coleções, e o MbUnit possui, então fui com ele.

A idéia do Kata é criar um software que permita decompor o fator primo de qualquer número. Assim, ele deve receber o número a ser decomposto, e retornar uma lista destes números. No meu caso, este é o teste do fatorial de 6:

[Test]
public void Deve_Fatorar_6()
{
    Assert.AreElementsEqual(new[] { 2, 3 }, Fatorial.Fatorar(6));
}

Ou seja, o método Fatorar deve retornar uma lista dos primos que compõe 6, ou seja, 2 e 3.

Pra quem quiser ver, o vídeo está no Viddler, e no final tem a solução. Não me inspirei só na idéia do Uncle Bob, mas também no formato do vídeo, espero que gostem (feedbacks, como sempre, são bem vindos).

Fiz também com IronRuby, e realmente é nos testes que o Ruby arrebenta. Foi também muito interessante.

A solução também está aqui para download. Você também pode ver a solução do Uncle Bob com Java, desta vez com uma apresentação do Powerpoint.

E você, já fez o exercício? O que achou? Quais outros Katas você já fez?

(Em tempo: se você me segue no twitter viu o vídeo antes, anunciei por lá na segunda-feira.)


Postado na(s) categoria(s) Kata pelo Giovanni Bassi em 14 de outubro de 2009 às 09:21 | Tags: , , , ,

Quem é Giovanni Bassi

Giovanni Bassi Sou uma pessoa apaixonada por tecnologia e especificamente por .Net. Sou consultor independente especialista em .Net, focado em arquitetura e melhores práticas. Tenho dezenas de artigos publicados na .Net Magazine, revista da qual sou editor técnico. Ministro palestras e cursos de vez em quando, e quando dá tempo eu respiro um pouco. Mais detalhes nesta página.

Busca

Selos

MVP

MCPD

MCSD

.Net Magazine

Abaixo ao if!

Calendário

«  março 2010  »
seteququsedo
22232425262728
1234567
891011121314
15161718192021
22232425262728
2930311234
Ver detalhamento de posts no calendário

Blogs interessantes

    OPMLDownload OPML file

    Postagens recentes

    Comentários recentes

    Disclaimer / Aviso
    As opiniões colocadas neste blog são minhas e pessoais e não expressam necessariamente as opiniões de meus empregadores, pareceiros e amigos. Da mesma forma, os comentários feitos por leitores do blog não expressam a minha opinião.

    © Copyright 2010 .Net Unplugged
    Log in