Thursday, June 21, 2012

Apresentação NHibernate 2009

Padrões de Desenho

Há um tempo atrás eu fiz uma apresentação sobre padrões de desenho de software para os meus colegas da PMV e notei que existe ainda pouco material que trata desse assunto de maneira mais concreta em português. Estou compartilhando os meus slides para talvez ajudar alguém.

Friday, September 2, 2011

Implementando Bons Métodos em C#

Regras para construir bons métodos:
  • 1a regra: métodos devem ser pequenas
  • 2a regra: métodos devem ser menores ainda
  • Até 30 linhas. (Sugestão: deve caber na tela)
  • Métodos devem fazer somente uma tarefa mas devem fazer isso bem.
Quanto menor o código, melhor
  • Antes: O método ObterLogradouros esta longo demais:
public virtual IList ObterLogradouros()
{
  IList lstLogradouros = new ArrayList();
  foreach(Logradouro logradouro in this.relLogradouros)
  {
    if (logradouro.GetType() != typeof(Logradouro))
    {
      throw new SystemException("LogradouroVitoria se associa apenas com BairroVitoria.");			
    }
    // Verifica se o logradouro ja foi adicionado na lista
    bool bAdicionado = false;
    for (int i=0; i < lstLogradouros.Count; i++)
    {
      if (((Logradouro)lstLogradouros[i]).Id == logradouro.Id)
      {
        bAdicionado = true; break;
      }					
    }			
    // Se nao foi adicionado na lista
    if (! bAdicionado)
    {
      lstLogradouros.Add(logradouro);
    }
  }
  return lstLogradouros;
}
  • Depois: o método ObterLogradouro se resume a menos linhas:
public virtual IList ObterLogradouros()
{
  IList lstLogradouros = new List();
  foreach(Logradouro logradouro in this.relLogradouros)
  {
    EhLogradouroValidoParaBairro(logradouro);				
    if (!lstLogradouros.Contains(logradouro))
    {
      lstLogradouros.Add(logradouro);
    }				
  }
  return lstLogradouros;
}

Método deve se concentrar em apenas uma tarefa:
  • Antes: Método faz várias tarefas:
public void autenticarLogin(Sessao sessao,string strSenha,
                 Pessoa pessoaSelecionada,Sistema sistema)
{
  if(strSenha == string.Empty)
  {
    throw new ApplicationException
         ("Favor preencher o campo senha!");
  }
  if (pessoaSelecionada == null)
  {
    throw new ApplicationException
      ("Pessoa inexistente para o documento informado.");
  }
  Usuario usuarioPessoaSelecionada = DAOFactory.ObterDAOFactory()
    .ObterDAO(sessao).ObterUsuario(pessoaSelecionada);
  if(usuarioPessoaSelecionada == null)
  {					
    string strErro = string.Empty;
    strErro += "A pessoa informada não possui permissão ";
    strErro += "para nenhum sistema!";			
      throw new 
    ApplicationException(strErro);
  }
	if(!usuarioPessoaSelecionada.eAtivo())
  {					
    throw new 
      ApplicationException("O usuário informado está desativado!");
  }				 
  Projeto projeto = sistema.ObterProjeto();	
  if(!DAOFactory.ObterDAOFactory().ObterDAO(sessao)
    .ValidarSenhaProjeto(strSenha,projeto,usuarioPessoaSelecionada))
  {					 
    throw new ApplicationException("Senha inválida!");
  }			            
  AutenticarUsuario(usuarioPessoaSelecionada);			
}   
  • Depois: Método se concentra em apenas uma tarefa:
public void AutenticarUsuario(Sessao sessao,string strSenha,
                 Pessoa pessoaSelecionada,Sistema sistema)
{  
  Usuario usuario = ObterUsuario(sessao,pessoaSelecionada,sistema);
  ValidarSenha(sessao,usuario,senha,sistema);			
}


Deve haver o mesmo nível de abstração para cada linha do método
  • Antes: Níveis de abstração diferentes (checagem de strings)
public void AlteracaoObservacaoHistorico(
            Sessao sessao, string strObservacao, Historico historico)
{
  if ((strObservacao == null) && (strObservacao == string.Empty))
  {
    throw new ApplicationException("Observação do histórico deve ser informada.");
  }
  historico.AtribuirObservacao(strObservacao);
  sessao.BeginTransaction();
  DAOFactory.ObterDAOFactory().Salvar(sessao,ref historico);
  sessao.CommitTransaction();
}
  • Depois: Código com mesmo nível de abstração
public void AlteracaoObservacaoHistorico(
            Sessao sessao, string strObservacao, Historico historico)
{
  historico.AtribuirObservacaoComChecagem(strObservacao);
  sessao.BeginTransaction();
  DAOFactory.ObterDAOFactory().Salvar(sessao,ref historico);
  sessao.CommitTransaction();
}

Use nomes descritivos
Uma função com nome descritivo é melhor que um comentário descritivo.

  • Antes - código não muito claro auxiliado por comentários

// Verifica se a pessoa é um funcionário aposentado
if (funcionario.EstaAtivo()&&funcionario.ObterIdade()>65) 
{
  // Calculo o valor da sua aposentadoria
  valor = pessoa.CalculaValor();
} 

  • Depois - código claro com métodos descritivos

if (pessoa.EstaAposentado())
{
  valorAposentadoria = pessoa.CalculaValorAtualDaAposentadoria();      
}

Manter consistência com nomes de funções:


pessoa = DAO.Factory.ObterDAO().RecuperarPeloNome("Joelson");
pessoa = DAO.Factory.ObterDAO().RecuperarPeloCPF("08766563489");
pessoa = DAO.Factory.RecuperarPeloId(12);
pessoa = DAO.Factory.RecuperarPelaMatricula(524567);

Funções descritivas não surpreendem (negativamente) o programador

Quanto menos argumentos, melhor
  • O número ideal de argumentos para funções: 0 (ZERO), depois vem funções com 1 argumento, por último, funções com 2 argumentos
  • Funções com 3 ou mais argumentos devem ser evitadas
  • Quanto maior o número de argumentos, maior a possibilidade de confusão e erro

  • Antes: Método com muitos argumentos
public void DesenhaRetangulo(int xi,int yi,int xf,int yf,int red,int green,int blue)
{ ... }


  • Depois: Métodos com poucos argumentos

public void DesenhaRetangulo(Ponto cantoInicial,Ponto CantoFinal,RGB cor) { ... }


  • Depois: refuzindo mais ainda os argumentos

public void DesenhaRetangulo(BordaRetangulo borda,RGB cor) { ... }

Funções não devem ter efeito colateral inesperado
public class Tarefa
{
  private string _descricao;
  private DateTime _dataCriacao;
  public string Descricao
  {
    set 
    { 
      // Uma nova descrição é uma nova tarefa
      if (_descricao != value)
      {
        _dataCriacao = DateTime.Now;
      }
      _descricao = value;
    }
    get
    {
      return _descricao;
    }
  }
}

Argumentos de saída
  • Argumentos são naturalmente interpretado apenas como entrada
  • Argumentos de saída devem ser evitados, se a função tiver que
    mudar algo, então que mude o objeto que contém a mesma
Separação Comando - Consulta
As funções devem ser de comando ou de consulta mas nunca ambos logo um método deve retornar informações sobre um objeto ou mudar o seu estado mas ambas as tarefas frequentemente levam a confusão.

  • Antes: AtribuirDado é consulta e comando

if (pessoa.AtribuirDado("Nome","Pedro"))
{
  throw new ApplicationException("Atributo inválido");
}

  • Depois: Existe um método para consulta e outro para comando

if (pessoa.PossuiAtributo("Nome"))
{
  pessoa.AtribuirDados("Nome","Pedro");
}


Prefira exceções a retornar códigos de erro
Funções que retornam erros de código violam a regra de separação de comando e consulta pois estas fazem com que funções de comando sejam usados como funções de consulta. Finalmente, o maior problema é que o sistema que usa o método deve tratar o erro imediatamente no decorrer do fluxo.

  • Antes: Metodos retornam código de erro

if (funcionario.CalcularSalario() == EVENTO_OK)
{
  Salario salario = funcionario.ObterSalarioAtual();
  if (!salario.TransferirValorParaContaBancaria() == EVENTO_OK)
  {
    throw new ErroEventoException("Erro ao transferir valor conta"); 
  }
  if (!funcionario.Alegrar() == EVENTO_OK)
  {
    throw new ErroEventoExceptrion("Erro ao alegrar o funcionário");
  }
  if (!funcionario.EnviarEmailAgradecendo() == EVENTO_OK)
  {
    throw new ErroEventoExceptrion("Erro ao enviar email agradecendo");
  }  
}

  • Depois: Métodos disparam exceções que são capturadas separadamente

try
{
  funcionario.CalcularSalario();
  Salario salario = funcionario.ObterSalarioAtual();
  salario.TransferirValorParaContaBancaria();
  funcionario.Alegrar();
  funcionario.EnviarEmailAgradecendo();
}
catch(Exception exception)
{
  ...
}
finally
{
  ...
}


Não repita blocos de código (no copy-paste)
Código duplicado é a origem de vários males e por isso, vários padrões de projeto e práticas foram criados com o propósito de eliminar a duplicação. Entretanto, às vezes não é tão fácil identificar a repetição de código e essa repetição é uma omissão que abre a oportunidade para que erros aconteçam.

Monday, April 26, 2010

Boa Fonte para Aprender .NET

Acabo de descobrir via a lista de desenvolvedores de .NET no Google sobre esta revista digital
de conteúdo gratuito que ensina sobre como iniciar na tecnologia .NET e ASP.NET .

http://www.devmedia.com.br/websys.3/webreader.asp?cat=59&revista=easynetmag_1#a-2519

Sunday, April 25, 2010

Processo de Desenvolvimento baseado em Software Livre para um Simulador de Robôs

 Humberto Cardoso Marchezi - Departamento de Engenharia Elétrica, UFES, 2004

Abstract:

This article presents a propose of development process followed based on free software and a set of tools for process automation inspired in Mozilla project. The object of this new process is to correct the major flaws in order to be used to extend a robot simulator that allows on-line programming based on general purpose languages.

Resumo:

Este artigo apresenta uma proposta de processo de desenvolvimento baseado em software livre e um conjunto de ferramentas de automatização de processo inspirado no projeto Mozilla. O objetivo desse novo processo é corrigir as falhas mais graves para ser usado para estender um simulador de robôs que permite programação on-line baseada em linguagens de propósito genérico.

1. Introdução

Muito se tem falado do software de código aberto por ser um fenômeno importante e recente que apresenta a idéia atraente dos usuários terem o controle sobre o código-fonte. Neste artigo, os termos software livre e software de código aberto serão usados alternadamente para se referir a software cujo código pode ser acessado, alterado e distribuído livremente pelo usuário independente de licença ser GNU ou qualquer outra.
Grandes empresas de software como Microsoft e IBM mudaram a sua estratégia devido a esse novo paradigma e governos de alguns países como o do Brasil passaram a dar preferência a este tipo de software.
Em contrapartida a sua negável importância, de acordo com [1] o modelo de desenvolvimento de projetos de software livre tende a ser mais informal, em grande maioria devido ao fato do time de desenvolvimento desempenhar tarefas voluntárias e para nenhum ganho financeiro, pelo menos não diretamente.
A grande vantagem de modelos de software livre como o adotado pelo projeto Mozilla [2], está nos testes que são realizados paralelamente por muitos usuários que acabam por testar cenários bem específicos em plataformas específicas o que aumenta a qualidade do software.
Entretanto, conforme observado em [1] e [2], as maiores falhas na grande maioria dos projetos de software livre está na falta de documentação que só é encontrada em projetos maiores e na falta de um processo mais formal de captura de requisitos a medida que o projeto evolui.
A partir disso, surge a necessidade de se propor um modelo de desenvolvimento para projetos que usam software livre mas que corrija os problemas apontados anteriormente.
Para ilustrar o funcionamento desse modelo será utilizado como exemplo o projeto Robotbuilder [3] que é um simulador de robôs que será extendido para conter novas funcionalidades para que também seja possível fazer a programação de robôs nesse ambiente. A seção 3.1 explica o contexto desse projeto e o problema da programação de robôs virtuais on-line.
O novo modelo de processo para software livre tomará como base o processo de desenvolvimento de software utilizado no projeto Mozilla e deve contemplar também a definição de um ambiente de desenvolvimento de software confiável e livre.
É importante mencionar também que o processo proposto é baseado em software livre mas não funciona apenas para software livre. Conforme já explicado por [4], o software livre ou de código aberto não define um novo processo de desenvolvimento de software e por isso, nada impede que esse mesmo processo seja usado para software proprietário.
Na seção 2, é mostrado o estado atual dos processos de desenvolvimento em projetos de software livre e na seção 2.1 é apresentado com um pouco mais de detalhes o processo de desenvolvimento de software utilizado no projeto Mozilla e na seção 2.2 o conjunto de ferramentas que formam o ambiente de desenvolvimento integrado que automatiza grande parte das atividades do processo.
Na seção 3, são apontadas algumas falhas críticas no processo do projeto Mozilla. A seção 3.1 descreve brevemente o problema da simulação da programação de robôs o que se pretende ser revolvido através de um processo de software a ser proposto. A seção 3.2 introduz um novo modelo em sua grande parte baseado no projeto do Mozilla voltado para o caso-de-estudo mencionado anterior apresentando aspectos a serem melhorados. A seção 3.3 apresenta um conjunto de ferramentas a ser utilizado para o modelo de processo proposto visando automatizar algumas das atividades.

2. Uma Visão Geral dos Processos Utilizados em Software Livres

Um projeto de software livre tende a nascer como um resultado de uma ação puramente pessoal, começa com um desenvolvedor que não se encontra a resolver um dado problema completamente. Tal desenvolvedor deve ter o conhecimento requerido para pelo menos iniciar a resolvê-lo. Uma vez que ele ou ela conseguem alguma coisa usável, simples e com alguma funcionalidade, se possível, bem projetada  ou escrita, a melhor coisa que eles podem fazer é compartilhar a solução com a comunidade de software livre. Isso é conhecido no mundo do software livre como “releasing early” e tem o efeito de atrair a atenção de outras pessoas (geralmente desenvolvedores) que têm o mesmo problema e que podem estar interessados na solução.[1]
Um dos princípios básicos desse modelo de desenvolvimento é o de considerar usuários como co-desenvolvedores. Eles precisam ser “mimados”, não apenas por fazerem a propaganda boca-a-boca mas por conduzirem a tarefa mais cara na produção de software: o teste. Ao contrário do desenvolvimento, depuração e teste são altamente paralelizáveis. É o usuário que toma o software e testa em sua máquina  sob condições específicas (arquitetura, ferramentas, etc ...), uma tarefa que multiplicada por um grande número de arquiteturas e ambientes demandaria maior esforço do time de desenvolvimento.[1]
Se os usuários forem tratados como desenvolvedores então existe a possibilidade de que um deles encontre um erro, corrija e envie a correção (“patch”) para o desenvolvedor do projeeto para que o problema seja resolvido na próxima versão.[1]
Por fim, essa dinâmica é altamente benéfica para o desenvolvimento do software.

2.1 O Processo de Desenvolvimento de Software do Projeto Mozilla

Algumas razões fazem do processo de software do projeto Mozilla, um interessante alvo de pesquisas na área de desenvolvimento de software livre conforme a seguir: [2]
    • A base de código do Mozilla é uma das maiores e rápidas dentro dos projetos de sofware livre. O seu tamanho é comparável ao kernel do Linux mas é maior que todo o ambiente gráfico do Xfree86. O projeto do browser é estimado em dois milhões de linhas de código.
    • O número de desenvolvedores é alto, muito deles são pagos diretamente pela Netscape, OEone, Sun, IBM e outras.
    • Uma infraestrutura foi desenvolvida para lidar com requisitos de organização massiva
    • O projeto Mozilla tem como objetivo criar aplicações fáceis de usar para usuários finais ao contrário da maioria dos projetos de software livre que consideram o usuário também como um especialista no domínio
Os seguintes aspectos são considerados mais importantes no processo de software do Mozilla.[2]

2.1.1 Modularidade e a “Posse“ do Módulo:

A alta modularidade permite que desenvolvedores se concentrem em áreas do código sem terem de entender toda a arquitetura e permite uma curva de aprendizado gradual para iniciantes o que torna possível o desenvolvimento possível apesar da concorrência apresentada por uma comunidade de desenvolvedores distribuída.
Cada módulo possui um ou mais componentes e cada componente possui um “proprietário” que é responsável por garantir a qualidade do componente, delegar tarefas a programadores propondo consertos e é a autoridade responsável por decidir o que deve ser alterado no código-fonte e como deve ser alterado.
Essas atividades acima são automatizadas pela ferramenta Bugzilla que é o que faz o processo de software do projeto Mozilla possível conforme pode ser observado nas próximas seções que se seguem. Cada membro do projeto deve possuir um login e uma senha no Bugzilla para participar do projeto.

2.1.2 Desenvolvimento Dirigido a “Bugs”

Quase toda mudança no código na base de código do Mozilla é parte de um conserto para um “bug” unicamente numerado onde “bug” serve para se referir a qualquer pedido de modificação do código seja este um defeito, uma melhoria ou uma mudança de funcionalidade.
Cada “bug” possui as seguintes propriedades:
  • Proprietário:  A pessoa encarregada do “bug”
  • Sumário: Uma descrição on-line do “bug”
  • Attachments: Arquivos atachados ao “bug” com casos de teste, captura de tela ou modificações na base-de-código
  • Comentários: Comentários descrevendo e discutindo o problema
  • Estado: O estado corrente do “bug” que pode ser: NÃO-CONFIRMADO, NOVO, DESIGNADO (a um desenvolvedor), RESOLVIDO, REABERTO, VERIFICADO, FECHADO
  • Severidade e Prioridade: Descreve o impacto do “bug” e em que grau de importância este deve estar para ser consertado
Normalmente “bugs” são criados com o estado NOVO ou NÃO-CONFIRMADO e depois são enviados para proprietários de componentes de sua responsabilidade e alocados no projeto dependendo do grau de prioridade. Se o proprietário do componente não puder resolver o problema, ou ajuda voluntária é oferecida ou outro proprietário que conhece o código melhor está disponível, o “bug” pode ser re-designado a um desses proprietários.

2.1.3 Requisitos

Freqüentemente um ponto de controvérsia em projetos de software livre, o processo de captura de requisitos de alto nível são designados a gerência do projeto Mozilla. Entretanto, como o Mozilla é um browser de internet os seus requisitos são considerados poucos e tão abstratos como “completa conformidade com os padrões da Web”, a maior parte das decisões das funcionalidade incluídas são discutidas entre os proprietários dos componentes e módulos através de comentários nos “bugs” e grupos de notícias (newsgroups).
Um novo requisito pode ser proposto por um desenvolvedor ou membro da comunidade e pode ser aceito ou não pelo sistema de voto, pelos membros da comunidade, pelo proprietário e em última instância por um dos empregados da Mozilla.Org. Sendo esta a última autoridade pra determinar a relevância das mudanças propostas.
O fato dos proprietários dos módulos ou os empregados da Mozilla.org terem a última pode gerar barreiras para adoção de funcionalidades controversas entretanto isso é visto como uma conseqüência do nível de controle que o processo requer.

2.1.4 Design

O processo de design do Mozilla é difícil de abstrair por que o design que é herdado da Netscape não foi completamente inventado para uma visão pública e além disso as discussões são inerentemente difíceis de capturar e ficam espalhadas no meio dos “bugs”.
Assim como o processo de captura de requisitos, as questões de design são tratadas a medida que aparecem através de um “bug” que pede por mudanças na API de um certo componente ou classe seguido de uma discussão feita nos comentários desse “bug”.
Uma conseqüência negativa que essas mudanças constantes produzem é a “pesada” tarefa de manter a documentação atualizada e a documentação do Mozilla tem “envelhecido” consideravelmente após anos e está desatualizada.
Por causa do contínuo ajuste no design, há necessidade constante de re-implementação código legado para remover código não-usado, melhorar a modularidade e a legibilidade do código.

2.1.5 Desenvolvimento Distribuído e Revisões Formais

Assim como vários outros projetos de software livre, uma das premissas do projeto Mozilla era a de que comunicação pessoal não deveria ser um requisito par o desenvolvimento. Por isso, todo o código deve ser projetado, implementado, testado e integrado sem depender de contatos pessoais para resolver problemas.
As mudanças na base de código são feitas através de uma ferramenta de controle de versão CVS (veja a seção 2.2), o que permite o desenvolvimento concorrente e atualizações independentes dos vários desenvolvedores.
Um dos maiores desafios do processo é a revisão do código antes da sua integração no sistema. O projeto Mozilla foi um dos primeiros a implementar sistematicamente revisões formais apoiadas por ferramenta para evitar que um código incorreto no repositório pudesse prejudicar a compilação do sistema prejudicando dessa forma todo o time de desenvolvimento.
O processo de revisão funciona da seguinte maneira:
    • Um desenvolvedor trabalhando num “bug” produz uma correção (“patch”) que é um arquivo texto gerado que descreve as diferenças nas linhas de código desse desenvolvedor e a última versão do código no repositório
    • A correção é atachada no “bug” através sistema Bugzilla e enviada pelo desenvolvedor requisitando uma revisão
    • O revisor que pode ser um proprietário do módulo ou alguém familiar com o código, aprova a revisão ou pede novas mudanças
Na prática, a revisão consiste em comentários nos “bugs” que descreve o que deve ser feito para melhorar a qualidade do código, perguntas ou até recomendações sobre a correção.
Se não houver mais nenhuma questão, o revisor marca o seu selo de aprovação com “r=<nome do revisor>” no comentário do “bug”.
Em alguns casos, um super revisão é necessária, onde um desenvolvedor sênior, familiarizado com o código deve marcar a sua aprovação antes que a integração do código seja permitida.

2.1.6 Garantia da Qualidade e a Triagem de Bugs

A garantia da qualidade no Mozilla é realizada por diferentes classes de pessoas desde engenheiros contratados pela Netscape e outros membros comerciais até voluntários informais que desejam testar e fazer a triagem dos problemas.
As principais atividades nessa fase são: teste e triagem de “bugs”.
No primeiro caso, são feitos diversos tipos de teste desde testes informais dos voluntários, testes de fumaça ou até testes funcionais em alguma organização comercial que apóie o projeto como a Netscape.
No teste de fumaça (smoketesting), todos os dias a última versão do browser é compilada para diferentes nas diferentes plataformas suportadas e disponibilizadas em servidores FTP. Um grupo de testadores obtém essa versão gerada e executam uma série de casos de testes requeridos para que a versão do browser seja considerada estável.
Se falhas são encontradas, as pessoas responsáveis pela mudança no código são contatadas para corrigir ou até mesmo voltar atrás na mudança proposta.
Ter um fórum público para apontar problemas e conseguir o feedback do desenvolvedor sobre esses problemas é considerado uma importante vantagem por prevenir que erros sejam ignorados e por gerar um histórico dos dados armazenados.

2.2 Ferramentas Utilizadas no Projeto Mozilla

O seguinte conjunto de ferramentas é utilizado de forma integrada onde cada uma despenhando um papel no processo de software  e pode ser obtida por licença de código aberto livremente:
CVS[14]: sistema de controle de versão mais usado em projetos de software livre que permite gerenciar arquivos na internet.
Bugzilla[10]: é a ferramenta voltada para desenvolvimento mais madura do Mozilla que possui várias funcionalidades e recursos que se encaixam no processo de software do Mozilla. Esta ferramenta é usada por diferentes classes de pessoas da seguinte forma:
      • Desenvolvedores usam diariamente para enviar correções e requisitar uma revisão de código.
      • O grupo que trata da garantia da qualidade usa essa ferramenta para medir o progresso e para relatar ou fazer a triagem dos “bugs”
      • Gerentes usam a ferramenta para alocar desenvolvedores e monitorar o progresso nas questões mais importantes do desenvolvimento
As características mais importantes da ferramenta são:
Contas de Usuário: cada usuário tem uma conta identificada por email.
Atributos do Bug: Através das suas propriedades mencionadas anteriormente, permite controle sobre responsabilidade, marcar datas, dependências e estado.
Log de Comentário: Como o “bug” mantém uma seqüência de comentários, tal recurso serve como um fórum de discussões focado.
Monitoramento de “Attachment”: “bugs” podem possuir arquivos atachados como especificação, casos de teste e principalmente as correções para os “bugs”.
Interface para Consulta: Devido a enorme quantidade de “bugs”, existe uma ferramenta de busca de “bugs” através do conteúdo de seus atributos.
Integração com Email: Mudanças no Bugzilla são informadas a todas as partes relacionadas àquele “bug” específico.
Modelo Conceitual Simples: Como um registro de bugs, seus conveitos são simples de assimilar: produtos, componentes (subdivisões de um produto), “attachments” e “bugs”.
Bonsai[11]: interface de consulta para o repositório do CVS que permite o acompanhamento do código a partir das alterações (check-ins) e conta com os seguintes recursos:
      • Permite consultas para verificar as últimas alterações (check-ins) no repositório
      • Mostra os comentários das alterações (check-ins) com hyperlink para o “bug” na ferramenta Bugzilla.
      • Interface para visualizar diferenças entre versões de arquivos no repositório.
      • Identificação visual de quais desenvolvedores são responsáveis por quais seções de código
      • Provê um mecanismo de grafo que mostra diferentes versões de arquivos no repositório do projeto.
Tinderbox[12]: sistema cliente-servidor para monitoramento de compilações e testes. Cada máquina cliente com uma arquitetura e sistema operacional específicos compila, testa e relata os resultados para o Tinderbox servidor onde os resultados podem ser observados numa seção que indica o resultado da compilação através de cores:
      • vermelho indica que a compilação falhou
      • laranja indica compilação bem-sucedida mas caso-de-teste falhou
      • verde indica compilação e testes bem-sucedidos
      • amarelo indica compilação e/ou testes ainda em progresso
LXR[13]: ferramenta de hiper-texto que indexa o código-fonte gerando páginas HTML. A partir do HTML, o desenvolvedor pode navegar pelo código em HTML clicando no nome dos métodos, funções, classes e variáveis que foram indexadas além também de permitir busca de nomes de arquivos e conteúdos.
Ferramentas de Comunicação: lista de emails e grupos de notícia (Newsgroups) são usados para discussões menos técnicas como novos recursos, medidas, estatísticas, etc. Canais de IRC são criados para um público-alvo como (#mozilla) para discutir assuntos técnicos e (#smoketests) para voluntários de testes de fumaça além de bots que procuram responder a mensagens que seguem um padrão como a palavra “bug” seguido de um número dando um feedback sobre onde está o hyperlink no bugzilla.

3. Uma Proposta de Processo de Software Livre para um Simulador de Robôs

A proposta de processo de desenvolvimento de software a ser apresentada não tem como intuito produzir um modelo de processo ideal mas apenas apresentar um primeiro passo no sentido de atacar as falhas críticas no processo do projeto Mozilla para que este modelo também possa ser usado em outros projetos como um simulador de robôs.
Embora, as maiores vantagens desse modelo, estão nos testes que são feitos em paralelo por vários usuários da ferramenta, na triagem de “bugs”, designação de tarefas a programadores ou outros proprietários de componentes e a revisão do código de forma automatizada, por outro lado, conforme mencionado na seção 1, as maiores falhas desse processo estão na captura de requisitos feita de maneira informal e a falta de documentação global sobre o design do projeto.

3.1 Caso-de-Estudo: Simulação e Programação de Robôs

A classe de robôs que este artigo se refere é a de robôs industriais que podem ser descritos como uma cadeia de corpos rígidos ligados por juntas com uma ferramenta associada no final dessa cadeia.[3]
Dentro desse contexto, o Robotbuilder [3] é um projeto de simulador para fins educativos e agora este deve ser estendido para contemplar a funcionalidade de programação de robôs que descreve tarefas que estes devem desempenhar como mover a ferramenta de um ponto A a um ponto B, transferência de material, montagem, etc.
De acordo com [5], o campo da programação de robôs pode ser dividido em três categorias: programação automática, programação manual e arquitetura de software. Na programação automática, o usuário/programador tem pouco ou nenhum controle sobre o código do robô. Sistemas manuais requerem que o usuário/programador especifique diretamente o comportamento desejado do robô, geralmente usando um sistema de linguagem baseados em textos ou gráficos.A arquitetura de software é importante para todos os sistemas de programação já que elas provêem um suporte de baixo-nível como a comunicação assim como o acesso aos robôs.
Ainda de acordo com [5], as linguagens de controle baseadas em texto podem ser categorizadas em: linguagens específicas de controladores, linguagens procedurais genéricas e linguagens baseadas em comportamento.
O projeto vai se concentrar nas linguagens procedurais genéricas por serem servirem como uma alternativa às linguagens específicas de controladores onde “genérico” significa linguagens de alto nível de propósito geral como C++ que foi estendia em várias maneiras para prover funcionalidades específicas de robôs.
Após codificados pelo usuário/programador, os comandos serão lidos e enviados para um robô virtual on-line do simulador para que o seu comportamento seja observado com mais segurança antes de enviar para o robô real por motivo de segurança.
Dado este problema, a primeira vista os requisitos de alto nível dessa nova parte do simulador são:
    • Leitura dos Comandos – verifica erros a nível de sintaxe na programação
    • Verificação da Viabilidade dos Comandos – verifica se os comandos são fisicamente viáveis de serem realizados pelo robô dadas as restrições físicas das juntas e do ambiente onde este está inserido
    • Execução dos Comandos – executa os comandos passados por meio de uma animação

3.2 Modelo do Processo Proposto

Conforme mencionado na seção 1, os dois problemas principais percebidos nos processo de software livre do Mozilla e outros que são: falta de uma documentação do design e de um processo de captura de requisitos menos informal.
As seções seguintes apontam sugestões a serem utilizadas no aperfeiçoamento do processo utilizando o simulador de robôs como um exemplo ilustrativo de como isso pode ser feito apontando sugestões para:
    • Início do projeto
    • Captura de novos requisitos
    • Documentação da análise e design
    • Ambiente de desenvolvimento proposto descrevendo um conjunto de ferramentas

3.2.1 Como inicia o projeto ?

Um projeto de software livre começa quando o simulador Robotbuilder passa a ser um sistema usável e útil de alguma forma e este a atrai a atenção de outros usuários com o mesmo problema.
Por isso antes que um projeto livre as seguintes atividades devem ser desempenhadas:
    • Padronização do código incluindo nomenclatura de classes, métodos, variáveis e comentários conforme o exemplo a seguir:
      • Classes com nome de substantivo iniciadas por letra maiúscula. Ex: Robot
      • Variáveis com letra minúscula e prefixo que identifique o tipo. Ex: srtName
    • Padronização da documentação o que pode ser feito através de templates que os membros devem preencher para a documentação de casos-de-uso e componentes.
      • Projeto: Robotbuilder
      • Pacote:  Componente de Tarefa
      • Nome:   Parser
      • Descrição: descrição do objetivo do componente
      • Conteúdo: lista de métodos com uma descrição
      • Exemplo: exemplo de uso

3.2.2 Captura de Novos Requisitos

No processo do projeto Mozilla novos requisitos podem ser capturados através de listas de discussão ou através da ferramenta Bugzilla.
A falta de um processo de captura de requisitos e a falta de mecanismos que separa requisitos de erros (“bugs”) pode prejudicar na métrica do projeto e na documentação do sistema já que estes dados estarão dispersos e misturados num mesmo repositório.
Conforme visto na seção 2.2 o “bug” também funciona como um fórum de discussão focado, logo, para separar “bugs” como erros de implementação ou defeito dos novos requisitos, uma sugestão seria criar um símbolo especial na descrição do “bug” usando a ferramenta Bugzilla indicando que aquele se trata da discussão de um novo requisito e não da correção de um trecho de código.
A responsabilidade de identificar se um “bug” é um erro na funcionalidade do sistema ou um novo requisito deve ser feito na triagem de “bugs” fazendo as devidas alterações se necessário na classificação entre estas duas categorias.
Se julgar o “bug” relevante, este é encaminhado a uma comissão de especialistas no conhecimento do domínio pelo proprietário do módulo para juntos avaliarem a relevância conceitual e técnica de tal requisito e se este deve ser aceito. Se for aceito, esse “bug” deverá conter também um ponteiro para o arquivo de especificação desse requisito caso o requisito sugerido seja aprovado.
Por exemplo, um “bug” com a descrição “REQ: Esconder Links do Robô” deve ser interpretado como um novo requisito devido ao prefixo REQ que indica a intenção do usuário de sugerir um novo requisito.
Por outro lado um “bug” com a descrição “Exceção do Sistema ocorre ao abrir arquivo de geometria” deve ser interpretado como um erro na aplicação não só pela descrição mas por não possuir o prefixo identificador no início da descrição.
Veja a figura 1 abaixo, para um diagrama sobre o novo modelo de desenvolvimento proposto.

image
Figura 1

3.2.3 Documentação da Análise e Design

De acordo com [1], a falta de documentação do design global pode não só significar limitações na reusabilidade dos módulos mas também um grande deficiência ao convidar novos desenvolvedores já que estes terão uma curva de aprendizado lenta e custosa e por último são perdidas oportunidades de reuso de código.
Para um projeto orientado a objetos como o simulador proposto, pelo menos seguintes artefatos devem ser estar disponíveis em cada uma das etapas de desenvolvimento:
    • Análise de Requisitos: diagramas de casos-de-uso, especificação dos casos-de-uso
    • Análise: diagramas de classes, digramas de sequência e diagramas de estado
    • Projeto: diagramas de classes e de seqüências detalhados
    • Implementação: Comentários padronizados nos métodos
    • Testes: Casos de testes documentados
Como conseqüência da melhor documentação, espera-se atrair um maior número de pessoas interessadas, sejam desenvolvedores ou não, e um aumento na qualidade das contribuições da comunidade de software livre dado que a arquitetura do software agora é conhecida. Devido ao “tempo” que essa atividade consome, esta deve ter o trabalho o mais automatizado possível.
Os proprietários de módulos devem sempre trabalhar para manter a documentação dos requisitos atualizada se necessário.
A documentação dos componentes e de outras classes pode seguir o mesmo template de documentação e em grande parte esse processo pode ser automatizado pelo uso ferramentas de documentação de código que geram um HTML no formato de arquivos de ajuda a partir do código fonte como o Doxygen, por exemplo. Tais arquivos HTML servem como documentação da interface das classes para os outros desenvolvedores.
É importante que nos comentários dos métodos e funções que implementem casos-de-uso (como é o caso das classes do componente de tarefas) haja alguma indicação do nome da especificação que deu origem ao método e que isso seja indexável pelo LXR (ver seção 2.2), o que promove a rastreabilidade entre o código e a especificação.

3.3 Qual o ambiente de desenvolvimento proposto ?

Para esse modelo de processo melhorado é sugerido o mesmo conjunto de ferramentas  do Mozilla complementado de outras ferramentas principalmente para o suporte de testes e documentação que devem ser usadas de forma integrada conforme pode ser visto:
CVS: sistema de controle de versão. (seção 2.2)
Bugzilla: centro de controle de “bugs”. (seção 2.2)
Bonsai: ferramenta de busca de “bugs” na base-de-código do CVS. (seção 2.2)
Tinderbox: monitoramento de compilação e testes em diferentes plataformas. (seção 2.2)
LXR: gera páginas HTML do código-fonte. (seção 2.2) O uso deve ser expandido par permitir também indexar as especificações de requisito às classes de aplicação.
Ferramentas de Comnicação: criando canais de comunicação para diferentes classes de desenvolvedores e com diferentes tipos de conteúdo. (seção 2.2)
Eclipse[6]: um ambiente de desenvolvimento integrado universal e multiplataforma que pode ser conseguido gratuitamente.  É um meta-ambiente que pode ser estendido para qualquer coisa mas construído para nada em particular e cujo integração e extensão para um ambiente de desenvolvimento é feita através de plug-ins. Na realidade, a linguagem utilizada no simulador de robôs é C++, logo, qualquer compilador C++ poderia ser utilizado para o projeto. O único cuidado que se deve ter é com os diferentes “dialetos” de C++ utilizados nos diferentes compiladores o que é verificado pela ferramenta Tinderbox. Uma outra sugestão seria escolher um “dialeto” de C++ que rodasse em todas as plataformas alvo e disponibilizar um documento para os desenvolvedores especificando esse “dialeto” escolhido.
CppUnit[7]: É um framework para testes unitários em C++ mas baseado no JUnit do Java. Ao enviar a correção de um arquivo, o programador deve também criar ou alterar a classe de teste para garantir que o que ja foi implementado continue correto. As classes de teste deverão usadas pelo Tinderbox ao compilar e testar em várias plataformas.
Doxygen[8]: Ferramenta de documentação automática do código-fonte que serve como um guia para os desenvolvedores compreenderem a interface das classes. Um exemplo da documentação gerada pelo projeto Mozilla Firefox pode ser visto em [9].

4. Conclusões

Embora o modelo de processo de desenvolvimento usado em projetos de software livre ainda esteja na sua infância cada vez mais os projetos de software livre aparecem com um modelo de desenvolvimento mais bem elaborado.
De acordo com [1], as seguintes questões ainda têm que ser tratadas num futuro próximo nos processos de software:
    • classificação de projetos de software livre.
    • criação de uma metodologia baseada na automação da análise.
    • uso do conhecimento adquirido para produzir modelos nos permitam entender o desenvolvimento de software livre facilitando na tomada de decisões baseadas na experiência adquirida.
De qualquer forma, embora o modelo proposto neste artigo não ataque todos os problemas mencionados acima, ele serve com um degrau na direção de um modelo de processo ideal que poderia inclusive utilizar técnicas de gerência do conhecimento.
Por fim, vale a pena ressaltar que ao utilizar este modelo de processo de desenvolvimento, o projeto Robotbuilder[3], pode servir como um interessante caso-de-estudo para softwares que se utilizam de conhecimento de domínio específico como é o caso da robótica mas ao mesmo tempo produzindo um software confiável.

Referências 

[1]   Jesús M. González-Barahona e Gregorio Robles. Free Software Engineering: A
Field to Explore. Upgrade Vol IV, No 4, August 2003.

[2]   Christian Robottom Reis e Renata Pontin de Mattos Fortes. An Overview of the
Software Engineering Process and Tools in the Mozilla Project. February 2002.
<http://opensource.mit.edu/papers/reismozilla.pdf>

[3]  Humberto Cardoso Marchezi e Hans-Jorg Andreas Schneebeli. Um Ambiente para
Simulação e Animação de Robôs. SBIE 2004. Manaus.

[4]  Alfonso Fuggetta. Open Source and Free Software: A New Model for the Software Development Process ? Upgrade Vol V, No 5, October 2004.

[5]   Geoffrey Biggs and Bruce MacDonald. A Survey of Robot Programming Systems.
Departament of Electrical & Electronic Engineering. University of Auckland.

[6]   Eclise.org <http://www.eclipse.org/> acessado em 07 de Março de 2005.

[7]  CppUnit – Wiki <http://cppunit.sourceforge.net/cgi-bin/moin.cgi> acessado em 07 de
Março de 2005.

[8]  Doxygen <http://www.stack.nl/~dimitri/doxygen/> acessado em 07 de Março de
2005.

[9]  Document Repository – Mozilla Firefox
          <http://unstable.elemental.com/mozilla/build/latest/mozilla/htmlparser/dox/index.html>
acessado em 07 de Março de 2005.

[10] Home::Bugzilla::buzilla.org < http://www.bugzilla.org/> acessado em 07 de Março de
2005.

[11]  Bonsai <http://bonsai.mozilla.org/cvsqueryform.cgi?> acessado em 07 de Março de
2005.

[12]  Tinderbox <http://tinderbox.mozilla.org/showbuilds.cgi?tree=SeaMonkey> acessado
em 07 de Março de 2005.

[13]  LXR <http://lxr.mozilla.org/seamonkey/> acessado em 07 de Março de 2005.

[14] CVS home <https://www.cvshome.org/ > acessado em 04 de Março de 2005.
Engenharia de Software – Mestrado – UFES - 2005

Comparação Doc-View e Model-View-Contoller

Mestrado em Automação Industrial – Departamento de Eng Elétrica - UFES
Humberto Cardoso Marchezi – Data 25/05/2005
TÓPICOS ESPECIAIS EM PROGRAMAÇÃO

Introdução

O objetivo desse artigo é explicar os dois padrões de projeto mais utilizados para arquitetura de sistemas, que são o MVC e o Doc-View, e comparar as vantagens e desvantagens no uso de cada um deles.

O Framework Doc-View

O Doc-View (Document/View) é um padrão de projeto foi criado pela Microsoft ao liberar a MFC junto com o seu ambiente de desenvolvimento para C++, o Visual Studio. A motivação para a criação desse padrão de projeto mais conhecido como framework foi a de separar os dados da aplicação da apresentação desses dados.
Um documento (Document) é um objeto que age como um container dos dados da aplicação enquanto que a visão (View) é um objeto de interface gráfica associado a uma área cliente de uma janela podendo ser a própria janela e que é responsável pela interação do usuário com os dados por meio de cliques do mouse e do teclado.
Além disso, um documento contém também as funcionalidades principais da aplicação encapsuladas através dos métodos executados através das mensagens vindas das visões ou da interface gráfica.
Por fim, as informações de um documento podem ser representadas por várias visões, por exemplo, os dados de velocidade de um veículo no tempo no formato tabular ou gráfico, aumentando, dessa forma, a modularidade do programa.
image

O Framework MVC

O padrão MVC (Model View Controller) surge como uma outra maneira de quebrar a aplicação só que desta vez em três partes: controlador, modelo e visão respectivamente representando a entrada de dados, o processamento e a saída no domínio da interface gráfica. 
image
 Num diagrama UML de classes, as três partes seriam representadas da seguinte forma:
image
Não existe uma maneira única de implementar o padrão MVC sendo essa acima uma proposta da SUN para os desenvolvedores JAVA. Existem outras propostas que inclusive derivadas ou que estendem o conceito 
como o Model-Pipe-View-Controller, Model-View-Presenter, Hierarchical-Model-View-Controller, Four-Layer-Architecture, etc. 
De qualquer maneira, pode-se perceber que a classe Modelo fica isolada das outras duas classes o que produz algumas vantagens que serão vistas a seguir.

Framework Doc-View versus Framework MVC

Ao desenvolver uma aplicação para dar suporte ao um tipo de aplicação cliente, misturar regras de negócio e acesso a dados com lógica específica de interface gráfica para apresentação e controle não é uma abordagem adequada. Como diferentes aplicações precisam ser desenvolvidas para cada tipo de cliente, um código que não pertence a interface é replicado em cada aplicação o que resulta em esforço extra para na implementação, no teste e na manutenção.
Ao utilizar o um dos frameworks acima tal dificuldade não existe pois as regras de negócio são isoladas no Documento no caso do Doc-View, ou no Modelo no caso do MVC sendo essa a vantagem principal ao se
utilizar qualquer um desses frameworks. Permite a reutilização do código que diz respeito a regra de negócio.
As diferenças maiores entre os dois padrões esta no controle da interface gráfica. Enquanto que o Doc-View concentra todo o controle da interface gráfica na classe Visão, o MVC quebra este controle entre nas classes de Visão e Controle. Ao fazê-lo dessa forma, o MVC pressupõe que os métodos de controle de interface gráfica sejam mais bem distribuídos entre a Visão e o Controlador a medida que a aplicação a ser desenvolvida vai crescendo.
Entretanto o que na prática tem se observado é que a classe Controlador no padrão MVC cresce na mesma proporção que a classe Visão no padrão Doc-View a medida que aumenta a complexidade no controle da interface gráfica e na interação com o usuário.
imageimage
a) Crescimento do Controlador no MVC   
b) Crescimento do Documento em Doc-View

Um outro benefício que pode ser obtido pelo MVC em relação ao Doc-View é a independência da Visão em relação ao Modelo (ou Documento) o que permite a reusabilidade da Visão em outras aplicações. 
Além disso, ao utilizar um Controlador, o padrão MVC permite que um mesmo Modelo possa ser representado por várias dessas Visões independentes o que pode ser muito útil para aplicações gráficas de CAD, por exemplo, onde um mesmo objeto é mostrado em várias perspectivas diferentes. 
Por sua vez, o framework Doc-View tem como vantagem o fato de poder ser implementado de forma mais simples que o MVC. Além do mais, na maioria das aplicações como os sistemas de informação, por exemplo, não existe a necessidade de representar os dados em várias visões o que faz o Doc-View ser igualmente útil e até mais bem aproveitado nesses tipos de sistemas.

Conclusões

A partir das comparações feitas pode-se concluir é mais interessante analisar como a aplicação a ser desenvolvida vai funcionar antes de escolher um dos dois padrões apresentados.
Se a reusabilidade das Visões ou o uso de múltiplas Visões para um mesmo modelo de dados for uma questão importante no projeto de arquitetura de um sistema, vale a pena utilizar o padrão MVC.
Por outro lado, em outros tipos de sistemas, o Doc-View é uma alternativa igualmente útil com a vantagem de ser mais simples e portanto mais produtiva.  
De qualquer forma, seja qual for a alternativa escolhida ambos os padrões permitem uma melhor gerenciamento, clareza e reutilização do código por isolar a camada que gerencia a regra de negócios.

Referências:

http://www.mindcracker.com/mindcracker/c_cafe/docview/dw0.asp
http://java.sun.com/blueprints/patterns/MVC-detailed.html
http://c2.com/cgi/wiki?ModelPipeViewController
http://c2.com/cgi/wiki?ModelViewPresenter
ftp://www6.software.ibm.com/software/developer/library/mvp.pdf
http://c2.com/cgi/wiki?FourLayerArchitecture
http://c2.com/cgi/wiki?HierarchicalModelViewController

Thursday, April 1, 2010

Validação de Entidades usando Microsoft Validation Application Block

Existe uma forma interessante de validar objetos utilizando o Microsoft Validation Application Block.

http://msdn.microsoft.com/en-us/library/cc511802.aspx

Dessa forma, ao invés de validar os objetos dentro das propriedades ou métodos, esses campos podem ser validados
através de Decorators.( [ ] )

Exemplo: ( tirado de http://msdn.microsoft.com/en-us/library/cc511619.aspx )

using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Validation;
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;

public class Customer
{
 private string firstName;
 private string lastName;
 private DateTime dateOfBirth;
 private string email;
 private Address address;

 [StringLengthValidator(1, 50, Ruleset="RuleSetA",
              MessageTemplate="First Name must be between 1 and 50 characters")]
 public string FirstName
 {
   get { return firstName; }
   set { firstName = value; }
 }

 [StringLengthValidator(1, 50, Ruleset = "RuleSetA", 
              MessageTemplate = "Last Name must be between 1 and 50 characters")]
 public string LastName
 {
   get { return lastName; }
   set { lastName = value; }
 }

 [RelativeDateTimeValidator(-120, DateTimeUnit.Year, -18, 
                  DateTimeUnit.Year, Ruleset="RuleSetA", 
                  MessageTemplate="Must be 18 years or older.")]
 public DateTime DateOfBirth
 {
   get { return dateOfBirth; }
   set { dateOfBirth = value; }
 }

 [RegexValidator(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", 
                Ruleset = "RuleSetA")]
 public string Email
 {
   get { return email; }
   set { email = value; }
 }

 [ObjectValidator("ValidAddress", Ruleset="RuleSetA")]
 public Address Address
 {
   get { return address; }
   set { address = value; }
 }

 [RangeValidator(0, RangeBoundaryType.Inclusive, 1000000, 
       RangeBoundaryType.Inclusive, Ruleset="RuleSetA", 
       MessageTemplate="Rewards points cannot exceed 1,000,000") 
 public int RewardPoints
 {
   get { return rewardPoints; }
   set { rewardPoints = value; }
 }

}

Depois o Customer pode ser validado de uma vez só da seguinte forma:

Exemplo: ( http://msdn.microsoft.com/en-us/library/cc511605.aspx )

Customer cust = new Customer();
ValidationResults results = Validation.Validate(cust, customerRuleSetCombo.Text);

Os objetos também podem implementar um método que faz todas as validações de uma só vez.

Exemplo: ( http://msdn.microsoft.com/en-us/library/cc511640.aspx )

using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Validation;
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;

[HasSelfValidation]
public class TemperatureRange
{
 private int min;
 private int max;

 // ...

 [SelfValidation]
 public void CheckTemperature(ValidationResults results)
 {
   if (max < min)
     results.AddResult(new ValidationResult("Max less than min", this, "", "", null));
 }
}

É importante notar que o Validation Application Block pode ser usado em aplicações ASP.NET, Winforms e WCF. ( http://msdn.microsoft.com/en-us/library/cc511714.aspx )

* Integrando Validations no Winforms: http://msdn.microsoft.com/en-us/library/cc511884.aspx

* Integrando Validations em ASP.NET: http://msdn.microsoft.com/en-us/library/cc511745.aspx

* Integranto Validations no WCF: http://msdn.microsoft.com/en-us/library/cc511692.aspx