Introdução
Conforme já tínhamos apresentado em artigo anterior, a tecnologia ASP.NET MVC foi introduzida pela Microsoft, na Framework .NET, em 2009.
Se repararmos, nos últimos anos, o foco da Microsoft tem sido o MVC, MVC e MVC. Então a questão que se coloca é porque razão a Microsoft está tão interessada em abandonar uma tecnologia bem sucedida como as ASP.NET Web Forms e persuadir a comunidade de desenvolvimento Web a adoptar o ASP.NET MVC?
Não me interpretem mal, existem milhares e milhares de aplicações baseadas em ASP.NET Web Forms que necessitam de suporte e evolução e esta tecnologia continua a existir no ecossistema da Framework .NET. Continuamos a poder criar novas aplicações baseadas em Web Forms. A questão é perceber se esta continua a ser a melhor opção.
Conteúdo
Desambiguação
Antes de iniciarmos a abordagem ao tema proposto, convém fazer uma pequena desambiguação. Para muitos programadores, o ASP.NET é diferente do MVC, o ASP.NET é uma tecnologia antiga, enquanto o MVC é a novidade. Não é bem assim, o ASP.NET e o MVC não são coisas distintas. O MVC faz parte do ASP.NET.
O ASP.NET é a framework Web da Microsoft. O MVC é um modelo de programação, construído em cima do ASP.NET. O que podemos classificar como antigo, em relação ao MVC, é o modelo de programação das Web Forms.
Podemos confirmar esta situação ao criar uma nova Aplicação Web no Visual Studio:
As Web Forms e o MVC são apresentados como dois modelos (templates) de desenvolvimento de uma aplicação ASP.NET.
A vitória das ASP.NET Web Forms
Uma das principais razões para a rápida adopção do ASP.NET foi, sem dúvida, o facto de se tratar de uma abordagem RAD ao desenvolvimento Web. Com as Web Forms, a Microsoft, basicamente, estendeu o modelo de programação do Visual Basic, para a Web, permitindo a utilização de técnicas de drang-and-drop e de point-and-click, comuns no desenvolvimento para Windows. O modelo das Web Forms abstraía uma série de funcionalidades para apresentar uma simulação do modelo stateful (com estado) do Windows, aos programadores Web. Como resultado, não é necessário ser um especialista, com um profundo conhecimento de HTML e Javascript, para conseguir criar aplicações Web eficazes.
Podemos resumir algumas das vantagens das ASP.NET Web Forms:
Controlos Servidor ricos
Quando se trabalha com HTML puro, as coisas não são sempre as mesmas em todos os lugares, como já deve ter notado. Um UI que parece óptimo no IE pode ficar distorcido no Firefox ou vice-versa.
Um controlo de servidor ASP.NET detecta o navegador Web e gera o HTML adequado e, se necessário, Javascript também.
Muitos controlos de servidor como o GridView e o ListView possuem recursos de data-binding, que permitem a redução de muitos esforços e a escrita de muito código.
Suporte de ViewState
Já deve ter lido várias vezes que "o HTTP é um protocolo sem estado (stateless)". Os controlos não mantém os seus valores entre Requests. Para simular a programação stateful, as Web Forms introduziram funcionalidades como o viewstate e postbacks. O último estado conhecido de todos os controlos é guardado na própria página, na forma de um campo oculto chamado ViewState.
O code-behind
Quando está a desenvolver uma aplicação web, o programador faz drag-and-drop dos controlos no designer da form e o Visual Studio cria o código por trás (code-behind). Enquanto o programador ajusta visualmente o layout da web form, actuando no ficheiro aspx, o código é colocado numa classe parcial, num ficheiro aspx.cs (ou aspx.vb).
Estes ficheiros de code-beind foram a chave para o sucesso do desenvolvimento e entregas mais rápidas das aplicações baseadas em ASP.NET Web Forms. Os programadores puderam-se abstrair de muitos detalhes técnicos, como eventos, protocolo HTTP, POST, GET, gestão de sessão, etc.
Programação baseada em Eventos
Com a ajuda de:
-
code-behind
-
Mecanismo de postback (fazer
post de volta à mesma página)
-
ViewState
a Microsoft introduziu a programação baseada em eventos (event-driven) no mundo da Internet.
O programador já não necessita usar métodos POST e GET para lidar com as interações do utilizador com o servidor. Basta arrastar um controlo (p.ex. um botão) para a página, clicar duas vezes sobre o mesmo e é gerado um bloco de código para a manipulação do evento clique no servidor.
Eram precisamente estas características que, anos antes, os programadores de páginas ASP procuravam. Além disso, as ASP.NET Web Forms até conseguiram superar essas expectativas, fornecendo uma camada de abstração total em cima de toda a pilha Web: Javascript, CSS, HTML.
Menor esforço de aprendizagem
Com a utilização de controlos de servidor ricos, o ViewState e eventos, conforme já afirmamos acima, não é necessário ser um especialista, com um profundo conhecimento de HTML e Javascript, para conseguir criar aplicações web eficazes.
Os problemas das ASP.NET Web Forms
Já vimos que o code-behind foi a principal razão do sucesso das Web Forms, mas a forma como é posicionado e invocado, provoca alguns problemas sérios. Vamos então analisar alguns destes problemas e depois vamos ver como a evolução para o MVC ajuda a lidar com os mesmos.
Arquitectura do projecto
Não existe uma Arquitectura de Projecto predefinida para aplicações Web baseadas em Web Forms. Os programadores têm total flexibilidade para escolher a sua própria arquitectura.
Pode-se usar a arquitectura base de 3 camadas, dividindo o sistema em UI, Camada de Negócio e Camada de Acesso a Dados ou um modelo mais avançado como o Model-View-Presenter. Mas muitos programadores acabam por escolher usar apenas o code-behind e escrevem lá todo o código da aplicação, o que não é de todo considerado uma boa prática. O code-behind está fortemente acoplado ao UI, acabando sempre por ter uma lógica de apresentação e não de negócio ou acesso a dados.
Solução baseada em Views (view-based) para requisitos baseados em Acções
Os websites existem para os utilizadores finais. Os utilizadores chegam a um website com um propósito específico e comunicam esse propósito por acções. P.ex., numa rede social, o utilizador comunica os seus propósitos através de acções como:
-
Partilhar imagem
-
Escrever comentário
-
Enviar mensagem
Estas acções são comunicadas através de cliques do rato, ou do URL no browser. Devido a esta estrutura baseada em acções, foi escolhido o protocolo HTTP para a Web, porque tem acções como GET, POST, PUT, DELETE, etc. que comunicam as intenções do utilizador de uma forma mais clara. Se conseguirmos mapear estas acções para métodos ou funções do nosso programa, faz mais sentido e mantém a arquitectura mais simples.
Mas as ASP.NET Web Forms tinham um problema, queriam manter o conceito RAD, implementado através da programação visual e por isso acabaram por oferecer uma solução baseada em Views (view-based), para uma estrutura baseada em Acções (action-based).
A arquitectura, em si, não está adaptada, do ponto de vista lógico, à abordagem baseada em acções, do utilizador final. Dito de outra forma, se um utilizador envia uma acção “Compra”, primeiro ela chega a uma view como “Loja.aspx” que, por sua vez, chama a “Loja.aspx.cs”, que executa um ciclo complexo (page life cycle) que, finalmente, executa a acção que responde ao pedido do utilizador.
Isto é bastante confuso. Os pedidos são mapeados para uma acção real apenas depois de se completar um complexo ciclo da página.
Efeitos secundários de uma má arquitectura – Alto Acoplamento Quando se começa com uma arquitectura incorrecta, acaba-se por fazer ajustes que vão provocar efeitos secundários graves. É o que acontece neste caso. O code-behind que pode parecer ser fisicamente diferente, colocado num ficheiro à parte, nunca foi, na verdade, desacoplado, i.e. o ficheiro aspx.cs (ou aspx.vb) nunca pode ser separado do respectivo ficheiro aspx.
Por outras palavras, não é fácil anexar o código “Cliente.aspx.cs” à view “DetalhesCliente.aspx”. O code-behind está intimamente ligado à view. Não é reutilizável.
O HTML não é o único tipo de resposta
Por causa da forte ligação entre a view e o code-behind, até mesmo o tipo de resposta é fixo nas Web Forms – HTML por defeito. Se desejar alterar o tipo de resposta, terá que lidar com tipos de conteúdo e métodos "Response.End", o que é complexo e trabalhoso.
Combinação de View e dados
Quando enviamos uma resposta a um utilizador, esta é uma combinação de view (display) e de dados (modelo). Como as Web Forms são uma arquitectura view-first, é a view que vai decidir qual o modelo a conectar, o que a torna pouco flexível, para além de estarmos a envolver a view em tomadas de decisão complexas. Isto viola claramente o princípio SRP (SOLID) (pode ler mais sobre os Princípios SOLID aqui).
Fazer do code-behind uma classe normal para Testes Unitários O code-behind de uma Web Form é tipicamente uma classe parcial volumosa e pesada, que não pode ser instanciada através de código simples. Lembre-se que o ecran da Web Form herda da classe "System.Web.UI.Page". Esta classe de página não podem ser criada diretamente, pois tem muitas dependências.
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
public void Button1_Click(object sender, EventArgs e)
{
Session["SomeSession"] = "Is this set";
}
}
Podemos agora perguntar por que razão queremos instanciar directamente esta classe de página. Bem, um lugar onde eu gostaria de a instanciar seria para realizar Testes Unitários. Gostaria de invocar as acções do método Click do botão e testar se as variáveis de sessão são definidas correctamente, se o estado da view está correcto, etc.
Mas se tentar criar um método de teste para esta classe, vai acabar com um código semelhante ao mostrado abaixo.
[TestMethod]
public void TestMethod1()
{
WebApplication1.WebForm1 obj = new WebApplication1.WebForm1();
obj.Button1_Click(this, new EventArgs());
}
Para além de ser um pouco estranho, quando o código do teste for invocado vai pedir mais coisas e gerar erros que tornam os testes unitários do UI impossíveis de realizar.
Performance
O ViewState é uma solução para alguns dos problemas das ASP clássicas, mas também se torna um problema em si próprio. O ViewState é armazenado na própria página pelo que tem que ser passado do cliente para o servidor e de novo do servidor para o cliente em cada acção de GET ou POST. Estamos a passar mais e mais dados, o que provoca uma visível degradação da performance.
Menor controlo sobre o HTML gerado
Nas Web Forms, muitas vezes não sabemos exactamente que HTML é gerado, tornando a integração com frameworks Javascript, como o jQuery, numa tarefa difícil.
SEO (Search Engine Optimization)
Os URLs apontam para páginas ASPX fixas que podem ainda ser decoradas com uma string de consulta. Eles não são, obviamente, user-friendly e afetam o SEO.
Desenvolvimento paralelo
A página ASPX está intimamente ligada ao code-behind. Logo não é possível ter dois programadores diferentes a trabalhar na mesma secção (um no aspx e o outro no code-behind) em simultâneo.
ASP.NET 4.0
Em 2010, a Microsoft lançou a nova versão ASP.NET 4.0, que inclui algumas boas características para superar alguns dos problemas acima:
-
ViewState: permite desabilitar ou controlar o tamanho do ViewState (mas não há nenhuma regra ou obrigatoriedade de o fazer);
-
URL Routing: passamos a poder fornecer o nosso próprio URL em vez do caminho físico da página;
-
ID: No ASP.NET 4.0 temos maior controlo sobre o Id dos elementos e, assim, a integração com uma framework Javascript tornar-se mais fácil. (mas ainda não temos o controlo completo sobre HTML que é gerado).
Mesmo após a evolução das características revolucionárias do ASP.NET:
-
Ainda não foi possível resolver os problemas com os Testes Unitários;
-
É quase impossível encontrar um programador de ASP.NET Web Forms que tenha desabilitado o ViewState;
-
Temos algum controlo sobre o Id dos elementos, mas não o controlo completo sobre o HTML gerado, mantendo-se o problema de implementar Javascript.
As vantagens do ASP.NET MVC
O ASP.NET MVC é mais uma framework de desenvolvimento Web da Microsoft, desenhada com a separação de conceitos e testabilidade em mente. Está construída sobre o CLR e completamente baseada no Padrão MVC. Por isso pensamos em termos de controladores e views.
O ASP.NET MVC não tem suporte para ViewState nem controlos de servidor, de modo que se sente um pouco da “velha” Web por aqui.
Vejamos algumas das vantagens do ASP.NET MVC:
Arquitectura do projecto
Uma das grandes vantagens de usar ASP.NET MVC é que impõe a separação de conceitos. Portanto, há muito menos hipóteses de tornar as coisas demasiado complexas ou fortemente acopladas.
Solução baseada em Acções (action-first)
Como vimos anteriormente, as Web Forms implementam uma arquitectura baseada em Views (view-first). Então como podemos transformá-la numa arquitectura orientada por acções em vez de orientada por views?
Que tal chamar primeiro a Acção e depois a acção escolhe a view? Faria com que o fluxo fosse mais lógico e claro. Isto é exactamente o que a arquitectura do MVC faz. A primeira chamada chega a uma Acção, que pertence a um Controlador e o controlador chama a View com o Modelo apropriado.
Baixo Acoplamento
A nossa arquitectura baseada em acções, permite-nos reutilizar o código duma acção em diferentes views. Por exemplo, se um utilizador enviar a acção “Display”, pode ser exibida a view “DispalyDesktop.aspx” ou a view “DisplayMobile.aspx”, dependendo do tipo de dispositivo usado.
Assim, na acção MVC, dependendo da situação, podemos invocar a "MobileView" ou "DesktopView". Abaixo está um pequeno exemplo de código que ilustra este exemplo. Agora podemos tentar imaginar conseguir o mesmo efeito, directamente, no code-behind das Web Forms. Difícil, muito difícil mesmo.
public ActionResult Index(string deviceType)
{
if (deviceType == "Mobile")
{
return View("Mobile");
}
else
{
return View("Desktop");
}
}
O HTML não é o único tipo de resposta
Ao usarmos uma estrutura action-first, então a acção pode dar-se ao luxo de decidir que tipo de tipo de resposta deve produzir. Isto torna o nosso sistema mais flexível em termos de uma mesma acção com diferentes outputs.
Abaixo está mais um pequeno exemplo de uma ação MVC, que envia um resultado JSON ou HTML, dependendo do valor do parâmetro. Este tipo de flexibilidade é difícil de conseguir com nas Web Forms, porque forma desenhadas para retornar apenas HTML.
public ActionResult Index(string viewType)
{
if (viewType == "JSON")
{
return Json(new Customer(), JsonRequestBehavior.AllowGet);
}
else
{
return View("DisplayCustomer", new Customer());
}
}
Combinação de View e dados
Numa arquitectura action-first, o pedido chega primeiro à acção e esta escolhe a view e o modelo para retornar diferentes respostas.
Vejamos mais um pequeno exemplo em que uma acção MVC usa o mesmo modelo anexado a diferentes views. Neste exemplo, temos o modelo "CustomerData” que é anexado à view “DetailCustomer”, mas que noutra situação é anexado à view “Customer”.
public ActionResult Index(string ViewName, Customer customerdata)
{
if (ViewName == "Detailed")
{
return View("DetailCustomer", customerdata);
}
else
{
return View("Customer", customerdata);
}
}
Este tipo de flexibilidade é muito difícil de alcançar através das Web Forms, porque a invocação do modelo está na própria view. Em seguida, é necessário escrever toda a lógica de decisão dentro do ciclo de vida da página e finalmente redirecionar para outra view, tornando a implementação muito pouco clara.
Testabilidade
No caso do MVC, um Controller é uma classe normal. Uma classe que pode ser instanciada num projecto de testes unitários simples, onde se podem facilmente testar vários aspectos, como a sessão, ViewBag, TempData, etc. Os controladores não estão acoplados a qualquer view específica, por isso pode ser reutilizados para realizar os testes necessários.
public class HomeController : Controller
{
public ActionResult Index()
{
Session["SomeSession"] = "Is this set";
return View("SomeView");
}
}
Performance
O ASP.NET MVC não tem suporte para o ViewState, de modo que não haverá qualquer gestão automática do estado, o que reduz o tamanho da página permitindo assim aumentar a performance.
Total controlo sobre o HTML
O ASP.NET MVC não suporta controlos de servidor. A única opção disponível é usar controlos de input do HTML, por isso sabemos exactamente que HTML vai ser gerado no final. Também vamos estar cientes sobre o Id de cada elemento. E assim a integração com bibliotecas Javascript, como o jQuery, torna-se bastante fácil.
SEO, URL Routing e REST
Fortes recursos de roteamento permitem tratar cada URL como um recurso com suporte a interfaces RESTful. Para além disso, são user-friendly e melhoram o SEO.
Desenvolvimento paralelo
No ASP.NET MVC as camadas têm baixo acoplamento entre si, pelo que um programador pode trabalhar num controlador, ao mesmo tempo que outro trabalha na View e um terceiro desenvolve o modelo. Tudo em simultâneo. É isto o chamado desenvolvimento paralelo.
Extensibilidade
O ASP.NET MVC suporta múltiplos motores de views, como o ASPX ou o Razor e, se necessário, podemos criar o nosso próprio motor.
Recursos ASP.NET existentes
O ASP.NET MVC é construído em cima da framework ASP.NET e, portanto, fornece ao programador a utilização de muitas características boas, como a autenticação de formulários, a autenticação do Windows, cache de sessão, etc.
A solução ASP.NET MVC
Para mudar de uma arquitetura baseada em views para uma arquitectura baseada em acções MVC, é necessário fazer algumas alterações estruturais.
A figura acima dá uma ideia dessas alterações:
-
Mover o code-behind para uma classe do tipo Controller, convertendo os eventos em métodos to tipo Action;
-
A Middle-layer ou Camada de Negócio transforma-se no Model, que fornece dados e aplica lógica e regras;
-
A View só faz a exibição, posicionamento e layout dos dados;
-
A DAL e outras camadas não mudam muito, já que não têm uma grande ligação com a questão do code-behind, diretamente.
Assim, com a arquitetura MVC temos o seguinte fluxo de três etapas:
-
O utilizador final envia um Request. A aplicação direciona o Request para o controlador. O controlador é uma unidade lógica que agrupa um conjunto de acções;
-
O controlador mapeia o Request para uma acção particular;
-
Agora a ação tem duas tarefas para realizar, primeiro necessita obter os dados apropriados e de seguida esses dados têm que ser ligados à view adequada. A Acção cria o objeto do modelo e liga o modelo à view, para enviar a resposta final.
O que perdemos?
A maior vantagem das ASP.NET Web Forms é o RAD / Programação Visual. Mesmo que seja uma forma mais “suja” de fazer as coisas, pode ajudá-lo a completar as aplicações mais rapidamente e satisfazer os clientes num mais curto espaço de tempo. Mas esta rapidez tem um preço a longo prazo.
Outra questão é que o ASP.NET MVC tem uma maior curva de aprendizagem. A ausência de ViewState e dum modelo de programação orientado por eventos torna o ASP.NET MVC um pouco difícil para os programadores com pouca ou nenhuma experiência em desenvolvimento de aplicações Web.
Conclusões
A grande questão que se coloca sempre nestas alturas é quando e porque devemos utilizar determinada tecnologia em detrimento de outra.
Existem dois factores que determinam de imediato a escolha da tecnologia a usar:
-
Se é fundamental entregar um resultado muito rapidamente, então as Web Forms são a única opção, uma vez que nem se pode sequer considerar o ASP.NET MVC para RAD (as razões para necessitar de RAD podem estar relacionadas com o cliente estar a pagar pouco pelo projecto, ou a aplicação vir a ser usada apenas durante poucos meses e não exigir muita manutenção);
-
Se a testabilidade da aplicação, em particular Testes Unitários, for fundamental, então a única opção é mesmo o MVC.
Para além destas razões, a sugestão é dar prioridade à utilização do ASP.NET MVC. É uma evolução da framework ASP.NET, resolve a maioria dos problemas identificados nas Web Forms, permite uma grande testabilidade das aplicações e óbvios ganhos a longo prazo em termos de manutenção. Podem-se ainda ponderar os seguintes factores:
-
A equipa de desenvolvimento tem uma boa experiência de Web Forms e Windows Forms? Então deve-se levar em conta a curva de aprendizagem do MVC e a disponibilidade (mental e de tempo) da equipa para efectuar a transição. Poderá optar-se por manter as Web Forms em detrimento do MVC, mas com os custos e problemas anteriormente identificados;
-
A equipa tem experiência em ASP ou em tecnologias não-Microsoft, como Android, iOS, JSP, Ruby, PHP? Este tipo de tecnologias costuma usar a arquitectura MVC por defeito, pelo que será um passo natural usar o ASP.NET MVC;
-
O JavaScript vai ser amplamente usado? Mais uma vantagem para o MVC;
-
A performance é um factor importante? O MVC, sem o suporte para o ViewState oferece um bom ganho de desempenho em relação às Web Forms;
-
Prevê-se a reutilização da mesma lógica de input? Usar o MVC, sem dúvida.
Como resumo final, podemos dizer que as ASP.NET Web Forms foram o caminho correcto para a Microsoft em 2000. O objectivo era atrair os programadores de VB6, VF e VC++, que eram viciados em programação RAD. As Web Forms atingiram o seu objectivo, mas agora está na hora de evoluir e avançar na direcção de uma melhor arquitectura, ou seja o MVC.
Referências
http://msdn.microsoft.com/en-us/magazine/dd942833.aspx#id0080030
http://www.codeproject.com/Articles/821275/Webforms-vs-MVC-and-Why-MVC-is-better
http://www.codeproject.com/Articles/528117/WebForms-vs-MVC