terça-feira, 8 de junho de 2010

Como reutilizar componentes

Muito se fala de reutilização de componentes. Todos sabem que é muito importante reutilizar para reduzir o esforço, porém, o que muitos não entendem é que a reutilização não é tão simples.

Principalmente pessoas em cargos de chefia, que não estão diretamente ligados ao desenvolvimento, não entendem o que realmente é a reutilização. O que, à princípio parece ser algo simples, na verdade, deve ser feito com cuidado. Não adianta chegar um dia na empresa e dizer “vamos reutilizar componentes” sem ter uma política adequada.

Vejo três formas comuns de se reutilizar componentes:
  • Utilizar componentes de terceiros;
  • Desenvolver componentes próprios reutilizáveis;
  • Copiar e colar (sim, isso mesmo).

Utilizar componentes de terceiros

Essa forma de reutilização é, à princípio, a que demanda menos esforço por parte da equipe de desenvolvimento, afinal, não é necessário desenvolver nada.

Porém, o custo do desenvolvimento é apenas uma parte do custo total de utilização de um componente. Ao adotar um componente de terceiro deve-se ter cuidado com algumas outras questões:
  • Qual a curva de aprendizado dele?
  • Quão extensível ele é? Pode ser customizado para atender as diversas necessidades?
  • No caso de um problema nesse componente, como será feita a correção?
  • Este componente está em desenvolvimento? Está maduro? Há previsão de continuidade no desenvolvimento dele?
Como pode-se ver, adotar um componente de terceiros geralmente não é uma opção tão simples quanto se imagina à princípio. Além da aprendizagem necessária, deve-se atentar ao desenvolvimento dele, se a equipe de desenvolvimento poderá contar com melhorias futuras e/ou suporte em caso de problemas.

Desenvolver componentes próprios reutilizáveis

Quando não há um componente de terceiros disponível, ou há alguma outra limitação como o preço ou inadequação do componente, a solução pode ser desenvolver seus próprios componentes reutilizáveis.

Um detalhe muito importante é: não desenvolver um componente sem um caso de uso em mente. Já vi diversas vezes componentes ultra genéricos, que resolvem todos os problemas do mundo, serem criados e quando precisam ser utilizados, simplesmente não servem para nada.

Normalmente a criação de um componente reutilizável deve ocorrer de forma natural. Se um determinado componente foi útil para uma situação, e poderá ser aproveitado para outras, então sim, podemos reutilizá-lo. Antes de pensar em reutilizar é necessário utilizar.

A questão mais complexa dessa reutilização é o versionamento do componente. Deve-se ter muita atenção no controle das versões e alterações que fazem outros projetos deixarem de funcionar. Esse componente, afinal, estará sendo utilizado em mais de um projeto e consequentemente, cada alteração deve ser muito bem pensada.

Copiar e colar

Não, não estou de brincadeira. Copiar e colar é uma ótima forma de reutilização.

Há situações onde determinado código é usado em várias situações, mas em todas com pequenas modificações, não sendo possível ou valendo a pena tentar criar um componente.

Por exemplo, nos últimos projetos que participei foi necessário fazer uso de um Application Controller. Apesar da base ser igual em todos os projetos, cada um tem suas peculiaridades. Nesse caso, foi muito mais simples copiar a classe e adaptá-la.

Deve-se tomar muito cuidado para o copiar e colar não virar regra. Essa forma de reutilização deve ser utilizada somente como exceção, e somente entre mais de um projeto, quando o custo de versionamento e gerenciamento do componente são maiores que o benefício da reutilização. Dentro de um mesmo projeto, o custo de versionamento é pequeno, por isso, normalmente o copiar e colar nunca será utilizado.

Conclusão

A reutilização de componentes não deve ser feita a esmo, sem nenhum planejamento. Não basta o diretor dizer “vamos reutilizar” e tudo sai funcionando. É necessário uma política de reutilização e acima de tudo, um ótimo versionamento.

Sem um planejamento adequado, aquilo que deveria ser uma forma de reduzir custos acaba se tornando uma tormenta.

quinta-feira, 15 de abril de 2010

Plugin do Visual Studio 2010 para exibir o código fonte na margem

Há algum tempo sugeri o plugin RockScroll, que exibe o código fonte na barra de rolagem, destacando alguns elementos.

Agora, acabei de ver a dica do Scott Hanselman no twitter de um plugin para o Visual Studio 2010 que tem funções parecidas com o RockScroll.

Bem, não adianta eu falar muito a respeito desse plugin, o mais fácil é instalar e ver pessoalmente. Você pode fazer o download do plugin nesse link.

Rolagem no Visual Studio 2010
À primeira vista achei um pouco poluído demais, mas ele tem várias funções que podem ser desabilitadas se necessário, e o melhor, tem o código fonte disponível.

quarta-feira, 14 de abril de 2010

Usando reflection para simplificar nossa vida

Em um projeto que estou trabalhando (o mesmo que citei aqui), existe a necessidade de se comunicar com programas COBOL. A comunicação é feita de uma forma um tanto arcaica. Temos que passar um string contendo os diversos campos, cada um com o tamanho exato.

Digamos que precisamos passar as informações de uma nota fiscal, teríamos essa definição:
  • Data de expedição – 10 caracteres;
  • Nome do Cliente – 15 caracteres;
  • Número da nota – 5 dígitos;
  • Valor – 5 dígitos.
Ao gerar a string contendo o seguintes valores:
  • Data: 01/01/2010;
  • Nome: ALGUM NOME;
  • Número: 123;
  • Valor: 15.
Temos isso como resultado: “2010-01-01ALGUM NOME     00012300015”.

A SOLUÇÃO ANTIGA

A solução que existia para facilitar isso era gerar uma classe de acordo com a definição dos campos, que retorna a string formatada. A classe gerada ficaria assim:
class NotaFiscal 
{ 
  private string dataExpedicao; 
  private string nomeCliente; 
  private string numero; 
  private string valor; 

  public string DataExpedicao 
  { 
    get{return dataExpedicao;} 
    set{dataExpedicao = Utils.FormataCaracteres(value, 10);} 
  } 

  public string NomeCliente 
  { 
    get{return nomeCliente;} 
    set{nomeCliente = Utils.FormataCaracteres(value, 15);} 
  } 

  public string Numero 
  { 
    get{return numero;} 
    set{numero = Utils.FormataDigitos(value, 5);} 
  }

  public string Valor 
  { 
    get{return valor;} 
    set{valor = Utils.FormataDigitos(value, 5);} 
  }
 
  public string ObtemString() 
  { 
    return dataExpedicao + nomeCliente + numero + valor; 
  } 
}
Essa classe tem alguns problemas:
  • todos os dados são strings, não é usada a tipagem da linguagem (int, string, DateTime);
  • a definição de tipo e tamanho dos campos fica espalhada pelo código;
  • a ordem dos campos precisa ser verificada dentro da função ObtemString;
  • caso alguma modificação seja feita nos campos, fica ruim de dar manutenção nesse código.

A Nova solução

A solução que procurei desenvolver tinha alguns pré-requisitos, entre eles:
  • a classe não deveria ter informações relacionadas aos campos que seriam montados na string (definição de tipo, tamanho, etc);
  • poder utilizar os tipos da linguagem (int, DateTime, Enum);
  • a definição de mapeamento da classe para a string a ser gerada deveria ser clara e facilmente editável;
O caminho natural foi desenvolver algo semelhante a um Mapeamento Objeto-Relacional. Eu batizei-o de Mapeamento Objeto-Cobolar. ;)

Com isso temos uma classe de modelo, contendo os dados devidamente tipados e um mapeamento que define quais campos serão transportados para a string, o formato e a posição. Todas essas informações conseguimos obter usando reflection e o mapeamento definido.
class NotaFiscal 
{ 
  public DateTime DataExpedicao { get; set; } 
  public string NomeCliente { get; set; } 
  public int Numero { get; set; } 
  public int Valor { get; set; } 
}

<mapping class=”NotaFiscal”> 
  <field name=”DataExpedicao” Length=”10” /> 
  <field name=”NomeCliente” Length=”15” /> 
  <field name=”Numero” Length=”5” /> 
  <field name=”Valor” Length=”5” /> 
</mapping>

Como você pode ver, não é necessário definir o tipo do campo pois ele é inferido à partir do tipo utilizado no modelo. Ou seja, sabemos que um DateTime deverá ser convertido para o formato yyyy-MM-dd, um inteiro deve ser preenchidos com zeros a esquerda e uma string com espaços a direita.

Para obter a string à partir de um modelo, o que precisa ser feito é chamar um método assim:
conversor.GetString(meuModelo);

Implementando a solução

A implementação não tem muito segredo é apenas uma questão de obter cada valor do nosso modelo seguindo a definição do XML.

O ponto mais importante é a conversão do valor tipado para a string. Como cada tipo tem um formato específico, criei um conversor para cada um. Por exemplo:
class IntConverter : ITypeConverter 
{ 
  public string GetString(Field field, object value) 
  { 
       int valorInteiro = Convert.ToInt32(value); 
       return valorInteiro.ToString().PadLeft(‘0’, field.Length); 
  } 
}

Conclusão

Muitas vezes vale a pena perder um pouco de tempo desenvolvendo uma infra-estrutura que facilite o desenvolvimento. Alguns minutos perdidos no início do projeto podem salvar muitos minutos mais adiante, e, o mais importante, evitar muita dor de cabeça.

segunda-feira, 12 de abril de 2010

Validando bindings usando Reflection

Em um projeto que estou trabalhando percebi a facilidade de criar problemas de binding. Basicamente, ao renomear uma simples propriedade do modelo os bindings ligados a ela param de funcionar. O pior disso é que, para saber que há um problema neles, só mesmo executando as telas uma a uma. Nenhum erro de compilação é gerado.

Pra resolver esse problema, resolvi criar um teste que seja executado automaticamente no build e verifique qualquer problema nos bindings.

Relacionando o componente ao modelo

Fazer a validação do binding a princípio é bastante simples, basta buscar cada propriedade do componente que está ligada ao modelo e verificar se o modelo contém a propriedade com o nome definido no componente. Por exemplo, em um ComboBox, pegamos o nome definido no DisplayMember e buscamos no modelo se existe uma propriedade com o nome correspondente.
Porém, há um pequeno problema, no componente não há nenhuma informação dizendo qual o modelo ao qual ele está relacionado. Sem essa informação, não tem como fazer a validação.

Nesse ponto procurei criar uma forma de descobrir qual modelo está relacionado ao componente.

A convenção

O projeto está sendo desenvolvido em WinForms e adotamos o padrão MVP, mais especificamente o Passive View. Como você já deve saber, no MVP temos a camada de View (exibição) separada do Presenter (lógica da tela). A view apenas recebe os dados a serem exibidos.

Olhando a view pude ver um padrão na atribuição de valores utilizados no binding:
class View 
{ 
  public IEnumerable<Usuario> Usuarios 
  { 
    set{ algumGrid.DataSource = value; }
  } 
}

Fica claro que, ao fazer um binding temos:
  • uma propriedade do tipo IEnumerable<T>;
  • a propriedade permite escrita (contém um set);
  • dentro da propriedade atribuímos o valor ao DataSource do componente.
Com essas informações já temos uma base de como podemos verificar o binding.

Buscando o modelo correspondente ao componente

Com essa convenção, é possível descobrir quais componentes fazem binding e qual o modelo correspondente. Para isso temos de fazer duas coisas:
  1. buscar todas as propriedades das telas que sejam do tipo IEnumerable<T> e que contenham um set;
  2. para cada propriedade, obter o componente para o qual está sendo atribuído o valor.
O primeiro passo é bastante simples, via reflection conseguimos ter essa informação:
private IEnumerable<PropertyInfo> GetProperties(Type type)
{
  return type.GetProperties()
      .Where(x => x.CanWrite && EhLista(x))
}

private bool EhLista(PropertyInfo propertyInfo)
{
  return TipoEhEnumerable(propertyInfo.PropertyType) ||
    propertyInfo.PropertyType.GetInterfaces().Any(x => TipoEhEnumerable(x));
}

private bool TipoEhEnumerable(Type type)
{
  return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>);
}

O segundo passo é um pouco mais complicado. Precisamos analisar o código executado, buscando o componente ao qual é atribuído o valor. Via reflection não temos acesso fácil ao código que está sendo executado, para isso foi necessário uma biblioteca externa. Basicamente, foi necessário analisar o MSIL à procura do componente.

Finalmente, Validando os bindings

Agora que já temos todas as informações necessárias, fazer a validação dos bindings é simples. Basta pegar cada propriedade do componente que faz o binding e verificar se o campo existe no modelo. Essa verificação varia conforme o componente, por exemplo, em um ComboBox simplesmente verificamos o DisplayMember e o ValueMember. Em um grid, por sua vez, é necessário verificar essas propriedades para cada uma das colunas.

Tendo a validação pronta, bastou criar um teste que busca os problemas de binding e reporta cada erro encontrado.

Código fonte de exemplo

Pra entender melhor isso, o mais fácil é olhar o código fonte.  Disponibilizei o código no GitHub, nesse repositório.

Caso você ainda não conheça o Git, recomendo a leitura desse artigo.

quinta-feira, 25 de fevereiro de 2010

Download do PHP Editor 2.22

Percebi que muita gente ainda procura um programa que desenvolvi a alguns anos chamado “PHP Editor” (nome muito criativo). Ele é um editor de HTML e PHP, mas também pode ser utilizado para editar outras linguagens como Javascript, CSS e XML. Você pode criar seus sites sem custo, o programa é grátis.
PHP Editor Vou deixar aqui o link para o download da versão em português, o arquivo está hospedado no RapidShare.
O download do programa pode ser feito nesse link: Programa de instalação em português.

A versão mais recente do programa é a 2.22. Esse programa foi desenvolvido a alguns anos e infelizmente perdi o código fonte dele. Deste modo, não terei como continuar o seu desenvolvimento e nem mesmo passar para outra pessoa. De qualquer forma, para quem está contente com ele, fica aí o link.