MVVM e Asp.Net MVC com KnockoutJS    

Introdução

Hoje vou falar de um tema novo, porém, muito importante para quem desenvolve sistemas Web. Atualmente, os sistemas têm ficado com interfaces cada vez mais ricas e rápidas, o casamento de Asp.Net MVC (ou mesmo WebForms) com Jquery possibilitou trazer muito da experiência de usuário de sistemas Desktop para Web, e quanto mais nós desenvolvedores vemos as possibilidades mais as telas ficam cheias de “efeitos”.

Porém, conforme as telas ficam mais complexas e com mais informações, mais o código para tratar tudo isso fica confuso. É comum em grandes telas de sistemas Web, existirem arquivos JavaScript com algumas centenas de linhas, e para piorar o suporte do Visual Studio para JavaScript, por mais que tenha melhorado muito, continua ainda um pouco restrito.

Se olharmos, muito das linhas de um arquivo JavaScript tem a responsabilidade de ler e escrever em campos HTMLs, muito do arquivo é a utilização do método val() do Jquery com ou sem parâmetros, e por não ter uma bom editor acabamos muitas vezes duplicando trechos de códigos.

Muito do meu esforço nos últimos projetos em que trabalhei era diminuir o esforço para fazer esse mapeamento entre dados (modelo) e tela, tentando mesclando alguns puglins JQuery para resolver o meu problema. Nesse esforço, esbarrei no padrão MVVM, muito utilizado em aplicações Silverlight, e tentei aplicar esse padrão a minha realidade MVC/WebForms X JQuery. Algum tempo tentando “reinventar” a roda, descobri o Knockout, uma bela biblioteca JavaScript projetada para implementar o padrão MVVM em Javascript.

O objetivo deste post é tentar mostrar um pouco das facilidades que essa biblioteca nos dá ao integrar código e interface de maneira simples e limpa. Espero que goste!

O padrão MVVM (Model – View – ViewModel)

Meu conhecimento de MVVM não é amplo, então vou basear essa breve explicação no que você pode encontrar no Wikipedia ou mesmo no site do Knockout.

A definição básica é: “MVVM é um padrão arquitetural criado pela Microsoft como uma espacialização do Design Patter Presentation Model, introduzido originalmente por Martin Fowler”.

A Microsoft introduziu esse padrão com o advento do WPF e Silverlight, então desenvolvedores dessas plataformas já devem estar bem familiarizado com esse padrão.

Basicamente, MVVM é um padrão para criar UI (tela) de forma transparente sofisticada, separando esta tarefa em três partes:

  • Modelo (Model) – Assim como o M do MVC, o modelo representa os dados e operações do domínio da sua aplicação. É totalmente independente de interface e representa o negócio da sua aplicação, que vai muito além de tela. Para conseguir identificar da melhor forma possível o domínio da sua aplicação, que te leva a um bom modelo, recomendo a leitura do livro sobre DDD do Erick Evans, que pode ser algumas páginas online no google.
  • View – Sua tela, com campos, labels e botões, representando o estado da aplicação e permitindo que o usuário interaja com a aplicação, em resumo, a Interface com Usuário – UI (HTML).
  • ViewModel – Uma representação somente de código dos dados e operações de uma UI. Não é a UI de fato, porque não tem nada que lembre botões, campos de texto, etc. Armazena os dados não salvos do usuário e tem conhecimento para conversões de informação. Utilizando Knockout é puro JavaScript.

A técnica de MVVM pode ser aplicada praticamente em qualquer linguagem que tenha interface de usuário rica, com botões, campos de textos, etc. Como comentei, é muito utilizada com Silverlight e WPF, mas pode ser utilizada com WindowsForm, WebForm, VB6, etc, e obviamente não está amarrado ao Knockout.

É importante frisar também que MVVM não substitui MVC, e a View do MVC não tem a mesma função da View do MVVM, visto que no MVC, view pode ser qualquer saída da aplicação, podendo ser relatório, arquivo de texto, prompt de comando, etc; enquanto que no MVVM é sempre uma interface de usuário rica, com botões, campos de textos, combo, etc.

Em geral, em uma aplicação Asp.Net MVC que faz uso de Ajax, a View é um JSON, que muitas vezes é um objeto do próprio Model, ou um objeto ViewModel.

KnockoutJS – MVVM com Javascript

KnockoutJS (KO), como disse anteriormente, é uma biblioteca de MVVM feita em JavaScript puro, ou seja, sem dependências de outras bibliotecas JS para funcionar (na maioria dos casos). Foi criado pelo Steve Sanderson, há pouco tempo atrás e já está ganhando certa notoriedade no mundo Asp.Net, e promete ganhar muito mais (não só no Asp.Net), porque realiza muito bem a tarefa que se dedica a fazer.

Todas as informações necessárias, como documentação, exemplo, releases e download pode ser encontrado no site http://knockoutjs.com/

Os conceitos básicos do KO são:

  • Bindings declarativos;
  • Atualização de UI automática (Observables) e Controle de Dependência;
  • Template (precisa de JQuery);

Neste post, tentarei abordar cada um dele, apenas para se ter uma noção da capacidade dessa biblioteca. Para não me alongar muito, mostrarei apenas um exemplo de cada um. Muitos outros podem ser encontrado no site do KO.

Exemplo 1: Binding declarativo.

Obs.: Para esse exemplo funcionar, é necessário baixar o arquivo do KO, a partir daqui.

O Binding no Knockout é realizado através de atributos HTML5 data-bind, e pode ser utilizado em praticamente todas as TAGs HTMLs. Como o atributo é interpretado pela biblioteca do KO, não importa se o Browser suporta ou não HTML5. Na realidade, o Knockout é suportado por todos os Browsers, inclusive mobile.

Como primeiro exemplo, vou fazer um bem básico. Na minha View Index do Controller Home, vou colocar o seguinte HTML:

   1: <p>Codigo: <span data-bind="text:Codigo"></span></p>
   2: <p><span>Nome:</span><input type="text" data-bind="value:Nome" /></p>
   3: <p><span>Email:</span><input type="text" data-bind="value:Email" /></p>

O código acima é bem simples: Estou dizendo que o atributo text do controle span, por exemplo, será preenchido com o atributo Codigo do meu Modelo. Em outros palavras, seria o mesmo que fazer assim:

   1: <p>Código: <span>1</span></p>

O JavaScript é muito simples para fazer o Knockout funcionar. Vou criar um modelo, que nada mais é que um objeto JSON, e depois invocar o método que efetiva o Bind no formulário. O Código está abaixo:

   1: var usuario = {
   2:     Codigo: 1,
   3:     Nome: "Frederico",
   4:     Email: "blog@fredericoemidio.com"
   5: }
   6:  
   7: ko.applyBindings(usuario);

Com essas poucas linhas de código o Bind já funciona, a única novidade ai é a chamada applyBindings do objeto ko. KO é o objeto de entrada a todas as funções do Knockout. Esse método tem dois overloads, este que estou usando, que a partir de um modelo de dados ele realiza o bind para toda a página onde tiver controller com o atributo data-bind e o outro é com um segundo parâmetro que recebe um container (div por exemplo), informando que o bind só deve ser realizada nos controles dentro do Container.

Com o código acima, o resultado é o seguinte:

 

image

E voilá! Funcionando! Foi um exemplo muito simples, porém, extremamente útil.

Exemplo 2: Implementando atualização automática de UI com Observables

Um dos conceitos centrais do Knockout sãos os Obervables. Observables basicamente é a forma que o Knockout utiliza para que uma atualização feito no JavaScript automaticamente reflita no HTML e vice-versa.

Vou utilizar o mesmo exemplo acima, porém, agora vou simular um botão Salvar, para percebemos como o modelo é automaticamente atualizado conforme o usuário digita nos campos da tela.

Vou alterar o meu modelo para ficar da seguinte forma:

   1: var usuario = {
   2:         Codigo: ko.observable(1),
   3:         Nome: ko.observable("Frederico"),
   4:         Email: ko.observable("blog@fredericoemidio.com"),
   5:  
   6:         Salvar: function() {
   7:         alert("Nome: " + this.Nome() + "\r\nEmail: " + this.Email());
   8:        }
   9:     }

O que eu fiz nesse código: Falei que minhas propriedades são observaveis, com o método ko.observable, veja que também adicionei um método no modelo, para simular um método Salvar.

O legal dessa abordagem é que o código JavaScript fica como um code-behind, e a gente não precisa fazer referência a controles HTMLs, e isso é incrível!

No HTML, para fazer o botão Salvar funcionar, eu também utilizo o atributo data-bind, veja, apenas utilizando o atributo click:

   1: <input type="button" value="Salvar" data-bind="click: Salvar" />

O resultado fica assim:

image

Perceba que alterei o conteúdo e ele refletiu no meus dados, sem eu precisar ficar me preocupando em como ler as informações. Como enviar para o servidor fica a seu critério. Você pode utilizar PageMethods ou métodos AJAX do JQuery.

Exemplo 4 – Mapeamento automático

Mas agora você pode falar: “Eu vou ter que ficar fazendo mapeando das minhas classes no JavaScript? Mas meu cadastro de Pessoa tem 50 campos, isso não vai dar certo!”

Realmente, e por isso o Knockout tem um plugin, que realiza esse mapeamento automaticamente. Para utiliza-lo, você terá que baixa-lo separadamente, neste site.

Para fazer esse exemplo, vou criar uma classe na pasta Models do meu site MVC:

   1: public class Pessoa
   2: {
   3:    public int Codigo { get; set; }
   4:    public string Nome { get; set; }
   5:    public string Email { get; set; }
   6: }

E vou criar uma uma Action no meu Controller para obter um registro de Pessoa do servidor:

   1: public JsonResult ObterPessoa()
   2: {
   3:     return  Json(new Pessoa { Codigo = 1, Nome = "Frederico", Email = "blog@fredericoemidio.com" }, JsonRequestBehavior.AllowGet);
   4: }

E vou alterar meu JavaScript para que ele processe o retorno e realize o bind. Meu HTML não vai mudar nada, apenas o JavaScript: Estou obtendo assincronamente os meus dados com Jquery e invocando o método fromJS do plugin ko.mapping.

   1: $.get("Home/ObterPessoa", function (retorno) {
   2:     var usuario = ko.mapping.fromJS(retorno);
   3:     usuario.Salvar = function () {
   4:         alert("Nome: " + this.Nome() + "\r\nEmail: " + this.Email());
   5:     }
   6:     ko.applyBindings(usuario);
   7: });

Com esse código o resultado é o mesmo do exemplo anterior, com a vantagem que não precisamos realizar o mapping manualmente. Existem outros métodos interessantes nesse plugin que deixarei para outros posts.

Exemplo 4 – Template

O último exemplo do post de hoje será utilizando template do JQuery, mostrando como a mescla de algumas bibliotecas pode fazer o desenvolvimento ficar muito bom. Neste caso, quem fará acesso ao JQuery template será o próprio Knockout, então você não precisa conhecer a fundo o JQuery template, caso queira, acesse o site do JQuery.

Vou criar uma listagem de pessoas e realizar o mesmo processo de binding no JavaScript:

   1: var modelo = { pessoas: [
   2:    { Codigo: 1, Nome: 'Nome 1', Email: 'nome1@email.com' },
   3:    { Codigo: 2, Nome: 'Nome 2', Email: 'nome2@email.com' },
   4:    { Codigo: 3, Nome: 'Nome 3', Email: 'nome3@email.com' }
   5:  
   6: ]
   7: }
   8:  
   9: ko.applyBindings(modelo);

O HTML que muda um pouco, utilizando o padrão do jquery template:

   1: <div data-bind='template: "pessoaTemplate"'>
   2: </div>
   3: <script id='pessoaTemplate' type='text/html'>
   4:     <table>
   5:     <thead>
   6:         <tr>
   7:             <th>
   8:                 Codigo
   9:             </th>
  10:             <th>
  11:                 Nome
  12:             </th>
  13:             <th>
  14:                 Email
  15:             </th>
  16:         </tr>
  17:     </thead>
  18:         <tbody>
  19:             {{each pessoas}}
  20:             <tr>
  21:             <td>${ Codigo }</td>
  22:             <td>${ Nome }</td>
  23:             <td>${ Email }</td>
  24:             </tr>
  25:             {{/each}}
  26:         </tbody>
  27:     </table>
  28:  
  29: </script>

Os templates do JQuery são colocados dentro de blocos Scripts com o tipo ‘text/html’. O resultado será:

image

O template gera uma linha para cada registro. Simples assim.

Para introduzir o Knockout, acredito que esses exemplos são suficientes. Acredito que vale a pena você navegar em http://knockoutjs.com/ e ver todas as possibilidades dessa biblioteca. Tem ajudado muito no meu projeto atual. Faz o seu código JavaScript ficar muito mais claro e simples.

Bom pessoa, por hoje é isso!

Abraços

Projeto de exemplo:

 

Knockout.zip (583,67 kb)

9. maio 2011 00:10 by Frederico B. Emídio | Comments (6) | Permalink

MVC–O padrão.    

Olá pessoal!

Estou planejando para os próximos posts uma pequena série sobre Asp.Net MVC. Uma série para quem é desenvolvedor WebForms, e quer fazer suas primeiras aventuras no mundo MVC. Para isso, vou fazer alguns posts introdutórios, sobre conceitos que um desenvolvedor Web deve saber antes de iniciar suas aventuras em Asp.Net MVC.

Praticamente todos os assuntos tratados nessa posts introdutórios devem ser de conhecimento de qualquer desenvolvedor Asp.Net, porém, muitos dos desenvolvedores WebForms migraram do VB6 sem o menor conceito de Web, por isso, para que não surjam desenvolvedores Asp.Net MVC tão desconhecedores de Web como existe no WebForms, acho interessante esses posts introdutórios.

Os temas serão tratados ao longo de quatro post, como segue:

Caso eu vá percebendo ao longo da escrita desses post a necessidade de mais assuntos, eu posso atualizar a lista acima. Qualquer dúvida quantos aos assuntos tratados, por favor, me avisem.

Então vamos lá!

Separation of concerns (Separação de Interesses)

Antes de começarmos a falar de MVC, devemos falar do que veio antes, que é a idéia de Separation of Concerns (SoC). SoC é o processo de agrupar códigos com características distintas, separando em blocos de códigos especialistas, responsáveis por interesses específicos.

Se falarmos em orientação a objetos, seria deixar cada objeto responsável apenas por aquilo para o que ele foi criado, conhecendo apenas o seu escopo, e interagindo com outros objetos quando necessário para realizar atividades fora do seu escopo de conhecimento.

Normalmente isso é feito através de padrões de projetos (Design Patters), implementável em qualquer linguagem, e em qualquer paradigma, não apenas em Orientação a Objetos, como Linguagens Procedurais, ou em programação orientada a serviços.

Entre muitos padrões que implementam SoC, existe o MVC, que vamos falar no próximo tópico.

MVC, o que é?

MVC é a sigla para Model View Controller, um Design Pattern que implementa o conceito de SoC. MVC não foi criado pela Microsoft e muitos menos é algo exclusivo do Asp.Net. É um padrão de projeto que existe desde 1979, originalmente utilizado em uma antiga linguagem chamada Smalltalk.

Sua implementação é possível em qualquer ambiente que tenha interface de usuário, ou seja, não é aplicável apenas em Web, inclusive sua utilização foi muito disseminada em aplicações Desktop, devido a complexidade das telas, onde era necessário existir um padrão para facilitar a manutenção.

A idéia do MVC é separar a lógica de apresentação da lógica de negócio, e fazer com que uma lógica não conheça a outra. Dessa forma, é possível alterar a interface (podendo mudar inclusive de Desktop para Web, por exemplo), sem ter necessidade de alterar a lógica de negócio, ou vice-versa.

Cada parte ficaria da seguinte forma:

Model – Define o domínio do negócio, muitas vezes representado pelo Modelo de Dados (não é o mais correto, mas com tantos ORMs por ai, acaba sendo o que acontece), ou entidades de negócio, como por exemplo Cliente, ContaCorrente,  etc. As operações de negócio fazem parte do Model (Domínio da aplicação), ou seja, um método para obter o saldo de uma conta corrente faz parte do domínio e está no Model do MVC. O Model conhece apenas o que diz respeito a ele, ou seja, não sabe quem está visualizando os dados ou para que os dados estejam sendo visualizados.

View – Define uma visão do Modelo (Model), de acordo com a necessidade de um usuário. Muitos acham que a View no MVC é sempre uma tela (Página na Web ou Formulário no Desktop), mas na realidade vai muito além disso, qualquer tipo de exibição de dados de um modelo é chamado de View. Pensando em uma aplicação Web, poderia ser: A própria página (mais comum), um relatório (em qualquer formado – PDF, Excel, etc), um arquivo (TXT, XML), um formado de dados (JSON), enfim, qualquer representação do domínio de negócio que seja necessário para representar uma necessidade da aplicação. Várias Views podem existir para o mesmo Model

Controller – Faz o meio campo entre o Model e a View, é ele quem sabe qual View gerar de acordo com uma entrada específica. Ele conhece a View e o Model na aplicação. Um Controller geralmente é invocado a partir de uma View gerada por um Controller anterior.

Abaixo segue uma ilustração retirada do Wikipédia.

image

Falando um pouco de Web, existem muitos frameworks que implementam o padrão MVC, um dos mais conhecidos é o Ruby On Rails, inclusive é um dos que mais inspiraram a criação do Asp.Net MVC. Em Asp.Net já existia MVC desde o .Net 1.1, mas em iniciativas particulares, como o Monorail. Nas demais tecnologias Web, como Java, PHP, Asp 3, etc; também existem framework MVC disponíveis.

É importante conhecer bem o padrão MVC, para que ao desenvolver uma página nesse conceito, você não fique perdido em relação de onde colocar suas informações, seria interessante estudar um pouco de outro padrões, como DDD (Domain Driven Design), que não pretendo abordar nesta série de posts, mas que ajuda muito a modelar seu Domínio (Model), sem sempre trabalhando apenas no Modelo de Dados (Com frameworks ORM, como NHibernate ou Entity Framework).

Desenvolvendo MVC sem conhecer bem o padrão MVC, você cai no risco de misturar conceitos, como é comum acontecer com Orientação a Objetos, onde muita genta fala que trabalha com OOP só porque a linguagem dá suporte, mas acaba programando sempre proceduralmente.

Bom para introduzir o conceito MVC, acredito que esse Post seja suficiente, caso necessite de mais informações, faça um comentário logo ali abaixo.

Até o próximo.

13. outubro 2010 07:42 by Frederico | Comments (2) | Permalink

Sobre mim

Minha Imagem

Meu nome é Frederico Batista Emídio, trabalho com desenvolvimento de sistemas profissionalmente a oito anos, porém, já faço sites pessoais a pelo menos dez anos.

Para saber mais clique aqui.

Páginas

Calendário

<<  novembro 2017  >>
seteququsedo
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

Visualizar posts em um Calendário
Sigua @fredemidio

MCP Asp.NET