n>
Instalando o ambiente de desenvolvimento para Azure
Se você já possui as ferramentas de desenvolvimento do Azure instaladas, pode pular para a próxima sessão. Recomendo também a leitura do meu artigo da edição passada para entender melhor o que é o Windows Azure e como ele funciona, caso não o tenha lido.
Você precisará instalar os componentes de desenvolvimento do Windows Azure se quiser acompanhar o artigo na sua máquina. Estou utilizando o SDK do CTP (Community Technical Preview) de Janeiro de 2009, disponível em http://tinyurl.com/azsdk0109. Instale também o SDK do .Net Services do CTP de Dezembro de 2008, disponível em http://tinyurl.com/nssdk1208, e por fim as ferramentas para o Visual Studio, disponíveis em http://tinyurl.com/aztools0109. Instale as ferramentas na ordem que foram apresentadas. Todas as ferramentas exigem o Windows Vista ou Windows Server 2008, não permitindo o uso de Windows XP. Infelizmente as ferramentas também não funcionam conforme o esperado no Windows 7 Beta, por problemas de compilação e depuração, mas é possível fazer o desenvolvimento. É também necessária a presença do Visual Studio 2008, podendo ser a versão Express.
Após a instalação você terá um arquivo zip com exemplos de aplicação com Azure, disponível na máquina no caminho “C:\Program Files\Windows Azure SDK\v1.0\samples.zip”. Recomendo que você descompacte estes exemplos no seu diretório de projetos do Visual Studio 2008 em uma pasta própria, chamando-a de “AzureSamples”. Depois volte a estes exemplos, lendo também a documentação. Apesar da documentação ser ainda inicial, ela já traz informações importantes.
Uma aplicação desenvolvida com Azure permite depuração local, já que foi desenvolvido um software que emula o Azure na sua máquina local, chamado de “Development Fabric”. Já para instalar a aplicação na nuvem, você precisar de uma conta no Azure. Acesse http://www.microsoft.com/azure/register.mspx e registre-se para obter uma chave de aplicação. Faça isso o quanto antes, porque essas chaves demoram a chegar, às vezes algumas semanas. Para completar o artigo você vai precisar disso.
A solução
A solução criada no artigo anterior foi uma simples prova de conceito, de forma que basta criar uma aplicação selecionando Visual C# > Cloud Service > Web Cloud Service, e nomeá-la PesquisaNasNuvens, (conforme pode ser visto na Figura 1) e já podemos continuar. Não se esqueça de sempre iniciar o Visual Studio como Administrador, uma necessidade nesta versão das ferramentas no estágio atual.
Figura 1. Criando um novo projeto de web com Windows Azure
Como o propósito é criar uma aplicação que se aproxime do mundo real, vou utilizar nos meus exemplos algumas boas práticas, incluindo um modelo de domínio, algumas interfaces, e o conceito de repositórios, lembrando vagamente o conceito de Domain Driven Design (DDD). Para mais informação sobre DDD busque a edição 57, onde apresentei o conceito, e a edição 58, onde demonstrei uma aplicação corporativa completa baseada em DDD, entre outras boas práticas.
Novos projetos para a solução
A aplicação será responsável por acompanhar questionários e provas feitas a partir destes questionários, oferecendo questões múltipla escolha. Adicione dois projetos de Class Library na solução. O primeiro deve se chamar PesquisaNasNuvens.Dominio, que conterá o modelo de domínio, e o segundo PesquisaNasNuvens.Dominio.RepositorioNuvem, que responderá pela classes de contato com o Azure. Nos dois casos exclua a classe padrão Class1. Como trabalharemos de forma desacoplada, com abstrações como repositórios, baseadas em interfaces .Net, deverá ser possível substituir os repositórios da nuvem por algum baseado em SQL Server ou XML, por exemplo.
A Figura 2 demonstra o diagrama de classes das entidades da aplicação. Essas classes também são agnósticas com relação à tecnologia de persistência dos dados, no caso, o Windows Azure Tables. A classe Questionario é responsável por abstrair a idéia de um questionário, que possui um conjunto de perguntas. A classe Pergunta representa uma pergunta, possuindo um peso, um texto, um conjunto de opções para resposta, e uma única resposta correta. A classe Resposta representa uma resposta. Por fim, a classe Prova representa uma prova realizada a partir de um questionário, e possui uma lista de respostas, que podem estar corretas ou não, para cada pergunta do Questionario. Todos os ids são baseados em GUID.
As classes Resposta e Questionário são simples, utilizando apenas propriedades automáticas, ou seja, não possuem qualquer comportamento. As outras duas estão disponíveis nas Listagens 1 e 2, onde você pode ver algumas regras de negócio implementadas. A classe pergunta, por exemplo, verifica se a resposta correta configurada faz parte das suas respostas disponíveis ou lança uma exceção (linhas
Listagem 1. Entidade Pergunta
1 namespace PesquisaNasNuvens.Dominio
2 {
3 public class Pergunta
4 {
5 public Pergunta()
6 {
7 this.Respostas = new List();
8 }
9 public Guid Id { get; set; }
10 public string Texto { get; set; }
11 public IList Respostas { get; private set; }
12 public int Peso { get; set; }
13
14 private Resposta _respostaCorreta;
15 public Resposta RespostaCorreta
16 {
17 get { return _respostaCorreta; }
18 set
19 {
20 if (value != null && !Respostas.Contains(value))
21 throw new InvalidOperationException(
22 @"Só pode configurar como correta uma resposta
23 que faz parte da coleção de respostas.");
24 _respostaCorreta = value;
25 }
26 }
27 }
28 }
Listagem 2. Entidade Prova
1 namespace PesquisaNasNuvens.Dominio
2 {
3 public class Prova
4 {
5 public Prova(Questionario questionario)
6 {
7 this.Questionario = questionario;
8 this.Respostas = new Dictionary();
9 foreach (var pergunta in questionario.Perguntas)
10 {
11 this.Respostas.Add(pergunta, null);
12 }
13 }
14
15 public Guid Id { get; set; }
16 public Questionario Questionario { get; set; }
17 public IDictionary Respostas { get; set; }
18 public Decimal Nota { get; set; }
19
20 public void Resolver()
21 {
22 var nota = VerificarPontuacao();
23 this.Nota = nota;
24 }
25 private decimal VerificarPontuacao()
26 {
27 if (this.Questionario.Perguntas.Count == 0) return 0;
28 decimal notaBruta = 0m;
29 int pesoTotal = 0;
...