Tag Archives: clean code

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.

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. :)

Conselho do Tio Bob

Esse vídeo foi gravado já faz um tempo pelo Fabio Akita e foi postado no blog dele. Eu acho este vídeo tão bom que resolvi colocá-lo aqui, talvez alguém ainda não tenha visto.

Livro: Clean Code, A Handbook of Agile Software Craftsmanship

Sabe aqueles livros que você lê e não para? Então, aconteceu isso comigo ao ler este, Clean Code é um dos poucos livros que dei nota 5 no shelfari.

Martin_MECH.qxd

O primeiro cápitulo é um dos pontos chaves da leitura, ele fala sobre as vantagens de um código limpo, e porquê você deveria se preocupar com isso. Mesmo que um trecho de código compile e funcione da maneira esperada ( certificando-se através de testes unitários )  pode ser ser considerado ruim, legado e mal escrito. O problema é que é muito difícil manter um código limpo, toda a equipe precisa estar ciente dos ganhos que isso pode trazer, e basta uma pessoa violar as regras e o código já vira um carnaval. O que acontece geralmente é que a primeira versão de um componente é desenvolvido de forma clara e bem escrito, nas manutenções subseqüentes as primeiras sujeiras começam a ser inseridas até o momento que vira um monstro onde ninguémtem coragem de tocar.

Nos Estados Unidos as reservas florestais possuem uma regra que diz: “Leave the campground cleaner than you found it”. Imagine isso em um ambiente de desenvolvimento de software, não seria o máximo ter um projeto que o código está sempre mais limpo do que ontem?

Não sei exatamente o que leva algumas empresas a não se preocupar com as boas práticas, é fato que a maior parte dos problemas ocorrem na fase de análise de sistemas, uma análise errada pode resultar em um software inútil, assim como uma ótima análise é um péssimo código resulta em um sistema com os dias contados, daqui 2 ou 3 anos vai sair mais barato fazer outro do que dar manutenção no sistema “legado”. No final quem ganha com isso são as Fábricas de Software, no final do mês são mais horas contratadas, enquanto isso o pobre cliente está lá investindo em algo que logo morre.

wtf-per-minute

Talvez você não tenha como mudar as coisas na sua empresa, mas faça sua parte, limpe o acampamento antes de fazer check-in, tudo bem que um urso pode vir e destruir seu código, mas pelo menos você fica com a consciência limpa de que fez o que era certo.

Como escrever um código clean?

Sugiro a leitura do livro, ele trata sobre nomenclatura de métodos, classes e variáveis, comentários, funções, tamanho da função e responsabilidades (SRP). Dentre outros assuntos, também fala sobre testes automatizados, vejam que esse assunto está presente em todo lugar.

Não adianta ler e achar que vai virar um ninja, é claro que depois de terminar você já vai ter aprendido diversos truques, mas os mais as práticas mais elaboradas precisam de tempo e prática. Na teoria é tudo muito bonito e aparentemente fácil, quando você coloca a mão na massa você percebe que não é tão fácil e que requer muito estudo.

Segue mais alguns links interessantes sobre o assunto:

Sharing Buttons by Linksku