• Nenhum resultado encontrado

ASP.net Mvc - Apostila

N/A
N/A
Protected

Academic year: 2021

Share "ASP.net Mvc - Apostila"

Copied!
26
0
0

Texto

(1)

C# e ASP.NET MVC

Conceitos principais

Apostila de apoio

STAFF Business

São José dos Campos, 2015

(2)

Sumário

1. Introdução ... 3 2. Conhecendo melhor o C# e o .NET Framework ... 4 3. Gerenciamento de memória em uma aplicação .NET, value-types e reference-types .... 7 4. O padrão MVC e o ASP.NET MVC ... 15 5. O protocolo HTTP ... 19 6. Persistência de informações e a impedância ... 23

(3)

1. Introdução

Olá, tudo bem? Seja bem-vindo ao treinamento de ASP.NET MVC da Staff Business. É um prazer estar com você! Neste curso, iremos abordar então o framework para desenvolvimento web da Microsoft: o ASP.NET MVC. Iremos aplicar o ASP.NET MVC em conjunto com a principal linguagem da plataforma: o C#. Também discutiremos algumas características da linguagem em si, bem como também abordaremos alguns princípios de arquitetura de software e de Application Lifecycle Management (ALM). Este material tem como objetivo servir de apoio e complemento ao conteúdo prático do curso de ASP.NET MVC, detalhando com um pouco mais de profundidade técnica alguns conceitos do framework e também da própria linguagem. Neste material você encontrará mais referências teóricas e um pouco mais de aprofundamento dos conteúdos que serão vistos nas aulas hands on.

Note que, então, o conteúdo do treinamento presencial e o conteúdo desta apostila são complementares entre si: um conteúdo não substitui o outro.

(4)

2. Conhecendo melhor o C# e o .NET Framework

O C# é uma linguagem desenvolvida pela Microsoft. Foi apresentada no ano 2000, junto com a plataforma .NET, sendo a principal linguagem da plataforma. É considerada uma linguagem multi-paradigma, porém, sua vocação é a orientação a objetos. É também uma linguagem type-safe (cada variável é de um determinado tipo e somente daquele tipo).

Alguns dos benefícios mais importantes do uso de C# vem seus recursos em tempo de execução, que nos oferece serviços como segurança sandboxing (execução de código dentro de um ambiente controlado), verificação de tipos em tempo de execução, tratamento de exceções, gerenciamento de thread (códigos executados simultaneamente) e, talvez o recurso mais importante, o gerenciamento automático de memória. Em tempo de execução há um coletor de lixo (garbage collector), que livra os desenvolvedores de grande parte do trabalho associado à memória, recuperando o que não é mais usado pelo programa. O C# também oferece suporte sem maiores problemas para a utilização de recursos corriqueiros de uma linguagem, como conexão à bancos de dados e consumo de WebServices. Atualmente, o C# é multi-plataforma e também open-source. Toda a gerência da parte open source não somente do C#, mas de todos os projetos da plataforma .NET, é desenvolvida pela .NET Foundation, o braço open-source da Microsoft. O C# também é multi-plataforma porque hoje existem uma portabilidade do .NET Framework para ambientes Unix (Linux e Mac) chamada Mono. O Mono é também um projeto open-source coordenado pela Microsoft que consiste na portabilidade do .NET Framework do Windows para ambientes Unix. Além disso, também é possível rodar código native .NET sem o auxílio do Mono graças ao microframework .NET Core, também criado pela Microsoft.

Já o .NET Framework é uma infraestrutura (framework) sobre a qual se reúne um conjunto de linguagens e serviços que simplificam o desenvolvimento de aplicações. Mediante essa ferramenta se oferece um ambiente de execução altamente distribuído, que permite criar aplicações robustas e escaláveis. Os principais componentes desse ambiente, que serão detalhados a seguir, são: • Linguagens suportadas pelo .NET; • Biblioteca de classes comuns do .NET Framework; • CLR (Common Language Runtime); • JIT (Just-in-time Compiler) •

O .NET Framework suporta múltiplas linguagens de programação e, embora cada linguagem tenha características próprias, é possível desenvolver qualquer tipo de aplicação com qualquer uma das linguagens. Existem mais de 30 linguagens adaptadas a .NET, desde as mais conhecidas como C#, Visual Basic.NET e C++, até outras linguagens menos conhecidas, como Perl ou Cobol.

(5)

O processo de compilação e execução de uma aplicação .NET pode ser detalhado da seguinte maneira:

• Ambiente de desenvolvimento: é onde os desenvolvedores escrevem os códigos necessários para o desenvolvimento de uma aplicação. Geralmente, é utilizada uma IDE para auxiliar na escrita do código. Para a plataforma .NET, a IDE mais utilizada é o Visual Studio, da Microsoft; • Compilação: após a escrita do código, é necessário o converter para uma linguagem de um nível mais baixo. No caso específico do C#, quem faz essa conversão, conhecida como compilação, é o executável csc.exe. No caso de utilização de IDEs, a própria IDE se encarrega de chamar o compilador com os parâmetros necessários, além de fazer uma série de verificações no código (por exemplo: verificação de erros de sintaxe); • Assembly intermediário: no caso da plataforma .NET, o código-fonte é convertido para

uma linguagem unificada da plataforma .NET, a Microsoft Intermediate Language (MSIL). Essa conversão ocorre devido ao fato de que a plataforma .NET possui várias implementações de diferentes linguagens que, inclusive, podem conversar entre si. Para isso, é necessário converter todos os códigos-fonte para uma linguagem única, que é a MSIL. Atualmente, a MSIL também é chamada de CIL (Common Intermediate Language). A CIL/MSIL se assemelha muito ao bytecode da plataforma Java.O MSIL/CIL ainda apresenta algumas meta- informações sobre as classes compiladas e seu conteúdo nos arquvos gerados pelo processo de compilação e conversão para a MSIL/CIL. É importante salientar que o resultado do processo de compilação e conversão para a MSIL ainda não é código de máquina (a MSIL/CIL ainda apresenta até uma certa legibilidade para humanos), e sim uma linguagem unificada intermediária da plataforma .NET. A conversão dos códigos escritos nas diferentes linguagens da plataforma .NET para a MSIL/CIL é feita de acordo com a Common Language Specification (CLS), um conjunto de funções básicas que todas as linguagens da plataforma devem conter para que seja possível que “uma converse com a outra”,

(6)

principalmente efetuar a conversão e correspondência de tipos de dados entre as diferentes linguagens; • .NET Framework: é o conjunto de todos os utilitários e infraestrutura necessárias para se executar uma aplicação .NET na máquina-cliente. Os componentes principais do .NET Framework são: o Common Language Runtime (CLR): o CLR é o verdadeiro núcleo do .NET, já que é o ambiente de execução onde se carrega e gerencia os códigos MSIL/CIL; o JIT (Just-in-Time Compiler): é o componente do .NET Framework responsável por converter os códigos MSIL/CIL para o código de máquina correspondente à plataforma onde a aplicação é executada. A CLR, quando detecta que é necessário um trecho de código que ainda não foi convertido para linguagem de máquina, solicita ao JIT essa conversão e, só depois, o código é executado, já no formato de máquina. Esse processo é conhecido como Dynamic Translation (“Tradução dinâmica”); o o Garbage Collector (GC): componente do .NET Framework que é responsável por verificar a memória da máquina cliente onde a aplicação é executada. Caso ele encontre uma localização da memória que contenha alguma informação que não é mais necessária para nenhum processo que esteja rodando dentro da plataforma .NET (por exemplo: uma referência para um objeto que não é mais utilizado em nenhum ponto de uma aplicação .NET), o GC limpa a região da memória que era utilizada para guardar esta informação e a libera, permitindo que novas informações úteis sejam gravadas naquela posição de memória;

o o .NET Class Libraries: é um conjunto de bibliotecas próprias do .NET Framework utilizadas para interação com recursos da infraestrutura do framework e/ou recursos do sistema operacional. Essas bibliotecas são utilizadas por qualquer aplicação que seja escrita em cima do .NET Framework.

Ao final do processo de compilação e conversão da MSIL/CIL por parte do .NET Framework, é gerado um código de máquina que será gerenciado pela CLR. Este código de máquina está otimizado para o ambiente onde a aplicação está sendo executada, o que adiciona a característica de interoperabilidade ao .NET Framework: basta existir uma implementação da infraestrutura do .NET Framework para um sistema operacional que já se torna possível executar uma aplicação .NET neste sistema, sem necessidade de portabilidade e/ou reescrita de código para o sistema em questão. Isso também é possível graças à própria MSIL/CIL: no final, todo o código é convertido para uma única linguagem unificada, que não depende de sistema operacional: ela depende somente da própria infraestrutura do .NET Framework.

(7)

3.

Gerenciamento de memória em uma aplicação .NET, value-types e reference-types

O ambiente de execução do .NET, de maneira geral, divide a memória em duas grandes áreas: a stack (uma área bem menor) e a heap (uma área bem maior). A stack, por ser menor e por contar com um algoritmo de organização mais eficiente, é de acesso muito mais rápido do que a memória heap. Podemos ilustrar esta divisão da memória conforme o diagrama abaixo: As variáveis de alguns tipos de dados leves (tipos primitivos - int, double, bool etc. - e structs) são armazenadas diretamente na stack, a área menor e mais eficiente para localização dos conteúdos. Elas ficam diretamente nessa área justamente por serem tipos de dados que não ocupam tanto espaço na memória. O mais interessante é que o valor que elas contêm também fica junto delas na stack. Ou seja, quando você faz a declaração abaixo: int numero = 3; O compilador armazena essa variável diretamente na memória stack, como na ilustração abaixo:

(8)

Perceba que o valor da variável fica junto com a própria variável. Variáveis onde isso acontece são chamadas de Value-Types, justamente porque o valor delas fica junto com a própria variável na memória, alocados na stack. Assim, quando você tem o seguinte código: if (numero <= 2) { //... } O compilador tem acesso direto ao conteúdo, pois ele está junto com a própria variável na memória:

(9)

Agora, outros tipos de dados ocupam muito mais espaço de memória do que estes tipos leves que são value-types. Por isso, eles não podem ser armazenados na stack como os value-types. Sendo assim, estes dados são armazenados na memória heap. Vamos imaginar que você tenha o seguinte código, com uma classe chamada Pessoa: class Pessoa {

public int Id {get; set;} public string Nome {get; set;} }

Quando você cria um objeto dessa classe, esse objeto será armazenado na memória heap:

Pessoa minhaPessoa = new Pessoa();

(10)

Porém, o compilador não acessa a heap. Por que ele não acessa? Justamente porque ela é muito grande... Se ele fosse procurar o objeto minhaPessoa dentro da heap, ele iria demorar uma quantidade considerável de tempo. O compilador precisaria ter um jeito de acessar pela stack (que é rápida pra encontrar as coisas) o que está alocado na heap (que é bem maior). Como o compilador contorna isso? Criando uma referência dentro da stack para o objeto minhaPessoa, apontando onde na heap que este objeto está de fato guardado.

(11)

Essa porção de memória que é alocada na stack para apontar para uma posição de memória da heap é chamada de ponteiro. Por isso ele tem esse asterisco (*) na frente do seu nome.

Repare então que é criada uma referência da stack para uma determinada posição de memória da heap, referência essa guardada por um ponteiro na stack. Esse tipo de variável (como no caso da variável minhaPessoa, do tipo Pessoa) é chamada de reference-type, já que é necessário uma referência da stack para a heap para que esta variável seja acessível. Variáveis reference-type geralmente precisam que seja chamado o new, pois ele que define que uma porção de memória da heap deverá ser utilizada para guardar aquele objeto. Dessa maneira, quando temos o código abaixo: if (minhaPessoa.Id <= 2) { //... } O compilador faz o acesso ao objeto minhaPessoa através da stack, ou seja, através do ponteiro. Esse ponteiro encaminha o compilador para a posição de memória da heap que contém de fato o objeto minhaPessoa.

(12)

Ou seja, resumindo: • Value-Type: são tipos leves que ficam armazenados diretamente na memória stack. Os valores das variáveis ficam armazenados juntamente com as próprias variáveis, sendo o acesso ao seu conteúdo feito de maneira direta; • Reference-Type: tipos pesados (objetos de classes, etc.) que ficam armazenados na heap. Para não sacrificar a performance, é criada uma referência (ponteiro) na stack que aponta para qual posição de memória o objeto está armazenado na heap. O acesso é feito via essa referência na stack, portanto, o acesso é indireto, dependendo dessa referência. Agora, o que acontece se fizermos o código abaixo?

Pessoa minhaPessoa = new Pessoa(); Pessoa outraPessoa = minhaPessoa;

Os objetos minhaPessoa e outraPessoa são reference-types. Sendo assim, podemos ilustrar a alocação do objeto minhaPessoa da seguinte maneira:

(13)

Agora, nós criamos um outro ponteiro, chamado outraPessoa, mas o igualamos ao objeto minhaPessoa. Nesse ponto, o que vai acontecer, é que na verdade o ponteiro outraPessoa vai apontar exatamente para a mesma posição de memória que minhaPessoa está apontando...

(14)

Se nós já instanciamos o objeto através do minhaPessoa e outraPessoa vai apontar exatamente para a mesma posição de memória que o minhaPessoa, isso quer dizer que quando fazemos Pessoa outraPessoa = minhaPessoa, o objeto outraPessoa também já vai estar instanciado: afinal, ele aponta para a mesma posição de memória que o objeto minhaPessoa.

(15)

4. O padrão MVC e o ASP.NET MVC

Desenvolver uma aplicação para a web não é uma tarefa fácil… Precisamos nos preocupar mais com questões como segurança e performance em relação ao desenvolvimento de aplicações desktop por exemplo. Ainda há o fato de o ambiente de desenvolvimento de aplicações web ser completamente heterogêneo, já que há a mistura da própria linguagem a ser utilizada (como o C# por exemplo) com linguagens próprias do ambiente web, como o JavaScript e até mesmo o CSS, quando utilizado juntamente com LESS por exemplo. Adicionando mais problemas a esse caos todo, ainda podemos esbarrar na organização do código a ser escrito. Se, por muitas vezes, o código de uma aplicação mais homogênea, como aplicações desktop, já tende a ser bagunçado, imagine um código que mistura várias tecnologias como é o caso de aplicações web? Talvez um dos maiores problemas para se organizar o código de aplicações web nem seja a heterogeneidade envolvida com relação às linguagens, mas sim a divisão de responsabilidades. Aonde é que as regras de negócio devem ser tratadas? Onde devo tratar a exibição de conteúdo e o HTML a ser exibido? Onde devo fazer a persistência dos dados? Para auxiliar nessa tarefa de organização e separação de responsabilidades, nós podemos empregar um design pattern muito conhecido pelos desenvolvedores de aplicações web: o MVC. MVC é um acrônimo para Model – View – Controller. A intenção do MVC é promover uma organização mais efetiva através da separação de responsabilidades, onde cada camada é responsável por desempenhar um papel na estrutura da aplicação. O papel de cada camada geralmente é o seguinte: • Model: representa as entidades envolvidas em seu negócio e, no MVC puro, também é a camada responsável pela persistência. Por exemplo, se seu software é um software que administra o estoque de alimentos, provavelmente você terá uma classe chamada “Alimento” para representar cada alimento controlado por sua aplicação. Neste caso, a classe “Alimento” é um dos models de sua aplicação;

• View: representa toda a parte de apresentação e exibição para o usuário. Ou seja, nesta camada ficam os arquivos HTML, os arquivos CSS e eventualmente algum arquivo JavaScript responsável por controlar a interação do usuário; • Controller: é como se fosse o cérebro da aplicação, fazendo a ligação entre o model e a view. Como mencionado, o coração de uma aplicação MVC é o controller. Quando disparamos uma requisição (chamando uma página, por exemplo), é o controller quem vai interpretar nossa requisição e processá-la, chamando as classes da camada model quando necessário e também chamando os arquivos HTML da camada da view. Podemos representar esse esquema de comunicação entre as camadas com a seguinte ilustração:

(16)

Perceba a diferença entre o modelo tradicional... O que pode ser nitidamente notado é que não chamamos mais as views diretamente: nós não chamamos um arquivo HTML, nós vamos sempre chamar o controller e este se encarregará em chamar a view correspondente. Na verdade, nós não chamamos diretamente o controller, mas sim um método do controller. Por exemplo, podemos ter um controller com um método responsável por devolver uma view com a lista de todos os alimentos cadastrados. Provavelmente você terá os seguintes elementos em uma aplicação que siga a arquitetura MVC: • Um model para representar o alimento em sua aplicação. Provavelmente será uma classe chamada “Alimento”; • Um controller para fazer a ligação entre o model e a view de listagem. Provavelmente este controller se chamará “AlimentoController”;

• O AlimentoController provavelmente terá um método que utilizará o model para recuperar todos os alimentos cadastrados e enviar a listagem obtida para a view. Geralmente, métodos que servem para listar as coisas nós chamamos de “Index”;

• Também deverá ter uma view responsável por renderizar a lista de alimentos retornada pelo controller. Geralmente, o arquivo que representa a view ganha o mesmo nome do método que interage com ela. Dessa maneira, teríamos então uma

Controller

View

(HTML, CSS, JS)

Model

(Classes)

Browser

(Chrome, Safari…)

Requisição HTTP

(Request)

Resposta HTTP

(Response)

(17)

http://<servidor>/<controller>/<método> Dessa maneira, se quiséssemos chamar o método “Index” do “AlimentoController” em um servidor localizado por “www.meuapp.com.br”, a URL teria o seguinte formato: http://www.meuapp.com.br/alimento/index A chamada para a URL acima dispararia o método “Index” do “AlimentoController” no servidor em “www.meuapp.com.br”. Por consequência, o método “index” do “AlimentoController” se comunicaria com o model “Alimento” para obter a lista de todos os alimentos cadastrados e repassaria para a view “Index.html”, para que esta então exibisse a listagem de alimentos obtida pelo controller. Logo após a view processar esta lista, ela seria devolvida como resposta para o browser que disparou a URL, fechando o processo de renderização da resposta.

É importante salientar a terminologia de alguns elementos apresentados: • No padrão MVC, a URL que utilizamos para chamar um método de um controller é chamada de rota; • O método do controller que é invocado por uma rota também é chamado de action. O ASP.NET MVC segue exatamente este modelo, baseando-se em controllers, views, models e actions. Os models e controllers são escritos com C# mesmo, utilizando-se classes que herdam classes pré-determinadas. Por exemplo, no ASP.NET MVC, se quisermos um controller, basta criarmos uma classe terminada em “Controller” e que herda a classe “Controller”. Os models são classes convencionais. As views no ASP.NET MVC não têm a extensão HTML, mas sim a extensão CSHTML. Este arquivo CSHTML é um HTML que pode ser misturado com código C#, o que facilita o processo de interação com Controller (AlimentoController/Index) View (Index.html) Model (Alimento) Browser (Chrome, Safari…) http://www.meuapp.com.br/alimento/index Index.html processado e com a lista de alimentos

(18)

o controller que também é escrito em C#. Quando utilizamos os arquivos CSHTML, também dispomos de uma série de classes chamadas HTML Helpers, que reduzem drasticamente o tempo de escrita da view. Tudo isso só é possível porque toda a parte de visualização do ASP.NET MVC é implementada em cima de uma engine de visualização chamada Razor.

(19)

5. O protocolo HTTP

HTTP é um acrônimo para HyperText Transfer Protocol, ou Protocolo de Transferência de HiperTexto. Trata-se de um protocolo que estabelece como deve ocorrer a comunicação entre uma máquina cliente que faz pedidos para uma máquina servidora. Ele é normatizado por uma especificação, a RFC 2616. Como já foi dito, o protocolo HTTP é baseado na comunicação entre uma máquina cliente que faz requisições para uma máquina servidora. Cada pedido que a máquina cliente faz para o servidor é chamado de requisição ou request; ao passo que a resposta do servidor para cada pedido é chamada de resposta ou response. O protocolo HTTP é utilizado desde a década de 90 em páginas e aplicações Web. Neste caso, quem faz o papel de cliente na história é o browser, o seu navegador. Hoje, os browsers conseguem interpretar uma série de protocolos, inclusive o HTTP. Vamos a um exemplo: vamos acessar a página do Google. Se quisermos acessar a página inicial do Google, devemos digitar em nosso navegador: http://www.google.com.br Acima, nós temos um HiperTexto, determinado por uma URL (Uniform Resource Locator - Localizador de Recursos Uniforme). Perceba que de fato vamos utilizar o HTTP para fazer a comunicação com o servidor do Google, pois a URL até se inicia com HTTP! Quando damos o enter para que o browser processe a solicitação, uma requisição HTTP é então encaminhada para os servidores do Google, onde ela será processada.

Toda requisição HTTP é composta basicamente por duas partes distintas: cabeçalho (header) e corpo (body). O cabeçalho contém algumas informações específicas da requisição, como o browser que está fazendo a requisição, o tipo de resposta esperada do servidor e até mesmo o tempo de timeout. Já o corpo pode conter informações adicionais que o cliente pode enviar para o servidor que estarão atreladas à requisição (request). O corpo não é obrigatório, mas o cabeçalho é.

Quando fazemos uma requisição para o Google, nós vamos ter o request similar ao exibido abaixo:

(20)

Perceba que o cabeçalho da requisição envia para o servidor uma série de informações, por exemplo: • A URL que gerou a requisição (Request URL); • O tipo de resposta esperada do servidor (Accept); • O idioma nativo do browser que disparou a requisição (Accept-Language). Da parte do request, há uma informação importantíssima que é enviada no cabeçalho: o método de requisição (Request Method). Este dado do cabeçalho indica que tipo de ação a URL que foi disparada para o servidor deverá realizar, dando sentido semântico - ou seja, significado - à requisição. Os métodos HTTP que podemos utilizar são: GET, POST, PUT, DELETE, HEAD, OPTIONS, TRACE e CONNECT. Nós, na maioria do tempo, utilizamos mais os métodos GET, POST, PUT e DELETE. O significado destes métodos está na tabela abaixo:

Método Significado semântico

GET Significa que queremos “pegar” algo no servidor: uma página, por exemplo. Requisições GET fazem com que o servidor devolva algo para o cliente, algo que estava “dentro” do servidor

POST Significa que estamos querendo incluir alguma coisa no servidor. Por exemplo, se temos uma página de cadastro de usuários, a requisição que vai fazer com que o servidor faça o insert no banco de dados deve ser uma requisição POST, afinal, estamos criando um novo item que vai ficar no servidor PUT Significa que estamos querendo atualizar alguma coisa no servidor DELETE Significa que estamos querendo apagar alguma coisa do servidor Voltando à requisição para o Google, verifique que é uma requisição com o método GET. Isso significa que os servidores do Google deverão retornar alguma coisa para o cliente que disparou a requisição: neste caso, deverá ser retornado o HTML da página inicial do Google, para que o navegador (o nosso cliente neste caso) possa então desenhar a página para nós. As respostas também possuem cabeçalho. Vamos analisar o cabeçalho da resposta do servidor do Google.

(21)

Perceba que o servidor também retorna uma série de informações sobre ele. A resposta também contém indicadores sobre o controle de cache que o browser deverá executar (cache-control), o tipo de resposta retornado pelo servidor (content-type) e até mesmo a data em que a requisição foi processada no servidor. Agora, existe um item muito importante no cabeçalho de resposta: trata-se do status da resposta. É através deste status que o cliente sabe se a requisição retornou sucesso ou se algo deu errado. Os status HTTP também são padronizados pela especificação. Os principais status HTTP que temos são: Status Descrição

200 OK. Significa que o servidor entendeu a requisição e a processou sem problemas. 302 Found. Significa que o recurso solicitado de fato existe no servidor (status típico de requisições GET) 401 Unauthorized. Significa que você tentou acessar algum recurso do servidor que exige autenticação para acesso, e você ainda não realizou este processo. 404 Not Found. Significa que você solicitou algum recurso no servidor que não existe no lugar que você indicou. Por exemplo: se você tenta acessar alguma página de algum site que não Existe. 500 Internal Server Error. Significa que o servidor encontrou um erro durante o processamento da requisição. É através destes status HTTP que o cliente sabe se a requisição que ele disparou deu certo ou não. O protocolo HTTP ainda possui algumas características que precisamos conhecer: • O protocolo HTTP é stateless. Isso significa que ele não guarda estado. Por exemplo, você não consegue, somente com o protocolo HTTP, guardar se você acessou determinada página ou não, ou mesmo se um usuário fez o login em sua aplicação web ou não. Isso ocorre porque as requisições HTTP são independentes entre si: quando você faz uma requisição, é aberto um canal de comunicação com o servidor.

(22)

resposta, este canal é imediatamente fechado (salvo algumas indicações que podemos fornecer no cabeçalho da requisição). Devido a isso, ele não pode guardar estado, pois esse canal é constantemente aberto e fechado, fora que as requisições ocorrem de maneira isolada (uma requisição não sabe se existe alguma outra requisição sendo feita ou não)... Existem estruturas que podemos utilizar para burlar esta característica do HTTP que veremos neste curso;

• Como foi dito, o protocolo HTTP é independente. Quando você faz uma requisição para o servidor, ela é tratada de maneira isolada das demais requisições, sendo impossível fazer com que requisições se comuniquem umas com as outras. Por exemplo: vamos imaginar que você faz uma requisição para uma página HTML que possui um texto e uma imagem. O navegador fará no mínimo duas requisições para carregar esta página: uma para recuperar o texto e outra para recuperar a imagem. Porém, apesar de ambas as requisições serem necessárias para montar uma única página, o servidor as entenderá de maneira completamente isolada, cabendo ao cliente juntar ambas as respostas para montar a página solicitada; • O protocolo HTTP é assíncrono, ou seja: você pode fazer várias requisições ao mesmo tempo. Como estas requisições são independentes, elas também serão tratadas ao mesmo tempo. O servidor também irá devolver as respostas não necessariamente na mesma ordem em que as requisições foram realizadas, ele irá devolver à medida que o processamento for sendo finalizado.

(23)

6. Persistência de informações e a impedância

É difícil construirmos uma aplicação que não necessite armazenar informações em algum lugar. Um dos meios mais utilizados para persistência de informações por parte das aplicações são os bancos de dados relacionais. Porém, existem algumas barreiras técnicas ocasionadas pela utilização de bases de dados relacionais para armazenamento de informações. Estas barreiras ocorrem basicamente pelo fato de que softwares modernos são desenvolvidos seguindo-se o paradigma orientado a objetos, enquanto bancos de dados relacionais seguem o paradigma relacional. Enquanto no modelo orientado a objetos o foco é criar estruturas que possibilitem a representação do mundo real dentro das linhas de código de um projeto de software, o paradigma relacional dá foco às relações entre entidades e consistência das informações. Sendo assim, o modelo orientado a objetos não é compatível naturalmente com o modelo relacional, exigindo um esforço de conversão do modelo orientado a objetos para o modelo relacional e vice-versa. A este esforço de conversão, bem como as barreiras técnicas que ocorrem devido à incompatibilidade entre os modelos orientados e relacionais é chamada de impedância

objeto-relacional (em inglês, object-relational impedance mismatch). Alguns problemas característicos da impedância são: • Diferenças entre tipos de dados: em bases relacionais, um tipo de dado que pode ser utilizado para representar números inteiros (sendo INT, NUMBER ou qualquer outro) não tem as mesmas características de tipos inteiros em linguagens orientadas a objeto. Essas características podem ser o intervalo de números entre os modelos relacional e orientado a objeto que são diferentes, ou mesmo o comportamento com números negativos. Outro tipo de dado que sofre direrenças entre os modelos relacional e orientado a objeto são as strings. Enquanto no modelo relacional elas possuem a possibilidade de delimitação (em um banco de dados, você pode limitar um campo VARCHAR para suportar no máximo 100 caracteres por exemplo), o modelo orientado a objeto não oferece a possibilidade de se atribuir esse tipo de limitação às strings. Em suma, o sistema de tipagem de

(24)

dados de bases relacionais e linguagens orientadas a objeto são completamente diferentes um do outro;

• Há uma grande diferença com relação à integridade de dados entre o modelo

relacional e o modelo orientado a objetos: a maneira como as estruturas se relacionam. Em linguagens orientadas a objeto, nós temos a menor unidade como sendo um objeto, que pode ser composto por outros objetos ou se relacionar a outros objetos (seja por associação ou composição). Em bases relacionais, não existe essa possibilidade: a menor unidade é uma tupla de uma tabela, que segue um modelo rígido definido de acordo com os campos da tabela. O relacionamento é feito com outras estruturas é feito com base em chaves estrangeiras. Ou seja: o modelo relacional enfatiza a maneira como um objeto conversa com o outro, o modelo relacional dá enfoque às relações; • Há também problemas relacionados à visibilidade de estruturas. Em linguagens orientadas a objeto, existem os conceitos de public, private e protected, o que permite utilização de técnicas como o encapsulamento. O modelo relacional não oferece nada nesse sentido. Isso é um problema, pois muitas vezes é necessário se inserir uma informação que não é acessível de maneira pública em um objeto para uma coluna em um banco de dados; • Há uma diferença enorme com relação à estrutura entre o modelo orientado a

objeto e o modelo relacional: o modelo orientado a objetos lida com classes, interfaces, herança e por aí vai. O modelo relacional não oferece esse tipo de estrutura: em bancos de dados, ele se resume à tabelas, índices e chaves primárias e estrangeiras. Há uma enorme diferença estrutural entre os elementos destes dois paradigmas.

Sendo assim, é necessário fazer a conversão do modelo relacional para o modelo orientado a objetos quando nossa aplicação lê informações de um banco de dados e vice-versa quando nossas aplicações enviam informações para um banco de dados. Abaixo podemos ver um exemplo de um código que realiza essa conversão: trata-se da leitura de uma tabela utilizando-se ADO.NET “puro”.

string connectionString = “”;

List<Pessoa> pessoas – new List<Pessoa>();

using (SqlConnection connection = new

SqlConnection(connectionString)) {

(25)

Pessoa p = new Pessoa { Id = Convert.ToInt32(reader[“ID”]), Nome = reader[“NOME_PESSOA”].ToString() }; pessoas.Add(p); } } }

Perceba o trecho que a impedância é tratada: dentro do while que trata a leitura do DataReader, as informações são extraídas do modelo relacional para o modelo orientado a objetos, já que um objeto do tipo Pessoa é criado e abastecido com as informações obtidas de um banco de dados. Porém, essa não é uma maneira “interessante” de se realizar a conversão ente os modelos relacional e orientado a objeto, pois é uma maneira muito “manual”. Além de que, se a tabela PESSOAS sofrer qualquer tipo de alteração em sua estrutura, isso pode causar a quebra do código que realiza a leitura da tabela PESSOAS e faz a conversão para um objeto do tipo Pessoa. O ideal era ter algum tipo de framework para fazer a conversão de maneira mais automatizada. E aí entram os frameworks ORM. ORM é um acrônimo para object-relational mapping – mapeamento objeto-relacional. Trata-se de um tipo de framework que visa auxiliar na redução da impedância, realizando todas as conversões necessárias entre os modelos relacional e orientado a objeto de maneira automatizada. Frameworks ORM tratam as conversões entre as estruturas relacionais para as estruturas orientadas a objeto geralmente da seguinte forma: • Cada classe acaba sendo interpretada como uma tabela;

• Cada linha de uma tabela, bem como seus relacionamentos, é tratada como

instância do objeto relacionado à tabela em questão.

Frameworks ORM também visam retirar a necessidade de o desenvolvedor de software se preocupar com linguagem SQL, bem como as conversões necessárias entre os diferentes tipos de dados. O desenvolvedor sempre programa no paradigma orientado a objeto, inclusive quando há a necessidade de se fazer manipulação e leitura de informações a partir de uma base relacional. Todo este trabalho, inclusive a geração dos comandos SQL necessários, fica a cargo do framework ORM. E, na plataforma .NET, temos um representante de peso nesse segmento: o Entity Framework.

O Entity Framework é framework ORM fornecida pela própria Microsoft. Ele é uma implementação do ADO.NET em conjunto com o LINQ, mais especificamente utilizando o provider LINQ to Entities (LINQ para entidades). Atualmente, há providers para os principais bancos de dados do mercado para o Entity Framework, ou seja: é possível utilizar o Entity Framework com SQL Server, Oracle, MySQL, PostGres e outros bancos de grandes players disponíveis no mercado.

O Entity Framework é um projeto open source, também fazendo parte da .NET Foundation (http://www.dotnetfoundation.org). O código-fonte, bem como a abertura e

(26)

http://entityframework.codeplex.com. Porém, a tendência é que com o tempo o projeto seja migrado para o GitHub, assim como alguns outros projetos da .NET Foudation. Para utilização nos projetos, o Entity Framework é disponibilizado via pacote NuGet. É possível utilizar o Entity Framework para todos os templates de projeto da plataforma .NET, desde Windows Forms até projetos Web (MVC e WebForms), passando até por aplicações Console. Não há restrição com relação à plataforma para utilização do Entity Framework. A restrição para utilização do Entity Framework na verdade se encontra do banco de dados que será utilizado: deve haver um provider para o Entity Framework relacionado ao banco de dados com o qual se deseja trabalhar. Porém, como dito anteriormente, a grande maioria dos bancos de dados comerciais já possuem providers para o Entity Framework. O Entity Framework nos fornece três modos de trabalho: • Code First: permite trabalhar sem a necessidade de se executar configurações, seja de mapeamento ou de ambiente. A idéia é o desenvolvedor simplesmente escrever as classes desejadas como classes POCO e depois acrescentá-las à estrutura do Entity Framework, deixando este responsável por fazer a conversão para a criação das estruturas necessárias no banco de dados;

• Model First: permite que você crie suas classes de domínio e também as estruturas

necessárias no banco de dados a partir de um arquivo XML de mapeamentos. No caso de utilização do Entity Framework, esse arquivo possui a extensão EDMX - ;Entity Data Model XML. Quando o arquivo EDMX é modificado, estas modificações são convertidas em classes POCO e também em estruturas (tabelas, índices...) no banco de dados de destino; • Database First: permite que as classe POCO sejam geradas a partir de um banco de dados existente. O Entity Framework faz a engenharia reversa da base de dados no qual ele se conecta, convertendo as tabelas em classes para serem utilizadas no paradigma orientado a objetos. POCO é um acrônimo para Plain-Old CLR Objects. Tratam-se de classes desacopladas de qualquer framework. Classes POCO são classes simples, com somente suas propriedades, seus métodos assessores e nada mais. Ou seja, objetos POCO são objetos “planos”.

Referências

Documentos relacionados

E) CRIE NO SEU CADERNO UM TÍTULO PARA ESSA HISTÓRIA EM QUADRINHOS.. 3- QUE TAL JUNTAR AS SÍLABAS ABAIXO PARA FORMAR O NOME DE CINCO SUGESTÕES DE PRESENTE PARA O DIA

Os estudos originais encontrados entre janeiro de 2007 e dezembro de 2017 foram selecionados de acordo com os seguintes critérios de inclusão: obtenção de valores de

Há alunos que freqüentarão o AEE mais vezes na semana e outros, menos. Não existe um roteiro, um guia, uma fórmula de atendimento previamente indicada e, assim sendo, cada aluno terá

A seleção portuguesa feminina de andebol de sub-20 perdeu hoje 21-20 com a Hungria, na terceira jornada do Grupo C do Mundial da categoria, a decorrer em Koprivnica, na

Este texto é uma reflexão em torno da necropolítica, a partir de Achille Mbembe, e das esculturas de Niemeyer, de como estas obras artísticas representam a enunciação e

É importantíssimo que seja contratada empresa especializada em Medicina do Trabalho para atualização do laudo, já que a RFB receberá os arquivos do eSocial e

É também utilizado, juntamente com outros fármacos, para tratar o cancro da mama que se disseminou, o cancro dos ovários em estadio avançado e o cancro do pulmão de células

1 Seleccione as imagens a editar na Área de Exploração do ImageBrowser (filmes ou imagens fixas). Pode seleccionar múltiplos filmes ou imagens fixas. 3 Siga os passos exibidos no