VB.NET - SQL Server e Entity Framework na Copa do mundo de 2014 - IV (fim)


Na terceira parte do artigo eu apresentei os formulários para cadastro das sedes, dos jogos das 1a fase e da atualização de resultados desses jogos permitindo a simulação da classificação. Vamos concluir apresentando os formulários para os jogos das oitavas, quartas, semi e final e a rotina para imprimir os jogos.

Nesta parte do artigo os formulários apresentados se baseiam nos que já foram vistos nos artigos anteriores por isso não vou entrar em detalhes do código, pois vou disponibilizar o código fonte para estudo, testes, simulações e aperfeiçoamento.

Devido ao exíguo tempo eu confesso que o sistema praticamente não foi testado e deverá apresentar bugs que deverão ser corrigidos. E aproveitando essa deixa, neste artigo eu quero escrever um pouco sobre um assunto muito importante, mas que fica quase sempre relegado a segundo plano; o teste de software.

Falando um pouco sobre Teste de Software

Geralmente no desenvolvimento de software se trabalha com uma enorme pressão para redução de custos e prazos, onde o desenvolvedor muitas vezes é obrigado a cumprir um prazo irreal para entregar um produto de qualidade. A equipe de desenvolvimento muitas vezes faz algumas simulações, testa o caminho feliz e libera o software para produção para cumprir o prazo prometido de entrega. Dessa forma não foram realizados testes confiáveis e robustos e isso vai se refletir na manutenção mais adiante.

Em geral são apresentadas muitas desculpas como:

Mas por que precisamos realizar testes ?

Você conhece as leis de Murphy ? Não ?  Então vejamos:

- Leis de Murphy

"É de conhecimento geral entre os analistas de software que nunca se elimina o último bug de um programa. Os bugs são aceitos como uma triste realidade. Esperamos eliminá-los todos, um por um, mas nunca conseguiremos nos livrar deles."   DeMarco, Tom , Editora Campus, 91

Mas o que são testes de software ?

"O teste consiste em executar o programa com a intenção de encontrar erros (bugs)". Myers, 1979

Dentre os principais objetivos do processo de teste temos: (Beizer, 90)

Antes de continuar deve ficar bem claro que teste e depuração são conceitos diferentes.

Para poder realizar testes com eficácia é necessário definir um processo de teste de software. Podemos seguir as seguintes etapas:

  1. Definir os processos
  2. Medir os processos
  3. Controlar os processos (garantir que a variabilidade é estável e os resultados previsíveis)
  4. Melhorar os processos

Os principais tipos de testes com processos definidos são :

  1. Teste Estrutural (Caixa Branca) - são testados os caminhos lógicos através do software, fornecendo casos de teste que põem a prova conjuntos específicos de condições e/ou garante que todos os caminhos independentes dentro de um módulo tenham sido exercitados pelo menos uma vez;
  2. Teste funcional (caixa preta) -  são usados para demonstrar que as funções dos softwares são operacionais, que a entrada é adequadamente aceita e a saída é corretamente produzida; que a integridade das informações externas é mantida;
  3. Teste de Unidade - Deve ser escrito pelo mesmo programador que desenvolveu o código a ser testado. Serve como documentação do sistema sendo essencial para análise de desempenho;
  4. Teste de Sistema - Compara o sistema com seus objetivos originais enfatizando a análise do comportamento da estrutura hierárquica de chamadas de módulos. É uma fase mais complexa, devido à quantidade de informações envolvidas;
  5. Teste de Regressão - Teste necessário para assegurar que modificações no programa não causaram novos erros;
  6. Teste de Aceitação -  A validação é bem sucedida quando o software funciona de uma maneira razoavelmente esperada pelo cliente; Pressman , 1995

Aplicando o esquema tático - Implementando a camada de interface e suas funcionalidades - III

1- Formulário de cadastro dos jogos das Oitavas de final

Abaixo vemos o leiaute do formulário para cadastro dos jogos das oitavas de final, onde o usuário poderá inserir, alterar e excluir os jogos.

Para cadastrar um jogo, após definir a data, hora e o local basta selecionar o grupo e isso irá filtrar apenas as duas seleções classificadas do grupo para escolha da seleção no jogo.

2- Formulário para atualização dos jogos das oitavas de final

Neste formulário o usuário poderá atualizar os resultados dos jogos das oitavas, verificar a classificação e fazer simulações.

O destaque neste formulário é a rotina para exibir a classificação que usa uma consulta LINQ e o operador Take().

Nota: Para mais detalhes veja o meu artigo : LINQ - Usando os operadores TAKE e SKIP

O operador Take é usado para selecionar os primeiros n objetos de uma coleção. No exemplo estamos selecionando apenas as 8 primeiras seleções na classificação que passaram para a próxima fase.

 Private Sub exibeClassificacao(ByVal grupo As Integer)
        Using ctx As New Copa2014Entities
            Try
                Dim classificacao = (From clsf In ctx.Classificacao
                                    Where clsf.GrupoId = grupo
                                    Order By clsf.Pontos Descending, clsf.SaldoGols Descending, clsf.GolPro Descending
                                    Select clsf.Selecoes.NomeSelecao, clsf.Pontos, clsf.Jogos, clsf.Vitorias, clsf.Empates, clsf.Derrotas, clsf.GolPro, clsf.GolContra, clsf.SaldoGols).Take(8)
                dgvOitavas.DataSource = classificacao.ToList
                formataGridView()
            Catch ex As Exception
                MessageBox.Show("Erro " + ex.Message, "Erro:: ", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End Try
        End Using
    End Sub

Na classificação serão exibidas somente as oito seleções classificadas para as quartas de final.

3- Formulário de cadastro dos jogos das Quartas de final

Abaixo vemos o leiaute do formulário para cadastro dos jogos das quartas de final, onde o usuário poderá inserir, alterar e excluir os jogos.

Nas combobox para escolher as seleções, somente serão exibidas as oito seleções classificadas.

Eu não tive tempo de definir um código mais inteligente que com base no regulamento fizesse os possíveis cruzamentos entre as seleções dos grupos. Fica então como exercício.

4- Formulário para atualização dos jogos das quartas de final

Neste formulário o usuário poderá atualizar os resultados dos jogos das quartas, verificar a classificação e fazer simulações.

Na classificação somente serão exibidas as 4 seleções classificadas para as semifinais.

5- Formulário de cadastro dos jogos das semifinais

Abaixo vemos o leiaute do formulário para cadastro dos jogos das semifinais, onde o usuário poderá inserir, alterar e excluir os jogos.

Nas combobox das seleções somente serão exibidas as quatro seleções classificadas.

6- Formulário para atualização dos jogos das semifinais

Neste formulário o usuário poderá atualizar os resultados dos jogos das semifinais, verificar a classificação e fazer simulações.

 

Na classificação somente serão exibidas as duas seleções classificadas para a grande final.

7- Formulário de cadastro do jogo da grande final

Abaixo vemos o leiaute do formulário para cadastro do jogo da final, onde o usuário poderá inserir, alterar e excluir informações do jogo.

Nas combobox das seleções serão exibidas somente as duas seleções classificadas.

Como eu estava sem tempo não pude criar o código para já montar o jogo da final de forma automática. Fica como um exercício.

8- Formulário para atualização do jogo da final

Neste formulário o usuário pode informar o resultado do jogo da grande final e Comemorar ou Chorar...

Aqui podem ser feitas melhorias como uma apresentação melhor do campeão com inclusão de sons, etc.

9- Imprimindo os jogos dos Grupos

Eu ainda tive um tempinho para criar uma rotina para imprimir os jogos dos grupos na primeira fase.

Primeiro declarei as seguintes variáveis no início do formulário FrmMenu:

Private contador As Integer = 0

Private relacaoJogos As List(Of Jogos)

Private tJogos As New Jogos

Dim botao As Button

Private RelatorioTitulo As String = ""

Private paginaAtual As Integer = 1

Depois inclui um botão de comando - btnImprimir - no formulário FrmMenu :

E no seu evento Click define o seguinte código:

 Private Sub btnImprimir_Click(sender As Object, e As EventArgs) Handles btnImprimir.Click
        'define o titulo do relatorio
        RelatorioTitulo = "Jogos do Grupo  - " & botao.Tag.ToString()
        'define os objetos printdocument e os eventos associados
        Dim pd As Printing.PrintDocument = New Printing.PrintDocument()
        'IMPORTANTE - definimos 3 eventos para tratar a impressão : PringPage, BeginPrint e EndPrint.
        AddHandler pd.PrintPage, New Printing.PrintPageEventHandler(AddressOf Me.pdRelatorios_PrintPage)
        AddHandler pd.BeginPrint, New Printing.PrintEventHandler(AddressOf Me.Begin_Print)
        AddHandler pd.EndPrint, New Printing.PrintEventHandler(AddressOf Me.End_Print)
        'define o objeto para visualizar a impressao
        Dim objPrintPreview As New PrintPreviewDialog
        Try
            'define o formulário como maximizado e com Zoom
            With objPrintPreview
                .Document = pd
                .WindowState = FormWindowState.Maximized
                .PrintPreviewControl.Zoom = 1
                .Text = "Jogos da Copa do Mundo"
                .ShowDialog()
            End With
        Catch ex As Exception
            MessageBox.Show(ex.Message.ToString())
        End Try
    End Sub

 

A seguir defini as rotinas para evento que inicia a impressão : Begin_Print:

    Private Sub Begin_Print(ByVal sender As Object, ByVal e As Printing.PrintEventArgs)
        paginaAtual = 1
        contador = 0
    End Sub

Depois para o evento de finalização da impressão : End_Print

    Private Sub End_Print(ByVal sender As Object, ByVal byvale As Printing.PrintEventArgs)
        MessageBox.Show("Impressão Concluída.")
    End Sub

E a rotina principal que realiza a impressão - pdRelatorios_PrintPage :

 Private Sub pdRelatorios_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs)
        'Variaveis das linhas
        Dim LinhasPorPagina As Single = 0
        Dim PosicaoDaLinha As Single = 0
        Dim LinhaAtual As Integer = 0

        'Variaveis das margens
        Dim MargemEsq As Single = e.MarginBounds.Left
        Dim MargemSuperior As Single = e.MarginBounds.Top + 100
        Dim MargemDireita As Single = e.MarginBounds.Right
        Dim MargemInferior As Single = e.MarginBounds.Bottom

        Dim CanetaDaImpressora As New Pen(Color.Black, 1)

        'Variaveis das fontes
        Dim FonteNegrito As Font = Nothing
        Dim FonteTitulo As Font = Nothing
        Dim FonteSubTitulo As Font = Nothing
        Dim FonteRodape As Font = Nothing
        Dim FonteNormal As Font = Nothing

        'define efeitos em fontes
        FonteNegrito = New Font("Arial", 9, FontStyle.Bold)
        FonteTitulo = New Font("Arial", 15, FontStyle.Bold)
        FonteSubTitulo = New Font("Arial", 12, FontStyle.Bold)
        FonteRodape = New Font("Arial", 8)
        FonteNormal = New Font("Arial", 10)

        'define valores para linha atual e para linha da impressao
        LinhaAtual = 0

        Using ctx As New Copa2014Entities
            Try
                Dim jogos = From jg In ctx.Jogos
                               Where jg.GrupoId = grupoAtual
                               Select jg

                relacaoJogos = jogos.ToList()
            Catch ex As Exception
                MessageBox.Show("Erro " + ex.Message)
                Return
            End Try

            'Cabecalho
            e.Graphics.DrawLine(CanetaDaImpressora, MargemEsq, 60, MargemDireita, 60)
            e.Graphics.DrawLine(CanetaDaImpressora, MargemEsq, 160, MargemDireita, 160)
            'nome da empresa
            e.Graphics.DrawString("Copa do Mundo de 2014 - JcmSoft", FonteTitulo, Brushes.Blue, MargemEsq + 150, 80, New StringFormat())
            'Imagem
            e.Graphics.DrawImage(Image.FromFile(getCaminhoImagem() + "\maco.gif"), 100, 68)
            e.Graphics.DrawString(RelatorioTitulo, FonteSubTitulo, Brushes.Black, MargemEsq + 220, 120, New StringFormat())

            LinhasPorPagina = Convert.ToInt32(e.MarginBounds.Height / FonteNormal.GetHeight(e.Graphics) - 9)

            While (LinhaAtual < LinhasPorPagina And relacaoJogos.Count >= contador + 1)

                'obtem o valor da entidade
                tJogos = relacaoJogos.Item(contador)

                'obtem os valores das entidades e atribui as variaveis
                Dim jogoid As String = tJogos.JogoId
                Dim jogoLocal As String = tJogos.Locais.Endereco
                Dim jogoData As String = tJogos.Data.ToString()
                Dim jogoHora As String = tJogos.Hora.ToString()
                Dim jogoSelecao1 As String = tJogos.Selecoes.NomeSelecao.ToString()
                Dim jogoSelecao2 As String = tJogos.Selecoes1.NomeSelecao.ToString()

                'inicia a impressao
                PosicaoDaLinha = MargemSuperior + (LinhaAtual * FonteNormal.GetHeight(e.Graphics))

                'impressão dos dados
                e.Graphics.DrawString(jogoLocal, FonteNormal, Brushes.Black, MargemEsq, PosicaoDaLinha)
                e.Graphics.DrawString(jogoData, FonteNormal, Brushes.Black, MargemEsq + 100, PosicaoDaLinha)
                e.Graphics.DrawString(jogoHora, FonteNormal, Brushes.Black, MargemEsq + 300, PosicaoDaLinha)
                '------------------------
                e.Graphics.DrawString(jogoSelecao1, FonteNormal, Brushes.Black, MargemEsq + 250, PosicaoDaLinha + 20)
                e.Graphics.DrawString(" X ", FonteNormal, Brushes.Black, MargemEsq + 380, PosicaoDaLinha + 20)
                e.Graphics.DrawString(jogoSelecao2, FonteNormal, Brushes.Black, MargemEsq + 450, PosicaoDaLinha + 20)
                '
                'pula pagina
                LinhaAtual += 5
                contador += 1
            End While

            'Rodape
            e.Graphics.DrawLine(CanetaDaImpressora, MargemEsq, MargemInferior, MargemDireita, MargemInferior)
            e.Graphics.DrawString(System.DateTime.Now.ToString(), FonteRodape, Brushes.Black, MargemEsq, MargemInferior, New StringFormat())
            LinhaAtual += Convert.ToInt32(FonteNormal.GetHeight(e.Graphics))
            LinhaAtual += 1
            e.Graphics.DrawString("Pagina : " + paginaAtual.ToString, FonteRodape, Brushes.Black, MargemDireita - 50, MargemInferior, New StringFormat())

            'Incrementa o n£mero da pagina
            paginaAtual += 1

            'verifica se ainda existem páginas a imprimir
            If (relacaoJogos.Count > contador) Then
                e.HasMorePages = True
            Else
                e.HasMorePages = False
            End If
        End Using
    End Sub

Para obter o caminho da imagem que esta sendo impressa no cabeçalho criei a rotina abaixo que obtém a imagem da pasta Imagens criada no projeto:

   Public Shared Function getCaminhoImagem() As String
        Dim caminhoArquivo As String = Application.StartupPath
        If caminhoArquivo.IndexOf("\bin\Debug") <> -1 Then
            caminhoArquivo = caminhoArquivo.Replace("\bin\Debug", "")
        ElseIf caminhoArquivo.IndexOf("\bin\Release") <> -1 Then
            caminhoArquivo = caminhoArquivo.Replace("\bin\Release", "")
        End If
        Return caminhoArquivo + "\Imagens\"
   End Function

Abaixo vemos o resultado para os jogos do grupo A:

E assim encerramos a nossa aplicação para gerenciar os jogos da copa do mundo de 2014.

Devido à falta de tempo eu não pude criar uma aplicação em camadas e por isso estou usando o Entity Framework na camada de apresentação. Embora isso não seja recomendado, a aplicação ainda serve como base de estudo para quem esta iniciando na linguagem VB .NET e no Entity Framework, e mostra como podemos usar alguns recursos do Entity Framework em uma aplicação Windows Forms.

A utilização do Entity Framework acelerou muito o desenvolvimento pois se tivesse usado ADO .NET o tempo com certeza seria maior.  De forma geral o Entity Framework nos dá rapidez no desenvolvimento da aplicação enquanto a ADO .NET nos dá um melhor desempenho da aplicação.

Repeito novamente que eu não tive como testar a aplicação, fiz somente algumas simulações, e por isso, com toda a certeza, muitos bugs deverão aparecer. Na verdade a aplicação deve ser considerada como um protótipo e não como uma aplicação de produção.

Muita coisa pode ser melhorada na aplicação, que possui muito código repetido nos formulários, e muitos erros deverão ser corrigidos. Você pode fazer isso enquanto assiste aos jogos, nos intervalos das partidas.

Um bom estudo !!

Pegue o projeto completo e os scripts SQL para gerar o banco de dados e as tabelas aqui : Copa_2014.zip e Copa2014_BD_SQLServer.zip (sem as referências do Entity Framework)

Nota: Se preferir usar o banco de dados já criado e com os dados do projeto você terá que anexar o arquivo ao seu SQL Server Local DB.

Salmos 19:1 Os céus proclamam a glória de Deus e o firmamento anuncia a obra das suas mãos.

Salmos 19:2 Um dia faz declaração a outro dia, e uma noite revela conhecimento a outra noite.

Salmos 19:3 Não há fala, nem palavras; não se lhes ouve a voz.


Veja os Destaques e novidades do SUPER DVD VB (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Veja mais sistemas completos para a plataforma .NET no Super DVD .NET , confira...

Quer aprender C# ??

Chegou o Super DVD C# com exclusivo material de suporte e vídeo aulas com curso básico sobre C#
 

   Gostou ?   Compartilhe no Facebook    Compartilhe no Twitter

Referências:


José Carlos Macoratti