Compilando Views com o ASP.NET MVC 2

Olá!

Com o lançamento do ASP.NET MVC 2 e o advento dos Html Typed-Helpers, é possível criar elementos HTML baseados em expressões lambdas.

Legal, e o que isso significa?

Podemos selecionar as propriedades do Model a serem ligadas ao controle HTML (da View) como se estivéssemos escrevendo uma função lambda. Com isso ganhamos tipagem e intellisense. E onde há intellisense, há compilação estática.

No ASP.NET MVC 1 isso não era possível, de modo que os Html Helpers trabalhavam com strings (passávamos o nome da propriedade por parâmetro) e as más notícias vinham em tempo de execução: tela amarela do ASP.NET + runtime error. Antes escrevíamos:

<%= Html.TextBox("Name") %>

No MVC 2 fazemos isso com uma expressão lambda, que usamos para selecionar a propriedade do model:

<%= Html.TextBoxFor(modelVar => modelVar.Name) %>

Ao habilitar a compilação das Views, podemos identificar model-bindings errados em caso de alteração das propriedades.

Porém, este novo recurso do MVC 2 não vem habilitado por padrão, é preciso modificar as configurações do projeto MVC. Para tanto, clique com o botão direito em cima do projeto MVC Application e escolha a opção Unload Project, conforme a figura 1:

Agora é possível editar o *.csproj/*.vbproj do projeto sem precisar abri-lo como arquivo pelo VS. Novamente, clique com o botão direito em cima do projeto e vá até “Edit [Nome-do-projeto].csproj”.

O VS abrirá o modo de edição XML do csproj/vbproj, altere o valor do nodo MvcBuildViews para true, salve o arquivo e pronto. Piece of cake.

Agora você já pode dar “Reload Project” e usufruir do recurso de compilação estática das Views. Entretanto, utilize este recurso com cuidado, pois dependendo do tamanho do projeto seu build poderá ficar bem mais lento e a necessidade (ou falta de) de compilar as Views pode não justificar seu uso. Assim como quase tudo em desenvolvimento de software, depende do contexto.

Até mais ver!

foreach vs List.ForEach – Otimização de código

Escrever código otimizado é uma boa prática? Óbviamente, isso faz parte de toda cartilha de desenvolvimento, está sempre sendo falado, etc etc etc..

Mas O.k, agora defina otimização.

Ainda essa semana uma questão parecida surgiu no trabalho e me senti tentado à relatá-la.

Para quem não sabe, com o advento do .NET 3.5 a classe List(T) ganhou o método ForEach que recebe como parâmetro a delegate Action(T). Esse método, segundo a própria documentação do Framework, executa uma determinada ação para cada elemento da lista.

Desta forma, além de percorrer os itens de uma List(T) da forma já conhecida:

IList<string> names = new List<string>()
{
    "John Locke",
    "Mary",
    "James Bond",
    "Sam"
};

foreach (string name in names)
{
    Console.WriteLine(name);
}

Podemos usar:

names.ForEach(name => Console.WriteLine(name));

Ou ainda (para quem não quiser a expressão lambda ou precisar usar mais de uma expressão por iteração):

names.ForEach(delegate(string name) { Console.WriteLine(name); });

Mas o que muita gente não sabe, e aqui entra a discussão, é que para algumas operações (e.g: soma total dos números de uma lista) este método ForEach mostrou-se ser mais otimizado EM TERMOS de tempo de resposta.

Sugiro o post do Dustin Campbell (MVP C#) para quem quiser dar uma olhada nos números e curvas de performance das várias formas de percorrer os itens de uma lista (e no exemplo, somá-los) utilizando duas configurações no compilador: não otimizar geração de código (e.g: Debug) e otimizar geração de código (e.g: Release). Ele ainda disponibilizou os códigos de teste para quem quiser baixar e conferir.

Também sugiro que, assim como eu, quem se interessar implemente seus próprios testes para fixar as diferentes sintaxes 🙂

Mas e se meu critério de otimização não for tempo de resposta? For legibilidade ou produtividade ao manter contato com o código?

Há quem defenda as formas tradicionais (as quais grande parte dos desenvolvedores .NET conhecem) e acha que essa nova “sintaxe” ou forma de iterar não adiciona nenhum “poder representativo à linguagem”. Podemos conferir alguns motivos para não usar o List(T).ForEach no blog do Eric Lippert.

Por outro lado, existem pessoas que defendem que essa nova forma adiciona um poder de leitura ao código orientado à fluência, da esquerda pra direita. (Particularmente, mais do que a performance, esse argumento me agrada). Neste caso, sugiro a leitura do Coffee Driven Development.

Ainda assim, fui questionado por um colega sobre como interromper uma iteração com .ForEach e, com um pouco de procura a “solução” mais comum encontrada foi utilizar “return;” dentro do delegate passado para o .ForEach.

Porém, acredito que a melhor forma de usá-lo seria para expressões simples, como o Console.WriteLine acima, usufruindo de uma melhor performance e não comprometendo a legibilidade do código.

O legal é discutir com diferentes pontos de vista e chegar a um consenso que agregue valor ao software da forma como for mais prioritária: será que vale mais a pena otimizar a resposta de uma iteração? otimizar uma boa leitura e entendimento para outros desenvolvedores? otimizar.. otimizar…

WPF Service Host Template (Free!)

Olá pessoal,

Enquanto as aulas não voltam (devido ao vírus H1N1) e não termino um conteúdo para postar aqui, vou colocar uma curtinha:

http://www.codeplex.com/wpfservicehost

O que é?

Um template para o Visual Studio 2008 (*.vsi), que cria projetos WPF Application para hospedar serviços WCF.

Para que serve?

Facilitar a criação de self-hosting de serviços WCF em aplicativos WPF, sem precisar ter/fazer hospedagem gerenciada (e.g: hospedagem com IIS ou WAS instalados na máquina).

Como utilizar?

Muito simples, basta baixar o *.vsi na seção de downloads, instalá-lo e sair customizando.

Básicamente basta editar as operações expostas no contrato do serviço (e implementá-las!), executar a aplicação WPF e pronto: o seu serviço WCF está hospedado no processo rodando o executável do WPF!

O template ainda vem com um projeto de teste (é uma Console Application fazendo o papel de um proxy gerado pelo svcutil.exe) que instancia os canais de comunicação e realiza a chamada para o método default do template, servindo de exemplo de como consumir o serviço.

Conclusões

Apesar de ser um template extremamente útil e facilitador, particularmente senti falta da exposição dos meta-dados do serviço, mas isso pode ser feito através da adição das seguintes linhas (8 e 16), no App.config do projeto WPF (clique na imagem para ampliar):

Ainda é possível baixar uma webcast (altamente recomendável) da autora (Michele Leroux) na seção downloads do codeplex. O webcast explica alguns pontos importantes:

  • Gerenciamento de concorrência e lifetime do serviço (singleton por default).
  • Como fazer para comunicar cada requisição do serviço na aplicação WPF.
  • Como fazer para customizar o contrato do serviço (adicionar novas operações, etc.)

Antes de usar o template para desenvolver seus próprios hosts, recomendo a leitura da licensa de uso (CDDL), disponível em:

http://www.codeplex.com/wpfservicehost/license

Próximo post será sobre o padrão de Injeção de Dependência (Dependency Injection – DI) utilizando o Unity Application Block. Abraço e até a próxima!