Author Archive

Conta-me como foi!

Thursday, January 14th, 2010
Autor: cesar.silva


Acordei eram 4:10 da manhã… estava sem sono. A bolonhesa que havia feito para jantar pontapeava-me agora o estômago pelo que decidi levantar-me para beber uma água das pedras. Bolas… acabaram! Não fazia sentido tentar voltar a dormir, por isso, liguei o portátil e fui ao Google pesquisar por quantos dias aguenta um gato sem comer. Pobre Sushi! Mal sabe o que a espera…

Acabei no youtube… e depois de escolher o sonzinho que me apetecia ouvir, passei pelo facebook e servi as Impossible Quiche que havia feito 2 dias atrás… eheheheh, continuo em primeiro lugar entre todos os meus vizinhos (desde que o Cruz desistiu)!

Lembrei-me então que no dia anterior tinha circulado um e-mail pelo departamento, que perguntava se alguém havia feito um “métodozinho” que devolvesse uma frase à la facebook que indicasse quanto tempo faltava para determinada data ou quanto tempo havia passado desde então.

Hoje não vou perder muito tempo a explicar o que fiz ou porque fiz desta ou daquela maneira. Mas para quem quiser saber há quanto tempo foi o 25 de Abril de 1974… aqui fica mais um exercício que pode dar jeito.

Porque uma imagem vale por 1000 palavras…

image thumb Conta me como foi!

Este resultado foi obtido através das seguintes linhas de código:

// Output the time capsule result
TimeCapsuleResult1 = new TimeCapsule(new DateTime(1974, 4, 25)).TakeUsToWarpSpeedMrScott().ToString();

// Output the time capsule result
TimeCapsuleResult2 = new TimeCapsule(new DateTime(2010, 1, 14, 14, 53, 12)).TakeUsToWarpSpeedMrScott().ToString();

// Output the time capsule result
TimeCapsuleResult3 = new TimeCapsule(DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0))).TakeUsToWarpSpeedMrScott().ToString();

Para quem quiser os ficheiros com a implementação deste exercício (sem os quais a chamada de cima não faz qualquer sentido), podem retirá-los em Source Code.

Curiosidades

Ao que parece o PHP já faz isto de forma nativa… alguém se deve ter dado ao mesmo trabalho! icon razz Conta me como foi!

Regular expressions…!

Friday, October 30th, 2009
Autor: cesar.silva


Há relativamente pouco tempo atrás, pediram-me para incluir em dada página de um dos nossos clientes uma secção que fosse buscar tweets de uma dada conta. Como seria de esperar encontrei no site do Twitter informação sobre as libraries existentes para C# e depois de alguma leitura acabei por utilizar aquela que me pareceu melhor ir de encontro às minhas necessidades, que foi o TweetSharp. O site por si já faz um excelente trabalho a explicar como a API funciona pelo que não vou perder muito tempo com isso.

Fiz o que tinha a fazer e reparei que a estrutura de cada tweet vinha com a propriedade Text, sem qualquer tipo de formatação (e ainda bem), o que me fez deparar com uma necessidade: como formatar os links dos tweets?! Como já devem ter visto, cada tweet pode conter referências a @users, #trends ou http://weblinks, e como tal costumam ser links.

Para mim tornou-se claro que este era um problema a ser resolvido com regular expressions.

Geek Stuff!

As regular expressions permitem-nos procurar padrões em variáveis de texto e determinar se pretendemos executar acções sobre as mesmas caso esse mesmo padrão seja encontrado. Para isso, utilizamos a classe Regex.

Para efeito de exemplo, criei a classe TweetFormatter com o método Twitterize que converte a esta variável RawTweet num tweet formatado com links.

RawTweet = "@csilva parece que o @rfiel andou a comentar sobre #silverlight ultimamente. Mais informações em http://silverlight.net/";
Tweet = TweetFormatter.Twitterize(RawTweet);

Utilizando o método Replace da classe Regex, conseguimos substituir todas as ocorrências que obedeçam ao padrão por nós definido através de uma regular expression, por uma expressão por nós definida através de um MatchEvaluator, que não é nada mais que um delegate que recebe o Match encontrado na expressão original.

internal static string Twitterize(string rawTweet)
{

  // Return the tweet itself if null or empty
  if(String.IsNullOrEmpty(rawTweet))
      return rawTweet;

  // Replace all the user links
  var twitterUserRegex = new Regex(@"(?<startPattern>(^|[^a-z0-9])@)(?<twitterUser>\w+)");
  var resultTweet = twitterUserRegex.Replace(rawTweet, TwitterUserEvaluator);

  // Replace all the trend links
  var twitterTrendRegex = new Regex(@"(?<startPattern>(^|\s))\#(?<twitterTrend>\w+)");
  resultTweet = twitterTrendRegex.Replace(resultTweet, TwitterTrendEvaluator);

  return resultTweet;
}

Com efeito, reparem que estou a utilizar 2 métodos diferentes, para determinar a expressão pela qual um @user ou uma #trend serão substituídos.

private static string TwitterUserEvaluator(Match currentMatch)
{
  var userTwitterLink =
    String.Format("{0}<a href=\"http://twitter.com/{1}\" target=\"_blank\">{1}</a>",
      currentMatch.Groups["startPattern"],
      currentMatch.Groups["twitterUser"]);
  return userTwitterLink;
}

private static string TwitterTrendEvaluator(Match currentMatch)
{
  var userTwitterLink =
    String.Format("{0}<a href=\"http://twitter.com/#search?q=%23{1}\" target=\"_blank\">#{1}</a>",
      currentMatch.Groups["startPattern"],
      currentMatch.Groups["twitterTrend"]);
  return userTwitterLink;
}

Para quem quiser os ficheiros com a implementação deste exercício, pode retirá-los em Source Code.

Wicked Tools!

Para quem não conhecer fica aqui a sugestão: existe uma ferramenta muito boa não só para testar como para aprender a trabalhar com regular expressions que se chama Expresso e foi desenvolvida pela Ultrapico.

Sorted…!!! :)

Thursday, October 29th, 2009
Autor: cesar.silva


Uma vez numa entrevista de trabalho perguntaram-me:

“Se tiveres um problema em mãos e não souberes como o resolver, o que fazes?!”

Comecei por achar a pergunta um tanto ou quanto estranha e vaga mas era nitidamente uma daquelas que poderia fazer a diferença entre ser contratado ou não. A resposta que o entrevistador estava à procura era:

“Quando tudo o resto falhar e todos os que conhecer não souberem… vou ao Google! Se não estiver no Google, então é porque não existe…”

Há uns tempos atrás andei à procura de uma forma de ordenar listas/colecções/arrays por múltiplas colunas. Nesta altura Linq não era opção. Como qualquer bom programador, fui ao Google procurar por quem já tivesse partido pedra e encontrei um artigo muito interessante:

Sorting with Objects on multiple fields
http://www.codeproject.com/KB/recipes/Sorting_with_Objects.aspx

“Nada como o belo de um copy/paste para dentro do nosso projecto para resolver o problema!” – pensei.

O código estava interessante, eu faria algumas coisas de forma diferente e rapidamente deu para perceber que não funcionava assim tão bem como haviam vendido. A ordenação só funcionava correctamente para o primeiro campo. Como o meu amigo Antoine diria:

“Não são bugs… são novas e entusiasmantes oportunidades de refactoring!” icon smile Sorted…!!! :)

Dito, feito… e resolvi criar a minha própria classe de ordenação utilizando reflection e alguma recursividade.

Geek stuff!

Aquilo que eu queria era no fundo ordenar um array de objectos (que a título de exemplo são os developers da fullsix)

// Initialize array
var fullsixEmployees = new[] {
    new FullsixEmployee {
        Id = 1,
        Name = "César Silva",
        Birthdate = new DateTime(1977, 7, 16),
        IsPortuguese = true
    },
    new FullsixEmployee {
    ...
    ...
    

A ideia era conseguir dizer de alguma forma que queria ordenar este array por um número ilimitado de propriedades e determinar a direcção dessa ordenação.

// Sort the fullsix employee's array
Array.Sort(fullsixEmployees, new MultiColumnComparer<FullsixEmployee>("IsPortuguese DESC, Birthdate"));

A “magia” reside basicamente nos 2 métodos que determinam a comparação entre as propriedades de cada objecto. Ao invocar o método Sort da classe Array, passamos como argumentos o array a ordenar, seguido de um IComparer<T> que neste caso é a nossa classe MultiColumnComparer.

public int Compare(T x, T y)
{

  // Initialize the source object's type
  var columnsOrder = GetColumnsOrder(this.OrderExpression);
  var comparissonResult = 0;

  if (0 < columnsOrder.Count)
      comparissonResult = ColumnCompare(x, y, columnsOrder, 0);

  return comparissonResult;
}

Após esta primeira invocação há que chamar o segundo método de nome ColumnCompare de forma a permitir a recursividade entre as várias propriedades (caso a comparação de determinada propriedade resulte em igualdade).

public int ColumnCompare(T x, T y, IList<Column> columnsOrder, int columnIndex)
{

  // Get the object's type
  var sourceType = x.GetType();
  var columnProperty = sourceType.GetProperty(columnsOrder[columnIndex].Name);

  // Initialize the comparisson result object
  var comparissonResult = 0;
  comparissonResult = Comparer.DefaultInvariant.Compare(columnProperty.GetValue(x, null), columnProperty.GetValue(y, null));

  // Invert the order if descending
  if (columnsOrder[columnIndex].Direction.Equals(ColumnDirection.Descending))
      comparissonResult = -comparissonResult;

  // If the properties are equal then go to the next property (if available)
  if (comparissonResult.Equals(0) && columnIndex < columnsOrder.Count - 1)
      return ColumnCompare(x, y, columnsOrder, columnIndex + 1);

  return comparissonResult;
}

Através de reflection conseguimos aceder às propriedades dos objectos a serem comparados e através de um ciclo recursivo aceder aos valores de cada uma delas para estabelecer as comparações. O ciclo mantém-se enquanto existir igualdade entre as propriedades a serem comparadas e a direcção da comparação é determinada pela negação do resultado, caso seja descendente.

Acabou por ser um exercício engraçado para brincar mais uma vez com a ordenação de listas/colecções/arrays.

Para quem quiser os ficheiros com a implementação deste exercício, pode retirá-los em Source code.


Better Tag Cloud