Estou de mudança. Até logo!

Depois de algum tempo sem atualizar este blog estou aqui para escrever que estou de mudança. Quer dizer, não eu exatamente, mas sim o blog.

Fiz o registro do domínio http://geekstuff.cc algum tempo atrás e tentei fazer dele um blog/site/wiki pessoal utilizando código próprio, ou seja, sem CMS algum. O motivo era que eu gostaria de utilizar alguns recursos não habilitados em Shared Hosting, e por isso até então eu estava hospedando-o no AppHarbor.

Depois de algum tempo me batendo para fazer simples tarefas (como escrever ou atualizar um post) resolvi definitivamente matar este site e colocar um wordpress lá. Tentei reinventar a roda, mas acho que não ficou muito bom :)

De qualquer forma, tive a ideia de manter um subdomínio no AppHarbor para colocar meus experimentos lá. O setup já foi feito, só falta jogar o conteúdo, e o endereço será: http://playground.geekstuff.cc/

Além disso resolvi fazer os posts em inglês. Em primeiro lugar eu espero que com isso eu possa treinar mais o meu inglês escrito, outro motivador para esta mudança é que na teoria haverá mais leitores. Mas isso também depende mais de mim já que ultimamente eu estou meio parado com as atualizações.

E é isso ai pessoal, um grande abraço para todos e nos vemos no GeekStuff :)

Artigo sobre Refatoração na .NET Magazine 85

Olá pessoal,

Gostaria de divulgar que meu segundo artigo para a revista .NET Magazine foi publicado este mês na edição 85.

Os assuntos abordados nesta edição foram:

  • Novidades do universo .NET
  • Ouvindo os clientes
  • Neutralidade da rede
  • ASP.NET Generic Handlers
  • Bing Maps na nuvem
  • Windows Azure
  • WCF
  • Reflection com Banco de Dados (Capa da Revista)
  • Refatoração
  • Data Binding
  • Injeção de dependência com Unity
  • Integração Contínua

Escrevi sobre Refatoração, assunto na qual defendo sua importância com unhas e dentes.

Juro que logo volto a postar, palavra de escoteiro :)

Até a próxima!

Meu primeiro artigo para a .NET Magazine

Olá pessoal, tudo certo?

Em dezembro de 2010 tive a oportunidade de escrever um artigo para a .Net Magazine. O artigo saiu na revista deste mês, na edição número 84.

Escolhi o tema Behaviour-Driven Development focando principalmente no SpecFlow, ferramenta na qual acho fenomenal. A edição ainda  ainda conta com outros artigos, são eles:

  • Vaporware do Google
  • ClickOnce
  • TweetSharp (Capa da Revista)
  • Desmitificando delegates
  • Reflection
  • Behaviour-Driven Development
  • MSF for Agile 5 e TFS 2010
  • REST com WCF Data Services
  • Metodologias Ágeis

A experiência de escrever um artigo pela primeira vez para uma revista foi fantástica. Estou bastante feliz com o resultado. Tanto que até escrevi outro artigo, deve sair na 85 ou 86. Gostaria de agradecer o Leandro Daniel e o Guinther Pauli pela oportunidade e incentivo.

Aproveitando o post, gostaria de pedir desculpas pela minha ausência no blog. Estou bastante atarefado com as atividades do último semestre da faculdade (finalmente!). Pretendo voltar à ativa em 2011/2, tanto no blog quanto na revista.

Quem tiver qualquer comentário sobre meu artigo pode ficar a vontade para me procurar. Estou aceitando elogios, críticas, dúvidas e sugestões.

Vou ficando por aqui, abraços e até mais!

Usando Builder Pattern com Interfaces Fluentes

Boa noite, tudo certo? :)

Acabei de passar por uma situação bastante interessante onde apliquei uma solução que eu achei bastante elegante. Gostaria de compartilhá-la aqui no Blog na esperança de que isso possa ajudar alguém. Vou utilizar uma exemplo hipotético,  porém parecido com a situação real.

A situação atual

Um time está criando uma aplicação nova e decide escrever seu próprio mecanismo de logging.
Em um determinado momento foi criado um objeto de valor – que representa uma entrada de log – conforme a seguinte definição:

public class LogEntry
{
    public LogLevel Level { get; set; }
    public string Message { get; set; }
    public DateTime DateTime { get; set; }
    public string Url { get; set; }
}

public enum LogLevel
{
    Warning,
    Information,
    Error
}

Alguém consegue achar um problema no código acima?

Teeeeempo!

1
2
3

10

Vamos imaginar que nosso framework de log cria uma instancia desta classe em um determinado local e depois repassa para uma classe de filtro conforme o código abaixo.

public class OnlyWarningFilter : IFilter
{
    public bool ShouldLog(LogEntry entry)
    {
        return entry.Level.Equals(LogLevel.Warning);
    }
}

Até ai tudo bem, este filtro vai fazer com que grave apenas os logs do tipo Warning. O problema é que estamos dando a oportunidade para esta classe simplesmente alterar completamente qualquer detalhe da LogEntry. Não só no filtro como também em qualquer local em que esta instância for repassada. Isto acontece pois definimos todas as nossas propriedades como públicas, tanto o get quanto o set. Olha só o que algum desenvolvedor pode fazer dentro do filtro.

public class OnlyWarningFilter : IFilter
{
    public bool ShouldLog(LogEntry entry)
    {
        entry.Message = "All your base are belong to us!";
        entry.DateTime = DateTime.Now.AddDays(-123);
        return entry.Level.Equals(LogLevel.Warning);
    }
}

Está instalado o chaos! Todos os nossos logs terão um conteúdo indesejado ao invés de uma mensagem informativa e confiável. Isto foi apenas um exemplo, é muito provável que ninguém faça isso, mas se pudéssemos prevenir seria melhor, não acha? A solução mais obvia é marcar o set das propriedades como private e criar um construtor público recebendo as quatro propriedades. Ficaria assim.

public class LogEntry
{
    public LogLevel Level { get; private set; }
    public string Message { get; private set; }
    public DateTime DateTime { get; private set; }
    public string Url { get; private set; }

    public LogEntry(LogLevel level, string message, DateTime dateTime, string url)
    {
        this.Level = level;
        this.Message = message;
        this.DateTime = dateTime;
        this.Url = url;
    }
}

Problema resolvido. Se você se sente satisfeito por aqui, tudo bem, mas eu vou mais além!

Neste caso temos apenas quatro propriedades e o construtor ainda está bastante enxuto. Apesar de que, na minha opinião, quatro parâmetros no construtor já começa a ficar feio. Toda nova propriedade faria o construtor crescer mais e mais, o que é certamente algo indesejado.

A solução aplicada

Com certeza já ouviram falar que Design Pattern deve ser utilizado quando surge um problema já conhecido, este exemplo é a prova disto. Temos um problema e há um grupo de padrões exclusivos para criação de objetos. Vamos utilizar o Builder Pattern com algumas pitadas de Interfaces Fluente. O resultado é excelente. Para mais detalhes sobre estas duas técnicas, utilize os links acima, vou direto para a solução e explicação.

public class LogEntry
{
    public LogLevel Level { get; private set; }
    public string Message { get; private set; }
    public DateTime DateTime { get; private set; }
    public string Url { get; private set; }

    private LogEntry(Builder builder)
    {
        this.Level = builder.Level;
        this.Message = builder.Message;
        this.DateTime= builder.DateTime;
        this.Url = builder.Url;
    }

    public class Builder
    {
        public LogLevel Level { get; private set; }
        public string Message { get; private set; }
        public DateTime DateTime { get; private set; }
        public string Url { get; private set; }

        public Builder AsError()
        {
            return WithLevel(LogLevel.Error);
        }

        public Builder AsInformation()
        {
            return WithLevel(LogLevel.Information);
        }

        public Builder AsWarning()
        {
            return WithLevel(LogLevel.Warning);
        }

        public Builder WithLevel(LogLevel level)
        {
            this.Level = level;
            return this;
        }

        public Builder MessageIs(string message)
        {
            this.Message = message;
            return this;
        }

        public Builder CreatedOn(DateTime dateTime)
        {
            this.DateTime = dateTime;
            return this;
        }

        public Builder OnUrl(string url)
        {
            this.Url = url;
            return this;
        }

        public static implicit operator LogEntry(Builder builder)
        {
            return new LogEntry(builder);
        }
    }
}

A criação de uma nova entrada passou de:

LogEntry entry = new LogEntry(LogLevel.Error, "System is out of memory!", DateTime.Now, "http://localhost/ListOnlineUsers.aspx");

Para:

LogEntry entry = new LogEntry.Builder()
                                .AsError()
                                .MessageIs("System is out of memory!")
                                .CreatedOn(DateTime.Now)
                                .OnUrl("http://localhost/ListOnlineUsers.aspx");

A maior vantagem desta nova solução é a facilidade na leitura do código. No primeiro caso é mais difícil saber o que cada parâmetro significa, é necessário ver o nome de cara parâmetro no construtor da classe. Além disso, o primeiro exemplo está nos obrigando a atribuir as quatro propriedades, se uma delas fosse opcional, teríamos que escrever um novo construtor (aka Telescopic Constructor Pattern). Novamente a tendência é criarmos vários construtores conforme a necessidade. No segundo caso é possível atribuir apenas as propriedades que sejam necessárias.

Percebam também que temos a opção de definir o tipo de log utilizando os método auxiliares AsError(), AsWarning() e AsInformation() ou então, caso necessário, ainda podemos utilizar o WithLevel(LogLevel). Fica bastante agradável de ler e escrever, não acham?

Em Java seria necessário criar um método build() em nosso LogEntry.Builder que iria ser responsável por criar e devolver uma instância do LogEntry. No .Net é possível substituirmos este método por um operador de conversão implícita e evitar ter que explicitamente pedir para o builder construir o objeto.

Gostou? Espero que façam um bom uso :)

Não gostou de algo ou achou algum problema? Compartilhe!

Ps1.: Para quem nunca achou uma utilidade para as classes internas do .Net/Java, eis aqui um bom exemplo.
Ps2.: O código está no GitHub.
Ps3.: Nó GitHub eu dividi a classe em em dois arquivos utilizando o recurso de classes parciais, achei que ficou mais organizado.

Alterando a convenção de nomenclatura usada no Fluent NHibernate

Recentemente iniciei um projeto na qual decidi utilizar o NHibernate 3.0 e testar o Linq to NHibernate. Posso dizer que estou muito satisfeito com o resultado desta versão e até agora consegui escrever todas as minhas queries usando Linq. Além disso, resolvi também utilizar o Fluent NHibernate já que, das 3 opções que temos, é a que mais me agrada.

Para quem me conhece sabe que eu extremamente chato quanto a nomenclatura de classes, variáveis, tabelas, pacotes etc. Nem sempre consigo achar um nome legal, as vezes demora, por isso prefiro colocar um nome temporário e deixar para melhorar em uma próxima refatoração.

Foi exatamente isso que aconteceu quando comecei a utilizar o Fluent NHibernate (FH) e foi o que me levou a escrever este post. Por padrão, sempre que temos uma relação ManyToMany, como por exemplo Usuário e Grupo, o FH cria uma tabela intermediária e esta recebe o nome de UsuarioToGrupo, ou seja, ela segue o padrão {Tabela1}To{Tabela2}. Muitos de vocês devem ter suas próprias convenções para nomear tabelas, por exemplo nunca utilizar nomes no plural ( eu uso bastante esta ) e também utilizar um underline nas tabelas com relacionamento N-N. Seguindo este padrão, o resultado da tabela seria Usuario_Grupo, na qual eu acho mais legível e limpo.

Caso você tambem goste deste formato e deseja utilizá-lo no Fluent NHibernate, crie uma nova classe que extenda ManyToManyTableNameConvention e faça uma sobrescrita dos métodos GetBiDirectionalTableName e GetUniDirectionalTableName conforme o exemplo abaixo.

public class BetterManyToManyTableNameConvention : ManyToManyTableNameConvention
{
    protected override string GetBiDirectionalTableName(IManyToManyCollectionInspector collection, IManyToManyCollectionInspector otherSide)
    {
        return collection.EntityType.Name + "_" + otherSide.EntityType.Name;
    }

    protected override string GetUniDirectionalTableName(IManyToManyCollectionInspector collection)
    {
        return collection.EntityType.Name + "_" + collection.ChildType.Name;
    }
}

Work complete! Essa foi fácil ein? Adoro frameworks extensíveis :)
Não se esqueça de registrar esta customização ao criar a SessionFactory, se você não sabe como fazer isso, estou colando abaixo um exemplo.

ISessionFactory factory = Fluently.Configure().Database(
    MsSqlConfiguration.MsSql2008.ConnectionString("MY SECRET CONN STRING").Mappings(
    x =>
    {
        x.FluentMappings.AddFromAssemblyOf<User>();
        x.FluentMappings.Conventions.Add<BetterManyToManyTableNameConvention>();
    }
).BuildSessionFactory();

Vale lembra também que este é apenas um exemplo de customização, para maiores opções basta consultar a namespace “FluentNHibernate.Conventions” e procurar a interface ou classe de seu interesse.

Até mais!

Melhorando a legibilidade do C# com Extension Methods

É difícil achar alguém que não goste da sintaxe do Ruby, é simples e agradável, tanto para ler quanto para escrever. Muitas vezes as instruções se tornam verdadeiras frases e parece que você está lendo um artigo e não um código. Olha como fica um loop em Ruby.

5.times { puts "Hi" }

“5 vezes imprima Hi”. O melhor de tudo é que é possível termos algo muito semelhante em C#, fica assim.

//New Style
5.Times((i) => {
    Console.WriteLine(i);
});

//Old Style
for(int i = 0; i < 5; i++) {
    Console.WriteLine(i);
}

Ok, um pouco mais verboso que o exemplo em Ruby, mas ainda assim é muito agradável. Para conseguirmos usar o exemplo acima é preciso incluir este pequeno extension method.

public static void Times(this int times, Action<int> action)
{
    for (int i = 0; i < times; i++)
        action(i);
}

Extension Methods, adoro :)
São várias as possibilidades de extensão, basta usar a criatividade.

//Loop de 5 até 10
5.To(10, (i) => {
    Console.WriteLine(i);
});

//string.IsNullOrEmpty() é chato demais, que tal isso?
string nome = "Guilherme";
if (nome.IsNullOrEmpty()) {
    Console.WriteLine("Nome está vazio");
}

//3.Minutes(), 10.Seconds(), 2.Hours(). nuff said
Thread.Sleep(3.Minutes());

A implementação fica assim.

public static bool IsNullOrEmpty(this string value)
{
    return string.IsNullOrEmpty(value);
}

public static void To(this int start, int end, Action<int> action)
{
    for (int i = start; i <= end; i++)
        action(i);
}

public static TimeSpan Minutes(this int minutes)
{
    return TimeSpan.FromMinutes(minutes);
}

public static TimeSpan Hours(this int hours)
{
    return TimeSpan.FromHours(hours);
}

public static TimeSpan Minutes(this int seconds)
{
    return TimeSpan.FromSeconds(seconds);
}

Dica: Quer conhecer uma infinidade de métodos legais e criativos? Este tópico no StackOverflow posusi vários métodos enviados pela comunidade. Escolhas os que mais lhe agradam. Tem também o projeto Fluent DateTime no CodePlex, pode ser útil para aqueles que precisam utilizar datas.

Controlando a crição dos Controllers no ASP.NET MVC

Uma das características que eu mais gosto do ASP.NET MVC é sua extensibilidade, existem diversos pontos que são possíveis de customizar e configurar para que o framework se comporte da maneira que você quer.

A criação dos controllers é um destes pontos e possivelmente um dos menos usados pelos desenvolvedores por ai. Talvez por desconhecimento ou não saber como tirar proveito disso, não sei. Foi isso que me levou a criar este post onde vou apresentar o que podemos fazer ao tomar controle sobre a construção dos controllers.

Antes de prosseguirmos, sabiam que os Controllers utilizam o princípio de Hollywood? Este princípio se resume na seguinte frase “não nos chame, nós chamaremos você” (don’t call us, we’ll call you). Isso significa que, ao criar um novo Controller, você não precisa dizer ao ASP.NET MVC quando chamar ou então como criá-lo, você apenas o define e deixa que o próprio framework cuide do ciclo de vida  dele.

Voltando ao assunto principal, quando realizamos um HTTP Request o framework utiliza as definições de rotas para descobrir qual o controller que deve ser criado e então repassa a responsabilidade de criação para a classe DefaultControllerFactory.

Os controllers são objetos como qualquer outro e é da natureza da Programação Orientada a Objetos que haja a “troca de mensagens” entre os objetos e consequentemente uma dependência de um objeto para outro. É comum um controller depender de uma classe de serviço ou de acesso à dados, a maneira mais comum de gerenciarmos isso é através dos contrutores. Um controller com dependência ficaria assim:

private IMailService mailService;

public HomeController(IMailService mailService)
{
    this.mailService = mailService;
}

Se executarmos assim como está, recebemos uma exception com a mensagem “No parameterless constructor defined for this object.“. Se olharmos um pouco o código do DefaultControllerFactory é possível perceber que é utilizado o Activator.CreateInstance sem a passagem de parâmetros, isso significa que ele irá procurar um construtor sem parâmetros. No nosso caso onde não podemos aceitar a construção do HomeController sem o serviço de e-mail, a solução é tomar controle sobre a criação dos controllers e customizá-los como bem quisermos. Uma implementação bem simples ficaria assim.

public class CustomControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType == typeof(HomeController))
            return new HomeController(new LocalMailService());
        return base.GetControllerInstance(requestContext, controllerType);
    }
}

Apesar de eu ter herdado de DefaultControllerFactory, seria perfeitamente aceitável implementar diretamente a IControllerFactory, a diferença é que assim eu economizo diversas linhas de código já que não preciso escrever todos os métodos exigidos pela interface. Para registrar esta customização, é necessário adicionar a seguinte instrução no Application_Start do Global.asax.

ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory());

Done! Agora nosso controller está sendo criado com uma instância de LocalMailService. Isso é chamado de injeção de dependência via construtor. Como eu disse acima, essa é uma implementação simples, se olharmos com mais cuidado a classe CustomControllerFactory é possível verificar que esta solução não escala. Se para cada controller for necessário adicionar uma nova condição, nossa classe vai crescer em tamanho e complexidade.

A solução mais utilizada e até onde eu sei a mais recomendada, é utilizar um framework de injeção de dependência. Neste exemplo vou utilizar o StructureMap, o download está disponível no site oficial.

Ao utilizar o StructureMap, a solução final fica assim.

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterDependencies();

    ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory());

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
}

private void RegisterDependencies()
{
    ObjectFactory.Configure(x =>
        x.For<IMailService>().Use<LocalMailService>()
    );
}

E nossa ControllerFactory ficou bem mais limpa.

protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
    return ObjectFactory.GetInstance(controllerType) as IController;
}

Quando tivermos novos controllers e novas dependências basta registar no StructureMap e o resto já estará sendo feito sozinho.

UPDATE: Para quem está usando o MVC3 e está buscando injeção de dependência nos controllers, uma outra opção ainda mais elegante é usar o DependencyResolver,  o Vínicius Quaiato fez um post sobre isso.

Espero que seja útil :)

3 em 1 – Mapeamento Objeto-Relacional com NHibernate

No NHibernate existem três formas de fazer o mapeamento entre suas classes de domínio e suas tabelas relacionais, são elas:

  1. Arquivos XML;
  2. Atributos (Anotações);
  3. Mapeamento Fluente;

Vou explicar como fazer o mapeamento usando cada uma destas opções bem como apontar as vantagens e desvantagens de cada uma delas.

1. Arquivos XML

Este é o mais comun pois se trata da forma mais antiga de se fazer o mapeamento. Como o NHibernate surgiu do Hibernate (Java), e em Java era muito comum utilizar arquivos XML para fazer configurações (ainda é comum), foi assim que o NHibernate começou também. Nesta opção nós temos um arquivo XML para cada entidade. Veja este exemplo.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
  <class name="MyApplication.Domain.Customer, MyApplication.Domain" lazy="true">
    <id name="Id">
      <generator class="identity" />
    </id>
    <property name="FirstName" type="String" column ="FirstName" length="40" not-null="true" />
    <property name="LastName" type="String" column="LastName" length="100" not-null="true" />
    <property name="Birthday" type="DateTime" column="Birthday" not-null="false" />
  </class>
</hibernate-mapping>

E a entidade ficaria assim.

public class Customer
{
    public virtual int ID { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public virtual DateTime Birthday { get; set; }
}

Simples assim, não tem muito segredo.

  • Vantagens
    • É o mais maduro pois já está a bastante tempo em uso;
  • Desvantagens
    • Configuração complicada;
    • É necessário lembrar de compilar junto com os Assemblies;
    • Está muito propício ao erro, se alterar a entidade precisa lembrar de alterar o mapeamento;

2. Atributos (Anotações)

Atributo é o nome dado às classes em C# que são usadas para decorar propriedades ou métodos. É equivalente à anotação em Java. Nesta opção agora não temos mais arquivos externos, todo o mapeamento é feito na própria classe. Olha só um exemplo do mesmo mapeamento que fizemos acima.

[Class]
public class Customer
{
    [Id(Name = "Id")]
    [Generator(1, Class = "Identity")]
    public virtual int ID { get; set; }

    [Property(Name="FirstName", NotNull = true, Length = 40)]
    public virtual string FirstName { get; set; }

    [Property(Name="LastName", NotNull = true, Length = 100)]
    public virtual string LastName { get; set; }

    [Property(Name="Birthday", NotNull = false, )]
    public virtual DateTime Birthday { get; set; }
}
  • Vantagens
    • Compilação facilitada;
    • Alteração fica centralizada em apenas um lugar;
  • Desvantagens
    • Poluição da classe, começa a ter mais linhas, fica menos legível e cria uma forte dependência com o NHibernate;

3. Mapeamento Fluente

Este é a mais nova opção de mapeamento e apenas disponível para .Net. Trata-se de uma combinação do melhor de cada um dos modelos acima. Olha como fica.

public class Customer
{
    public virtual int ID { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public virtual DateTime Birthday { get; set; }
}

Veja que minha entidade não mudou nada com relação ao primeiro exemplo.

public class CustomerMap : ClassMap<Customer>
{
    public CustomerMap()
    {
        Id(x => x.Id);
        Map(x => x.FirstName).Length(40).Not.Nullable();
        Map(x => x.LastName).Length(100).Not.Nullable();
        Map(x => x.Birthday).Nullable();
    }
}

Agora sim chegamos numa solução que eu chamaria de perfeita. Para saber mais sobre o Fluent NHibernate acesse o site oficial.

  • Vantagens
    • Compilação facilitada;
    • Classes pequenas, simples e limpas;
  • Desvantagens
    • Este framework é bem novo quando comparado com os outros dois, por isso pode apresentar alguns defeitos. Entretanto, até agora nunca tive problemas.

Fico pensando se existe alguma outra forma de realizar os mapeamentos. Me parecem que todas elas já foram exploradas. Acho que ficou claro que eu gosto bastante do Fluent NHibernate, e você?

Dica #6: Escrevendo testes fluentes


Aqui vai uma dica rápida. Quando comecei a escrever meus primeiros testes automatizados eu tinha algo assim.

int actual = calculadora.Somar(1 +2);
int expected = 3;
Assert.AreEquals(expected, actual);

Após um tempo, comecei a ganhar mais experiência e aprendi algo chamado de Fluent Interfaces. O objetivo desta “técnica” é escrever código que seja fácil de ler. O código acima é fácil, correto? Mas da para melhor, quer ver?

Veja este exemplo aqui.

int actual = calculadora.Somar(1 +2);
Assert.That(actual, Is.EqualTo(3));

Melhorou, não acha? Legibilidade faz parte do Clean Code e Fluent Interfaces é uma excelente técnica que pode te ajudar a deixar seu código mais fácil de ler. Reserve um tempo e procure entender melhor como funciona. Além disso, a partir do C# 3.0 tivemos a adição das Closures que também é outro recurso poderosísimo na busca pela Legibilidade.

Nota: Estes exemplos acima foram construidos com NUnit e já vem pronto, não sendo necessário adicionar dependência para nenhuma outra biblioteca. No caso do MSUnit, eu recomendo o Sharp Tests Ex, que alías também funciona com o NUnit.

É isso ai e até a próxima.

Um código limpo diz mais que mil comentários

Você comenta seu código? Sim? Por quê?

Cuidado! Comentários podem ser perigosos! O uso deles pode ser um indício de que seu código está confuso e você tem medo de precisar alterar algo mais tarde e esquecer o que aquela variável aux armazena.

A forma mais elegante de se remover comentários é refatorando. Aux é um nome sem sentido, você pode até lembrar o que essa variável significa enquanto você ainda está programando, mas daqui duas semanas você já vai ter esquecido. Nomeie melhor suas variáveis, não tenha medo de ter uma variável assim: listaDeClientesInativos ao invés de lista.

Outro caso bastante comum de comentários é quando você tem aquele método gigante com 100 linhas e a cada 10 você resolve colocar um comentário para dizer o que está acontecendo. Nestes casos você pode (e deve) utilizar extract method. Divida seu grande método em outros pequenos, assim você pode substituir os comentários por métodos com nome auto-explicativos, além disso estará de acordo com o Single responsibility principle.

Não é possível garantir que outras pessoas do seu time irão atualizar o comentário quando alguma alteração for feita. Pior do que ter um método cheio de comentário é ter um método com um comentário obsoleto. Além disso, a leitura do comentário é opcional, você não tem como saber se seu comentário será lido ou não. Se você tem algo importante para dizer, diga no seu código, através de nomes bem definidos e código limpo.

Dito tudo isso, não preciso nem comentar sobre o exemplo abaixo né?

//Chamado #213: Corrigido bug onde o desconto final estava sendo somado ao invés de descontar.
int total = pedido.getTotal() - descontoFinal;

Se você faz isso, sugiro procurar algum software de controle de versão.

Algum tempo atrás escrevi sobre Expressões Regulares (aqui) e falei sobre comentários em Regex pattern. Continuo achando uma forma elegante de se utilizar comentários já que um pattern quase nunca é limpo, é sempre complicado ler aquilo e entender. Os comentários ajudam neste caso tornando-o mais legível. Outra opção seria escrever testes automatizados para seu Regex. Além dos testes servirem como exemplos de uso, você estará tendo uma maior cobertura do seu código e a garantia de poder alterar o pattern sem medo de inserir um novo bug.

Falando em Regex e Testes, lembrei deste tweet do @gchapiewski.

It’s impossible to program complex regular expressions without TDD. Period.

Resumindo. Mais código limpo e menos comentários. Ah, não esqueça de ler o livro Clean Code. :)

Sharing Buttons by Linksku