Resenha do livro Clean Coder

Robert C. Martin, mais conhecido como “Uncle Bob”, é uma grande referência quando se trata de desenvolvimento e agilidade. A sua obra mais conhecida, Clean Code, é um clássico absoluto da área de programação e deve ser lido por qualquer desenvolvedor que deseja melhorar a sua técnica.

Mas hoje, gostaria de chamar a atenção para um livro menos conhecido, mas extremamente importante: The Clean Coder – A Code of Conduct for Professional Programmers.

Considero esse livro um sucessor natural do Clean Code e inclusive, existe uma versão dois-em-um desses livros, que foi a que eu li, seguindo a sequência dos dois, e achei que as duas obras se complementam de forma perfeita.

Se me pedissem para resumir o livro em uma palavra, seria: profissionalismo.

O livro te desafia a repensar a sua relação de responsabilidade com o trabalho, colocando questões como: se você comete um erro que custa 10 mil de prejuízo para a empresa para a qual você trabalha, quem deveria arcar com as consequências? Na opinião do Uncle Bob, é o desenvolvedor quem deve se responsabilizar e fazer um cheque de 10 mil para a companhia. Claro que essa é uma situação um tanto exagerada, mas te faz repensar a postura ao publicar código em produção. Você se torna muito mais cuidadoso quando assume a responsabilidade sobre o seu código nesse nível.

Outro ponto interessante do livro é o paralelo que ele faz entre um programador profissional e um músico. Músicos profissionais praticam muito para refinar a sua técnica e segundo o Uncle Bob, nós desenvolvedores deveríamos fazer o mesmo. Ele até propõe que trabalhemos 20 horas por semana para a nossa carreira, seja praticando código, seja fazendo katas, dojos, assistindo a palestras, indo a eventos, lendo livros técnicos e blogs, escrevendo, etc. Na visão dele, a responsabilidade sobre a carreira é 100% do profissional e a empresa contratante não possui a menor obrigação de investir tempo e dinheiro na nossa carreira. Afinal, o nosso trabalho remunerado é performance, ou seguindo a analogia do músico, é o nosso show. Temos que performar bem no nosso trabalho, temos a obrigação de aplicar o nosso melhor esforço e a nossa melhor técnica para auxiliar o negócio dos nossos contratantes da melhor maneira possível. Não é profissional adotar tecnologias, linguagens e frameworks no nosso trabalho só por que queremos aprender aquilo. No nosso trabalho temos que aplicar somente coisas que conhecemos bem, que testamos e que avaliamos a fundo. Você não vai ver nenhuma banda compondo e ensaiando uma música ao vivo. Em um show, a banda só vai tocar aquilo que ela ensaiou exaustivamente. Nós desenvolvedores deveríamos fazer o mesmo.

O livro é escrito de desenvolvedor para desenvolvedor, e o autor consegue a nossa empatia ao colocar cenários e situações extremamente aderentes à realidade de qualquer um que trabalha com software. O Uncle Bob mostra com exemplos da própria carreira erros que ele cometeu, situações em que ele foi pouco profissional, e esse tipo de experiência prática é inestimável para quem vive de escrever código. O livro aborda uma gama muito grande de fatores, inclusive pessoais, soft e hard skills e também técnicas e ferramentas que auxiliam na produtividade de um desenvolvedor.

Ele é categórico ao afirmar que todo profissional que se preze aplica TDD. Não aplicar TDD é não-profissional. Pra quem trabalha com desenvolvimento no Brasil essa afirmação soa desanimadora, já que boa parte das empresas ainda não despertaram para o valor dessa prática, mas por outro lado, serve para reforçar para cada desenvolvedor que lê o livro que precisamos lutar diariamente para evangelizar as empresas, colegas e clientes da importância dos testes unitários, de componente, integração e sistema. Afinal, é não profissional colocar código não testado em produção.

O meu curso de graduação possuía disciplinas baseadas em livros canônicos da computação, tais como Sistemas Operacionais do Tanenbaum e o Projeto de Algoritmos do Ziviani. Acredito que deveria haver uma disciplina em todo curso relacionado a informática baseada no The Clean Coder. De preferência no primeiro período.

É muito importante possuir modelos e exemplos a serem seguidos na carreira e esse livro serve como uma mentoria. Inclusive, o Uncle Bob destaca que a mentoria é algo essencial para ajudar no desenvolvimento do programador. Depois de lê-lo, muitas vezes me peguei pensando no trabalho: “o que o Uncle Bob faria nessa situação? O que ele recomendaria?”. Acredito que se os jovens estudantes da área lessem esse livro o nível geral dos nossos profissionais seria elevado.

Se você quer escrever código limpo, seja um profissional.

Pré compilação de views Razor no ASP.NET MVC 6

Imagine o cenário de uma aplicação ASP.NET MVC básica, com uma classe de modelo servindo dados para uma view, conforme código abaixo:

Agora, suponha que precisamos fazer alguma alteração simples, como mudar o namespace da classe de modelo, para maior organização do projeto. Passamos a classe HomeViewModel para dentro da pasta Home, debaixo do diretório Models, conforme figura abaixo:

Novo namespace
Novo namespace

Se tentarmos rodar a aplicação nesse momento, vamos obter erro de compilação e o build vai falhar, já que o namespace referenciado na controller não mais possui a classe HomeViewModel:

Erro de compilação
Erro de compilação

Esse é o resultado esperado. O compilador nos ajuda a detectar esse tipo de erro básico e aponta onde está o problema.

Depois de corrigido o namespace no controller, ainda obteremos erro ao rodar a aplicação, dessa vez em tempo de execução:

Erro em tempo de execução
Erro em tempo de execução

 

Você vem me dizer que o código não compila em tempo de execução?
Você vem me dizer que o código não compila em tempo de execução?

Isso ocorre, pois não atualizamos a referência do namespace do modelo no código da view.

Seria muito mais eficiente se o compilador nos informasse desse erro em tempo de compilação, da mesma forma que ocorreu na controller. No ASP.NET MVC 5, é possível alterar a configuração do arquivo .csproj, de forma a forçar a pré renderização da view, de modo que o compilador avise de qualquer erro em tempo de compilação. Basta adicionar a tag abaixo no código do arquivo .csproj:

<MvcBuildViews>true</MvcBuildViews>

Mas em uma aplicação ASP.NET MVC 6, o arquivo de projeto mudou para o formato JSON e já não temos mais o recurso de pré compilação da forma que existia nas versões anteriores do framework, conforme mostrado acima. Como fazer agora?

Utilizando o RazorPreCompileModule

O ASP.NET 5, antes conhecido como vNext, traz consigo o novo compilador do C#, chamado Roslyn. Com ele, a Microsoft disponibilizou formas do desenvolvedor alterar o comportamento de compilação de uma aplicação, através de interfaces e classe abstratas que podem sem implementadas ou estendidas para adicionarmos comportamento customizado.

No nosso caso, vamos criar uma classe chamada PreCompilacaoRazor, que herda da classe abstrata RazorPreCompilaModule, que por sua vez implementa a interface ICompileModule. Essa classe será responsável por realizar a pré renderização das views da nossa aplicação:

Observe que não é necessário declarar o módulo de compilação no nosso código. Basta adicionar o código acima em qualquer ponto do projeto, que o Roslyn se encarrega de encontrar qualquer classe que implemente a interface ICompileModule para aplicar os seus módulos.

Ao adicionarmos essa classe na aplicação, obtemos o comportamento desejado. Agora, o Roslyn informa erro em tempo de compilação ao tentarmos rodar a aplicação com erro no código da view e o build falha:

Erro de compilação na view
Erro de compilação na view

Observação: Esse recurso não funciona com a versão beta 1 das dlls do ASP.NET 5. Já foram lançadas as versões beta 3 com a versão mais recente do Visual Studio 2015 CTP 14.0.22609.0 D14REL. Inclusive, o template padrão de uma aplicação ASP.NET MVC 6 já está incluindo a classe para efetuar a pré compilação das views Razor.

O novo modelo de compilação como serviço introduzido com o ASP.NET 5 permite diversos recursos interessantes para as aplicações baseadas no .Net Framework. Vale muito a pena ficar atento às novidades e entender melhor o funcionamento do Roslyn.

SHOW ME THE CODE!!

https://github.com/marcellalves/pre-compilacao-view-razor-asp-net-mvc-6

Para saber mais sobre o assunto, leia também:

http://www.strathweb.com/2014/12/razor-views-pre-compilation-asp-net-5-mvc-6/

Flush no ASP.NET MVC 6

Fazer o flush parcial do HTML gerado no servidor já é uma técnica bem conhecida, divulgada e recomendada no desenvolvimento de aplicações web de alta performance. Desde o ASP clássico até as versões mais recentes do .Net Framework, o recurso já estava presente, através do método Flush da classe Response.

Para facilitar o uso de flush em uma aplicação ASP.NET MVC de versão anterior à 6, podemos utilizar um pacote NuGet chamado Courtesy Flush. Para saber mais, recomendo a leitura do post do Scott Hanselman:

http://www.hanselman.com/blog/NuGetPackageOfTheWeekCourtesyFlushToFlushBuffersEarlierAndOptimizeTimeToFirstByte.aspx

Com a nova versão do Razor, que acompanha o ASP.NET MVC 6, fazer o flush parcial do conteúdo de uma view ficou ainda mais fácil.

Para exemplificar esse recurso na prática, vou utilizar a aplicação construída no post anterior, que é uma página estilo dashboard, com elementos que possuem um delay total de 3 segundos para processar.

Onde colocar o flush?

Para fazer uso efetivo do flush, é muito importante definir o local correto da chamada do método na aplicação. Segundo Steve Souders, autor dos clássicos livros sobre performance de aplicações web: High Performance Web Sites e Even Faster Web Sites, o flush deve ser colocado logo antes da execução de algum método de servidor que demore mais para responder, mas também deve trazer estrutura e recursos mínimos para que, pelo menos uma parte da página, possa ser renderizada e exibida para o usuário.

Seguindo essa diretiva, alterar a aplicação de exemplo utilizada no post passado, adicionando o novo recurso de flush parcial do Razor.

O primeiro passo é criar uma section chamada “corpoDaPagina”  no layout geral da aplicação:

Na página index, a chamada ao método FlushAsync fica logo antes da renderização das views parciais que possuem delay, dessa forma, todo o cabeçalho e os recursos referenciados no header da página são enviados para o navegador do usuário antes do processamento ser completado:

Notem a diferença no gráfico waterfall de renderização de cada uma das páginas:

Sem flush
Sem flush
Com flush
Com flush

Quando não utilizamos flush, a aplicação espera todo o processamento no servidor para carregar o css da página e do bootstrap. Quando usamos, esses recursos são carregados durante o processamento do lado do servidor, dando ao usuário uma sensação de que a página respondeu mais rápido à sua requisição, já que o cabeçalho é exibido rapidamente, antes do processamento pesado do lado do servidor ocorrer.

Esse é mais um recurso interessante para a melhoria do desempenho de uma aplicação ASP.NET MVC 6.

Aplicação de exemplo: http://razorasyncmvc6.azurewebsites.net

SHOW ME THE CODE!!

https://github.com/marcellalves/asp-net-mvc-6-razor-async

Para ampliar o conhecimento sobre esse assunto, leia também:

http://www.stevesouders.com/blog/2013/01/31/http-archive-adding-flush/

http://nikcodes.com/2014/03/04/flushing-in-asp-net-mvc/

http://nikcodes.com/2014/03/17/more-http-flushing-in-asp-net-mvc/

 

Views com métodos assíncronos em uma aplicação ASP.NET MVC 6

Continuando a série que explora a utilização de programação assíncrona para melhorar o desempenho de uma aplicação ASP.NET MVC, nesse post mostrarei como utilizar uma nova funcionalidade presente no ASP.NET MVC 6, que é a possibilidade de utilizar chamadas assíncronas dentro de uma view utilizando o Razor, que é a engine de renderização de HTML utilizada pelo framework.

Para contextualizar esse exemplo, é recomendado ler os posts anteriores da série:

http://www.dotnetflash.com.br/2015/01/melhorando-a-performance-percebida-com-views-parciais-assincronas/

http://www.dotnetflash.com.br/2015/01/utilizando-chamadas-assincronas-no-servidor-em-uma-aplicacao-asp-net-mvc/

No segundo post da série, implementei chamadas assíncronas para os métodos mais lentos, que causavam a queda do desempenho da aplicação. Vou utilizar essa mesma aplicação como base para exemplificar o uso de chamadas assíncronas dentro de uma view Razor.

Relembrando os métodos assíncronos utilizados para retornar as informações pesadas da view:

Para simular os métodos lentos, introduzi um atraso de 1 segundo na execução do RecuperarContasAPagarRecentesAsync() e 2 segundos no RecuperarLogsRecentesAsync(), utilizando o método Delay(Int32) da classe Task. Os métodos assíncronos em uma aplicação .Net retornam um objeto do tipo Task<TResult> e é justamente isso que vocês podem ver no exemplo de código acima. Implementamos os métodos lentos do nosso repositório de modo que eles retornem tasks a serem executadas quando a informação for necessária. Observe que não estamos utilizando a palavra reservada await para recuperar o resultado dos métodos assíncronos, e sim repassando as tarefas para as propriedades dos modelos das views:

Com essa nova implementação, só vamos utilizar o await para executar o resultado dos métodos dentro do código da view, conforme código abaixo:

A nova sintaxe do Razor nos permite fazer chamadas a métodos assíncronos dentro do código da view.

O ganho de desempenho utilizando essa técnica é de 30%, conforme mostra a tabela abaixo.

ViewTempo total de renderização da página
Com chamadas síncronas4,52 segundos
Com chamadas assíncronas3,17 segundos
Ganho de desempenho com chamadas assíncronas30%

Esse ganho de desempenho ocorre, pois a chamada de um método assíncrono utilizando a palavra reservada await não bloqueia a thread principal da aplicação, liberando-a para continuar a execução. No nosso exemplo, a view chama primeiro o método RecuperarContasAPagarRecentesAsync() e continua executando, até chamar o método RecuperarLogsRecentesAsync(). Com isso, o tempo de resposta melhora, pois uma função não fica esperando a outra terminar de executar para iniciar o seu processamento.

O modelo de programação assíncrona é uma tendência forte no mundo .Net e vemos que a Microsoft está cada vez mais incorporando esse paradigma dentro do framework, com o objetivo de facilitar e incentivar o uso. Vale a pena investir o seu tempo para dominar esse tipo de técnica, pois desempenho é um fator vital para qualquer aplicação.

Para ver uma demonstração ao vivo da aplicação, clique no link: http://razorasyncmvc6.azurewebsites.net

SHOW ME THE CODE!!

https://github.com/marcellalves/asp-net-mvc-6-razor-async

Para ampliar o conhecimento sobre esse assunto, leia também:

http://www.rodolfofadino.com.br/2014/11/asp-net-mvc-6-razor-com-suporte-ao-async-e-flush/

http://blog.stephencleary.com/2012/02/async-and-await.html (em inglês)

A Microsoft voltou a ser legal

A minha porta de entrada para o mundo da tecnologia foi através dos produtos e tecnologias da Microsoft. O DOS, as primeiras versões do Windows, o Visual Basic, o Office, o ASP e o FrontPage me fizeram interessar por computadores e programação. Durante a faculdade, tive contato com tecnologias de outros fabricantes, como o Turbo C e o Delphi da Borland, o Linux (distribuição RedHat), o Dreamweaver, nessa época ainda da Macromedia, mas comparados com os equivalentes da Microsoft, eles me pareciam complicados e menos amigáveis. Na minha visão, a Microsoft era a empresa que realmente estava levando a computação para as pessoas comuns, como eu. Ela de certa forma moldou a visão que carrego até hoje de que tecnologia não precisa ser algo complicado, e deve chegar a todo tipo de pessoa de forma amigável e confiável.

Claro que tinha uma grande dose de inocência nessa admiração que eu sentia pela Microsoft, e isso começou a ficar claro pra mim com o passar do tempo. A empresa foi acusada de monopólio, lançou produtos inacabados e desastrosos, como o Windows Millenium, não apoiava iniciativas de código livre, não seguia os padrões do W3C pra web e muitas outras atitudes que me fizeram perceber que a empresa não era tão legal assim.

O tempo passou e as coisas foram mundando no mundo da TI. Agora, a web era o futuro. Lembro como se fosse hoje a minha primeira busca no Google, lá nos idos de 1998. Poder acessar todo o conteúdo da internet com uma busca tão rápida quanto o piscar dos olhos mudou a nossa vida pra sempre. A internet tinha chegado para ficar e, pra mim, o Google foi a primeira empresa que realmente a entendeu. Dentro de pouco tempo vieram o Orkut, o Google Desktop Search, o Gmail, o Google Books, e muitos outros. Era uma empresa de perfil jovem, focada na web, extremamente inovadora, que tinha uma ética de trabalho totalmente diferente de tudo o que eu já havia visto, que dava 20% do tempo para os funcionários trabalharem em projetos próprios que acabavam virando produtos reais (Google News, Orkut). Rapidamente o Google se tornou para mim a empresa-de-tecnologia-mais-legal-de-todos-os-tempos.

Mas como tudo é cíclico, a dominância do Google também foi caindo ao longo do tempo, com acusações de quebra de privacidade, traindo o seu slogan: “Don’t be evil”. A empresa se tornou um colosso de proporções inimaginadas, e já não era mais tão inovadora como antes, lançando fracassos como o Google Buzz, o Wave (alguém lembra deles?) e o Google+.

Foi aí que surgiu o Facebook, a rede social criada em um dormitório de Harvard, por estudantes, e que estava destinada a mudar o mundo. De novo. Eu passei a admirar a empresa por causa da sua cultura hacker, de alto nível técnico. Eles representavam o que o Google representou no começo, com o seu perfil jovem e inovador. Se o Google tinha entendido a web 1.0, o Facebook estava definindo a internet moderna, em tempo real, social e dinâmica. Quando descobri que eles desenvolveram um interpretador PHP que compilava para C++, com o seu projeto Hip Hop, minha cabeça simplesmente explodiu e eles passaram a ser a minha nova empresa-de-tecnologia-mais-legal-de-todos-os-tempos.

Foi mais ou menos nessa época que a Apple renasceu pra mim. Não com o iPhone, e sim com o iPod. Pra mim, a Apple era a primeira empresa que tinha entendido que não adiantava brigar contra o conteúdo digital, e sim encontrar maneiras de lucrar com ele. O iPod era o meu sonho de consumo, era a minha caixinha infinita de música. Depois dele, entrei de cabeça no mundo da maçã: comprei um iPhone, uma Apple TV, um iPad, um Mac Book. Aprendi a desenvolver aplicativos nativos para iOS. A maneira como o ecossistema da Apple simplesmente funcionava entre si me fascinava. Além disso, percebi que os seus produtos realmente estavam conseguindo atingir usuários que não tinham tanta intimidade com a tecnologia. Depois desse tempo todo trabalhando com programação, foi a primeira vez que achei que a tecnologia realmente estava chegando às pessoas, de todos os tipos, de maneira amigável e confiável.

Depois da morte do Steve Jobs, veio um vácuo. Nenhuma empresa de tecnologia era mais tão legal assim. De modo geral, estavam todos trabalhando para aperfeiçoar o que já tinham.

E foi aí que veio a Microsoft de novo, correndo por fora. A primeira mostra que ela poderia voltar a ser legal, pra mim, foi o Kinect. Depois disso, ela abriu o código fonte de diversas partes do .Net Framework (e vem abrindo constantemente outras partes desde então), além de garantir que ele vai rodar em Linux e Mac. Também anunciou que o Windows 10 será uma atualização gratuita (alguém poderia imaginar Windows de graça há alguns anos atrás?), e agora, lançam o HoloLens:

A Microsoft não lançava nada que me empolgava tanto desde o primeiro Surface, de 2007:

Agora ela fez de novo. E volta oficialmente a ser a empresa-de-tecnologia-mais-legal-de-todos-os-tempos pra mim.

Utilizando chamadas assíncronas e paralelas para melhorar o desempenho de uma aplicação ASP.NET MVC

No post anterior, mostrei que o desempenho percebido pelo usuário pode ser melhorado através da renderização das views de forma assíncrona. Esse é um recurso de cliente muito útil e possui diversas aplicações, mas ele melhora muito pouco o tempo de resposta total da aplicação. Para conseguirmos um ganho real de desempenho, precisamos melhorar o tempo de resposta no lado do servidor, que é o principal ponto de lentidão da aplicação proposta. Para entender melhor o contexto desse artigo, sugiro a leitura do post anterior.

Um dos recursos que o .Net Framework oferece desde a versão 4.5 é a opção de trabalhar com métodos assíncronos, utilizando as palavras reservadas async e await. Esse tipo de função não bloqueia a thread principal do servidor web, que é rapidamente liberada para atender a outras requisições.  Quando termina de executar, esse tipo de método retorna um objeto do tipo Task<TResult>, que vai executar em uma thread que esteja disponível, podendo ser a thread que iniciou a execução ou não. Para maiores detalhes, sugiro a leitura desse artigo: http://www.asp.net/mvc/overview/performance/using-asynchronous-methods-in-aspnet-mvc-4.

Esse tipo de chamada permite melhorar a escalabilidade de uma aplicação, tornando-a capaz de receber mais requisições de usuário, o que melhora o tempo de resposta da aplicação de forma geral.

Vamos alterar a aplicação apresentada no post anterior, transformado os métodos lentos do repositório em assíncronos.

O método  RecuperarTodasContasAPagar fica assim:

O método RecuperarTodosLogs fica assim:

Para chamar os novos métodos assíncronos, precisamos tornar a action do controller assíncrona. Observe que é necessário utilizar a palavra reservada await nas chamadas:

Testando o desempenho da versão assíncrona, percebemos que o tempo de resposta é praticamente o mesmo da versão síncrona:

Versão síncrona executou em 3010 milissegundos
Versão síncrona executou em 3010 milissegundos
Versão assíncrona executou em 3001 milissegundos
Versão assíncrona executou em 3001 milissegundos
ActionsTempo Execução em Milissegundos
Síncrona3010
Assíncrona3001
Ganho porcentual de performance0,30%

O ganho de performance obtido ao mudar os métodos lentos para assíncrono foi de menos de 1%. Podemos perceber, dessa forma, que chamadas assíncronas permitem um ganho de tempo de resposta para aplicações com muitos usuários simultâneos concorrendo por recursos do servidor. O nosso cenário é um pouco diferente, estamos focados em melhorar o tempo de resposta para cada usuário. A aplicação tem poucos acessos concorrentes e o uso de async/await não melhorou muito nesse cenário. Para conseguirmos um ganho mais expressivo de desempenho, precisamos utilizar um outro recurso oferecido pelo .Net Framework, que é a execução em paralelo de métodos síncronos. Essa funcionalidade é fornecida através da classe Parallel, com o seu método Invoke. Dessa forma, continuaremos utilizando os métodos originais, síncronos. O que muda é que agora eles executarão em paralelo na action da controller: Um ponto interessante é que o método Invoke da classe Parallel é um helper, que utiliza o método WaitAll da classe Task. Abaixo, um exemplo de como a chamada acima poderia ser escrita utilizando WaitAll:

O Elemar Jr escreveu uma série de posts sobre programação assíncrona e paralela utilizando C#, vale a pena conferir: http://elemarjr.net/2011/09/07/paralelismo-em-mtodos-sncronos/http://elemarjr.net/2011/08/13/classe-task-alguns-exemplos/.

Executando a aplicação com a action paralela, percebemos um ganho efetivo de desempenho em relação à versão original:

Utilizando chamadas paralelas, obtemos ganho real de desempenho.
Utilizando chamadas paralelas, obtemos ganho real de desempenho.
ActionsTempo Execução em Milissegundos
Síncrona3010
Assíncrona3001
Paralela2013
Ganho porcentual de performance33,12%

Utilizando métodos síncronos executados de forma paralela, conseguimos um ganho de desempenho de 33% no servidor.

A partir desses exemplos, podemos concluir que o .Net Framework apresenta diversas opções de melhoria de desempenho e escalabilidade de uma aplicação. Porém, é necessário conhecer os detalhes de cada uma delas para poder avaliar e decidir qual é a melhor opção para atingir os objetivos específicos que você procura para o seu caso de uso.

Demonstração funcional da aplicação:

Action com chamadas assíncronas: http://viewassincronasaspnetmvc.azurewebsites.net/Home/IndexAsync

Action com execução paralela: http://viewassincronasaspnetmvc.azurewebsites.net/Home/IndexParallel

Código da aplicação: https://github.com/marcellalves/viewsparciaisassincronasASPNETMVC

Melhorando a performance percebida com views parciais assíncronas

A velocidade é um dos principais fatores de sucesso de uma aplicação web. Os usuários buscam uma experiência semelhante à que eles encontram em aplicativos nativos para smartphone ou serviços que utilizam tecnologia de ponta, como Facebook, Google e Twitter. Atender às expectativas de um público cada vez mais exigente é um desafio constante para os desenvolvedores web.

O desempenho de uma aplicação é um fator tão relevante que o Google estima que cada 0,5 segundo extra na renderização de uma página de resultado de pesquisa causa uma queda de 20% na audiência. A Amazon calcula que cada 100 milissegundos de latência custam 1% de prejuízo nas vendas.

Fonte: http://highscalability.com/blog/2009/7/25/latency-is-everywhere-and-it-costs-you-sales-how-to-crush-it.html (em inglês)

Nesse post, apresentarei uma técnica interessante para melhorar a performance percebida pelo usuário em uma aplicação ASP.NET MVC. Com ela, fazemos uso de views parciais para renderizar um layout de maneira assíncrona. Importante notar que essa técnica melhora a performance percebida pelo usuário, mas não substitui otimizações do lado do servidor. No cenário apresentado, a página responde mais rápido para o usuário, mas o tempo total de carregamento da página é praticamente o mesmo.

O cenário que vou expor é de uma página no estilo painel, com diversas áreas que trazem informações diferentes, como a do iGoogle Portal. Essa aplicação de exemplo é a página inicial de um sistema financeiro, que mostra as últimas 5 transações de contas a pagar e a receber e uma lista com os últimos 10 logs de evento gerados pelo sistema:

Tela inicial
Clique para ampliar

Cada um dos painéis possui a sua própria origem de dados. Ocorre que por motivos de processamento interno, as fontes de dados de contas a pagar e logs demoram para serem recuperadas, fazendo com que o carregamento inicial da página fique lento. Dessa forma, a página inicial e o painel de contas a pagar, que são rápidos, demoram a aparecer devido à lentidão dos outros dois painéis.

Ao executarmos a aplicação com renderização da página inicial de forma síncrona, obtemos o seguinte resultado:

Desempenho síncrono
Clique para ampliar

O tempo total de carregamento da página é de 3,97 segundos, suficiente para tirar a paciência de qualquer usuário. Observe que o gargalo maior se encontra no tempo que o servidor demora para enviar os dados para a aplicação: 3,21 segundos, 98% do tempo total.

Agora, é hora de aplicar a técnica proposta. A estratégia é simples: vamos carregar primeiro a página inicial e o painel de contas a receber, que são rápidos, e delegar o carregamento dos painéis lentos de contas a pagar e log para chamadas AJAX, que são naturalmente assíncronas. Além disso, vamos obter um benefício adicional ao executar as duas requisições de forma paralela.

Para atingir esse objetivo, precisamos alterar a página inicial. Antes, ela renderizava as views parciais de forma síncrona:

Agora, vamos criar divs que funcionarão como marcadores para o carregamento das informações. Elas foram marcadas com a classe css “conteudoParcial”, para serem referenciadas pelo código jQuery. Além disso, fazemos uso do atributo customizado “data-url”, para armazenar o endereço da fonte de dados da view parcial. Esse é um recurso muito útil introduzido na especificação do HTML 5, para armazenamento de informações customizadas em elementos de marcação. Mais detalhes nesse link (em inglês). Por fim, adicionamos um gif de load para dar um retorno para o usuário quanto ao carregamento dos painéis:

jQuery necessário para executar o carregamento assíncrono das views parciais:

Também foi necessário alterar o controller da página, criando actions separadas para a página inicial / painel de contas a receber e para os outros dois painéis (contas a pagar e logs):

Depois de aplicadas as alterações, percebemos um ganho substancial no tempo de resposta da página:

Desempenho assíncrono
Clique para ampliar

Agora, o tempo total de carregamento inicial é de 1,29 segundo, um ganho de 68% em relação ao anterior. Esse é o novo desempenho percebido pelo usuário no tempo de resposta da aplicação, mesmo que as requisições dos outros painéis continuem demorando um pouco mais para aparecer na tela.

Concluindo: é possível aplicar técnicas no cliente para melhorar a performance percebida pelo usuário em uma aplicação ASP.NET MVC. Esse exemplo poderia ficar ainda melhor se trabalhássemos o lado do servidor, tornando a recuperação das informações necessárias para a página mais ágil. Isso poderia ser conseguido através de chamadas assíncronas dos métodos de recuperação dos dados e será o tema do próximo post. Fique ligado!

Aplicação de exemplo:

Síncrono: http://viewassincronasaspnetmvc.azurewebsites.net/

Assíncrono: http://viewassincronasaspnetmvc.azurewebsites.net/Assincrono

Código da aplicação: https://github.com/marcellalves/viewsparciaisassincronasASPNETMVC.

Layouts e sections aninhados em uma aplicação ASP.NET MVC 5

Alguns detalhes de layout em uma aplicação ASP.NET MVC podem ser desafiadores, especialmente quando se trata de algum site com uma estrutura um pouco mais complexa, que possua layouts aninhados.

Um dos problemas que podem surgir em aplicações desse tipo é como adicionar um JavaScript específico para uma sub página respeitando a diretiva de adicionar os scripts no final do código HTML da página, logo antes do fechamento da tag body.

Ao criarmos uma nova aplicação ASP.NET MVC utilizando o layout fornecido pelo Visual Studio, obtemos uma página de layout padrão, chamada _Layout.cshtml. Nela, existe uma section chamada “scripts”, conforme mostra a imagem abaixo, que é renderizada logo antes do fechamento da tag body do HTML da página.

Scripts Section
Scripts Section

É importante concentrar a escrita de scripts específicos de página nessa section, pois dessa forma o código JavaScript da página fica centralizado em um local específico, sendo mais fácil de localizar e de manter. Além disso, temos a garantia de que todos os arquivos de script incluídos na página foram carregados antes da execução do JavaScript específico da página, evitando erros devido a falta de referência.

Vamos a um exemplo prático. Suponha que temos uma aplicação que possui o seu layout padrão, _Layout.cshtml. Essa página de layout possui a section “scripts”. Além da página de layout padrão, também temos a necessidade de criar uma outra página de layout, que vai herdar os estilos da _Layout.cshtml, mas também vai adicionar elementos específicos. Vamos chamar essa página de _LayoutCustomizado.cshtml. Agora imagine que temos duas páginas que precisam utilizar esse layout customizado: Pagina1.cshtml e Pagina2.cshtml. A página 1 está ok, funciona corretamente, mas a página 2 possui um campo que utiliza o componente Date Picker, do jQuery UI. Como poderíamos fazer isso? Poderíamos adicionar o script diretamente no corpo da página, conforme imagem abaixo:

Script
Script no corpo da página.

Ao tentarmos executar a página, algo inesperado acontece. O Date Picker não funciona, pois ele depende do arquivo do jQuery UI referenciado pela _Layout.cshtml, só que esse arquivo ainda não foi carregado, pois a sua referência está localizada algumas linhas abaixo  da tag <script> que adicionamos na página 2:

Script2
Script no corpo da página não funciona. Clique para ver maior.

Ou seja, precisamos adicionar essa tag script na section “scripts”. Só que há outro problema aqui: a Pagina2.cshtml não herda diretamente da _Layout.cshtml, que contém a section “scripts”, e sim da _LayoutCustomizado.cshtml. Se tentarmos renderizar a section “scripts” na página 2, obteremos um erro em tempo de execução:

Script3
Erro em tempo de execução por falta de definição de section na página.

Como resolver esse problema? Adicionando a section “scripts” na página _LayoutCustomizado.cshtml, conforme imagem abaixo:

Script4
Redefinindo a section “scripts”

O “pulo do gato” aqui é que estamos redefinindo a section “scripts” da _Layout.cshtml dentro da _LayoutCustomizado.cshtml.

Dessa forma, ao rodar a aplicação, a página 2 funciona corretamente, exibindo o Date Picker:

 Script5
jQuery UI Date Picker funcionando corretamente. Clique para ver maior.

É uma solução simples, mas não tão óbvia assim. O código de exemplo se encontra no GitHub.

Por que blogar?

A internet é uma fonte de informação valiosíssima para os desenvolvedores, todos sabem disso. Fóruns de discussão, Stack Overflow, blogs, documentações técnicas, etc, já me ajudaram de inúmeras formas ao longo da minha carreira. Com o passar do tempo, à medida que fui adquirindo experiência, essa posição de apenas consumir conteúdo técnico gerado por outras pessoas começou a me incomodar um pouco. Eu queria entrar no clube dos geradores de conteúdo, queria utilizar a minha experiência no mercado para ajudar outros desenvolvedores, assim como fui e ainda sou ajudado por pessoas que, generosamente, utilizaram o seu tempo para disponibilizar informações valiosas de forma gratuita para quem quiser consultar.

Esse projeto foi consistentemente sendo posto em segundo plano, por diversos motivos, mas o principal deles era a clássica falta de tempo. Outro impeditivo era uma certa insegurança em relação a escrever, eu sempre achava que não estava pronto, que tinha que evoluir mais na área… Resumindo: eu estava sofrendo da síndrome do impostor.

No final de 2014, resolvi que tinha que sair da inércia e estabeleci um contrato interno: fazer um blog focado em tecnologia em 2015 e postar com regularidade.

Estou colocando todo esse contexto, pois acredito que vários desenvolvedores já cogitaram contribuir com a comunidade de alguma maneira, mas acabaram esbarrando nas mesmas dificuldades que eu. Portanto, a minha dica para todos os que estão nessa situação é: comece. O mais rápido possível. Não importa se você acha que não sabe escrever bem, não importa se você acha que ainda não tem o conhecimento técnico necessário, não importa se você pensa que não tem tempo. O ato de começar a fazer vai te obrigar a encarar essas barreiras como problemas a serem resolvidos e com esse mindset, você vai acabar percebendo que quando existe vontade (ou um deadline) conseguimos encontrar soluções para problemas que antes pareciam insolúveis.

Coincidência ou não, tomei conhecimento do blog http://simpleprogrammer.com, escrito pelo John Sonmez, mais ou menos nessa época e comecei a seguir seus posts desde então. E foi aí que descobri um curso gratuito e por e-mail que ele estava oferecendo, sobre como promover a sua carreira como desenvolvedor através da criação de um blog. O curso é bastante prático e direto ao assunto, de desenvolvedor para desenvolvedor. Ele aborda os principais pontos a serem considerados ao decidir fazer um blog sobre desenvolvimento, desde a escolha de um tema, dicas para manter a consistência de postagens, técnicas para se manter tendo assuntos para posts, como gerar tráfego para o seu blog e até mesmo dicas de WordPress.

Me inscrevi e desde então estou trabalhando no meu mais novo blog de tecnologia. Se você está lendo isso, grande parte da motivação surgiu desse curso. Ele é em inglês, mas acredito sinceramente que todo desenvolvedor deveria investir em ser fluente pelo menos na leitura em inglês. Mais sobre isso em algum post futuro.

É isso. Espero que esse post ajude alguém a dar o pontapé inicial no sentido de criar um blog e contribuir de alguma forma para a comunidade de desenvolvimento. Até breve!