quarta-feira, 6 de junho de 2007

Revista Codificando.Net

É com muito prazer que aceitei o desafio de falar sobre qualidade na revista eletrônica Codificando.Net e-Magazine compartilhando espaço com outros profissionais brilhantes como o Israel Aéce e grandes amigos como Feio Tomaz, Hélio Sá e Alexandre Tarifa.

A primeira edição contém artigos sobre uma grande variedade de assuntos desde Microsoft Sharepoint Server e Biztalk até desenvolvimento de jogos para Windows e XBOX 360 com XNA.

Abaixo um trecho do meu artigo sobre os ganhos de qualidade quando se projeta o software visando facilidade de testes automáticos e manutenção futura:

"Nós desenvolvedores “Microsoft” sempre nos orgulhamos de sermos os mais produtivos, os únicos que cumprem as necessidades de uma inteligência de negócio sempre mutante, que algo que um desenvolvedor Java levaria um mês, um desenvolvedor VB poderia fazer em uma semana.
As nossas ferramentas de trabalho (Visual Studio, SQL Server, Reporting Services, etc) sempre acompanharam essa mentalidade do simples e rápido, deixemos o Java com o IDE Eclipse e suas dezenas de plug-ins. E neste meio tempo enquanto nós, desenvolvedores “Microsoft” melhorávamos a nossa produtividade, eles evoluíram em diversas técnicas de qualidade de software como automação de testes, refactoring de código, design patterns, software factories, processo de integração contínua e muitas outras frentes."

Espero ter sucesso e este blog está aberto para qualquer opnião, crítica ou sugestão sobre os artigos.

domingo, 20 de maio de 2007

Test Patterns: Mock, Fake, Stub e Dummy Objects parte 1 de 4

Esta é o primeiro de uma série de posts sobre padrões de teste (test patterns) que sempre encontramos em testes unitários. É muito importante conhecer estes padrões, da mesma maneira que os design patterns, eles contém soluções já empregadas com sucesso em um número imenso de problemas e permitem que todos se comuniquem de forma consistente.

O primeiro passo é entender o que são cada um destes tipos de objeto e quando devemos usar cada um deles. Todos estes tipos de objetos vêm solucionar dois grandes problemas ao se trabalhar com unit tests:

Testes não confiáveis devido a dependências que não podem ser utilizadas

Muitas vezes é díficil criar unit tests para um sistema porque ele contém dependências que não podem ser utilizadas no ambiente de testes.

Estas dependências podem causar diversos problemas, por exemplo, utilizar bancos de dados ou arquivos pode impedir que os testes retornem sempre valores consistentes (a não ser que seja criada lógica para restaurar as fontes de dados a um estado conhecido). Outro problema é simular exceções, é relativamente complexo por exemplo simular uma exceção de concorrência entre dois usuários tentando acessar um recurso, quando o único usuário é o desenvolvedor executando os testes!

Outra problema é quando temos códigos não testados*, como um Web Service de uma outra equipe ou ainda não construídos, nos quais é necessário esperar um certo tipo de comportamento consistente com as entradas informadas pelo sistema. Neste caso também se encaixa código que simplesmente não roda na máquina do desenvolvedor, como um código de acesso ao Active Directory (que necessitaria um infraestrutura imensa somente para executar um teste que deve ser reproduzível desde que mantidos os parâmetros de entrada).

*Não é recomendado criar testes para todo e qualquer tipo de código. Por exemplo, é insano querer criar qualquer teste para o .NET Framework. Código não testado aqui significa código cuja qualidade não foi verificada.

Testes muito lentos

Testes demorados significam que os desenvolvedovedores não os executarão cada vez que uma mudança é realizada no sistema, ponto.

Este único fator já deveria ser suficiente para rever os seus testes unitários já que uma das maiores vantagens de se desenvolverem tais testes é que qualquer bug inserido no código é rapidamente identificado quando os testes falham. Além disso, existe o custo óbvio de produtividade do desenvolvedor que precisa esperar que os testes terminem de executar antes de realizar qualquer alteração no código.

Nestas situações, quando escrevemos testes para um sistema e não podemos (ou não queremos) utilizar um objeto real, nós simplesmente escrevemos um substituto para ele. De modo que o sistema testado acredite que este objeto falso é real.

É claro que este objeto falso não precisa ser a cópia do original (implementar todos os membros de uma interface ou sobrescrever todos os métodos de uma classe base) ele somente precisa conter a implementação necessária para executar o conjunto de testes. Muitas vezes até um valor hard-coded é suficiente, em outras, teremos que implementar algum tipo de funcionalidade rudimentar para o teste ter algum valor.

A mensagem importante é que não importa o tipo de objeto falso que você deseje criar, ele não pode executar um caminho diferente do objeto real no código! Por isso o objeto falso deve ser "instalado" no sistema a ser testado no lugar do objeto real, abaixo temos um exemplo.

class ServicoCadastroCliente
{
void CadastrarCliente(string nome, string rg) {
CadastroCliente cad = new CadastroCliente();
cad.Adicionar(nome, rg);
}
}
class CadastroCliente
{
public void Adicionar(string nome, string rg)
{
//Lógica omitida para simplificar exemplo
}
}



Como eu criaria um objeto falso sem interferir no código de produção? O código abaixo contém um exemplo:


class ServicoCadastroCliente
{
ICadastroCliente _cadastroCliente;
// Esse é o construtor utilizado pelo código de produção, instancia a classe real CadastroCliente
void ServicoCadastroCliente() {
_cadastroCliente = new CadastroCliente();
}

// Esse é o construtor utilizado pelo código de teste, o código de teste apenas precisa passar uma
// instancia de CadastroClienteMock para trocar a classe real pela falsa
void ServicoCadastroCliente(ICadastroCliente cadastroCliente)
{
_cadastroCliente = cadastroCliente;
}
void CadastrarCliente(string nome, string rg) {
_cadastroCliente.Adicionar(nome, rg);
}
}



class CadastroCliente : ICadastroCliente
{
public void Adicionar(string nome, string rg)
{
//Lógica omitida para simplificar exemplo
}
}

interface ICadastroCliente
{
void Adicionar(string nome, string rg);
}

class CadastroClienteMock : ICadastroCliente
{
public void Adicionar(string nome, string rg)
{
//Pronto, aqui posso realizar qualquer tipo de checagem que garanta que
// tanto nome como rg foram passados corretamente pelo sistema testado
}
}


No próximo post entrarei em detalhes de cada tipo destes objetos falsos.

Microsoft Popfly (formally named Springfield)

Sexta feira foi anunciado o lançamento do primeiro preview do serviço Popfly da Microsoft, concorrente direto do Yahoo Pipes. O objetivo deste serviço é permitir a combinação de feeds RSS e APIs abertas para criar novos feeds e sites que combinem estas funcionalidades e informações, os chamados mashups.

A experiência de uso do Popfly parece muito amigável, você só precisa arrastar blocos de uma barra de ferramentas e conectados uns aos outros em um designer. Automaticamente o site diz os parametros que precisam ser informados para cada bloco e sugere as associações com os dados dos blocos conectados. Por exemplo, eu posso selecionar um bloco Flickr, um bloco Live Earth e um bloco GeoTags para exibir, em um mapa do Live Earth, thumbnails das fotos do Flickr.

Diferente do Yahoo Pipes pelos vídeos e screenshots que eu vi é muito mais simples e amigável, com uma bela interface desenvolvida em Silverlight e vários pontos de extensibilidade como a capacidade de criar os seus próprios blocos no Visual Studio .NET e outras funcionalidades interessantes como criar a sua própria página HTML para conter os seus mashups de APIs públicas (Flickr, Live Earth, GeoTags, Live Contacts, Tweeter, etc em programmableweb.com você pode ter uma idéia do número de APIs que poderão ser utilizadas).

Este ainda é um serviço em alpha privado, ou seja, somente algumas centenas de pessoas possuem acesso, no entanto aqui você pode fornecer o seu nome para receber um convite quando o serviço estiver disponível em beta. Se você tiver curiosidade assista esta entrevista com a equipe do Popfly no Channel9.

"A Fair(y) Use Tale" curta hilário sobre a lei do copyright, com legendas

Eric Faden criou este incrível montagem sobre a lei do copyright ironicamente somente com trechos de desenhos da Disney. A minha noiva Pri já havia me explicado um pouco sobre a lei Mickey Mouse criada praticamente sob medida para extender os direitos para toda a eternidade sobre a propriedade intelectual. Claramente um absurdo que visa somente atrapalhar o desenvolvimento de novas idéias, exatamente como grandes empresas como a Disney fizeram com quase todos os seus desenhos animados (consegue lembrar de algum trabalho da Disney que não seja baseada em um conto ou história já existente?).

Chapter 1: Copygright Definition

What the heck is copyright? It's the law, that's the problem. You know the law? That stupid law... What the heck is copyright? I will tell you: Copyright is determinate fix a original work in some form that it can be revived, seen or heard. Now listen, this is important, only the copyright owner has the right to use their work. It's mine!

-How can that be? That's not fair!

It's forbidden to use a copyrighted work without the permission granted by the copyright owner. And everybody who is fool enought to break the copyright has broken the law. But we've forgotten a tiny little detail, you better be able to pay for that copyright permission.

-We haven't discussed the subject of payment yet, you can't get something for nothing, you know?

-But I don't have any...

-I don't ask much, just a token in your trayful.

-One moment, back up. You're saying this is about money?

-Sorry sir, I don't have any money...

-Distortion!

-I prefer the term capitalist...

-Listen that, it's the sound of your freedom flying over the window...

Chapter 2: What things can be copyrighted?

Well, just the usual things like: books, plays, music, dance, movies and pictures.

-No, no, listen caryfully, you can't copyright an idea.

-Yes, I can.

-No you can't

A culture would be unwise to limite the power of a great idea. So we can only copyright the form an idea takes.

Chapter 3: Copyright duration and the public domain

The law says that the copyright only last for a fixed amout of time. For example, copyrighted photos(?) only last 40 years. For a culture, that is long enought to a copyright owner to make money from their work. After just 40 years the work falls into public domain, so anyone can use the work. And what the heck is the public domain? The public domain is a disgrace to the forces of evil.

-What are you saying exactally?

Any work in the public domain is free for anyone to use.

-Can you do that?

Yes, it's essential. A culture create new ideas by building on earlier works. So the public domain is necessary for a living, trilling society.

Unfortunatelly copyright keeps getting longer, and it seems to be no limit to how long a copyright can be extended(?). Now copyright lasts a life time: 70 years, and for some companies more than 100 years. So copyright last more like, forever.

Chapter 4: Fair use

And what the heck is fair use? You may thing this is crazy, but there are some limitations on copyright.

-Is it possible?

Yes, copyright can be broken. You may borrow a centain amount of a copyrighted work to: teach, news reporting, parody and critical comment.

-But how do I konw if it is fair use? There are centain rules that demonstrate fair use: first of all the nature of the work you borrowed, second of all is the amount of the work you borrowed, and there is one more, it must be something that doesn't shrink the work's value in the marktplace.

Now this is important: note that fair use is not a right, fair use is only a defensible position, and this is not fair.

Chapter 5: Why use Disney cartoons

Because this company is intimidating anybody who takes their copyrighted work. The point is, if fair use actually works, then movies like this one will have legal protection.

domingo, 13 de maio de 2007

Debugging sucks, Testing rocks

Inspirado pelo blog de Testes do Google  que eu redescobri esse fim de semana vou dar para o blog a direção de escrever sobre testes unitários, automação, quality assurance e assuntos relacionados.

A verdade é que eu me cansei de fazer debugging na primeira execução do código, de quebrar coisas com alterações, em parte também porque fiquei decepcionado com número de resultados na pesquisa de blogs do Googles para o termo "testes unitários", é ridículo (130, mesmo a pesquisa na web retorna poucos registros), e o pior é que a grande maioria foca em ferramental e não em "como escrever testes de modo eficiente".

Faz um tempo que ando incorporando a idéia de testes no meu dia-a-dia de deselvolvedor, mas sempre quando o prazo ou a complexidade aumenta eu digo "bom isso vai do jeito antigo mesmo" e entro no velho ciclo de erro->debug->acerto->novo erro. Chega. Agora quero ser um verdadeiro praticante de desenvolvimento orientado a testes, vamos ver no que isso vai dar.

O que não é um teste unitário

Muito interessante este post do Michael Feathers sobre o que não é um teste unitário:

Um teste não é unitário se...

...Acessa o banco de dados
...Comunica através da rede
...Grava/acessa arquivos no file system
...Não pode ser executado em paralelo com outros testes unitários
...Você precisa fazer coisas especiais como alterar arquivos de configuração, para executá-lo.

O seu argumento é que testes que façam as coisas acima não são ruins, mas também fogem da idéia principal que é testar código, quando nós começamos a misturar código de testes com acesso a bancos de dados, por exemplo, temos uma série de problema como capacidade de repetir os testes, simular erros e verificar se o problema está no código ou no sistema com o qual você está interfaceando.

Não que este tipo de teste não precise ser escrito, é que os testes unitário puros são muito subvalorizados.

Eu cometo todos estes erros e concordo com ele, apesar de achar um pouco de exagero o último item. A solução clara para estas limitações é trabalhar com Mock ou Fake Objects.

Por exemplo, ao testar um código de CRUD (create-read-update-delete) eu poderia criar uma classe falsa que contém um DataSet moldado com todas as variações de registros de uma tabela do meu banco de dados, como é uma representação em memória os testes irão executar rápido, sempre com resultado previsível e sem atrapalhar outros desenvolvedores.

É claro que eu precisaria de uma maneira de substituir a minha classe de acesso a dados para chamar a classe falsa ao invés do banco de dados verdadeiro, mas isso pode ser uma tarefa simples se você utilizar frameworks como o Enterprise Library ou o NHibernate que têm suporte para chamar classes parametrizadas em arquivos de configuração.

No próximo post coloco um exemplo prático, com código.

Links interessantes

Nos últimos dias coloquei algumas coisas interessantes no meu feed de links. Destaques:

Anúncio do Microsoft SQL Server Katmai

Que deve sair junto com o Longhorn Server e entre as novidades contém: extensões para armazenar dados espaciais e foco em Business Inteligence.

Propaganda do Windows Live Hotmail

Muito bacana onde o pai não deixa a filha voltar tarde porque acredita que a filha dançará o mambo na horizontal com um cara suspeito ("suspicious male" trocadilho intraduzível com e-mail suspeito "suspicious mail")

Lançamento do Windows Live Folders

Disco virtual da Microsoft com 500MB de espaço e permite compartilhar dados com contatos (shared) ou com qualquer um (public)

Lançemento do Windowsclient.net

Site focado para desenvolvimento de aplicações windows  forms e Windows Presentation Foundation.

Uma bela lista de recursos para Sharepoint no CodePlex

De tudo, web parts, ferramentas, templates e muito mais.

Passo-a-passo para preparar uma máquina para as novas tecnologias da MS

Resumindo, se eu postar pouco, olhe no meu feed de links que sempre tem no mínimo um item por dia do melhor que eu leio na net.