<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3650164488068959224</id><updated>2011-08-08T08:17:38.746-03:00</updated><category term='Design Pattern'/><title type='text'>Paradigmas de TI</title><subtitle type='html'>Você saberá por que (e como) pode explorar o conhecimento e as lições aprendidas por outros desenvolvedores.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://hugoestevam.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650164488068959224/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://hugoestevam.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Hugo Estevam Longo</name><uri>http://www.blogger.com/profile/12778915451564782261</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_Q8o-StsG350/R7tskMQ5RlI/AAAAAAAAAAM/BsIRZ7tNBiI/S220/S2020024.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3650164488068959224.post-374667071695748848</id><published>2008-10-31T10:16:00.013-02:00</published><updated>2008-10-31T11:26:21.762-02:00</updated><title type='text'>Test-Driven Development no .NET (na prática)</title><content type='html'>&lt;span style="font-family:verdana;font-size:85%;"&gt;
No post &lt;a href="http://hugoestevam.blogspot.com/2008/10/test-driven-development-no-net.html"&gt;anterior&lt;/a&gt;, fiz uma introdução ao Test-Driven Development (TDD), falando resumidamente sobre seus conceitos e mostrando como funciona o NUnit Testing Framework. Neste post, pretendo falar mais sobre a metodologia TDD e mostrar um exemplo de sua aplicação na prática.
&lt;p&gt;
Com esses conhecimentos já posso sair desenvolvendo programas utilizando TDD? Infelizmente não funciona bem assim, apenas sabendo programar orientado a objeto, conhecendo a sintaxe, atributos e métodos do NUnit não é suficiente. É preciso ter em mente algumas técnicas utilizadas em TDD antes de sair desenvolvendo um sistema. Existem algumas técnicas que devem ser seguidas quando se desenvolve utilizando TDD que facilitam o entendimento, no entanto, conhecer essas técnicas é apenas um começo. Para melhorar a sua experiência e aptidão, você deve praticar, práticar e práticar. Segue uma imagem para ilustrar melhor essas técnicas.
&lt;p&gt;
&lt;a href="http://3.bp.blogspot.com/_Q8o-StsG350/SQr3ssEwG8I/AAAAAAAAABM/Cr3nWs4hsYM/s1600-h/Fluxo.jpg" target="_blank"&gt;&lt;img id="BLOGGER_PHOTO_ID_5263291461653240770" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 320px; CURSOR: hand; HEIGHT: 226px; TEXT-ALIGN: center" alt="" src="http://3.bp.blogspot.com/_Q8o-StsG350/SQr3ssEwG8I/AAAAAAAAABM/Cr3nWs4hsYM/s320/Fluxo.jpg" border="0" /&gt;&lt;/a&gt;
&lt;p&gt;
Se ainda não está familiarizado com TDD, o que estou escrevendo pode soar um pouco estranho. Muitas pessoas passaram muito tempo ouvindo que deve-se primeiro considerar cuidadosamente o design das classes, codificá-las e então testar. O que o TDD sugere é uma abordagem completamente diferente, o processo é iniciado de trás para frente, tendo o teste em primeiro lugar. Dito de outra forma, você não escreve uma linha de código até que você tenha um teste pronto para a função. A seqüência sugerida para desenvolvimento usando TDD é a seguinte:
&lt;p&gt;
1. Escrever um teste.&lt;br&gt;
2. Execute o teste. Não consegue compilar uma vez que o código ainda não existe mesmo! (Esta é a mesma coisa que falhar.)&lt;br&gt;
3. Escrever um esboço do que se deseja testar, só para fazer o teste compilar.&lt;br&gt;
4. Execute o teste. Ele deve falhar. (Se não falhar , então o teste não era muito bom.)&lt;br&gt;
5. Implementar o código completo para o teste passar.&lt;br&gt;
6. Execute o teste. Ela deverá passar. (Se não o fizer, volte um passo e tente novamente.)&lt;br&gt;
7. Começar com um novo teste!&lt;br&gt;
&lt;p&gt;
Antes de chegar na etapa 5, você estará utilizando um processo denominado Codificação por Intenção. Quando você pratica Codificação por Intenção, o código é escrito de cima para baixo em vez de baixo para cima, ou seja, primeiro você cria um código de acesso a rotina, depois você cria a rotina em si. Em vez de pensar, "Eu preciso de uma classe com estes métodos" basta escrever o código desejado, antes que a classe realmente exista. Se tentar compilar seu código, não conseguirá, o compilador não poderá encontrar a classe. Este é um bom sinal, pois como disse acima, a falta de compilar, conta como uma falha no teste. O que vai fazer aqui é experimentar a intenção do código que está escrito. Isto não só ajuda a produzir códigos bem testados, como resulta também em código que é mais fácil de ler, mais fácil de depurar e com uma melhor concepção.
&lt;p&gt;
No desenvolvimento de software, testes tradicionais foram pensados para verificar se um trecho de código foi escrito corretamente. Quando você fizer TDD, no entanto, os seus testes são utilizados para definir o comportamento de uma classe antes de escrever a mesma. Não vou arriscar dizer que este método é mais fácil do que as velhas formas, mas na minha experiência é muito melhor.
&lt;p&gt;
Vamos ver uma pequena amostra desta metodologia. Suponhamos que você necessita escrever o simples e famoso sistema de conta bancária. Esse sistema consiste em fazer uma classe que possa representar uma Conta, possuindo o nome do proprietário, o saldo, e o estado da conta. Também pode ser feitos Depósitos, Saques e rendimento de juros. Tudo isso em um sistema simples num projeto Console Application. Veja a imagem abaixo que ilustra melhor o exemplo.
&lt;p&gt;
&lt;a href="http://1.bp.blogspot.com/_Q8o-StsG350/SQr4bBksr3I/AAAAAAAAABU/0w_Ld5pi08Q/s1600-h/Conta.jpg" target="_blank"&gt;&lt;img id="BLOGGER_PHOTO_ID_5263292257698361202" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 196px; CURSOR: hand; HEIGHT: 320px; TEXT-ALIGN: center" alt="" src="http://1.bp.blogspot.com/_Q8o-StsG350/SQr4bBksr3I/AAAAAAAAABU/0w_Ld5pi08Q/s320/Conta.jpg" border="0" /&gt;&lt;/a&gt;
&lt;p&gt;
Antes de criar efetivamente a classe Conta, deve-se criar uma classe de teste, esses testes devem estar de acordo com as funcionalidades que imaginamos (“ou vemos na imagem acima”) que a classe Conta irá representar, com o desenvolvimento dessa classe iniciamos o TDD, o nome da classe de teste neste exemplo será ContaTests. Agora que já temos em mente o que a classe ContaTests deve ser capaz de fazer, vamos criar os testes com o NUnit Framework, conforme mostra o código abaixo:
&lt;p&gt;
&lt;pre class="c-sharp" name="code"&gt;
using System;
using NUnit.Framework;

namespace TDD.Banco
{
    [TestFixture]
    public class ContaTests
    {
        [Test]
        public void TestDeposito()
        {
            Conta conta = new Conta("Test");
            conta.Deposito(125.0);
            conta.Deposito(25.0);
            Assert.AreEqual(150.0, conta.Balanco);
        }

        [Test]
        public void TestSaque()
        {
            Conta conta = new Conta("Test");
            conta.Saque(125.0);
            conta.Saque(25.0);
            Assert.AreEqual(-150.0, conta.Balanco);
        }

        [Test]
        public void TestJuro()
        {
            Conta conta = new Conta("Test");
            conta.Deposito(100.0);
            conta.AplicarJuro();
            Assert.AreEqual(105.0, conta.Balanco);
        }

        [Test]
        public void TestEstado()
        {
            Conta conta = new Conta("Test");
            conta.Deposito(1100.0);
            Assert.AreEqual("Ouro", conta.Estado);
            conta.Saque(600.0);
            Assert.AreEqual("Cinza", conta.Estado);
            conta.Saque(600.0);
            Assert.AreEqual("Vermelho", conta.Estado);
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;
Depois de escrever o código acima na classe ContaTests é hora de compilá-la. É óbviu que a classe de testes não irá compilar, uma vez que a não existi a classe Conta. Isto ilustra o principal princípio de TDD, não escrever qualquer código sem que se tenha um teste pronto para ele. Lembro, quando os seus códigos de teste não compilarem, isso contará como uma falha de teste, e será cumprida a primeira etapa de TDD. Agora vamos criar a classe Conta com código suficiente apenas para fazer os testes compilar.
&lt;pre class="c-sharp" name="code"&gt;
using System;

namespace TDD.Banco
{
    public class Conta
    {
        private String estado;       
        private String proprietario;

        public Conta(string proprietario)
        {           
            this.proprietario = proprietario;
            estado = "";           
        }

        public double Balanco
        {
            get { return 0.0; }
        }

        public String Estado
        {
            get { return estado; }
            set { estado = value; }
        }

        public void Deposito(double valor)
        {           
        }

        public void Saque(double valor)
        {           
        }

        public void AplicarJuro()
        {           
        }

        private void AlteraEstado()
        {           
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;
Logo após criarmos a classe Conta, podemos compilar o projeto que não terá mais erros. Com isso podemos rodar nossos testes através do NUnit GUI. Para rodar os testes, rode o executável do NUnit GUI e abra o arquivo executável do projeto Console Application que foi criado nesse exemplo de teste. Clicando em “Run”, os testes serão executados e a tela do NUnit ficará conforme a imagem abaixo.
&lt;p&gt;
&lt;a href="http://4.bp.blogspot.com/_Q8o-StsG350/SQr5gW628NI/AAAAAAAAABc/35BObIK8oOc/s1600-h/ContaFail.jpg" target="_blank"&gt;&lt;img id="BLOGGER_PHOTO_ID_5263293448839426258" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 320px; CURSOR: hand; HEIGHT: 218px; TEXT-ALIGN: center" alt="" src="http://4.bp.blogspot.com/_Q8o-StsG350/SQr5gW628NI/AAAAAAAAABc/35BObIK8oOc/s320/ContaFail.jpg" border="0" /&gt;&lt;/a&gt;
&lt;p&gt;
Notamos que todos os testes falharam. Isso já era esperado, pois a classe Conta foi criada apenas para compilar o projeto e os testes. Como pode ser visto na imagem, o teste “TestDeposito” mostrou a seguinte mensagem de erro: "TestDeposito: expected: &lt;150&gt; but was &lt;0&gt;". Esse resultado serviu para concluir mais uma etapa do TDD criar o teste de um método e fazer ele falhar. A próxima etapa é justamente implementar o método Deposito da classe Conta para que o teste “TestDeposito” passe sem erro.
&lt;p&gt;
Notém que por uma questão prática estou disponibilizando os códigos com todos os testes e métodos criados, quando se utiliza TDD essa não é uma boa prática, deve-se criar um teste para uma determinada rotina, criar a rotina apenas para compilar, rodar o teste propositalmente para que ele falhe, implementar a rotina para que o teste passe, tudo isso nessa respectiva ordem. Sabendo disso, vejam o código abaixo, com os testes implementados para que os testes passem.
&lt;pre class="c-sharp" name="code"&gt;
using System;

namespace TDD.Banco
{
    public class Conta
    {
        private String estado;
        private double balanco;
        private String proprietario;

        public Conta(string proprietario)
        {
            // Novas contas por default são 'Cinza' e o balanco é 0.0
            this.proprietario = proprietario;
            estado = "Cinza";
            balanco = 0.0;
        }

        public double Balanco
        {
            get { return balanco; }
        }

        public String Estado
        {
            get { return estado; }
            set { estado = value; }
        }

        public void Deposito(double valor)
        {
            balanco += valor;
            AlteraEstado();
            Console.WriteLine("Depositado {0:C} --- ", valor);
            Console.WriteLine(" Balanço = {0:C}", Balanco);
            Console.WriteLine(" Estado  = {0}", Estado);
            Console.WriteLine("");
        }

        public void Saque(double valor)
        {
            balanco -= valor;
            AlteraEstado();
            Console.WriteLine("Sacado {0:C} --- ", valor);
            Console.WriteLine(" Balanço = {0:C}", Balanco);
            Console.WriteLine(" Estado  = {0}", Estado);
            Console.WriteLine("");
        }

        public void AplicarJuro()
        {
            if (!String.Equals(Estado, "Vermelho"))
            {
                balanco += 0.05 * balanco;
                Console.WriteLine("Juros Aplicados --- ");
                Console.WriteLine(" Balanco = {0:C}", Balanco);
                Console.WriteLine(" Estado  = {0}", Estado);
            }
            else
            {
                Console.WriteLine("Juro não pode ser aplicado pelo Estado da conta.");
                Console.WriteLine(" Balanco = {0:C}", Balanco);
                Console.WriteLine(" Estado  = {0}", Estado);
            }
        }

        private void AlteraEstado()
        {
            if (balanco &lt; 0.0)
                Estado = "Vermelho";
            else if (balanco &lt; 1000.0)
                Estado = "Cinza";
            else
                Estado = "Ouro";
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;
Com o código acima já implementado, ao rodar os testes no NUnit, todos deverão passar como mostra a imagem abaixo. Tudo isso por que agora focamos no problema do teste, efetuamos a programação visando um objetivo, passar nos testes, por isso a importância de testar tudo que é possível.
&lt;p&gt;
&lt;a href="http://2.bp.blogspot.com/_Q8o-StsG350/SQr6L0WqYhI/AAAAAAAAABk/ZZ47GhCBA30/s1600-h/ContaPass.jpg" target="_blank"&gt;&lt;img id="BLOGGER_PHOTO_ID_5263294195475046930" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 320px; CURSOR: hand; HEIGHT: 219px; TEXT-ALIGN: center" alt="" src="http://2.bp.blogspot.com/_Q8o-StsG350/SQr6L0WqYhI/AAAAAAAAABk/ZZ47GhCBA30/s320/ContaPass.jpg" border="0" /&gt;&lt;/a&gt;
&lt;p&gt;
Agora temos a classe Conta implementada e uma classe de testes ContaTest garantindo que todos os métodos estão funcionando de acordo com o previsto. Então podemos dizer que o TDD se encerra por aqui? ERRADO. Ainda falta uma etapa muito importante dentro do TDD, é a etapa do Refactoring.
&lt;p&gt;
&lt;strong&gt;Refatoração&lt;/strong&gt; &lt;em&gt;(do inglês Refactoring) é o processo de modificar um sistema de software para melhorar a estrutura interna do código sem alterar seu comportamento externo. (Wikipedia)&lt;/em&gt;
&lt;p&gt;
Devemos fazer um Refactoring tanto na nossa classe de teste quanto na nossa classe Conta. Vamos começar com a classe de teste, no código dela podemos notar que existe várias duplicações. Para cada método criamos e instanciamos um objeto do tipo Conta. Com ajuda dos atributos do NUnit, podemos refatorar essa classe excluindo essas repetições em cada método e substituindo esse código pelos método Setup e TearDown. Com isso cada vez que um teste for executado antes passará pelo Setup e depois pelo TearDown. Confira o código abaixo.
&lt;pre class="c-sharp" name="code"&gt;
using System;
using NUnit.Framework;

namespace TDD.Banco
{
    [TestFixture]
    public class ContaTests
    {
        private Conta conta;

        [SetUp]
        public void Setup()
        {
            conta = new Conta("Test");
        }

        [TearDown]
        public void TearDown()
        {
            conta = null;
        }

        [Test]
        public void TestDeposito()
        {           
            conta.Deposito(125.0);
            conta.Deposito(25.0);
            Assert.AreEqual(150.0, conta.Balanco);
        }

        [Test]
        public void TestSaque()
        {           
            conta.Saque(125.0);
            conta.Saque(25.0);
            Assert.AreEqual(-150.0, conta.Balanco);
        }

        [Test]
        public void TestJuro()
        {           
            conta.Deposito(100.0);
            conta.AplicarJuro();
            Assert.AreEqual(105.0, conta.Balanco);
        }

        [Test]
        public void TestEstado()
        {           
            conta.Deposito(1100.0);
            Assert.AreEqual("Ouro", conta.Estado);
            conta.Saque(600.0);
            Assert.AreEqual("Cinza", conta.Estado);
            conta.Saque(600.0);
            Assert.AreEqual("Vermelho", conta.Estado);
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;
Após a refatoração, podemos rodar os testes e conferir que todos continuam funcionando. Então vamos partir para um refactoring na classe Conta. Ao implementar a classe conta podemos constatar que de acordo com o estado da conta é tomada uma decisão diferente para cada caso. Isso impacta em várias verificações em cada rotina que se aplica uma operação que necessita uma tomada de decisão de acordo com o estado. Portanto para um melhor design da classe e para facilitar possíveis alterações duranto o tempo de vida do projeto vamos aplicar a classe Conta o Desing Pattern State, conforme imagem abaixo.
&lt;p&gt;
&lt;a href="http://2.bp.blogspot.com/_Q8o-StsG350/SQr67Rkc7cI/AAAAAAAAABs/rBzjVH6zLxI/s1600-h/StateDesign.jpg" target="_blank"&gt;&lt;img id="BLOGGER_PHOTO_ID_5263295010771365314" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 320px; CURSOR: hand; HEIGHT: 274px; TEXT-ALIGN: center" alt="" src="http://2.bp.blogspot.com/_Q8o-StsG350/SQr67Rkc7cI/AAAAAAAAABs/rBzjVH6zLxI/s320/StateDesign.jpg" border="0" /&gt;&lt;/a&gt;
&lt;p&gt;
Conforme podemos ver no modelo acima, o design da classe vai mudar, porém o objetivo da classe Conta vai continuar sendo o mesmo, permitindo fazer deposito, saque e rendimentos de juro. Neste caso vamos supor que outro desenvolvedor resolveu fazer essa mudança, ele não vai seguir as metodologias TDD, não vai criar testes para as novas implementações, vai apenas alterar o design. Com isso podemos ver se o sistema está mais seguro com os testes que foram implementados. Vejam o código abaixo após o refactoring.
&lt;p&gt;
Classe Conta:
&lt;pre class="c-sharp" name="code"&gt;
using System;

namespace TDD.Banco
{
    public class Conta
    {
        private Estado estado;       
        private String proprietario;

        public Conta(string proprietario)
        {
            // Novas cotas por default são 'Cinza' e tem o balanco 0.0
            this.proprietario = proprietario;
            estado = new EstadoCinza(0.0, this);           
        }

        public double Balanco
        {
            get { return estado.Balanco; }
        }

        public Estado Estado
        {
            get { return estado; }
            set { estado = value; }
        }

        public void Deposito(double valor)
        {
            estado.Deposito(valor);
            Console.WriteLine("Depositado {0:C} --- ", valor);
            Console.WriteLine(" Balanço = {0:C}", Balanco);
            Console.WriteLine(" Estado  = {0}", Estado.GetType().Name);
            Console.WriteLine("");
        }

        public void Saque(double valor)
        {
            estado.Saque(valor);
            Console.WriteLine("Sacado {0:C} --- ", valor);
            Console.WriteLine(" Balanço = {0:C}", Balanco);
            Console.WriteLine(" Estado  = {0}", Estado.GetType().Name);
            Console.WriteLine("");
        }

        public void AplicarJuro()
        {
            estado.AplicarJuro();      
            Console.WriteLine("Juros Aplicados --- ");
            Console.WriteLine(" Balanco = {0:C}", Balanco);
            Console.WriteLine(" Estado  = {0}", Estado.GetType().Name);
            Console.WriteLine("");
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;
Classe Estado:
&lt;pre class="c-sharp" name="code"&gt;
using System;

namespace TDD.Banco
{
    public abstract class Estado
    {
        protected Conta conta;
        protected double balanco;

        protected double juro;
        protected double limiteMin;
        protected double limiteMax;
       
        public Conta Conta
        {
            get { return conta; }
            set { conta = value; }
        }

        public double Balanco
        {
            get { return balanco; }
            set { balanco = value; }
        }

        public abstract void Deposito(double valor);
        public abstract void Saque(double valor);
        public abstract void AplicarJuro();
    }
}
&lt;/pre&gt;
&lt;p&gt;
Classe EstadoVermelho:
&lt;pre class="c-sharp" name="code"&gt;
using System;

namespace TDD.Banco
{
    public class EstadoVermelho : Estado
    {
        double taxaServico;
       
        public EstadoVermelho(Estado estado)
        {
            this.balanco = estado.Balanco;
            this.conta = estado.Conta;
            Initialize();
        }

        private void Initialize()
        {           
            juro = 0.0;
            limiteMin = -100.0;
            limiteMax = 0.0;
            taxaServico = 15.00;
        }

        public override void Deposito(double valor)
        {
            balanco += valor;
            AlteraEstado();
        }

        public override void Saque(double valor)
        {
            valor = valor - taxaServico;
            Console.WriteLine("Sem saldo para efetuar saque!");
        }

        public override void AplicarJuro()
        {
            // Não tem juro estado vermelho
        }

        private void AlteraEstado()
        {
            if (balanco &gt; limiteMax)
            {
                conta.Estado = new EstadoCinza(this);
            }
        }

        public override String ToString()
        {
            return "Vermelho";
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;
Classe EstadoCinza:
&lt;pre class="c-sharp" name="code"&gt;
using System;

namespace TDD.Banco
{
    public class EstadoCinza : Estado
    {
        public EstadoCinza(Estado estado) :
            this( estado.Balanco, estado.Conta)
        {   
        }

        public EstadoCinza(double balanco, Conta conta)
        {
            this.balanco = balanco;
            this.conta = conta;
            Initialize();
        }       

        private void Initialize()
        {
            juro = 0.05;
            limiteMin = 0.0;
            limiteMax = 1000.0;           
        }

        public override void Deposito(double valor)
        {
            balanco += valor;
            AlteraEstado();
        }

        public override void Saque(double valor)
        {
            balanco -= valor;
            AlteraEstado();
        }

        public override void AplicarJuro()
        {
            balanco += juro * balanco;
            AlteraEstado();
        }

        private void AlteraEstado()
        {
            if (balanco &lt; estado =" new"&gt; limiteMax)
            {
                conta.Estado = new EstadoOuro(this);
            }
        }

        public override String ToString()
        {
            return "Cinza";
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;
Classe EstadoOuro:
&lt;pre class="c-sharp" name="code"&gt;
using System;

namespace TDD.Banco
{
    public class EstadoOuro : Estado
    {
        public EstadoOuro(Estado estado) :
            this(estado.Balanco, estado.Conta)
        {
        }

        public EstadoOuro(double balanco, Conta conta)
        {
            this.balanco = balanco;
            this.conta = conta;
            Initialize();
        }

        private void Initialize()
        {
            juro = 0.05;
            limiteMin = 1000.0;
            limiteMax = 1000000.0;
        }

        public override void Deposito(double valor)
        {
            balanco += valor;
            AlteraEstado();
        }

        public override void Saque(double valor)
        {
            balanco -= valor;
            AlteraEstado();
        }

        public override void AplicarJuro()
        {
            balanco += juro * balanco;
            AlteraEstado();
        }

        private void AlteraEstado()
        {
            if (balanco &lt; 0.0)
            {
                conta.Estado = new EstadoVermelho(this);
            }
            else if (balanco &lt; limiteMin)
            {
                conta.Estado = new EstadoCinza(this);
            }
        }

        public override String ToString()
        {
            return "Ouro";
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;
Após terminarmos as implementações, podemos rodar os testes no NUnit e verificar se algum deles falhou, indicando que alguma alteração mecheu no funcionamento do sistema. Neste exemplo foi deixado propositalmente duas alterações para que fossem pegas pelos testes. Como mostra a imagem do NUnit abaixo.
&lt;p&gt;
&lt;a href="http://2.bp.blogspot.com/_Q8o-StsG350/SQr8rmc3iHI/AAAAAAAAAB0/hiVjrBzN6YU/s1600-h/ContaRefacFail.jpg" target="_blank"&gt;&lt;img id="BLOGGER_PHOTO_ID_5263296940522047602" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 320px; CURSOR: hand; HEIGHT: 218px; TEXT-ALIGN: center" alt="" src="http://2.bp.blogspot.com/_Q8o-StsG350/SQr8rmc3iHI/AAAAAAAAAB0/hiVjrBzN6YU/s320/ContaRefacFail.jpg" border="0" /&gt;&lt;/a&gt;
&lt;p&gt;
Dois testes falharam durante a execução, o primeiro deles foi o “TestEstado” onde esperava uma string “Ouro” e veio como retorno um tipo Ouro. No segundo teste que falhou, o “TestSaque” era esperado -150 no balanco e retornou -125, isso devido a uma alteração na lógica da conta com estado Vermelho, só pode sacar se tiver fundos. Vamos corrigir os testes, para que eles fiquem adequados as novas alterações.
&lt;pre class="c-sharp" name="code"&gt;
using System;
using NUnit.Framework;

namespace TDD.Banco
{
    [TestFixture]
    public class ContaTests
    {
        private Conta conta;

        [SetUp]
        public void Setup()
        {
            conta = new Conta("Test");
        }

        [TearDown]
        public void TearDown()
        {
            conta = null;
        }

        [Test]
        public void TestDeposito()
        {           
            conta.Deposito(125.0);
            conta.Deposito(25.0);
            Assert.AreEqual(150.0, conta.Balanco);
        }

        [Test]
        public void TestSaque()
        {
            conta.Deposito(200.0);
            conta.Saque(125.0);
            conta.Saque(25.0);
            Assert.AreEqual(50.0, conta.Balanco);
        }

        [Test]
        public void TestSaqueVermelho()
        {           
            conta.Saque(125.0);
            conta.Saque(25.0);
            Assert.AreEqual(-125.0, conta.Balanco);
        }

        [Test]
        public void TestJuro()
        {           
            conta.Deposito(100.0);
            conta.AplicarJuro();
            Assert.AreEqual(105.0, conta.Balanco);
        }

        [Test]
        public void TestEstado()
        {           
            conta.Deposito(1100.0);
            Assert.AreEqual("Ouro", conta.Estado.ToString());
            conta.Saque(600.0);
            Assert.AreEqual("Cinza", conta.Estado.ToString());
            conta.Saque(600.0);
            Assert.AreEqual("Vermelho", conta.Estado.ToString());
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;
Uma dica importante quanto à metodologia de TDD é a seguinte: toda vez que você encontrar um bug, primeiramente crie um teste que faça o bug aparecer. Só então, escreva o código que vai corrigir o bug. Com isso, o seu conjunto de testes melhora com o tempo, fica mais completo, e você vai ter certeza que daquele ponto em diante que o bug nunca mais voltará despercebido. É o que foi feito no caso do teste “TestSaque”, foi criado um teste “TestSaqueVermelho” apenas para simular o erro e depois corrigi-lo.
&lt;p&gt;
Podem acreditar, depois de usar NUnit por um tempo, vocês vão ver a importância dos testes, principalmente depois de fazer grandes alterações no sistema: se todos os testes passarem, você pode ter certeza que não quebrou nada, ao invés de só rezar. Também vai ter certeza que não danificou funcionalidades implementadas por outros programadores, o que em um ambiente de produção é fundamental. Você se sente mais seguro para fazer alterações, por que sabe que possívelmente pegará os erros que podem vir a ocorrer.
&lt;p&gt;
Como puderam notar a classe Conta com o novo design acabou ficando dependente de outras classes como EstadoVermelho, EstadoCinza e EstadoOuro. Testes de unidade procuram testar classes de um sistema isoladamente. Classes em um sistema normalmente alcançam seus objetivos com a ajuda de outras. Não funcionam isoladamente, freqüentemente se comunicam com outros elementos da aplicação. Quando construímos um teste de unidade, um dos principais desafios é exatamente isolar a classe que está sendo testada, para que nenhuma outra classe do sistema seja envolvida no teste.
&lt;p&gt;
Uma solução eficaz é o uso de mock objects (objetos “de mentira” ou objetos substitutos), que permitem isolar as classes de um sistema de forma bastante simples. No nosso exemplo, a classe Conta depende diretamente da classe EstadoVermelho. Usar um mock object significa que, quando estivermos testando, ao invés de usarmos a classe EstadoVermelho, usaremos uma outra, que “finge” ser essa classe, mas é mais simples e mais fácil de ser usada durante os testes (além disso, temos total controle sobre ela, pois é criada especialmente para os testes).
&lt;p&gt;
Mas isso pretendo mostrar em um próximo post, refatornado a nossa classe de teste, permitindo o uso de mock objects e criando novas classes de testes para cada classe separadamente.
&lt;p&gt;
Até a próxima…
&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650164488068959224-374667071695748848?l=hugoestevam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hugoestevam.blogspot.com/feeds/374667071695748848/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3650164488068959224&amp;postID=374667071695748848&amp;isPopup=true' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650164488068959224/posts/default/374667071695748848'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650164488068959224/posts/default/374667071695748848'/><link rel='alternate' type='text/html' href='http://hugoestevam.blogspot.com/2008/10/test-driven-development-no-net-na.html' title='Test-Driven Development no .NET (na prática)'/><author><name>Hugo Estevam Longo</name><uri>http://www.blogger.com/profile/12778915451564782261</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_Q8o-StsG350/R7tskMQ5RlI/AAAAAAAAAAM/BsIRZ7tNBiI/S220/S2020024.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_Q8o-StsG350/SQr3ssEwG8I/AAAAAAAAABM/Cr3nWs4hsYM/s72-c/Fluxo.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650164488068959224.post-838752668479948933</id><published>2008-10-27T16:59:00.013-02:00</published><updated>2008-10-28T14:56:50.274-02:00</updated><title type='text'>Test-Driven Development no .NET</title><content type='html'>&lt;span style="font-family:Verdana;font-size:85%;"&gt;
Esse post apresenta a técnica de desenvolvimento orientado a testes, que tem como um de seus objetivos antecipar a identificação e correção de falhas durante o desenvolvimento. Test-driven development ou TDD é um novo paradigma("adoro essa palavra") de desenvolvimento onde primeiro são criados os testes e somente depois é escrito o código necessário para passar por eles. Muita gente deve estar se perguntando: "Mas como vou fazer os testes se não tenho o código para testar?". Vamos tentar esclarecer essas dúvidas no decorrer desse post.
&lt;p&gt;
Antes de inicar o desenvolvimento utilizando TDD, deve-se ter o entendimento do que é Unit Test. Em termos práticos, Unit Test (Testes Unitários), significa escrever trechos de código que provem verdadeiro todas as categorias em sua aplicação, ou seja, testar se o objetivo do método está sendo atendido, verificar se a rotina não está sensível a um bug. São apenas testes que garantem que os métodos executam sem erros o que se espera deles.
&lt;p&gt;
Embora muitos dos desenvolvedores façam testes unitários em seus códigos, geralmente os testes são desenvolvidos/realizados após o código ser concebido e escrito. Como um grande número de desenvolvedores escreve os códigos antes dos testes, os testes acabam sendo viciosos e difícil de fazer muitas variações devido ao curto tempo. Desenvolvimento orientado a testes (TDD) tenta resolver este problema para gerar maior qualidade no código, evitando que se coloque a carroça na frente dos bois, redigindo os testes antes que escrever o código.
&lt;p&gt;
Uma das práticas de Extreme Programming (XP), TDD está adquirindo uma forte comunidade em Java, mas muito pouco foi escrito sobre como fazer em .NET. Ainda assim, foi desenvolvido para .NET, o NUnit Testing Framework, um framework de testes baseado no JUnit da comunidade Java, que serve para executar e apresentar o resultado dos testes. Como ele faz isso? O Test Runner do NUnit faz uma busca no código compilado, procurando por atributos que identifiquem as classes e métodos como de teste. Em seguida, através do uso do Reflection, ele executa essas classes e métodos que foram considerados como de testes. Para informar que a classe é uma classe de testes, não é preciso que ela derive de uma classe base de testes, somente é necessário que sejam utilizados os atributos. O NUnit, possui uma variedade de atributos que devem ser utilizados em seus testes unitários. Eles são utilizados para definir test fixtures, test methods, setup e teardown. Veremos para que servem cada um deles logo abaixo.
&lt;p&gt;
&lt;em&gt;Obs.: A forma mais prática de instalar NUnit no seu sistema é instalando o pacote Test Driven.Net, da versão mais recente do NUnit, instalará um add-in pro Visual Studio.Net para que você possa executar os testes dentro do ambiente, diretamente. Outra alternativa (por exemplo pra quem não usa VS.Net) é instalar apenas o NUnit executá-lo como um programa independente.&lt;/em&gt;
&lt;p&gt;
&lt;strong&gt;TestFixture&lt;/strong&gt;
&lt;p&gt;
O atributo TestFixture é usado para indicar que a classe contém métodos de teste. Quando esse atributo é incluído na classe em seu projeto, o Test Runner irá procurar por métodos de teste para então executá-los. O código abaixo mostra o uso desse atributo.
&lt;pre class="c-sharp" name="code"&gt;
namespace ExemploNUnitTest
{
  using System;
  using NUnit.Framework;

  [TestFixture]
  public class ClasseDeTeste
  {
  }
}&lt;/pre&gt;
&lt;p&gt;
A restrição para classes que possuem o atributo TestFixture é que deve ter defino um construtor padrão como public.(Ou nenhum construtor definido o que é a mesma coisa).
&lt;p&gt;
&lt;strong&gt;Test&lt;/strong&gt;
&lt;p&gt;
O atributo Test é utilizado para indicar que o método é um método de teste e deve ser executado pelo Test Runner. O método deve ser público, não deve retornar nada e não pode receber parâmetros. Caso contrário o teste não será executado. O código abaixo mostra o exemplo desse atributo.
&lt;pre class="c-sharp" name="code"&gt;
namespace ExemploNUnitTest
{
  using System;
  using NUnit.Framework;

  [TestFixture]
  public class ClasseDeTeste
  {
    [Test]
    public void TesteUm()
    {
      // Faz alguma coisa...
    }
  }
}
&lt;/pre&gt;
&lt;p&gt;
&lt;strong&gt;Setup &amp;amp; TearDown&lt;/strong&gt;
&lt;p&gt;
Muitas vezes é necessário inicializar ou limpar variáveis antes de começar a execução dos testes, poderia fazer isso criando um método privado com essas rotinas e chamá-los em cada método de teste. Mas, para isso existem os atributos SetUp e TearDown que indicam que um método deverá ser executado antes(SetUp) ou depois(TearDown) de cada método de teste. A utilização mais comum desses atributos é quando é necessário criar objetos dependentes (e.g., database connections, etc). Este exemplo mostra o uso desses atributos.
&lt;pre class="c-sharp" name="code"&gt;
namespace ExemploNUnitTest
{
  using System;
  using NUnit.Framework;

  [TestFixture]
  public class ClasseDeTeste
  {
    private int _valor;

    [SetUp]
    public void Setup()
    {
      _valor = 5;
    }

    [TearDown]
    public void TearDown()
    {
      _valor = 0;
    }

    [Test]
    public void TesteUm()
    {
       // Faz alguma coisa...
    }
  }
}
&lt;/pre&gt;
&lt;p&gt;
&lt;strong&gt;Assert Class&lt;/strong&gt;
&lt;p&gt;
Além dos atributos, um importante recurso que o NUnit disponibiliza é a classe Assert. Essa classe oferece uma variedade de métodos estáticos que podem ser usados para verificar se o resultado da execução do método está de acordo com o esperado. A seguir veja um exemplo do uso da classe Assert.
&lt;pre class="c-sharp" name="code"&gt;
namespace ExemploNUnitTest
{
  using System;
  using NUnit.Framework;

  [TestFixture]
  public class ClasseDeTeste
  {
    [Test]
    public void TesteUm()
    {
      int i = 4;
      Assert.AreEquals( 4, i );
    }
  }
}&lt;/pre&gt;
&lt;p&gt;
O resultado do método de teste do código acima seria Verdadeiro, caso o valor de i fosse diferente de 4 o método seria validado como Falso.
&lt;p&gt;
&lt;strong&gt;Rodando seus Testes&lt;/strong&gt;
&lt;p&gt;
É muito simples rodar seus testes com o NUnit, ele possui duas aplicações diferentes para execução dos testes, a aplicação Windows GUI e a aplicação console XML. Para rodar os testes com a aplicação Windows GUI, basta rodar a aplicação, abrir o assembly onde residem seus testes e clicar no botão "Run". Veja um exemplo da aplicação Windows GUI na imagem abaixo:

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Q8o-StsG350/SQcUYZ_4EyI/AAAAAAAAABE/OqXNvriWRJ4/s1600-h/NUnit.JPG" target="_blank"&gt;&lt;img id="BLOGGER_PHOTO_ID_5262197099133932322" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 320px; CURSOR: hand; HEIGHT: 218px; TEXT-ALIGN: center" alt="" src="http://3.bp.blogspot.com/_Q8o-StsG350/SQcUYZ_4EyI/AAAAAAAAABE/OqXNvriWRJ4/s320/NUnit.JPG" border="0" /&gt;&lt;/a&gt;
&lt;p&gt;
A interface do NUnit é bem simples, ela nos mostra todos os testes, com o seguinte código de cores ao lado de cada um: vermelho se o teste não passou, e verde se passou. Uma barra de progresso à direita dá um resultado geral (ou seja, verde só se todos passaram).
&lt;p&gt;
Os testes ainda podem ser executados pela aplicação console através de linhas de comando. Ela também gera um XML com os resultados do teste, possibilitando formatá-los com XSLT e CSS para integra-los no Visual Studio. Porém essa aplicação é mais utilizada para Integração Contínua.
&lt;p&gt;
Vou terminar esse post por aqui para não ficar muito extenso, com esse conteúdo já da para ir treinando seus testes com o NUnit. No próximo post pretendo ir mais fundo em TDD, mostrar seu exemplo na prática e algumas dicas de metodologia no desenvolvimento.
&lt;p&gt;
Dica de Livro: Test-Driven Development by Example;
&lt;p&gt;
Até a próxima...&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650164488068959224-838752668479948933?l=hugoestevam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hugoestevam.blogspot.com/feeds/838752668479948933/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3650164488068959224&amp;postID=838752668479948933&amp;isPopup=true' title='4 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650164488068959224/posts/default/838752668479948933'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650164488068959224/posts/default/838752668479948933'/><link rel='alternate' type='text/html' href='http://hugoestevam.blogspot.com/2008/10/test-driven-development-no-net.html' title='Test-Driven Development no .NET'/><author><name>Hugo Estevam Longo</name><uri>http://www.blogger.com/profile/12778915451564782261</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_Q8o-StsG350/R7tskMQ5RlI/AAAAAAAAAAM/BsIRZ7tNBiI/S220/S2020024.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_Q8o-StsG350/SQcUYZ_4EyI/AAAAAAAAABE/OqXNvriWRJ4/s72-c/NUnit.JPG' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650164488068959224.post-8521125637494324272</id><published>2008-08-14T21:12:00.020-03:00</published><updated>2008-08-17T23:17:18.345-03:00</updated><title type='text'>Extension Methods - (Parte 2)</title><content type='html'>&lt;span style="font-family:verdana;font-size:85%;"&gt;Como foi visto no &lt;/span&gt;&lt;a href="http://hugoestevam.blogspot.com/2008/08/extension-methods-c-30-visual-basic-90.html"&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;post anterior&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;, &lt;/span&gt;&lt;span style="font-family:verdana;"&gt;os Extension Methods são uma nova feature do .NET Framework 3.5, mas isso não significa que esse recurso pode ser usado somente nessa versão do Framework. Neste post veremos como utilizar os Extension Methods em aplicações com o Framework 2.0.&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;span style="font-family:Verdana;font-size:85%;"&gt;&lt;/span&gt;
&lt;span style="font-family:Verdana;font-size:85%;"&gt;Para utilizar os Extension Methods em aplicações ou bibliotecas que são compiladas com o Framework 2.0 teremos que criar nosso próprio atributo do tipo System.Runtime.CompilerServices.Extension que é encontrado no assembly System.Core.dll. Ao criar um aplicação para o Framework 2.0 você irá notar que não poderá referenciar o assembly System.Core.dll pois o mesmo só pode ser utilizado para o Framework 3.5.&lt;/p&gt;&lt;/span&gt;
&lt;span style="font-family:Verdana;font-size:85%;"&gt;&lt;/span&gt;
&lt;span style="font-family:Verdana;font-size:85%;"&gt;Então para poder utilizar os Extension Methods em aplicações 2.0, teremos que criar nosso próprio atributo, para criá-lo, basta digitar o seguinte código em seu projeto:&lt;/span&gt;

&lt;pre class="c-sharp" name="code"&gt;using System;
using System.Text;
using System.Timers;
using System.Runtime.CompilerServices;

namespace ExtensionMethods
{
   static class Program
   {
      // DisplayInterval é um ExtensionMethod que estende a classe Timer
      static void DisplayInterval(this Timer t)
      {
         Console.WriteLine(t.Interval.ToString());
      }

      static void Main(string[] args)
      {
         System.Timers.Timer t = new System.Timers.Timer(2000);
         // Chama o método DisplayInterval normalmente
         Program.DisplayInterval(t);
         // Chama o método DisplayInterval estendido
         t.DisplayInterval();
         // Espera uma ação do usuário
         Console.ReadLine();
      }
   }
}

// Cria o namespace CompilerServices com a classe ExtensionAttibute
// que existe somente em System.Core.dll no .Net Framework 3.5
namespace System.Runtime.CompilerServices
{
   public class ExtensionAttribute : Attribute
   {
   }
}
&lt;/pre&gt;
&lt;p&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;No código acima criamos o namespace System.Runtime.CompilerServices com a classe ExtensionAttribute que herda da classe Attribute, isso fará com que o código da aplicação imite o código do assembly System.Core. Isto já será o suficiente para usarmos os Extension Methods em uma aplicação com o Framework 2.0. No código acima temos o método DisplayInterval que é um &lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Extension Method que estende a classe System.Timers.Timer.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Como uma das principais caracteristicas dos Extension Methods é estender as funcionalidades das classes sem estar mechendo diretamente no código fonte original nada melhor do que poder usá-lo em aplicações mais antigas, logo, aplicações que ainda usam o Framework 2.0 ao invés do 3.5&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Verdana;font-size:85%;"&gt;Para finalizar, vale resaltar que essa técnica não pode ser aplicada em aplicações ASP.NET que são compiladas no Framework 2.0, pois os Web servers ao efetuarem o deploy não entendem os Extension Methods.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Verdana;font-size:85%;"&gt;Até a próxima...&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650164488068959224-8521125637494324272?l=hugoestevam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hugoestevam.blogspot.com/feeds/8521125637494324272/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3650164488068959224&amp;postID=8521125637494324272&amp;isPopup=true' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650164488068959224/posts/default/8521125637494324272'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650164488068959224/posts/default/8521125637494324272'/><link rel='alternate' type='text/html' href='http://hugoestevam.blogspot.com/2008/08/extension-methods-parte-2.html' title='Extension Methods - (Parte 2)'/><author><name>Hugo Estevam Longo</name><uri>http://www.blogger.com/profile/12778915451564782261</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_Q8o-StsG350/R7tskMQ5RlI/AAAAAAAAAAM/BsIRZ7tNBiI/S220/S2020024.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650164488068959224.post-2228214309796328807</id><published>2008-08-07T23:19:00.008-03:00</published><updated>2008-08-17T23:20:14.152-03:00</updated><title type='text'>Extension Methods - C# 3.0 &amp; Visual Basic 9.0</title><content type='html'>&lt;span style="font-family:verdana;font-size:85%;"&gt;Com o tradicional desenvolvimento orientado a objeto, quando se deseja herdar funcionalidades de uma classe, é necessário criar uma classe que estenda a classe base. Visual Basic e C# suportam esse conceito de orientação a objeto, mas algumas vezes, podemos ter classes marcadas como "NotInheritable" ou "sealed" para previnir que sejam feitas modificações no comportamento da classe através da herança. Como resultado não podemos customizar essas classes. Um exemplo disso é a classe System.String do .Net Framework.&lt;/p&gt;
&lt;/span&gt;&lt;div&gt;
&lt;div&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Uma nova feature encontrada no C# 3.0 e Visual Basic 9.0 permite que você estenda as funcionalidades de um tipo existente que não permite utilizar herança. O responsável por isso são os Extension Methods(Extensão de médotos) que tem papel crucial na implementação do LINQ.&lt;/p&gt;
&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Extension Methods provém um mecanismo simples para estender tipos do sistema(valor, referência, tipos interface) com novos métodos. Os métodos estendidos, estendem as funcionalidades de um tipo original, podendo ser chamado normalmente. Eles criam a ilusão de que eles são definidos no tipo real, mas na realidade, não há alteração no tipo original.&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Isto não é um conceito padrão de orientação a objeto, isto é uma feature do .Net Framework, que gera um código no Intermediate Language(IL) através do compilador gerando uma chamada compartilhada a um método.&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;O código abaixo mostra os Extension Methods "AlternateCase" e "
IsValidEmailAddress" que estendem a classe System.String que é marcada como "NotInheritable" ou "sealed". O primeiro método retorna uma string com seus caracteres minúsculos e maiúsculos alternadamente. Já o segundo método retorna um valor booleano que resulta da validação de um e-mail.&lt;/p&gt;
&lt;/span&gt;&lt;/div&gt;
&lt;pre name="code" class="Vb"&gt;
'VB.NET
Imports System.Runtime.CompilerServices
Imports System.Text.RegularExpressions

Module Module1
   Sub Main()
      Dim mail As String = "test@test.com"
      'Chama método AlternateCase como uma extensão da variável mail
      Console.WriteLine("mail.AlternateCase: " &amp;amp; mail.AlternateCase)
      'Chama o método sem ser uma extensão da variável
      Console.WriteLine("Extensions.AlternateCase(mail): " &amp;amp;
      Extensions.AlternateCase(mail))
      'Chama método IsValidEmailAddress como uma extensão da variável mail
      Console.WriteLine("mail.IsValidEmailAddress(): " &amp;amp; mail.IsValidEmailAddress)
      'Chama o método sem ser uma extensão da variável
      Console.WriteLine("Extensions.IsValidEmailAddress(mail): " &amp;amp;
      Extensions.IsValidEmailAddress(mail))
      'Espera ação do usuário 
      Console.Read()
    End Sub
End Module

Module Extensions 
    &amp;lt;Extension()&amp;gt;_
    Function AlternateCase(ByVal x As String) As String
       Dim b = False
       Dim SB As New System.Text.StringBuilder
       For Each c In x
          If b Then
             SB.Append(Char.ToUpper(c))
          Else
             SB.Append(Char.ToLower(c))
          End If
          b = Not b
       Next
       Return SB.ToString
    End Function

    &amp;lt;Extension()&amp;gt;_
    Function IsValidEmailAddress(ByVal x As String)As Boolean
        Dim regex As Regex = New Regex("^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$")
        Return regex.IsMatch(x)
    End Function
End Module
&lt;/pre&gt;
&lt;/p&gt;
&lt;div&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Note que no Visual Basic é necessário importar o namespace System.RunTime.CompilerServices e utilizar o Annotation "Extension()" &lt;extension()&gt;em cima do método desejado.&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;pre name="code" class="C#"&gt;
//C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions; 

namespace ExtensionCSharp
{
   class Program
   {
       static void Main(string[] args)
       {
           String mail = "test@test.com";
           //Chama método AlternateCase como uma extensão da variável mail
           Console.WriteLine("mail.AlternateCase(): " + mail.AlternateCase());
           //Chama o método sem ser uma extensão da variável
           Console.WriteLine("Extensions.AlternateCase(mail): " + Extensions.AlternateCase(mail));
           //Chama método IsValidEmailAddress como uma extensão da variável mail 
           Console.WriteLine("mail.IsValidEmailAddress(): " + mail.IsValidEmailAddress());
           //Chama o método sem ser uma extensão da variável
           Console.WriteLine("Extensions.IsValidEmailAddress(mail): " + Extensions.IsValidEmailAddress(mail));
           //Espera ação do usuário 
           Console.Read();
        }
    }

    public static class Extensions
    {
        public static String AlternateCase(this String x)
        {
            Boolean b = false;
            StringBuilder SB = new StringBuilder();
            foreach(Char c in x)
            {
               if (b)
                  SB.Append(Char.ToUpper(c));
               else
                  SB.Append(Char.ToLower(c));
               b = !b;
            }
            return SB.ToString();
         }

         public static bool IsValidEmailAddress(this String x)
         {
             Regex regex = new Regex(@"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$");
             return regex.IsMatch(x);
         }
    }
}
&lt;/pre&gt;
&lt;/p&gt;
&lt;div&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Note que em C# também se faz necessário importar o namespace System.RunTime.CompilerServices contido no assemblie System.Core.dll. Porém em C# para identificar o método como um Extension Methods não precisa utilizar Annotations, basta utilizar a palavra reservada "this" na declaração do parâmetro no método, como mostra o código acima.&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Após o Extension Method ser criado, ele já fica associado a classe que ele estendeu, neste exemplo a classe System.String foi estendida, e o método pode ser visualizado através do IntelliSense do Visual Studio como mostra a figura abaixo:&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;a href="http://2.bp.blogspot.com/_Q8o-StsG350/SJvA5OdUD_I/AAAAAAAAAA4/1bLPAAQurLQ/s1600-h/Extension.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5231987481487085554" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://2.bp.blogspot.com/_Q8o-StsG350/SJvA5OdUD_I/AAAAAAAAAA4/1bLPAAQurLQ/s320/Extension.jpg" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Você irá ver que os Extension Methods aparecem com um ícone diferente(flecha azul apontando para baixo) para diferenciá-los dos métodos instanciados pela classe.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;As vantagens em usar Extension Methods é que ele permite adicionar funcionalidades para o tipo que você deseja customizar sem que você quebre o código de aplicações já existentes. Você pode estender interfaces padrões com métodos adicionais sem alterar fisicamente a biblioteca de classes existentes.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;No próximo post, pretendo mostrar outras vantagens de utilizar Extension Methods e também mostrar um macete para utilizá-lo em projetos com o .Net Framework 2.0&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Para baixar a solução completa deste exemplo clique &lt;/span&gt;&lt;a href="http://cid-17621fcd61d3a95a.skydrive.live.com/self.aspx/Blog/ExtensionMethods.rar"&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;aqui&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; (VS2008).&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Até a próxima...&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650164488068959224-2228214309796328807?l=hugoestevam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hugoestevam.blogspot.com/feeds/2228214309796328807/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3650164488068959224&amp;postID=2228214309796328807&amp;isPopup=true' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650164488068959224/posts/default/2228214309796328807'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650164488068959224/posts/default/2228214309796328807'/><link rel='alternate' type='text/html' href='http://hugoestevam.blogspot.com/2008/08/extension-methods-c-30-visual-basic-90.html' title='Extension Methods - C# 3.0 &amp; Visual Basic 9.0'/><author><name>Hugo Estevam Longo</name><uri>http://www.blogger.com/profile/12778915451564782261</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_Q8o-StsG350/R7tskMQ5RlI/AAAAAAAAAAM/BsIRZ7tNBiI/S220/S2020024.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_Q8o-StsG350/SJvA5OdUD_I/AAAAAAAAAA4/1bLPAAQurLQ/s72-c/Extension.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650164488068959224.post-643761235006738811</id><published>2008-07-18T22:06:00.005-03:00</published><updated>2008-08-17T23:40:52.914-03:00</updated><title type='text'>O uso do Reflection</title><content type='html'>&lt;span style="font-family:verdana;font-size:85%;"&gt;Um dos maiores benefícios do .NET Framework e do Common Language Run-Time(CLR) em particular é a riqueza dos tipos de informações em runtime. O System.Reflection permite que você navegue e analise um tipo de dados em tempo de execução. Esta capacidade permite desenvolver sistemas mais dinâmicos e que possuam uma arquitetura modular mais clara.
&lt;/p&gt;
Entre diversas outras funcionalidades, o Reflection nos pertime encapsular os assemblies. Com isso você pode utilizar o Reflection para acessar um assembly que não esteja diretamente referenciado em seu projeto, podendo obviamente, utilizar suas classes e métodos.
&lt;/p&gt;
O uso mais comum, útil e prático de Reflection é a chamada de métodos dinâmicos, de um assembly externo ou não.
&lt;/p&gt;
Veja no exemplo abaixo um código que usa Reflection para carregar a classe HttpUtility do assembly System.Web e usar os métodos HtmlEncode e HtmlDecode em um texto HTML:
&lt;/p&gt;
&lt;pre name="code" class="Vb"&gt;
'Código em VB.NET:
Imports System.Reflection

Public Class Program
   Public Overloads Shared Sub Main()
      Dim path As String = "C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Web.dll"
      'Instancia o Assembly através do arquivo
      Dim webAssemby As Assembly = Assembly.LoadFile(path)
      'Recebe o tipo de objeto da classe HttpUtility
      Dim utilType As Type = webAssemby.GetType("System.Web.HttpUtility")
      'Recebe os método estáticos HtmlEncode e HtmlDecode
      Dim encode As MethodInfo = utilType.GetMethod("HtmlEncode", _
      New Type() {GetType(System.String)})
      Dim decode As MethodInfo = utilType.GetMethod("HtmlDecode", _
      New Type() {GetType(System.String)})
      'Cria uma string para codificar
      Dim originalString As String = "Isto é um exemplo do uso de Reflection &lt;.&gt;"
      Console.WriteLine(originalString)
      'Codifica&lt;/span&gt; e mostra o valor codificado
      Dim encoded As String = CType(encode.Invoke(Nothing, New Object() {originalString}), String)
      Console.WriteLine(encoded)
      'Decodifica para comparar se funcionou corretamente
      Dim decoded As String = CType(decode.Invoke(Nothing, New Object() {encoded}), String)
      Console.WriteLine(decoded)
   End Sub
End Class
&lt;/pre&gt;
&lt;/p&gt;
&lt;pre name="code" class="C#"&gt;
//Código em C#:
using System;
using System.Reflection;

namespace ReflectionCSharp
{
   class Program
   {
       static void Main(string[] args)
       {
           String path = @"C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Web.dll";
           //Instancia o Assembly atrav‚s do arquivo
           Assembly webAssemby = Assembly.LoadFile(path);
           //Recebe o tipo de objeto da classe HttpUtility
           Type utilType = webAssemby.GetType("System.Web.HttpUtility");
           //Recebe os m‚todo est ticos HtmlEncode e HtmlDecode
           MethodInfo encode = utilType.GetMethod("HtmlEncode", new Type[] {typeof(System.String)});
           MethodInfo decode = utilType.GetMethod("HtmlDecode", new Type[] {typeof(System.String)});
           //Cria uma string para codificar
           String originalString = "Isto ‚ um exemplo do uso de Reflection &lt;.&gt;";
           Console.WriteLine(originalString);
           //Codifica e mostra o valor codificado
           String encoded = (String)encode.Invoke(null, new Object[] {originalString});
           Console.WriteLine(encoded);
           //Decodifica para comparar se funcionou corretamente&lt;/span&gt;
           String decoded = (String)decode.Invoke(null, new Object[] {encoded});
           Console.WriteLine(decoded);
        }
     }
}
&lt;/pre&gt;
&lt;/p&gt;
&lt;span style="font-family:Verdana;font-size:85%;"&gt;É claro que o Reflection não faz apenas isso, possúi vários recursos interessantes, que vale a pena serem explorados. Mas uma coisa é inegável, as chamadas dinâmicas feitas com o Reflection tornam a lógica da sua aplicação bem mais flexíveis.&lt;/p&gt;&lt;/span&gt;
&lt;span style="font-family:Verdana;font-size:85%;"&gt;&lt;/span&gt;
&lt;span style="font-family:Verdana;font-size:85%;"&gt;Até a próxima...&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650164488068959224-643761235006738811?l=hugoestevam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hugoestevam.blogspot.com/feeds/643761235006738811/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3650164488068959224&amp;postID=643761235006738811&amp;isPopup=true' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650164488068959224/posts/default/643761235006738811'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650164488068959224/posts/default/643761235006738811'/><link rel='alternate' type='text/html' href='http://hugoestevam.blogspot.com/2008/07/o-uso-do-reflection.html' title='O uso do Reflection'/><author><name>Hugo Estevam Longo</name><uri>http://www.blogger.com/profile/12778915451564782261</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_Q8o-StsG350/R7tskMQ5RlI/AAAAAAAAAAM/BsIRZ7tNBiI/S220/S2020024.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650164488068959224.post-3639418010819983564</id><published>2008-07-13T15:39:00.012-03:00</published><updated>2008-08-17T23:44:15.859-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Design Pattern'/><title type='text'>Builder</title><content type='html'>&lt;span style="font-weight: bold;"&gt;&lt;span style="font-family:verdana;"&gt;Definição:&lt;/span&gt;
&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;&lt;span style="font-size:85%;"&gt;Separa a criação do objeto complexo da sua representação. O mesmo processo de construção pode criar diferentes representações.&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_Q8o-StsG350/SHpPFzCG82I/AAAAAAAAAAg/rNjNkBJJuEA/s1600-h/Builder.JPG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp1.blogger.com/_Q8o-StsG350/SHpPFzCG82I/AAAAAAAAAAg/rNjNkBJJuEA/s320/Builder.JPG" alt="" id="BLOGGER_PHOTO_ID_5222573678906504034" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;span style=";font-family:verdana;font-size:85%;"  &gt;As classes &lt;/span&gt;&lt;span style="font-size:85%;"&gt; e/ou objetos que participam deste padrão são:
&lt;/p&gt;
&lt;span style="font-family:verdana;"&gt;• &lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;Builder&lt;/span&gt; (VeiculoBuilder) &lt;/span&gt;
&lt;span style="font-family:verdana;"&gt;       o especifica uma abstract interface para a criação das partes do objeto tipo Produto &lt;/span&gt;
&lt;span style="font-family:verdana;"&gt;• &lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;ConcreteBuilder&lt;/span&gt; (MotoBuilder, CarroBuilder, CaminhaoBuilder) &lt;/span&gt;
&lt;span style="font-family:verdana;"&gt;       o constrói e reúne partes do objeto Produto que implementa a interface Builder &lt;/span&gt;
&lt;span style="font-family:verdana;"&gt;       o define e marca a criação da representação do objeto&lt;/span&gt;
&lt;span style="font-family:verdana;"&gt;       o fornece uma interface para devolver um objeto do tipo Produto&lt;/span&gt;
&lt;span style="font-family:verdana;"&gt;• &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;Director&lt;/span&gt; (Concessionaria)&lt;/span&gt;
&lt;span style="font-family:verdana;"&gt;       o constrói um objeto usando a &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;interface &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;Builder&lt;/span&gt;
&lt;span style="font-family:verdana;"&gt;• &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;Product&lt;/span&gt; (Veiculo) &lt;/span&gt;
&lt;span style="font-family:verdana;"&gt;       o representa o objeto complexo antes da construção. &lt;/span&gt;
&lt;span style="font-family:verdana;"&gt;       o incluí as classes que definen as partes que constituem o objeto, incluindo interfaces para reunir as partes no resultado final&lt;/span&gt;
&lt;/p&gt;
&lt;span style="font-weight: bold;"&gt;Builder: Quando e onde usar?
&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;O padrão Builder é um padrão de projeto de criação de objetos que permite o cliente contruir um objeto complexo especificando somente seu tipo e conteúdo. Os detalhes da construção são escondidos inteiramente do cliente. A motivação mais comum para usar o padrão Builder é para simplificar o code do cliente que cria objetos complexos. O Cliente pode apenas especificar as etapas que são necessárias para o Builder criar o objeto, sem ter conhecimento de como o trabalho atual é finalizado.
Um cenário aonde você deve considerar o uso do padrão de projeto Builder é quando é deselvolvido um gerador de código. Você pode escrever uma aplicação que cria stored procedures para diferentes tipos de banco de dados(SQL Server, Oracle, DB2). A saída real é bastante diferente, mas as etapas para a criação dos procedimentos contidos no CRUD(Create, Read, Update, Delete) são todos muitos similares.
&lt;/p&gt;
O padrão Builder não é amplamente usado, mas pode ser encontrado em duas classes do .NET Framework. VBCodeProvider e CSharpCodeProvider criam classes Builder através do método CreateGenerator. O método CreateGenerator retorna uma interface ICodeGenerator onde a geração do código fonte pode ser controlado.
&lt;/p&gt;
Para ver um exemplo do design pattern Builder na prática é só baixar o projeto de exemplo que segue no link abaixo:&lt;/span&gt;
&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;&lt;a href="http://0l7txq.blu.livefilestore.com/y1pp1yUmKjRyUs6VDrCT4_X1q9C98O334fI2qqCIEnyTSCs0ddPtg-L-YInYduKEhAqQbpus_ozfiroEn7jpjBpow/Builder.zip?download"&gt;Exemplo padrão Builder&lt;/a&gt; (VS2008)
&lt;/p&gt;
Até a próxima...
&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650164488068959224-3639418010819983564?l=hugoestevam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hugoestevam.blogspot.com/feeds/3639418010819983564/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3650164488068959224&amp;postID=3639418010819983564&amp;isPopup=true' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650164488068959224/posts/default/3639418010819983564'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650164488068959224/posts/default/3639418010819983564'/><link rel='alternate' type='text/html' href='http://hugoestevam.blogspot.com/2008/07/builder.html' title='Builder'/><author><name>Hugo Estevam Longo</name><uri>http://www.blogger.com/profile/12778915451564782261</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_Q8o-StsG350/R7tskMQ5RlI/AAAAAAAAAAM/BsIRZ7tNBiI/S220/S2020024.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_Q8o-StsG350/SHpPFzCG82I/AAAAAAAAAAg/rNjNkBJJuEA/s72-c/Builder.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650164488068959224.post-6698664693831463353</id><published>2008-06-26T19:53:00.006-03:00</published><updated>2008-08-18T00:05:15.446-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Design Pattern'/><title type='text'>Abstract Factory</title><content type='html'>&lt;span style="font-size:85%;font-family:verdana;"&gt;&lt;strong&gt;Definição:
&lt;/strong&gt;Fornece uma interface para criar família de objetos relacionados ou dependentes sem especificar a classe concreta deles.&lt;/p&gt;&lt;/span&gt;
&lt;a href="http://bp2.blogger.com/_Q8o-StsG350/SGQghsE-RsI/AAAAAAAAAAY/DkMjZLT32Xo/s1600-h/AbstractFactory.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5216330031541667522" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp2.blogger.com/_Q8o-StsG350/SGQghsE-RsI/AAAAAAAAAAY/DkMjZLT32Xo/s320/AbstractFactory.jpg" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;span style="font-family:verdana;font-size:85%;"&gt;As classes e/ou objetos que participam deste padrão são:&lt;/span&gt;
&lt;span style="font-family:verdana;font-size:85%;"&gt;
• &lt;span style="color:#ff0000;"&gt;&lt;strong&gt;AbstractFactory&lt;/strong&gt;&lt;/span&gt; (ContinenteFactory)
        o declara uma interface para operações que criam produtos abstratos
• &lt;span style="color:#ff0000;"&gt;&lt;strong&gt;ConcreteFactory &lt;/strong&gt;&lt;/span&gt;(AfricaFactory, AmericaFactory)
        o implementa a operação para criar um objeto produto concreto&lt;/span&gt;
&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;• &lt;span style="color:#ff0000;"&gt;&lt;strong&gt;AbstractProduct &lt;/strong&gt;&lt;/span&gt;(Herbivoro, Carnivoro)
        o declara uma interface para um objeto do tipo produto
• &lt;span style="color:#ff0000;"&gt;&lt;strong&gt;Product&lt;/strong&gt;&lt;/span&gt; (Gnu, Leao, Bufalo, Lobo)
        o define um objeto produto para ser criado pela fábrica concreta que implementa a interface AbstractProduct
• &lt;span style="color:#ff0000;"&gt;&lt;strong&gt;Client&lt;/strong&gt;&lt;/span&gt; (MundoAnimal)
        o usa as interfaces declaradas pelas classes AbstractFactory e AbstractProduct
&lt;/p&gt;
&lt;strong&gt;Abstract Factory: Quando e onde usar?&lt;/strong&gt;&lt;/span&gt;
&lt;span style="font-family:verdana;"&gt;O padrão Abstract Factory provém um cliente com uma classe que cria objetos que possuem relação através de características comuns. Outra razão e benefício para criar objetos usando o padrão Abstract Factory é especialmente quando os contrutores das classes são chamadas diretamentes para criar objetos diferentes(overloads). Construtores são limitados no controle de processos de criação de objetos em geral. Se sua aplicação necessita de maior controle, considere usar um Factory. As Factorys incluem cenários que envolvem caching de objetos, sharing, re-using e aplicações que mantenham contadores de objetos e tipos.&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Existe momentos em que o cliente não conhece exatamente que tipo deve construir. Isso pode ser resolvido fácilmente com o uso de tipos base ou interface e a fábrica pode passar parâmetros ou outros tipos de informações para tomar essa decisão para o cliente. Um exemplo disso são os provider especificos dos objetos ADO.NET(DbConnection, DbCommand, DbDataAdapter, etc).&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Os contrutores não passam muito bem a sua intenção quando existem vários overloads por que eles necessitam ter o mesmo nome da classe (ou Sub New no VB.NET). Construtores com muitos overloads acabam confundindo os desenvolvedores na hora de decidir qual deles usar. Substituir construtores por métodos factory que mostram a sua intenção muitas vezes é o melhor a fazer.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Exemplo:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Vários construtores sobrecarregados, qual deles você deveria usar?
&lt;/span&gt;
&lt;pre name="code" class="C#"&gt;
// C# 
public Veiculo (int passageiros);
public Veiculo (int passageiros, int cavalosPotencia);
public Veiculo (int rodas, bool trailer);
public Veiculo (string tipo);
&lt;/pre&gt;
&lt;/p&gt;
&lt;pre name="code" class="Vb"&gt;
' VB.NET
Public Sub New(ByVal passageiros As Integer)
Public Sub New(ByVal passageiros As Integer, ByVal cavalosPotencia As Integer)
Public Sub New(ByVal rodas As Integer, ByVal trailer As Boolean)
Public Sub New(ByVal tipo As String) 
&lt;/pre&gt;
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Com o padrão Factory o código fica mais expressivo e os desenvolvedores mais produtivos:&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;
&lt;/p&gt;
&lt;pre name="code" class="C#"&gt;
// C#
public Veiculo CriaCarro(int passageiros);
public Veiculo CriaSport(int passageiros, int cavalosPotencia);
public Veiculo CriaOnibus(int rodas, bool trailer);
public Veiculo CriaBarco();
public Veiculo CriaMoto();
&lt;/pre&gt;
&lt;/p&gt;
&lt;pre name="code" class="Vb"&gt;
' VB.NET 
Public Function CriaCarro(ByVal passageiros As Integer) As Veiculo
Public Function CriaSport(ByVal passageiros As Integer, ByVal cavalosPotencia As Integer)As Veiculo
Public Function CriaOnibus(ByVal rodas As Integer, ByVal trailer As Boolean)As Veiculo
Public Function CriaBarco()As Veiculo
Public Function CriaMoto()As Veiculo
&lt;/pre&gt;
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Para ver um exemplo do padrão AbstractFactory na prática é só baixar o projeto que segue no link abaixo:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Verdana;font-size:85%;"&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;&lt;a href="http://cid-17621fcd61d3a95a.skydrive.live.com/self.aspx/Blog/AbstractFactory.zip"&gt;http://cid-17621fcd61d3a95a.skydrive.live.com/self.aspx/Blog/AbstractFactory.zip&lt;/a&gt; (VS 2008)&lt;/p&gt;Até a próxima...

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650164488068959224-6698664693831463353?l=hugoestevam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hugoestevam.blogspot.com/feeds/6698664693831463353/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3650164488068959224&amp;postID=6698664693831463353&amp;isPopup=true' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650164488068959224/posts/default/6698664693831463353'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650164488068959224/posts/default/6698664693831463353'/><link rel='alternate' type='text/html' href='http://hugoestevam.blogspot.com/2008/06/abstract-factory.html' title='Abstract Factory'/><author><name>Hugo Estevam Longo</name><uri>http://www.blogger.com/profile/12778915451564782261</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_Q8o-StsG350/R7tskMQ5RlI/AAAAAAAAAAM/BsIRZ7tNBiI/S220/S2020024.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_Q8o-StsG350/SGQghsE-RsI/AAAAAAAAAAY/DkMjZLT32Xo/s72-c/AbstractFactory.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650164488068959224.post-2508405967898045613</id><published>2008-02-19T21:02:00.001-03:00</published><updated>2008-08-18T00:08:55.629-03:00</updated><title type='text'>Bem-vindo aos padrões de projetos</title><content type='html'>&lt;span style="font-family:verdana;font-size:85%;"&gt;O que é padrão de projeto? Para que servem os padrões de projetos?&lt;/span&gt;
&lt;/p&gt;
&lt;span style="font-family:Verdana;font-size:85%;"&gt;Essas são perguntas que todo desenvolvedor deveria fazer antes de inicializar um projeto.&lt;/span&gt;
&lt;/p&gt;
&lt;span style="font-family:Verdana;font-size:85%;"&gt;Todos nós já usamos bibliotecas e APIs comerciais. Nós a pegamos, escrevemos alguns códigos, compilamos em nossos programas e aproveitamos um monte de códigos que outra pessoa escreveu. Pense nas APIs e em todas as funcionalidades que elas lhe dão: rede, I/O, etc. As bibliotecas e APIs demoram um tempão para chegar a um modelo de desenvolvimento onde podemos apenas selecionar os componentes e utilizá-los. Mas elas não nos ajudam a estruturar nossos próprios aplicativos de maneiras mais flexíveis, faceis de entender e manter. É aí que os Padrões de Projetos ou Design Patterns entram.&lt;/span&gt;
&lt;/p&gt;
&lt;span style="font-family:Verdana;font-size:85%;"&gt;Os padrões de projetos não são nada mais que o uso dos princípios de design orientado a objeto, estão num nível acima das bibliotecas. Os padrões de projetos nos dizem como resolver alguns problemas, e é tarefa nossa adaptar esses designs para adequá-los a nosso aplicativo.&lt;/span&gt;
&lt;/p&gt;
&lt;span style="font-family:Verdana;font-size:85%;"&gt;"Mas mesmo que eu siga o encapsulamento e conheça abstração, herança e polimorfismo, preciso mesmo conhecer os Padrões de Projetos? Não é muito direto? não é por isso que fiz todos esses cursos sobre Orientação a Objeto?"&lt;/span&gt;
&lt;/p&gt;
&lt;span style="font-family:Verdana;font-size:85%;"&gt;Este é um dos mal-entendidos do desenvolvimento orientado a objeto: que conhecendo os princípios de Orientação a Objetos automaticamente seremos bons na construção de sistemas flexíveis, reutilizáveis e de fácil manutenção. Lembre-se, conhecer conceitos como abstração, herança e polimorfismo não faz de você um bom designer orientado a objeto. Um bom design pensa em como criar designs flexíveis que possam lidar com mudanças.&lt;/span&gt;
&lt;/p&gt;
&lt;span style="font-family:Verdana;font-size:85%;"&gt;Obs.: Os padrões de projetos não entram diretamente no seu código, primeiro entram em seu CÉREBRO.&lt;/span&gt;
&lt;/p&gt;
&lt;span style="font-family:Verdana;font-size:85%;"&gt;Veja mais sobre padrões de projetos em:&lt;/span&gt;
&lt;span style="font-family:Verdana;font-size:85%;"&gt;&lt;a href="http://www.dofactory.com/Patterns/Patterns.aspx"&gt;http://www.dofactory.com/Patterns/Patterns.aspx&lt;/a&gt;&lt;/span&gt;
&lt;a href="http://pt.wikipedia.org/wiki/Padr%C3%B5es_de_projeto_de_software"&gt;&lt;span style="font-size:85%;"&gt;http://pt.wikipedia.org/wiki/Padr%C3%B5es_de_projeto_de_software&lt;/span&gt;&lt;/a&gt;
&lt;span style="font-family:Verdana;font-size:85%;"&gt;E para descontrair:&lt;/span&gt;
&lt;a href="http://desciclo.pedia.ws/wiki/Gambi_Design_Patterns"&gt;&lt;span style="font-size:85%;"&gt;http://desciclo.pedia.ws/wiki/Gambi_Design_Patterns&lt;/span&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;span style="font-size:85%;"&gt;Até mais,&lt;/span&gt;
&lt;span style="font-size:85%;"&gt;Hugo Estevam&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650164488068959224-2508405967898045613?l=hugoestevam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hugoestevam.blogspot.com/feeds/2508405967898045613/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3650164488068959224&amp;postID=2508405967898045613&amp;isPopup=true' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650164488068959224/posts/default/2508405967898045613'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650164488068959224/posts/default/2508405967898045613'/><link rel='alternate' type='text/html' href='http://hugoestevam.blogspot.com/2008/02/bem-vindo-aos-padres-de-projetos.html' title='Bem-vindo aos padrões de projetos'/><author><name>Hugo Estevam Longo</name><uri>http://www.blogger.com/profile/12778915451564782261</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp2.blogger.com/_Q8o-StsG350/R7tskMQ5RlI/AAAAAAAAAAM/BsIRZ7tNBiI/S220/S2020024.jpg'/></author><thr:total>0</thr:total></entry></feed>
