A tecnologia da Microsoft veio para ficar. Este blog regista o evoluir do meu conhecimento sobre .NET. No entanto este blog não pretende focar apenas a tecnologia em si mas também todas as aplicações desta.

Terça-feira, Fevereiro 08, 2005

Intersecções

Como já deve ter dado para reparar, mudei mais uma vez o visual do blog. Digamos que é uma eterna busca pelo visual ideal. Além da mudança de visual acrescentei à esquerda um conjunto de endereços que considero interessantes. O primeiro conjunto está relacionado com páginas sobre a tecnologia ou partes desta. O segundo conjunto está relacionado com a metodologia extreme programming. Estou a considerar colocar também um conjunto de ligações para páginas de livros sobre o tema.

Vamos continuar com o desenvolvimento da interface com o utilizador. Na última mensagem tinhamos acabado de escrever um teste que verificava que o menu principal continha apenas um item e que esse tinha o nome "Ficheiro". Vamos agora escrever um teste que verifica se o item "Ficheiro" tem ele próprio três items com os nomes já referidos.

[Test] public void FileMenuItems() {
    UserInterface userInterface = new UserInterface();
    Menu.MenuItemCollection fileMenuItems =
        userInterface.Menu.MenuItems[0].MenuItems;
    Assert.AreEqual(3, fileMenuItems.Count);
    Assert.AreEqual("Novo Jogo", fileMenuItems[0].Text);
    Assert.AreEqual("Terminar Jogo", fileMenuItems[1].Text);
    Assert.AreEqual("Sair", fileMenuItems[2].Text);
}

Ao correr este teste verificamos que está a vermelho, isto porque ainda não adicionámos os items ao menu. Na classe UserInterface existe o método FileMenuItem responsável pela criação do item "Ficheiro". Vamos acrescentar lá o código necessário para criar os três items que o teste pede.

private MenuItem FileMenuItem() {
    MenuItem menuItem = new MenuItem("Ficheiro");
    menuItem.MenuItems.Add(new MenuItem("Novo Jogo"));
    menuItem.MenuItems.Add(new MenuItem("Terminar Jogo"));
    menuItem.MenuItems.Add(new MenuItem("Sair"));
    return menuItem;
}

Agora o teste já está ok. Temos a garantia através dos testes que o menu da aplicação está como pretendemos. Mas para que as opções do menu tenham qualquer utilidade, estas têm que fazer algo. O nosso objectivo agora é dar funcionalidade às várias opções do menu. A opção de sair parece-me a mais simples. Quando o utilizador escolher aquela opção, a aplicação deve terminar. A solução que encontrei para realizar o teste foi testar se existe alguma janela activa após o click. Talvez este não seja o melhor teste mas por enquanto terá que servir. Quando tiver um maior conhecimento talvez encontre uma forma mais robusta de testar a aplicação. O teste fica assim:

[Test] private void UserPressExit() {
    UserInterface userInterface = new UserInterface();
    userInterface.Show();
    MenuItem exitMenuItem =
        userInterface.Menu.MenuItems[0].MenuItems[2];
    exitMenuItem.PerformClick();
    Assert.IsNull(Form.ActiveForm);
}

A propriedade estática ActiveForm de Form devolve uma referência para a janela que está activa ou o valor nulo se nenhuma janela estiver activa. O método PerformClick permite simular o click no botão. Após este click não deve estar nenhuma janela activa. Já sabemos que o teste vai falhar porque ainda não adicionámos comportamento ao menu, mas vamos compilar e correr os testes. Só demora um momento e temos a certeza que falha e que apenas este falha. Este pode ser um hábito interessante e que acho que devemos cultivar. Às vezes podemos estar à espera que o teste falhe e quando vamos a ver não falha. Aí algo está mal. Pode ser o teste ou a aplicação. Tanto nos ajudam os testes que não falham quando não era suposto falhar como aqueles que não falham quando era suposto falhar. O teste falha como estávamos à espera. Vamos escrever o código da aplicação para deixar de falhar.

private MenuItem FileMenuItem() {
    MenuItem menuItem = new MenuItem("Ficheiro");
    menuItem.MenuItems.Add(new MenuItem("Novo Jogo"));
    menuItem.MenuItems.Add(new MenuItem("Terminar Jogo"));
    menuItem.MenuItems.Add(ExitMenuItem());
    return menuItem;
}

private MenuItem ExitMenuItem() {
    MenuItem menuItem = new MenuItem("Sair");
    menuItem.Click += new EventHandler(ExitMenuItem_Click);
    return menuItem;
}

private void ExitMenuItem_Click(Object sender, EventArgs args) {
    Application.Exit();
}

Este código tráz algumas novidades em termos de sintaxe. Poderemos estudar essas novidades numa mensagem seguinte. Importa dizer que Click é um evento. Sobre um evento podemos tomar as acções de subscrição e de cancelamento da subscrição. Para subscrevermos um evento utilizamos o operador +=. Isto significa que, quando ocorrer o evento de click no menu, todos os métodos (de objectos) que subscreveram o evento vão ser executados. Neste caso o método a ser executado é o ExitMenuItem_Click e este método limita-se a chamar o método estático Exit da classe Application. Este método, como o nome indica, termina a aplicação. Vamos compilar e executar os testes. Tudo verde de novo.

Ficaram aqui algumas questões no ar, nomeadamente sobre os eventos. Secalhar é altura de ver o que são eventos, como se podem definir e as suas vantagens. Mas isso ficará para uma próxima mensagem.