Archive for October, 2009

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!” :)

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.

Silverlight: Routed Events and Silverlight toolkit

Tuesday, October 20th, 2009
Autor: goncalo.chaves


 

[PT]

Hoje, enquanto estava a desenvolver um aplicação em Silverlight, reparei num comportamento um pouco estranho quando a aplicação era iniciada… basicamente passado algum tempo a aplicação em Silverlight bloqueava e por consequência o browser também. Ok, até aqui tudo bem, costumam dizer que o problema reside entre a cadeira e o teclado, portanto fui analisar dentro das últimas alterações que tinha feito. Descobri que o problema estava relacionado com uma animação que estava a tentar fazer que envolvia algumas Storyboard que definiam a sequência da animação. Uma vez que necessitava de saber quando é que as storyboards terminavam para dar sequência na animação, declarei como normalmente se faz os routedevents para saber quando “agir” segundo o objectivo.

StoryboardTagLinePos1.Completed += new EventHandler(StoryboardTagLinePos1_Completed);
StoryboardTagLinePos2.Completed += new EventHandler(StoryboardTagLinePos2_Completed);
StoryboardTagLinePos3.Completed += new EventHandler(StoryboardTagLinePos3_Completed);

Até aqui tudo parace bem, mas o erro está no facto da declaração destes eventHandlers estar dentro do método que era chamado para dar seguimento na lógica da animação… ora isto gera algo como… stack overflow… porque são referenciadas muitas referências para os mesmos eventos! A maneira correcta e recomendada é que estas definições sejam feitas no método ini do controlo que estamos a utilizar, mas o que queria aqui destacar, é que não se trata de um erro de linguagem ou lógica, mas sim de fluxo da utilização das referências para os eventos. Além da aplicação ficar “gelada” e o browser também, o que é de destacar, a dificuldade em depurar este tipo de problemas ou mesmo existirem ferramentas para tal… mesmo o Silverlight spy também bloqueou. Todavia, é de salvar que o sistema operativo isolou o “problema” impedindo que este lindo e útil erro se propagasse na memória que nem um louco! Lol.

Ok, é só uma dica para ter em atenção quando estamos a desenvolver aplicações em Sl.

Já agora, saiu a versão de Outubro do Silverlight toolkit: http://silverlight.codeplex.com/, basicamente um turbo para as aplicações em sl.

Obrigado.

[EN]

Today when, I was developing a Silverlight application I noticed that after a while that application was launched on the browser, the application frozen… and even more frozen the browser…

So obviously I thought that was something related with a latest change on my project and it was related with some kind of animation that I was trying to do. I used some storyboards in order to give a sequence on the animation, and I need to know in the application when each storyboard ended so has usual I declared the routed events… something like:

StoryboardTagLinePos1.Completed += new EventHandler(StoryboardTagLinePos1_Completed);
StoryboardTagLinePos2.Completed += new EventHandler(StoryboardTagLinePos2_Completed);
StoryboardTagLinePos3.Completed += new EventHandler(StoryboardTagLinePos3_Completed);

But the slight mistake was that this declarations were inside of the method that I call each time that I need to do something with the animation… yeah… the stack and memory went crazy!! Many and multiple repeated references to the same trigger events! Lol

So obviously the right way is declare the same routed event but outside the method… usually and the recommended way is on the control init method to avoid situation like that.

But besides my “donkey” mistake, what I really notice is that I couldn’t find any tool to help on this issue, even Silverlight spy went frozen… so one good thing is that the OS in somehow protected the rest by “frizzing” the application and prevent a full stack overflow…

Just a thing to keep in mind when developing sl applications.

Btw the October Silverlight toolkit release is out: http://silverlight.codeplex.com/ this is a very very powerful “toy” to boost sl apps :P

Thanks.

Umbraco – Sem nós na árvore de documentos mas com conteúdos…

Monday, October 19th, 2009
Autor: goncalo.chaves


[PT]

Olá a todos. Não sei se já se depararam com o seguinte cenário, na abertura de uma instância de umbraco num dado site:

umbraco issue thumb Umbraco – Sem nós na árvore de documentos mas com conteúdos...

Como podem ver na imagem, a árvore de conteúdos do CMS está, ou aparenta, estar vazia. Mas o mais “estranho” foi verificar que tanto o site estava sem qualquer anomalia, como também na base de dados do CMS, tudo estava aparentemente bem. Inclusivé, as várias tabelas do umbraco continham os dados…

Pois bem. À uns dias ao aceder ao umbraco de um dado site, deparei-me com este cenário… e sem ter efectuado alterações na sua estrutura, em qualquer DocumentType, Media element, Template ou outro elemento pertencente à base de umbraco.

Após várias tentativas para perceber o que estava a acontecer, experimentámos usar a mesma base de dados em questão mas como uma nova “instância limpa” de umbraco. Para qual foi do nosso espanto que tudo estava bem. A estrutura de nós estava devidamente correcta e tudo o resto estava como se esperava.

Posto isto, a decisão foi publicar novamente toda a estrutura de umbraco para o site em questão, uma vez que nos pareceu ser um caminho para a solução. E não é que resolveu o problema?? Então o que deu origem a tal coisa? Não tenho resposta certa para o caso, mas uma das soluções plausíveis para o caso, foi talvez algum ficheiro que tenha ficado danificado durante publicação do site em questão! Daí que a re-publicação da estrutura de umbraco, tenha solucionado o problema.

Caso conheçam ou tenham mais informações sobre este tipo de questões ou problemas, não deixem de partilhar. :)

Obrigado a todos, e também ao Antoine pela sua ajuda neste processo.

[EN]

Hi all, I would like to share with you a little issue that happened with me a few days ago with an umbraco installation. Has you can see in the above picture I opened the cms of one site, and I saw that the content tree was empty… I thought… OMG! But the site was good with all the content and even the database was correct, and all tables with the right content… So we tried to figure out what happened and the cause. After some experiences, we tried first using that database with a brand new umbraco installation… and viola! Everything was fine!

Ok, so let’s try to re-publish the umbraco structure with all files and content… and it works! So what was the cause? We can’t know for sure, but one possible reason is related with the first publish of the site… maybe one of the umbraco’s files went corrupted during the upload process.

So we solved by re-publishing all umbraco’s structures files, if you know some related issues or other solution please share with us :)

Thanks for reading and also thanks for the help that Antoine provided.

Microsoft Ajax Minifier

Friday, October 16th, 2009
Autor: Nuno Costa


A equipa ASP.NET lançou a Microsoft Ajax Library (Preview 6) e o Microsoft Ajax Minifier. Este lançamento inclui updates significantes à Microsoft Ajax Libray (Preview 6) tais como : Better Imperative Syntax, Client Script Loader e Better jQuery Integration. Para referência aqui fica o post byTHE GU”. http://weblogs.asp.net/scottgu/archive/2009/10/15/announcing-microsoft-ajax-library-preview-6-and-the-microsoft-ajax-minifier.aspx

Em relação ao Microsoft Ajax Minifier fiquem a saber que podem fazer o download aqui e que tem os seguintes componentes:

  • ajaxmin.exe – command-line
  • ajaxmintask – MSBuild task para minimizar os ficheiros num projecto do VS
  • ajaxmin.dll – um componente que pode ser usado nos projectos programaticamente.

Para usar o componente como MSBuild task só é preciso adicionar as seguintes linhas ao ficheiro de projecto.

  1. Butão direito sob o ficheiro de projecto e escolher a opção “Unload Project
  2. Butão direito sob o ficheiro de projecto e escolher a opção “Edit
  3. Colocar as seguintes linhas imediatamente antes da tag </Project> no fim do ficheiro
    <Import Project="$(MSBuildExtensionsPath)\Microsoft\MicrosoftAjax\ajaxmin.tasks" />
        <Target Name="AfterBuild">
            <ItemGroup>
                <JS Include="**\*.js" Exclude="**\*.min.js" />
            </ItemGroup>
        <AjaxMin SourceFiles="@(JS)" SourceExtensionPattern="\.js$" TargetExtension=".min.js" />
        </Target>

Em cada build no VS a task irá criar um ficheiro .min.js para cada ficheiro .js encontrado.

Uma óptima forma de automatizar a tarefa de minimizar os ficheiros.

PS. E para quando uma ferramente identica para minimizar os .css ?


Better Tag Cloud