revista programar 26

64

Upload: filipe-bezerra-sousa

Post on 22-Apr-2015

1.510 views

Category:

Technology


0 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Revista programar 26
Page 2: Revista programar 26

2

EDITORIALEditorial

EQUIPA PROGRAMARCoordenadores

António Silva

Fernando Martins

Editor

António Silva

Design

Sérgio Alves (@scorpion_blood)

Redacção

André Lage, Augusto Manzano, Diogo

Constantino, Fernando Martins, João Mares,

João Matos, Jorge Paulino, Paulo Morgado,

Pedro Aniceto, Ricardo Rodrigues, Ricardo

Trindade, Sara Silva

Contacto

revistaprogramar@portugal-a-programar. info

Website

http: //www.revista-programar. info

ISSN

1 647-071 0

INDICETema de Capa - LINQ

BYACC

Introdução ao Entity Framework

Programação Funcional Perl (Parte I)BackgroundWorkers em WPF

jQuery - O quê, como e porquê?

Tutorial de Lua (Parte 6)

E se amanhã a Apple dominar?

SQL em Oracle

Aspectos low-level de 3D

Quando se é ! Produtivo

Client Object Model para Silverl ight

Sempre em movimento…

Porque sabemos que parar é morrer, nesta edição da Revista

PROGRAMAR introduzimos várias alterações que achamos importantes

para continuidade deste projecto. Das várias alterações introduzidas, a salta

imediatamente à vista, mesmo ao leitor que ainda está somente a ler a

página do editorial , é a mudança de design . Em qualquer tipo de

publicação o design influencia o modo como vemos como lemos. Aqui

temos que agradecer a todos quantos ajudaram a adaptar este novo design,

mas especialmente ao Sérgio Alves por toda a parte da idealização e

desenho do novo design.

Outra alteração, que todavia não será tão notada pelos leitores é a

alteração do software de paginação. Chegamos à conclusão que o Scribus

já evoluiu bastante desde a última vez que foi uti l izado para paginar a

Revista PROGRAMAR e está à altura das nossas necessidades. Assim

decidimos que não havia necessidade de continuarmos a uti l izar um

software pago e que trazia vários problemas de leitura a alguns uti l izadores

(dos quais chegamos a receber comentários).

Também fizemos várias parcerias com algumas comunidades

portuguesas que estão de algum modo relacionadas com programação, de

modo a obter mais e melhores artigos para si. Todavia não estamos

fechados a mais parcerias, continuamos abertos a futuros contactos para o

nosso endereço de correio electrónico, que serão posteriormente analisados

por toda a equipa.

Trazemos também até si, colunas de opinião e colunas direccionadas a

um tema específico. Assim poderá contar que surgirão artigos desse

assunto com uma periodicidade específica na sua Revista favorita.

Por fim, achamos que estamos prontos para voltar a trazer a Revista

PROGRAMAR até si de 2 em 2 meses, e por isso a próxima edição deverá

sair em Fevereiro ao invés de Março como estava programado.

Tudo isto para si, que está ler. Esperámos que as alterações sejam bem

recebidas por todos, mas também esperámos opiniões sobre todas estas

alterações, mesmo porque as novidades poderão não ficar por aqui,

contámos ter mais novidades na próxima edição. Por isso não tenha medo

de nos contactar para [email protected] a dizer o

que acha de todas estas alterações. Porque você é importante para nós,

quer as suas opiniões, quer o seu trabalho a divulgar o nosso projecto aos

seus amigos e colegas, e mais importante a sua preferência que nos

permite crescer para lhe oferecer algo maior e melhor.

A equipa da Revista PROGRAMAR

4

11

1 8

23

26

31

35

41

43

47

54

56

A revista PROGRAMAR é um projecto voluntário, sem fins lucrativos. Todos os artigos são da responsabilidade dos autores, não podendo a revista ou a

comunidade ser responsabilizada por alguma imprecisão ou erro. Para qualquer dúvida ou esclarecimento poderá sempre contactar-nos.

Page 3: Revista programar 26

3

NOTICIASNoticias

Up l oad Li sb oa e Up l oad Li sb oa

Pro 20 1 0O Upload Lisboa é um evento que por si só nomeia a era

em que estamos. A era da nova comunicação, da troca de

informação no momento, de forma prática e natural, e da

parti lha de conhecimentos em rede. O Upload Lisboa

pretende, mais uma vez, passar a esfera da rede interior e

global para a esfera da parti lha conjunta, física.

Este evento nasce da necessidade crescente de debate e

parti lha de conhecimentos sobre a web 2.0, numa altura em

que as novas plataformas de comunicação e informação

assumem um lugar cada vez mais central na vida de

pessoas e empresas. Hoje, mais que nunca, a parti lha

através das plataformas sociais na web ocupam um lugar

de destaque na influência na opinião pública e na formação

de critérios de análise ao que se passa no país e no

mundo.

São dois dias, 1 1 e 1 5 de Dezembro, que certamente não

irá perder!

Mais informações: http: //uploadl isboa.com/

Sem i n á ri o PocketPT sob re

tecn o l ogi as Wi n d ows PhoneEncontram-se abertas as inscrições para o 6º Seminário

PocketPT sobre tecnologias móveis Windows Phone. Este

ano o seminário será dedicado à nova plataforma móvel da

Microsoft, e irá incluir várias sessões que irão dar a

conhecer as funcionalidades do mesmo.

Será ainda uma excelente oportunidade para os

participantes testarem e verem em primeira mão os novos

equipamentos.

Como tem vindo a acontecer nos anos anteriores a

inscrição este ano é gratuita e irá ter lugar no auditório da

Microsoft Portugal no TagusPark em Porto Salvo no

próximo dia 1 8 de Dezembro pelas 1 0h.

Mais informações e inscrições:

http: //www.mtechseminar.com/201 0/index.htm

SAPO Cod eB i ts 20 1 0

De 11 a 1 3 de Novembro de 201 0 decorreu o Sapo

Codebits 201 0. A comunidade Portugal-a-Programar esteve

presente, tendo alguns membros efectuado alguns

projectos. Este ano, com oferta da comunidade, todos os

que participaram e solicitaram, tiveram direito a uma t-shirt

para usar durante o evento.

Esta foi a foto de grupo de alguns dos elementos que

estiveram presentes (infel izmente não foi possível juntar

todos):

1 6a Reu n i ão Presen c i a l d a

Comun i d ad e NetPon toNo dia 11 /1 2/201 0 será realizada a 1 6ª reunião presencial

da comunidade NetPonto, em Lisboa. Nesta sessão,

poderá ver duas apresentações presenciais sobre Domain

Driven Design e WP7 & XNA – Let’s play?

Para participar, basta efectuar a inscrição através do site

http: //netponto-l isboa-dezembro-201 0.eventbrite.com/ A

entrada é gratuita e são realizadas reuniões todos os

meses.

Para mais informações, consulta de próximas sessões e

inscrição: http: //netponto.org/

Page 4: Revista programar 26

4

TEMA DE CAPA

LI NQ: Imp l emen tação d os operad o res TakeLast ,TakeLastWh i l e , Ski p Last e Ski p LastWh i l e

original uma vez e mais três vezes sobre ositens que satisfazem o critério. Se a sequênciaoriginal for grande, isto pode consumir muitamemória e tempo.

Existe ainda um problema adicional quando seusa a variante que usa o índice de item nasequência original na avaliação do critério deselecção (>). Quando se inverte a ordem dositens, os índices destes serão invertidos e opredicado de avaliação do critério de selecçãoterá de ter isso em consideração, o que poderánão ser possível se não se souber o número deitens na sequência original.

Tinha de haver uma solução melhor, e é por issoque eu implementei os Operadores Take Last:

TakeLast<TSource>(IEnumerable<TSource>)

Retorna o número especificado de elementoscontínuos no fim da sequência.

Há algum tempo necessitei de obter os últimositens de uma sequência que satisfaziam umdeterminado critério e, olhando para osoperadores disponíveis na classe Enumerable,apercebi-me de que tal operador não existia.

A única forma de obter o resultado pretendidoera inverter a ordem dos itens na sequência,obter os itens que satisfaziam o critério e inverteros itens da sequência resultante.

Algo como isto:

Parece simples, certo? Primeiro chamamos ométodo Reverse para produzir uma novasequência com os mesmos itens mas na ordeminversa da sequência original, depois chamamoso método TakeWhile para obter os primeirositens que satisfazem o critério e, finalmente,chamamos novamente o método Reverse pararecuperar a ordem original dos itens.

O problema desta aproximação é que o métodorev memoriza toda a sequência antes de iterarsobre os seus itens na ordem inversa – e ocódigo acima usa-o duas vezes. Isto significaiterar sobre todos os itens da sequência originale memoriza-los, iterar sobre os primeiros itensque satisfazem o critério e memoriza-los e,finalmente, iterar sobre estes itens para produzira sequência final.

Se estiveram a contar, chegaram à conclusão deque se iterou sobre todos os itens da sequência

Sequence.Reverse()

.TakeWhile(criteria).Reverse();

int[] grades = 59, 82, 70, 56, 92, 98, 85;

var topThreeGrades = grades.OrderBy(grade => grade).TakeLast(3);

Console.WriteLine("As notas mais altassão:");

foreach (int grade in topThreeGrades)

Console.WriteLine(grade);

Page 5: Revista programar 26

5

TEMA DE CAPA

Tendo introduzido os operadores TakeLast, faztodo o sentido introduzido os seus duais: osoperadores SkipLast:

SkipLast<TSource>(IEnumerable<TSource>)

Retorna todos os elementos da sequência àexcepção do número especificado de elementoscontínuos no fim da sequência.

TakeLastWhile<TSource>(IEnumerable<TSou

rce>, Func<TSource, Boolean>)

Retorna os elementos do fim da sequência paraos quais a condição especificada é verdadeira.

TakeLastWhile<TSource>(IEnumerable<TSou

rce>, Func<TSource, Int32, Boolean>)

Retorna os elementos do fim da sequência paraos quais a condição especificada é verdadeira.

string[] fruits = "maçã", "maracujá","banana", "manga",

"laranja", "mirtilo", "uva", "morango" ;

var query = fruits.TakeLastWhile((fruit, index) =>fruit.Length >= index);

foreach (string fruit in query)

Console.WriteLine(fruit);

/*Este código produz o seguinte resultado:morango*/

/*Este código produz o seguinte resultado:As notas mais altas são:

989285*/

string[] fruits = "maçã", "maracujá","banana", "manga",

"laranja", "mirtilo", "uva", "morango";

var query = fruits.TakeLastWhile(fruit =>string.Compare("laranja",fruit, true) != 0);

foreach (string fruit in query)

Console.WriteLine(fruit);

/*Este código produz o seguinte resultado:maracujáuvamorango*/

int[] grades = 59, 82, 70, 56, 92, 98, 85 ;

var lowerGrades = grades.OrderBy(g => g).SkipLast(3);

Console.WriteLine("Todas as notas excepto astop 3:");

foreach (int grade in lowerGrades)

Console.WriteLine(grade);

LI NQ: Imp l emen tação d os operad o res TakeLast , TakeLastWh i l e , Ski p Last e Ski p LastWh i l e

Page 6: Revista programar 26

6

TEMA DE CAPA

SkipLastWhile<TSource>(IEnumerable<TSour

ce>, Func<TSource, Boolean>)

Retorna todos os elementos da sequência àexcepção dos elementos do fim da sequênciapara os quais a condição especificada éverdadeira.

SkipLastWhile<TSource>(IEnumerable<TSour

ce>, Func<TSource, Int32, Boolean>)

Retorna todos os elementos da sequência àexcepção dos elementos do fim da sequênciapara os quais a condição especificada éverdadeira.

IMPLEMENTADO OS OPERADORES

TAKELAST

Implementando O Operador TakeLast

O operador TakeLast retorna o númeroespecificado de elementos contínuos do fim deuma sequência e é implementado como ométodo de extensão TakeLast.

Para implementar este operador, primeirocomeçamos por memorizar, pelo menos, onúmero requerido (count) de itens da sequência

/*Este código produz o seguinte resultado:As notas mais altas, excepto:56597082*/

int[] grades = 59, 82, 70, 56, 92, 98, 85 ;

var lowerGrades = grades.OrderBy(grade => grade).SkipLastWhile(grade =>grade >= 80);

Console.WriteLine("Todas as notas menores que80:");

foreach (int grade in lowerGrades)

Console.WriteLine(grade);

/*Este código produz o seguinte resultado:Todas as notas menores que 80:565970*/

int[] amounts =

5000, 2500, 9000, 8000,6500, 4000, 1500, 5500

;

var query = amounts.SkipWhile((amount, index) => amount >

index * 1000);

foreach (int amount in query)

Console.WriteLine(amount);

/*Este código produz o seguinte resultado:50002500*/

LI NQ: Imp l emen tação d os operad o res TakeLast , TakeLastWh i l e , Ski p Last e Ski p LastWh i l e

Page 7: Revista programar 26

7

TEMA DE CAPA

fonte (source) num array que funciona comouma memória intermédia (buffer) circular:

Se o número de itens memorizados(numOfItems) for inferior ao número requerido(count), produzimos os itens memorizados:

Em seguida, iteramos pelos restantes itens evamos os armazenando, de forma circular, namemória intermédia:

E finalmente, iteramos sobre os itensmemorizados para produzir a sequência final:

Há duas optimizações que ainda podemos fazer.

A primeira é óbvia, se o número de itensrequerido for 0 (zero), retornamos umasequência vazia:

A segunda é se a sequência fonte (source)implementar a interface IList<T>. Os objectosque implementam esta interface têm umapropriedade Count e acesso indexado aos seusitens que nos permite optimizar a produção dasequência final.

A produção da sequência final passa porproduzir o número de itens requeridos do fim dalista (ou todos se a lista contiver menos que ositens requeridos):

Implementando os Operadores

TakeLastWhile

O operador TakeLastWhile retorna os últimos

var sourceEnumerator =source.GetEnumerator();var buffer = new TSource[count];var numOfItems = 0;int idx;

for (idx = 0; (idx < count) &&sourceEnumerator.MoveNext(); idx++,numOfItems++)buffer[idx] = sourceEnumerator.Current;

if (numOfItems < count)

for (idx = 0; idx < numOfItems; idx++)

yield return buffer[idx];yield break;

for (; numOfItems > 0; idx = (idx + 1) %count, numOfItems--)

yield return buffer[idx];

for (idx = 0; sourceEnumerator.MoveNext();idx = (idx + 1) % count)

buffer[idx] =sourceEnumerator.Current;

if (count <= 0)

returnSystem.Linq.Enumerable.Empty<TSource>();

int listCount = list.Count;for (int idx = listCount - ((count <listCount) ? count : listCount); idx <listCount; idx++)

yield return list[idx];

LI NQ: Imp l emen tação d os operad o res TakeLast , TakeLastWh i l e , Ski p Last e Ski p LastWh i l e

Page 8: Revista programar 26

8

TEMA DE CAPA

elementos contíguos que satisfazem o critérioespecificado e é implementado como osmétodos de extensão TakeLastWhile.Para implementar este operador, primeirocomeçamos com uma memória intermédia(buffer) vazia e, para cada item que satisfaça ocritério implementado pelo predicado (predicate),memorizamos esse item. Sempre que ocorrerum item que não satisfaça o critério de selecção,a memória intermédia é l impa:

Depois de percorrer toda a sequência fonte(source), produzimos todos os itens, seexistirem, da memória intermédia:

A diferença para o método que tem em conta oíndice do item no predicado (predicate) deselecção é apenas na invocação deste:

IMPLEMENTANDO OS OPERADORES

SKIPLAST

Implementando o Operador SkipLast

O operador SkipLast retorna o númeroespecificado de elementos contínuos do fim deuma sequência e é implementado como ométodo de extensão SkipLast.

Para implementar este operador, começamospor memorizar, pelo menos, o número requerido(count) de itens da sequência fonte (source) numarray que funciona como uma memóriaintermédia (buffer) circular:

Em seguida, iteramos pelos restantes itens dasequência fonte (source) memorizando

var buffer = new List<TSource>();var idx = 0;

foreach (var item in source)

if (predicate(item, idx++))

var buffer = new List<TSource>();foreach (var item in source)

if (predicate(item))

buffer.Add(item);else

buffer.Clear();

foreach (var item in buffer)

yield return item;

var sourceEnumerator =source.GetEnumerator();var buffer = new TSource[count];int idx;

for (idx = 0; (idx < count) &&sourceEnumerator.MoveNext(); idx++)

buffer[idx] = sourceEnumerator.Current;

buffer.Add(item);else

buffer.Clear();

foreach (var item in buffer)

yield return item;

LI NQ: Imp l emen tação d os operad o res TakeLast , TakeLastWh i l e , Ski p Last e Ski p LastWh i l e

Page 9: Revista programar 26

9

TEMA DE CAPA

Se o número de itens da sequência fonte(source) for superior ao número de itens aexcluir, produzir a sequência final consiste emproduzir todos os itens da sequência fonte(source) excepto os últimos count itens:

Implementando os Operadores

SkipLastWhile

O operador SkipLastWhile retorna os últimoselementos contíguos que satisfazem o critérioespecificado e é implementado como osmétodos de extensão SkipLastWhile.

Para implementar este operador, primeirocomeçamos com uma memória intermédia(buffer) vazia e, para cada item que satisfaça ocritério implementado pelo predicado (predicate),memorizamos esse item.

Sempre que ocorrer um item que não satisfaça ocritério de selecção, a memória intermédia él impa e o item que não satisfaz o critério éproduzido:

circularmente cada item e produzindo o itemarmazenado anteriormente na mesma posição:

Se o número de itens a excluir for igual ousuperior ao número de itens existentes nasequência fonte (source), o métodosourceEnumerator.MoveNext() retornará false naprimeira iteração do ciclo while e será produzidauma sequência vazia.

Tal como acontecia com o operador TakeLast,podem-se fazer algumas optimizações.

A primeira é óbvia, se o número de itensrequeridos for 0 (zero) ou inferior, retornamosuma sequência equivalente à fonte (source):

A segunda é se a sequência fonte (source)implementar a interface IList<T>. Os objectosque implementam esta interface têm umapropriedade Count e acesso indexado aos seusitens que nos permite optimizar a produção dasequência final.

Se o número de itens a excluir for igual ousuperior ao número de itens da sequência fonte(source), retornamos uma sequência vazia:

idx = 0;

while (sourceEnumerator.MoveNext())

var item = buffer[idx];buffer[idx] = sourceEnumerator.Current;idx = (idx + 1) % count;

yield return item;

if (count <= 0)

return source.Select(i => i);

var list = source as IList<TSource>;if (list != null)

if (count >= list.Count)returnSystem.Linq.Enumerable.Empty<TSource>();// ...

int returnCount = list.Count - count;

for (int idx = 0; idx < returnCount; idx++)

yield return list[idx];

LI NQ: Imp l emen tação d os operad o res TakeLast , TakeLastWh i l e , Ski p Last e Ski p LastWh i l e

Page 10: Revista programar 26

10

TEMA DE CAPA

A diferença para o método que tem em conta oíndice do item no predicado (predicate) deselecção é apenas na invocação deste:

Conclusão

Como podem ver, implementar este tipo deoperadores é muito fácil , pelo que, não se deveevitar a sua implementação sempre que sejustifique. Implementar um específico para anossa aplicação pode significar uma melhorlegibi l idade do código e até um aumento deperformance.Podem encontrar a implementação completadestes operadores (e outros) no meu projecto deuti l i tários e operadores para LINQ no CodePlex:PauloMorgado.Linq.

Recursos

O meu website: http: //PauloMorgado.NET/Livro “LINQ Com C#”PauloMorgado.LinqClasse EnumerableMétodos de extensão

var buffer = new List<TSource>();var idx = 0;

foreach (var item in source)

if (predicate(item, idx++))

buffer.Add(item);

else

if (buffer.Count > 0)foreach (var bufferedItem in buffer)

yield return bufferedItem;

buffer.Clear();

yield return item;

var buffer = new List<TSource>();foreach (var item in source)

if (predicate(item))

buffer.Add(item);else

if (buffer.Count > 0)foreach (var bufferedItem in buffer)

yield return bufferedItem;

buffer.Clear();

yield return item;

Escrito por Paulo MorgadoÉ licenciado em Engenharia Electrónica e Telecomunicações (Sistemas Digitais) pelo Instituto Superior deEngenharia de Lisboa e Licenciado em Engenharia Informática pela Faculdade de Ciências e Tecnologiada Universidade Nova de Lisboa. Pelo seu contributo para a comunidade de desenvolvimento em .NETem língua Portuguesa, a Microsoft premeia-o com o prémio MVP (C#) desde 2003. É ainda co-autor dolivro “LINQ Com C#” da FCA.

AUTOR

LI NQ: Imp l emen tação d os operad o res TakeLast , TakeLastWh i l e , Ski p Last e Ski p LastWh i l e

Page 11: Revista programar 26

11

A PROGRAMAR

eles seguem a gramática que ele define. Se oobjectivo do parser for só verificar que um certoficheiro, por exemplo um ficheiro xml, segue aespecificação da linguagem, podemos não terinteresse nenhum em saber o valor de qualquertoken. A nossa calculadora no entanto, precisade produzir resultados, portanto necessita desaber o valor de cada token NUMBER querecebe. O parser define os tokens e o tipo devalores que lhes podem estar associados nazona das definições, sempre que precisa de umtoken novo ele chama o scanner com o resto doinput que falta analisar. Vejamos a definição dostokens para a nossa calculadora:

BYACCNo artigo anterior adquirimos algumas noçõessobre flex e vimos como implementar umscanner simples. Relembrando, o flex é umgerador de analisadores lexicais ou scanners, eo byacc é um gerador de parsers. Usados emconjunto permitem escrever aplicações bastantesofisticadas, mas no nosso artigo l imitamo-nos aconsiderar uma calculadora simples, servindocomo exemplo introdutório. Agora que temos oscanner para a nossa calculadora escritopodemos começar a considerar o parser.

Um ficheiro byacc tem a mesma estrutura que oflex, já que o analisador lexical em que o flex sebaseia, o lex, copiou a sua estrutura do yacc, ogerador de parsers em que o byacc se baseia.Como tal o nosso ficheiro byacc vai ser algodeste género:

Comecemos por considerar como é que o parsere o scanner funcionam em conjunto. Um parserrecebe tokens e verifica se esses tokens estão aseguir uma gramática. O que nós estávamos aretornar no scanner, o NUMBER e o NL sãoesses tokens. Os tokens podem ter um valorassociado ou não. O que o parser faz é ver se

definições

%%

gramática

%%

int main()

yyparse();

%union double d;

;

%token<d> NUMBER%token NL

%left '+' '-'%left '*' '/'%right '^'%nonassoc UMINUS

%%

...

%%

int main()

yyparse();

Page 12: Revista programar 26

12

A PROGRAMAR

Esta versão do parser introduz a gramática, mascomecemos por observar as diferenças nasecção das definições. Podemos ver primeiroque a introdução de código C/C++ se processada mesma forma que no scanner. Em seguidatemos a instrução, %type<d> expr, expr não éum token, é outro símbolo da gramática masainda assim tem um tipo, portanto temos que oindicar.

Uma gramática, tal como a gramática da língua

A primeira coisa que encontramos é uma%union, seguida da declaração de dois tokens,NUMBER e NL. A %union serve para indicartipos que queiramos associar a tokens eeventualmente a elementos da gramática. Aoescrevermos %token<d> NUMBER estamos aindicar que para além de NUMBER ser umtoken, tem um valor associado do tipo d, nestecaso double. Isto vai ser importante quandopassarmos para a gramática e é por esta razãoque no scanner passávamos o número quetínhamos lido ao yylval.d antes de retornarmos otoken. A informação da union e dos tokens queescrevermos nesta secção vai servir para obyacc gerar o header ao qual o nosso scannerfez #include e que permite ao scanner e aoparser comunicarem entre si. O '+', '-', '*', '/', '^' eUMINUS também são tokens mas aqui paraalém de indicarmos que são tokens estamos aindicar a associatividade dos operadores, umconceito que o leitor deverá conhecer, mas queabordaremos com maior profundidade nagramática.

%#include <iostream>#include <cmath>%

%union double d;

;

%token<d> NUMBER%token NL

%left '+' '-'%left '*' '/'%right '^'%nonassoc UMINUS

%type<d> expr

%%expr_list : expr NL std::cout<< $1 << std::endl;

| expr_list expr NL std::cout << $2 << std::endl;

;

expr : NUMBER $$ = $1; | '-' expr %prec UMINUS $$ =

-$2; | expr '+' expr $$ =

$1+$3; | expr '-' expr $$ = $1-

$3; | expr '*' expr $$ =

$1*$3; | expr '/' expr $$ =

$1/$3; | expr '^' expr $$ =

pow($1, $3); | '(' expr ')' $$ = $2;

;

%%

int main()

yyparse();

BYACC

Page 13: Revista programar 26

13

A PROGRAMAR

portuguesa, serve para nos indicar a estruturada linguagem, quais as composições deelementos que são válidas ou não de acordocom a linguagem. É fácil de ver como isto é úti lpara um compilador. A nossa calculadora temuma gramática muito simples, mas ainda assimtem-la, portanto temos que compreender algunsprincípios sobre gramáticas. As gramáticas sãoum conjunto de regras, às quais chamamosproduções, constituídas por uma cabeça e umcorpo. Por exemplo,

é uma produção, com cabeça stmt e corpoWHILE expression stmt. A cabeça indica-nosuma construção da gramática e o corpo comoela é composta. Os elementos duma gramáticadividem-se em símbolos terminais e nãoterminais, sendo os terminais, para efeitos desteartigo, os tokens que o scanner envia e os não-terminais as cabeças de produções, ou sejasímbolos que podem ser produzidos atravésdoutros símbolos.

Por clareza, usamos maiúsculas pararepresentar terminais e minúsculas para nãoterminais, logo, no exemplo acima, stmt eexpression são símbolos não terminais enquantoque o WHILE é terminal. Um símbolo terminalnão pode ser obtido através da junção de outrossímbolos, portanto só pode aparecer em corposde produções. Um não terminal por outro ladopode ser derivado de terminais e outros nãoterminais, logo pode aparecer tanto na cabeçacomo no corpo duma produção. Um símbolo nãoterminal pode, e habitualmente, tem váriasdefinições. Pegando no exemplo anterior eexpandindo, obtemos,

faz sentido criar várias produções para um stmt,já que um stmt pode ser várias coisas. Nestecaso, um while, um if, um bloco, e continuandoteríamos um for, um switch, um do while, etc.Sendo usual a existência de várias produçõescom a mesma cabeça, o byacc permite usar aseguinte sintaxe, com significado equivalente,para aumentar a legibi l idade:

Se quiséssemos escrever um parser para umalinguagem de programação, tínhamos de teruma forma de relacionar as várias regras, poroutras palavras uma gramática necessita deuma estrutura. A forma de criar essa estrutura écriando um símbolo não terminal inicial ao qualtodos os outros estão subordinados. Pode ajudarpensar na estrutura da gramática como umaárvore na qual o símbolo não terminal inicial é araiz, os outros não terminais são nós e osterminais são as folhas.

stmt : WHILE expression stmt;stmt : IF expression stmt;stmt : IF expression stmt ELSE stmt;stmt : block;...

stmt : WHILE expression stmt| IF expression stmt| IF expression stmt ELSE stmt| block

...;

%%

program : list;

list : statement| list statement;

statement : declaration| function;

declaration : type identifier| type identifier '='

expression;

stmt : WHILE expression stmt;

BYACC

Page 14: Revista programar 26

14

A PROGRAMAR

Acima temos um esqueleto de uma linguagemmuito simplificada, ainda com vários nãoterminais sem produções associadas, mas bastapara termos uma noção da estrutura dumagramática. Qualquer que seja o programa escritopara esta l inguagem, se ele estiversintacticamente correcto deve ser possível partirde program e derivar todos os elementos que ocompõem. Neste caso program é o símboloinicial da gramática, e indicamos isso ao byacccolocando-o como a primeira produção doficheiro.Já vimos nos exemplos anteriores que asproduções podem ser recursivas, o corpo dumaprodução pode conter o mesmo não terminalque é a cabeça. A recursividade é necessária ealgo que o byacc processa muito eficientemente,mas usada sem cuidado é uma das coisas queintroduz confl ictos na gramática. Um confl ictosurge quando o parser não sabe que regra usarpara uma determinada sequência de tokens. Umexemplo segue-se:

Este caso é óbvio, temos duas produçõesdiferentes com o mesmo corpo, o parser nãosabe qual deve usar quando recebe os trêstokens. O mesmo se passa nos casos seguintes.

O byacc só tem um token de lookahead, ou seja,no caso abaixo ele não consegue decidir se oque recebeu foi o x ou o y porque no momentode escolher a produção ele só sabe que o sesegue é o token C. Como existem dois casoscom o token C, ele não sabe o que fazer. Istonão é um problema com a gramática, é umalimitação do byacc.

O mesmo não ocorre no caso seguinte. Nestasituação ele consegue saber que produção usarvendo se o lookahead é D ou F.

s : x| y;

x : A B C ;y : A z C ;z : B ;

s : x| y;

x : A B C ;y : z C ;z : A B ;

s : x C D| y C F;

x : A B;y : A B;

type : INT| DOUBLE| CHAR;

function : type identifier '(' arg_list ')'block

;

block : '' stmt_list '';

stmt_list : stmt| stmt_list stmt;

...%%

s : x| y;

x : A B C ;y : A B C ;

BYACC

Page 15: Revista programar 26

15

A PROGRAMAR

A existência de confl ictos na gramática nãoimpede o parser de ser gerado, já que o byacctem comportamentos default quando não sabeque produção usar, mas claro que ocomportamento default pode não ser o que oprogramador tinha em mente quando escreveu agramática portanto convém eliminar os confl ictosantes de gerar o parser.

Os confl ictos são introduzidos na escrita dagramática e podem sempre ser el iminadosreescrevendo-a, mas por vezes é preferívelel iminá-los usando precedências. Tomemos oseguinte exemplo clássico, o “dangling else”:

Para o seguinte input:

O problema que nos surge é que o parser nãosabe se o que ele tem é um IF expression stmtcom expression igual a (a) e o stmt igual a if(b) c= a + b; else c = a; ou se em vez disso tem umIF expression stmt ELSE stmt com expressiontambém igual a (a), o primeiro stmt igual a if(b) c= a + b; e o segundo stmt igual a c = a; . O quequeremos que o parser faça? Associe o else aoprimeiro if ou ao segundo? O comportamentoque esperamos é que associe ao segundo,portanto para o conseguir vamos usarprecedências.

s : x D| y F;

x : A B;y : A B;

stmt : IF expression stmt| IF expression stmt ELSE stmt;

Introduzimos o token IFX - o token ELSE já temde estar definido, tal como o IF se o estamos ausar na gramática - que não é retornado peloscanner. O IFX só existe dentro do parser eserve apenas para indicar o nível deprecedência de uma produção. Indicamos aobyacc o nível de precedência dos tokens pelaordem em que os declaramos, tendo os últimosmaior precedência que os primeiros. Aprecedência de um token determina aprecedência da produção em que ele seencontra, numa situação em que duasproduções são viáveis como no exemplo anteriora produção com maior precedência é usada. Sequisermos modificar a precedência de umaprodução sem afectar a precedência de nenhumdos seus tokens, podemos, como mencionadopreviamente, criar um token “falso” como o IFX eescrever %prec IFX no fim da produção para oconseguir. Usando o token IFX no primeiro IFestamos a dizer que aquele tipo de if tem menosprecedência que o segundo IF, já que o token IFXé declarado antes do token ELSE, portantoquando existem as duas hipóteses o parserescolhe sempre a segunda, o que é ocomportamento que desejávamos.

%nonassoc IFX%token ELSE

...

%%

...

stmt : IF expression stmt %prec IFX| IF expression stmt ELSE stmt;

...%%

if(a)if(b) c = a + b; else c = a;

BYACC

Page 16: Revista programar 26

16

A PROGRAMAR

Neste caso para o input NUMBER * NUMBER *NUMBER por exemplo, o parser não sabe se há-de fazer (NUMBER * NUMBER) * NUMBER ouNUMBER * (NUMBER * NUMBER). Pararesolver este problema precisamos de indicar aassociatividade do operador binário '*' ao byacc.Um operador com associatividade à esquerdapara o input NUMBER * NUMBER * NUMBER *NUMBER faz ((NUMBER * NUMBER) *NUMBER) * NUMBER, um operador comassociatividade à direita faz NUMBER *(NUMBER * (NUMBER * NUMBER)) para omesmo input. A forma de indicar aassociatividade de um token ao byacc éescrever %left ou %right em vez de %tokenquando o declaramos. Para declarar umoperador unário não associativo (ou seja umoperador que não se pode encadear)escrevemos %nonassoc em vez de %token.

Entendendo associatividade e precedênciaspodemos começar a compreender a gramáticada nossa calculadora.

expr : expr '*' expr| NUMBER;

Dizemos que os operadores binários '+' e '-' sãoassociativos à esquerda e têm a mesmaprecedência. Os operadores '*' e '/' funcionam deforma idêntica mas têm maior precedência. Ooperador de potência '^' é associativo à direita etem a maior precedência de todos os operadoresbinários. O UMINUS indica que uma expressãonegada tem a maior precedência e que não sepode negar uma negação. Os parênteses forçama avaliação de qualquer que seja a expressãoque estiver dentro deles, contornando asprecedências caso seja necessário. Para o input,-1 ^2 + 5 + 3 - 2 * 3 ^ 4 ^ 5 / -6 / 2 - 5 a nossagramática vai fazer (((((-1 )^2) + 5) + 3) - (((2 * (3^ (4 ^ 5))) / (-6)) / 2)) - 5 como seria de esperar.

Podemos associar acções a cada produção,para serem executadas quando o parser acabade processar o corpo de uma produção e osubstitui pela cabeça. As acções indicam-se damesma forma que no scanner, e é possível usarelementos da produção dentro delas desde queeles tenham valores associados. Para indicar ovalor da cabeça usamos $$, para os membrosdo corpo usamos $1 , $2, … $n de acordo com aordem em que eles aparecem. Um não terminaltem por default associado um int. Se quisermosassociar um tipo diferente declaramos%type<tipo-do-valor-associado> nome-do-símbolo-não-terminal na primeira secção doficheiro. Vejamos então o ficheiro inteiro:

%token NUMBER

%left '+' '-'%left '*' '/'%right '^'%nonassoc UMINUS

%%

expr : NUMBER| '-' expr %prec UMINUS| expr '+' expr| expr '-' expr| expr '*' expr| expr '/' expr

| expr '^' expr| '(' expr ')';

%%%#include <iostream>#include <cmath>%

BYACC

Page 17: Revista programar 26

17

A PROGRAMAR

O ficheiro começa com os #includes de C++ queprecisamos, seguidos da %union com o únicotipo que a nossa calculadora necessita, umdouble. Lemos a declaração dos tokens, com os

Escrito por João MaresEstando actualmente no terceiro ano de LEIC no IST, interssa-se preferencialmente por arquitectura decomputadores e computação gráfica.

AUTOR

tipos associados,associatividade eprecedência. Concluímos aprimeira secção com adeclaração que o símbolo nãoterminal expr tem um valorassociado do tipo double. Istoé essencial porque as nossasoperações não estão areceber tokens NUMBERcomo argumentos mas simnão terminais expr. O símboloinicial da nossa gramática éexpr_list e está definido comouma sequência de um ou maisnão terminais expr, separadospor mudanças de linha.Associamos a cada produçãode expr_list a acção daimpressão do valor de expr.As produções com cabeçaexpr tem associadas asacções que realizam oscálculos, guardando osvalores na cabeça. Na terceirasecção temos um main quechama o yyparse().

Neste momento temos umparser e um scanner para anossa calculadora, no próximoartigo veremos como ligá-los ecomo modificar o scanner e o

parser em conjunto de forma a adicionar maisfuncionalidades à calculadora.

%union double d;

;

%token<d> NUMBER%token NL%left '+' '-'%left '*' '/'%right '^'%nonassoc UMINUS%type<d> expr

%%expr_list : expr NL std::cout << $1 << std::endl;

| expr_list expr NL std::cout << $2 << std::endl; ;

expr : NUMBER $$ = $1; | '-' expr %prec UMINUS $$ = -$2; | expr '+' expr $$ = $1+$3; | expr '-' expr $$ = $1-$3; | expr '*' expr $$ = $1*$3; | expr '/' expr $$ = $1/$3; | expr '^' expr $$ = pow($1, $3); | '(' expr ')' $$ = $2; ;

%%int main()

yyparse();

BYACC

Page 18: Revista programar 26

18

VISUAL (NOT) BASIC

I n trod u ção ao En t i ty Frameworktenham como nome “Jorge” e que tenham comomorada a “Moita”.

Imaginemos que o programador ou o DBA(database administrator) altera o campo “nome”para “nomecompleto”, pois quer que se registe onome completo do uti l izador e, desta forma, onome do campo fica mais coerente. Seaplicação for compilada não é detectadoqualquer problema e só no momento deexecução irá ocorrer um erro. Situações comoestas são muito frequentes e podemrepresentam vários erros na aplicação.

Este é apenas um exemplo de como se podebeneficiar, e muito, da uti l ização do EntityFramework, mas existem muito mais vantagenscomo a uti l ização de LINQ to Entities,intel l isense no momento em que se está aescrever o código, código mais fácil de manter eactual izar, etc, etc.

Neste artigo, que será uma breve introdução aoEntity Framework, irá apenas mostrar comoconstruir um modelo relacional de uma base dedados SQL, uma abordagem database-first, ecomo executar algumas operações CRUD.

CRIAÇÃO DO MODELO RELACIONAL

(database-first)

Para criação de um modelo relacional iremosusar a seguinte base de dados SQL:

O ADO.NET Entity Framework permite criaraplicações em que o acesso a dados é feito combase em um modelo conceitual e não uti l izandocomandos directos à base de dados. Istopermite que o programador se abstraiatotalmente da base de dados (criação deligações de acesso, comandos, parâmetros, etc.)e uti l ize apenas objectos durante odesenvolvimento.

A versão 4.0 do Entity Framework (actual), queestá disponível na .NET Framework 4.0, tem umconjunto de novas funcionalidades e melhorias,como é o caso de suporte a POCO - Plain OldCLR Objects (permite criar classes que nãoherdam, nem implementam nenhuma outraclasses ou interface), abordagem Model-First(permite criar primeiro o modelo conceptual e,com base nele, criar a base de dados), suportepara o uso de funções em LINQ-to-Entities,Complex Types (criação de tipos de dadoscomplexos), Deferred Loading ou Lazy Loading(capacidade de carregar as propriedades deassociação das entidades no momento em sãochamadas, se forem chamadas), etc. Não éespecifica apenas para o SQL Server, poisexistem providers que permitem usar outrasbases de dados, como Oracle, MySql,PostgreSQL, DB2, SQL Anywhere, Ingres,Progress, Firebird, Synergy, etc.

Existem várias vantagens na uti l ização de umORM (Object-relational mapping), que tornam asua adopção quase inevitável, mas vejamos oseguinte exemplo:

“SELECT * FROM utilizadores WHERE nome =‘Jorge’ AND morada = ‘Moita’”Este exemplo irá l istar todos os uti l izadores que

Page 19: Revista programar 26

19

VISUAL (NOT) BASIC

Como é possível ver nesta imagem, existemapenas 3 tabelas, com as respectivas chavesprimárias/estrangeiras: produtos, cl ientes e umaterceira tabela onde se registam os movimentos.

O primeiro passo é adicionar um novo item aoprojecto (menu Project – Add New Item), eseleccionar no grupo de templates “Data” o item“ADO.NET Entity Data Model”. Isto irá iniciar umWizard que permitirá criar o modelo final.

De seguida seleccionar “Generate fromdatabase” e carregar em “Next”.

A próxima opção permite fazer a l igação à basede dados, escolhendo uma já existente oucriando uma nova ligação.

Para o nome da ligação, e para este exemplo,uti l ize “vendasEntities“.

A última opção deste Wizard é onde sãoseleccionados os objectos a uti l izar no modelo.Neste exemplo são escolhidas as três tabelas járeferidas.

Após este processo está criado o ficheiro EDMX,que não é mais do que um conjunto de classes emétodos que nos permitirá aceder à base dedados de uma forma simples, como iremos verde seguida.OPERAÇÕES CRUD

As operações CRUD (acrónimo de Create,Read, Update e Delete em Inglês) são quatrooperações básicas e fundamentais para amanipulação de bases de dados. São por isso

I n trod u ção ao En t i ty Framework

Page 20: Revista programar 26

20

VISUAL (NOT) BASIC

bastante importantes e requerem, sem auti l ização de um ORM como o Entity Framework,algum trabalho que é normalmente complexo.

Com o Entity Framework este trabalho estábastante simplificado para o programador,necessitando apenas de algumas linhas decódigo, com recurso a Intel l iSense, para asexecutar.

O funcionamento para todas as operações ésemelhante: é criada uma nova instância danossa entidade (neste exemplo “vendasEntities”)que herda de uma classe da EntityFrameworkchamada ObjectContext, que a classe primária eresponsável de gerir a informação comoobjectos e a ligação dos objectos aos dados.

Inserir registos

Para inserir novos registos, neste caso um novocliente, criamos uma nova instância darespectiva classe, definindo as suaspropriedades, que correspondem aosrespectivos campos. Depois adicionamos oobjecto através do método AddObject() e,finalmente, executamos o métodoSaveChanges() que irá efectuar as respectivasalterações, neste caso inserir um registo, nabase de dados.

Apagar registos

Para apagar um registo é necessário seleccionaro registo correcto, neste caso usando umaLambda Expression, e caso o resultado sejaválido, executamos o método DeleteObject(),indicando o registo a apagar.

Finalmente gravamos as alterações na base dedados.

Using context As New vendasEntities

' Procura o registo com o número de' cliente (ID) igual a 1

Dim cliente = context.clientes.Where(Function(c) c.id = 1).FirstOrDefault()

If cliente IsNot Nothing Thencontext.clientes.DeleteObject(cliente)context.SaveChanges()

ElseMessageBox.Show(

"Número de cliente inválido")End If

End Using

Using context As New vendasEntities

' Cria um novo clienteDim cliente As New clientes With

.nome = "Rui Paulo",.morada = "Lisboa",.datanascimento =New DateTime(1980, 10, 31)

context.clientes.AddObject(cliente)context.SaveChanges()

' Podemos verificar logo o número' (ID) do registo inserido

Debug.WriteLine("Número de registo: " &cliente.id.ToString())

End Using

I n trod u ção ao En t i ty Framework

Page 21: Revista programar 26

21

VISUAL (NOT) BASIC

Modificar Registos

Para modificar um registo, e à semelhança daoperação anterior, é necessário seleccionar oregisto. Neste exemplo uti l izamos LINQ toEntities para fazer essa selecção. Depois,modificamos o que for para modificar efinalmente gravamos as alterações.

Listar Registos

A listagem de registo é também muitosemelhante às operações anteriores. Nesteexemplo, usando LINQ to Entities, vamosseleccionar todos os registo com base numcritério, para uma variável do tipo IQueryable(OfT), e depois efectuamos um ciclo para mostraros resultados obtidos.

Entre entidades existir normalmenteassociações, e essas associações (tambémrepresentadas na última imagem), têm algo quese designa por Navigation Properties. AsNavigation Properties permitem uma navegaçãobidireccional entre entidades, de acordo com assuas associações. Isto é algo bastante práticopois permite-nos criar queries entre váriasentidades usando LINQ to Entities.

O seguinte exemplo mostra esta abordagem,definindo depois o resultado como DataSourcenum controlo DataGridView.

NOTA: Se utilizar uma base de dados anexa ao

Using context As New vendasEntities

Dim cliente =(From c In context.clientesWhere c.id = 1Select c).FirstOrDefault()

If cliente IsNot Nothing ThenWith cliente

.nome = "Rui Paulo"

.morada = "Setúbal"

.datanascimento =New DateTime(1979, 10, 31)

End Withcontext.SaveChanges()

ElseMessageBox.Show("Número de cliente inválido")

End If

End Using

Using context As New vendasEntities

Dim listaClientes =From c In context.clientesWhere c.morada.Contains("Lisboa") Andc.datanascimento <

New DateTime(1985, 1, 1)Select c

For Each c As clientes In listaClientesDebug.WriteLine(c.nome)

Next

End Using

Using context As New vendasEntities

Dim listaClientes =From c In context.clientesJoin m In context.movimentos

On m.clienteid Equals c.idJoin p In context.produtos

On m.produtoid Equals p.idSelect m.datavenda,

I n trod u ção ao En t i ty Framework

Page 22: Revista programar 26

22

VISUAL (NOT) BASIC

projecto (AttachDb), a base de dados é copiadapara as pastas Debug/Release. Podeseleccionar no menu Project a opção Show AllFiles e verificar as alterações nessa localização.

CONCLUSÃO

Como foi possível ver ao longo do artigo, queabordou de uma forma muito superficial algumasdas funcionalidades deste ORM, o EntityFramework é uma excelente opção para setrabalhar com bases de dados.

É simples de uti l izar, permite-nos trabalharapenas com objectos e com intel l isense, resolveinúmeros problemas que são habituais quandotrabalhamos directamente com a base de dados(formatos de datas, números, caracteres

especiais), etc

Estas são apenas algumas, das muitasvantagens, que nos devem fazer de uma vez portodas, deixar de usar SqlCommands,SqlConnections, DataSets, etc.

Alguns recursos interessantes:

Data Developer Centerhttp: //msdn.microsoft.com/en-us/data/ef.aspx

Data Access Hands-on Labshttp: //msdn.microsoft.com/en-us/data/gg427655.aspx

ADO.NET team bloghttp: //blogs.msdn.com/b/adonet/

Jul ie Lerman's Bloghttp: //thedatafarm.com/blog/

Select m.datavenda,c.nome,p.produto,m.preco

Me.DataGridView1.DataSource = listaClientes

End Using

Escrito por Jorge PaulinoExerce funções de analista-programador numa multinacional sediada em Portugal. É formador e ministracursos de formação em tecnologias Microsoft .NET e VBA. É Microsoft Most Valuable Professional (MVP),em Visual Basic, pela sua participação nas comunidades técnicas . É administrador da ComunidadePortugal-a-Programar e membro de várias comunidades (PontoNetPT, NetPonto, MSDN, Experts-Exchange, CodeProject, etc). É autor do blog http: //vbtuga.blogspot.com - twitter @vbtuga

AUTOR

I n trod u ção ao En t i ty Framework

Page 23: Revista programar 26

23

A PROGRAMAR

Programação Fu nc i ona l com Perl (p a rte I )sobre PF por exemplo). Como já há váriosartigos sobre PF em diversas l inguagens, comoPython, Scheme, Haskell (recomendo que osleiam), deixo aqui a sugestão a alguém, pararedigir um artigo teórico e agnóstico (em relaçãoa linguagens de programação) sobreProgramação Funcional.

Algumas das funcionalidades elementares daslinguagens funcionais são as funções anónimase as closures. O Perl tem ambas as features.

Uma das alterações que o Perl 5.1 2 trouxe foiuma função chamada say. O say é basicamenteum print que adiciona um newline à string quequeremos imprimir (poupa-nos pelo menos 4caracteres).

Qualquer uma das seguintes l inhas de códigovai imprimir isolado numa linha a string: «Helloworld!»:

Começo com este artigo uma série de artigosrelacionados com a Programação Funcional emPerl.

Nesta série de artigos pretendo demonstraralgumas das capacidades do Perl para uti l izaçãocom o paradigma de Programação Funcional.

Não pretendo ensinar nem as bases daProgramação Funcional, nem do Perl. Vou abrirexcepções quando se tratarem de aspectos maisavançados e/ou muito relacionados com aprópria Programação Funcional. A compreensãoelementar do Perl e da Programação Funcionalé um requisito para a compreensão destesartigos contudo tudo será explicado de forma apermitir que um principiante possa compreendertudo e quem tiver dúvidas poderá contactar-mepara as esclarecer.

Umas das principais características do Perl, emseguimento do mantra da sua comunidade(«There's more than one way to do it»), é nãoobrigar o programador a uti l izar, ou escolher umparadigma de programação, mas sim permitir aoprogramador uti l izar o que quiser quando quiser,ficando ao cuidado dele ter os cuidadosnecessários para que o código seja úti l e sigaboas práticas de programação. Há quemconcorde com esta fi losofia, há quem nãoconcorde, mas a fi losofia do Perl e da suacomunidade não é o âmbito deste artigo.

Um dos muitos paradigmas de programação quesão possíveis uti l izar em Perl é a ProgramaçãoFuncional (PF). Contudo não cabe a este artigoexplicar a PF. Por isso sugiro que antes deprosseguirem na leitura deste artigo leiam pelomenos uma curta explicação do que é PF (osprimeiros parágrafos do artigo da Wikipedia

print "Hello world!\n";print "Hello world!"."\n";print "Hello world!", "\n";say "Hello world!";

Umas das principaiscaracterísticas do Perl

(. . . ) é não obrigar oprogramador a uti l izar (. . . )mas sim permitir aoprogramador uti l izar o quequiser quando quiser

Page 24: Revista programar 26

24

A PROGRAMAR

uti l ização nas "dispach tables":

Explicação do código do exemplo anterior:

Começou por ser definido uma hash table que,como chaves contém, as opções válidas delínguas que queremos uti l izar na impressão deuma saudação e como valores, tem funçõesanónimas que imprimem uma saudação nalíngua representada pela sua chave na hashtable.

Isto poderia ter sido feito definindoindividualmente funções "regulares", criandovariáveis que eram referências para cada umadessas funções e uti l izando essas variáveiscomo valores a uti l izar na hash table.

Mas isso traria imediatamente dois problemas:aumentaria a quantidade de código necessário eeste artigo tem um limite de caracteres; não

Para demonstrar a uti l ização de funçõesanónimas decidi criar uma implementação dafunção say que permite definir antes da suauti l ização como queremos que a string sejaformatada:

Explicação do código do exemplo anterior:

Primeiro começamos por definir a função say,como definiríamos qualquer outra função emPerl. Depois definimos a função anónima deformatação, e atribuímos essa função a umavariável (que guarda uma referência paracódigo) para que possa ser passada de formavisualmente mais l impa à função say(poderíamos também ter definido a funçãoanónima, na invocação de say mas faria comque o código fosse muito menos legível).

Qual a uti l idade das funções anónimas?

As uti l idades são diversas. E vão desde auti l ização das funções anónimas para podermodificar o comportamento de uma função quetenha sido criada para poder permitir essaalteração. Há quem uti l ize isto para poder porexemplo poder voltar a correr código que tinhasido serial izado. E passam pela uti l ização em"dispach tables". Uma outra uti l idade é a

sub say #definição da função saymy ($string, $format) = @_;my $str = $format->($string);print $str;

my $format = sub #função anónima deformatação da string

my $str = shift;return $str."\n";

;say("Hello world!", $format);

my %lingua = ( #dispach table"pt" => sub return "Olá mundo!" ,"es" => sub return "Hola mundo!" ,"en" => sub return "Hello world!" ,"fr" => sub return "Bonjour monde!" ,

);

sub dispach my $l = shift;

if(defined $lingua$l && exists$lingua$l)

my $str = $lingua$l->();print $str."\n";

else

print "Erro: lingua desconhecida!\n";

dispach("fr");

Programação Fu nc i ona l com Perl (p a rte I )

Page 25: Revista programar 26

25

A PROGRAMAR

uti l izaria funções anónimas, que é o objectivodeste exemplo ;).

Para além de isso, o que é pretendido nesteexemplo, é algo tremendamente simples quepode perfeitamente ser feito uti l izando funçõesanónimas, sem se aumentar a dificuldaderelevante da sua compreensão como um todo eem parte.

A opção por esta solução, em vez de a uti l izaçãode um encadeamento maior de if-elsif, ou de umswitch-case (também maior) permite que a

solução escale para mais opções de línguas,sem qualquer alteração e atinge melhor váriosdos objectivos da uti l ização de funções naprogramação: conter/isolar os problemas deforma a simplificar a sua resolução, facil itar acompreensão do código.

No próximo, artigo vou falar da segunda dasprincipais capacidades do Perl para aProgramação Funcional de que falei antes, asclosures.

Escrito por Diogo Constantinoé Consultor na área as tecnologias l icenciadas como Software Livre, com aproximadamente vários anosde experiência profissional, especial izado em desenvolvimento com Perl.Larga experiência na área de sistemas, engenharia e de operações de redes de telecoms, tendodesenvolvido, mantido e uti l izado ferramentas para diversas telecoms nestas áreas.Conhecimentos em tecnologias como Perl, Python, PHP, MySQL, GNU/Linux, C, HTML, CSS, Javascript,GNU/Linux. Tendo tido ainda contacto profissional com tecnologias como Switchs, equipamentos derouting, firewall ing e switching de diversos fabricantes, diversos sistemas *nix e diversas outrasferramentas e tecnologias comuns em sistemas *nix e/ou uti l izadas em empresas de telecomunicações,redes e web. Relativamente conhecido advogado da causa do Software Livre em diversas comunidades.Sócio da Associação Nacional para o Software Livre e da Associação Portuguesa de Programadores dePerl.

AUTOR

Programação Fu nc i ona l com Perl (p a rte I )

(. . . ) permite que a soluçãoescale para mais opções delínguas, sem qualquer alteração eatinge melhor vários dosobjectivos da uti l ização defunções na programação (. . . )

Page 26: Revista programar 26

26

COMUNIDADE NETPONTO

Backgrou ndWorkers - Imp l emen tação p rá t i ca emWi nd ows Presen tat i on Fou nd at i on (WPF)

System.ComponentModel. Esta classe permite-nos ajudar a gerir uma tarefa numa threadseparada da thread principal sem termos de nospreocupar com a inicial ização e gestão da threadonde vamos executar a tarefa.

As propriedades a ter em conta são:

CancellationPendingPermite obter se a tarefa foi cancelada.

WorkerReportsProgressPermite obter e definir se o BackgroundWorkervai reportar o seu progresso da tarefa.

WorkerSupportsCancellationPermitir obter e definir se o BackgroundWorkervai permitir cancelar a tarefa.

Os métodos a ter em conta são:

RunWorkerAsyncPermite iniciar a tarefa.Existem duas assinaturas deste método. Umadelas não tem argumento, a outra que o temuti l iza-o na execução da tarefa.

CancelAsyncPermite cancelar a tarefa e consequentemente oBackgroundWorker irá terminar.Para que seja possível cancelar a tarefa énecessário que a propriedadeWorkerSupportsCancellation tenha o valor deverdade true.

ReportProgressPermite reportar o progresso da tarefa em dadomomento.Para que o progresso seja reportado énecessário que o WorkerReportsProgress tenha

Neste artigo pretendo mostrar o que é oBackgroundWorker e vou exemplificar como sedeve proceder à sua implementação usando atecnologia WPF na versão .Net Framework 4.

Suponhamos:

“Tenho um algoritmo complexo de OptimizaçãoCombinatória que irá ter como parâmetro deentrada um objecto do tipo World. Classe quedefine toda a estrutura de dados da minhaaplicação e no final retorna o objecto World comas alterações realizadas pelo algoritmo.”Esta geração vai implicar que tenhamos pelomenos três passos:1 . A partir do objecto World vamos criar aestrutura de dados do algoritmo;2. Gera-se o algoritmo a partir dos dadosrecebidos;3. Depois de gerar o algoritmo é precisoconverter o resultado de forma a reflectir noWorld o resultado do algoritmo;

Enquanto estes três passos estão a decorrer, euquero ser informada sobre o progresso dageração do algoritmo e pretendo ter acapacidade de a cancelar.

Este cenário é um dos muitos cenários onde oBackgroundWorker pode ser implementado.Outros exemplos reais são a leitura de ficheirosextensos, aceder a base de dados para efectuaro carregamento de dados, fazer o load deimagens e gerar relatórios.

Antes de passarmos à implementação vou daruma breve apresentação teórica:

Um BackgroundWorker é uma classe contida no

Page 27: Revista programar 26

27

COMUNIDADE NETPONTO

três propriedades relevantes.São a propriedade Cancelled - que nos informase a tarefa foi cancelada, a propriedade Error -que nos reporta a excepção que fez terminar atarefa e a propriedade Result - que representa oresultado da execução da tarefa.

Vamos agora passar à implementação

prática, para isso vou usar um projecto do

tipo WPF Application.

Na interface da janela vamos ter:- Um Button para executar a tarefa;- Um Button para cancelar a tarefa;- Um Progressbar para mostrar o progresso;- Uma Listbox que indica mais detalhesdo progresso.

Toda a interface é definida no ficheiro .xaml.Em Code Behind iremos proceder àimplementação de toda a funcionalidade pararesolver o problema em causa.

1. Comecemos então por definir uma variávelglobal:

2. De seguida vamos criar um método ondevamos fazer a inicialização desta variável edefinir as suas propriedades e subscrever oseventos:

o valor de verdade true.Este método apresenta duas assinaturas,ReportProgress(int percentProgress) eReportProgress(int percentProgress, objectuserState). Ambas permitem reportar apercentagem da tarefa que já foi real izada. Naúltima assinatura é possível enviar maisinformação sobre o estado da tarefa.

Os eventos a ter em conta:

DoWorkOcorre quando o método RunWorkerAsync échamado.Ao subscrever este evento é definido um handlerque recebe dois parâmetros:- Um parâmetro do tipo object que representa oobjecto que subscreveu o evento.- Um parâmetro do tipo DoWorkEventArgs quecontém informação respeitante ao parâmetro deentrada e permite devolver o resultado da tarefa.De referir ainda que este parâmetro possui duaspropriedades relevantes. Sendo elas, apropriedade Argument - que representa oobjecto que é enviado como parâmetro dométodo RunWorkerAsync e a propriedade Result- que representa o resultado do DoWork.

ProgressChangedOcorre quando o método ReportProgress échamado.Um dos parâmetros do handler deste evento éum objecto do tipo ProgressChangedEventArgs,que contém duas propriedades relevantes, quesão o ProgressPercentage e UserState, cujosvalores foram enviados pelo métodoReportProgress;

RunWorkerCompletedOcorre quando a tarefa é terminada, canceladaou é lançada uma excepção.Um dos parâmetros do handler deste evento éum objecto do tipoRunWorkerCompletedEventArgs, que contêm

private BackgroundWorker _backgroundWorker;

Backgrou ndWorkers - Imp l emen tação p rá t i ca em Wi nd ows Presen tat i on Fou nd at i on (WPF)

Page 28: Revista programar 26

28

COMUNIDADE NETPONTO

De notar que já estou a definir que o meuobjecto _backgroundWorker vai permitir que atarefa seja cancelada a meio e que o progressoda tarefa possa ser reportado.

3. Agora vamos definir os handler doseventos:

4. No handler do evento do Click dobtnRunBackground vamos mandar executara tarefa e como parâmetro vamos enviar oobjecto _world.

Caso não pretendêssemos enviar parâmetrosusávamos a assinatura do RunWorkerAsyncsem parâmetros.

5. No handler do evento do Click dobtnCancel vamos mandar cancelar a tarefa,chamando o método CancelAsync.

6. Neste momento estamos prontos paradefinir a tarefa (handler):private void DoWork(object sender,DoWorkEventArgs e)É executado quando o método RunWorkerAsyncé chamado. Consideremos a seguinte porção decódigo:

private void InitializeBackgroundWorker() _backgroundWorker =new BackgroundWorker();_backgroundWorker.DoWork +=new DoWorkEventHandler(DoWork);_backgroundWorker.ProgressChanged +=new ProgressChangedEventHandler(ProgressChanged);_backgroundWorker.RunWorkerCompleted +=new RunWorkerCompletedEventHandler(RunWorkerCompleted);

_backgroundWorker.WorkerReportsProgress =true;_backgroundWorker.WorkerSupportsCancellation= true;

private void DoWork(object sender, DoWorkEventArgs e)private void ProgressChanged(object sender, ProgressChangedEventArgsargs)

private void RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e)

private void RunBackground_Click(object sender,RoutedEventArgs e) ClearProgress();_backgroundWorker.RunWorkerAsync((object)_world);btnCancel.IsEnabled = true;btnRunBackground.IsEnabled=false;

private void btnCancel_Click(object sender, RoutedEventArgs e) _backgroundWorker.CancelAsync();btnCancel.IsEnabled = false;btnRunBackground.IsEnabled = true;

private void DoWork(object sender,DoWorkEventArgs e) Algorithm algorithm = new Algorithm();World world = (World)e.Argument;

object stepValue = world;foreach(IAlgorithmStep step in algorithm.Steps)stepValue = step.DoWork(stepValue);e.Result = stepValue;

Backgrou ndWorkers - Imp l emen tação p rá t i ca em Wi nd ows Presen tat i on Fou nd at i on (WPF)

Page 29: Revista programar 26

29

COMUNIDADE NETPONTO

Note-se que vou obter o objecto do tipo Worldque foi enviado por parâmetro e em seguida vouiterar pelos vários passos do algoritmo.

Por fim vou devolver o resultado da tarefa.

Aparentemente posso pensar que já defini aminha tarefa, no entanto, ainda não estou a terem conta que poderei cancelar a execução doalgoritmo nem estou a reportar o progresso.

A cada passo do algoritmo vou verificar se atarefa foi cancelada através da propriedadeCancellationPending e consoante o valor deverdade desta propriedade a tarefa continua ounão.

Por fim temos que reportar o progresso de cadapasso e para isso vamos recorrer ao métodoReportProgress.

Neste momento já temos a nossa tarefa definidatendo em conta as operações que pretendíamos.

7. Para que o progresso seja apresentado nainterface com o utilizador é preciso definir oseguinte handler:private void ProgressChanged(object sender,ProgressChangedEventArgs args)Que é executado quando o métodoReportProgress é chamado.

private void DoWork( object sender,DoWorkEventArgs e) Algorithm algorithm = new Algorithm();World world = (World)e.Argument;object stepValue = world;foreach(IAlgorithmStep step in algorithm.Steps) if(_backgroundWorker.CancellationPending) e.Cancel = true;return;else stepValue =step.DoWork(stepValue);e.Result = stepValue;

private void DoWork(object sender, DoWorkEventArgs e) Algorithm algorithm = new Algorithm();World world = (World)e.Argument;_backgroundWorker.ReportProgress(5, "Is starting...");

private void ProgressChanged(object sender,ProgressChangedEventArgs args) progressBar.Value +=args.ProgressPercentage;lbxProgress.Items.Add(args.UserState.ToString());

object stepValue = world;foreach(IAlgorithmStep step in algorithm.Steps) if(_backgroundWorker.CancellationPending) _backgroundWorker.ReportProgress(10,string.Format("0 is canceled.", step.Name));e.Cancel = true;return;else _backgroundWorker.ReportProgress(10,string.Format("0 is starting.", step.Name));

stepValue =step.DoWork(stepValue);_backgroundWorker.ReportProgress(20,string.Format("0 is finished.", step.Name));

e.Result = stepValue;_backgroundWorker.ReportProgress(5,"Finished.");

Backgrou ndWorkers - Imp l emen tação p rá t i ca em Wi nd ows Presen tat i on Fou nd at i on (WPF)

Page 30: Revista programar 26

30

A PROGRAMAR

Desta forma actualizamos o progresso nainterface com o uti l izador.

8. Para terminar, vejamos o handler:private void RunWorkerCompleted(objectsender, RunWorkerCompletedEventArgs e)Que é executado depois do DoWork terterminado, ter ocorrido uma excepção ou atarefa ter sido cancelada.

Vou verificar se a tarefa foi cancelada ou não.

Em caso de sucesso posso obter o resultado da

tarefa. Caso tenha ocorrido um erro, este seráapresentado ao uti l izador.

Em conclusão, a implementação de umBackgroundWorker permite-nos correr umatarefa numa thread separada sem que estainterfira com a interface com o uti l izador.Permite-nos ainda ter a capacidade de:- Cancelar a tarefa;- Reportar o progresso da tarefa;- Actual izar os controlos de WPF enquanto atarefa decorre.

A comunidade NetPonto é uma iniciativaindependente e sem fins lucrativos, que temcomo simples e único objectivo a parti lha deconhecimento na área de arquitectura edesenvolvimento de software na plataforma.NET, na tentativa de disseminar o conhecimentodiferenciado de cada um de seus membros.

Cada um de nós tem diferentes talentos, e comas dezenas de tecnologias que são lançadastodos os dias, é muito difíci l (para não dizerimpossível) estar por dentro de tudo, e essa éuma das principais vantagens em fazer parte deuma comunidade de pessoas ligadas à nossaárea. Podemos aprender mais, e mais rápido,com as experiências de cada um.

Visite-nos em http://netponto.org

private void RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e) if (!e.Cancelled) try _world = (World)e.Result;catch lbxProgress.Items.Add(e.Error.Message);lbxProgress.Items.Add("Aborted.");progressBar.Value =progressBar.Maximum;else lbxProgress.Items.Add("Finished.");progressBar.Value =progressBar.Maximum;btnRunBackground.IsEnabled = true;btnCancel.IsEnabled = false;

Escrito por Sara SilvaÉ licenciada em Matemática – Especial idade em Computação, pela Universidade de Coimbra,actualmente é Software Developer no Porto.O entusiasmo pela área resultou na obtenção dos títulos de Microsoft Certified Profissional Developer –Windows 3.5, Microsoft Certified Tecnology Special ist – WPF 3.5, WPF 4 e Windows Forms. Faz parte devárias comunidades, tendo uma participação activa na Comunidade NetPonto e no P@P.

AUTOR

Backgrou ndWorkers - Imp l emen tação p rá t i ca em Wi nd ows Presen tat i on Fou nd at i on (WPF)

Page 31: Revista programar 26

31

A PROGRAMAR

Page 32: Revista programar 26

32

A PROGRAMAR

j Qu ery - O q u ê , como e porq u ê?dispositivos móveis, pois o seu grande trunfo éser cross-browser entre as várias plataformasmóveis e além disso as próprias themes seremadaptadas ao aspecto do dispositivo em uso,fazendo com que o aspecto e usabil idade (look& feel) das aplicações desenvolvidas com esteplugin não se distingam das aplicações nativasdo dispositivo, o que é um avanço enorme nodesenvolvimento de aplicações web paradispositivos móveis.

Pode-se acrescentar que tanto o jQuery como ojQuery UI têm um mecanismo de extensibi l idadeque permite aos programadores criarem pluginscompletamente integrados na API , fazendo comque actualmente existam cerca de 4000 pluginsna página oficial de plugins do jQuery.De seguida irei apresentar um tutorial muitobásico de como desenvolver com jQuery que ireiaprofundar em futuras edições.

Para iniciar o desenvolvimento, deve-seadicionar uma referência ao ficheiro js quecontém o jQuery (minificado) na head do nossohtml document: (img.1 )

O objectivo deste artigo é dar a conhecer asprincipais funcionalidades do jQuery, um poucoda sua história e motivações e fornecerexemplos da sua uti l ização.

O jQuery, existente desde 26 de Agosto de 2006,criado por John Resig, é uma cross-browserJavaScript l ibrary (embora considerado umaverdadeira framework), l icenciado ao abrigo doMIT e GNU, fazendo dele software l ivre, e é omais usado mundialmente face aos seusconcorrentes (Dojo, MooTools, Prototype).

Os seus objectivos são simplificar a interacçãocom o DOM (Document Object Model), handl ingde eventos, criação de animações, interacçãoAJAX (Asynchronous JavaScript and XML), e,last but not least, ser cross-browser, que foi ofactor decisivo para John Resig o criar.

O jQuery tem uma sub-l ibrary de nome jQueryUI , que é um subset do jQuery específico paraanimações e interface visual, fornecendo muitasfuncionalidades out-of-the-box, como várioscontrolos, um motor de esti los visuais para estes(theme roller), várias funcionalidades uti l izadasem interfaces ricos como drag & drop, dialogs,tabs, sl iders, entre muitos outros.

O projecto jQuery gerou um spin-off de nomeSizzle, que é um motor de selectores CSS emJavaScript, sendo naturalmente uti l izado nojQuery, a partir do qual foi gerado.

Actualmente a versão do jQuery é a 1 .4.3 e dojQuery UI 1 .8.5.Para o futuro, a grande novidade é o jQueryMobile (do qual já foi feita uma release 1 .0 alpha1 em 1 6 de Outubro de 201 0), que irárevolucionar o desenvolvimento a nível de

<html><head>

<script type="text/javascript"src="jquery-1.4.3.min.js"></script>

<script type="text/javascript">

</script></head><body>

<a href="http://www.portugal-a-programar.org/">PaP</a>

</body></html>

Page 33: Revista programar 26

33

A PROGRAMAR

Existem mais 2 modos de assignar um handlerao evento ready do nosso document:

e o modo mais abreviado e mais uti l izado:

Neste momento podemos gravar o nossoficheiro HTML com todo o código e testar:Ao testarmos clicar no link, a popup aparece, ede seguida entramos na página Portugal aProgramar.

Para código assim que o nosso documentoestiver no estado ready (on document ready),antes do jQuery, o natural seria ter algumcódigo:

O problema de executar código neste evento éque este só é executado quando o DOM estácompletamente carregado e todas as referênciasexternas já foram descarregadas do servidor(imagens, js, css), o que não é nada agradávelpara o programador.

Por este motivo, o jQuery tem um evento que édespoletado logo que o DOM está carregado,não esperando pelos recursos externos:

Podemos adicionar código para ao clicarmos nolink, mostrar um alert:

$(document).ready(function() //código aqui

);

window.onload = function() alert("on docready");

$(document).bind(“ready”,function() );

$(document).ready(function() $(“a”).bind(“click”,

function(event) alert("Aceder ao site da comunidadePortugal a Programar”);

););

$(function() );

img.1

<html><head>

<script type="text/javascript"src="jquery­1.4.3.min.js">

</script><script type="text/javascript">

$(document).ready(function() $(“a”).bind(“click”,function(event) </html>

alert("Aceder ao site dacomunidade Portugal a Programar”);

); img.2

j Qu ery - O q u ê , como e porq u ê?

Page 34: Revista programar 26

34

A PROGRAMAR

Se quisermos prevenir o comportamento poromissão (default) do nosso clique sobre aâncora, podemos fazê-lo, chamando a funçãopreventDefault do objecto event, que é recebidono handler de qualquer evento:img. 4

Para carregarmos o jQuery, a melhor opção éuti l izar um CDN (Content Delivery Network, quefornece conteúdos na área geográfica douti l izador, de alta disponibi l idade e a altavelocidade) da Microsoft ou da Google. Quantoao script incluído inl ine, o ideal é ser colocadonum ficheiro externo, de modo a não poluir ohtml.

Como pude demonstrar neste pequeno tutorialbásico, de iniciação ao jQuery, ele é umaframework tão acessível quanto poderosa e comum potencial cada vez maior e com cada vezmais funcionalidade, por isso, irei continuar emartigos subsequentes, a aprofundar cada vezmais as suas funcionalidades, truques e dicas,assim como parti lhar boas prácticas dedesenvolvimento, por isso não percam ospróximos artigos!

img.3

img.2

Actualmente existemcerca de 4000 pluginsna página oficial !

$(document).ready(function() $(“a”).bind(“click”,function(event) alert("Deste modo, já não somosdireccionados para o site Portugala Programar”);

event.preventDefault(););

)

);</script>

</head><body>

<ahref="http://www.portugal­a­programar.org/">PaP</a></body>

</html>

j Qu ery - O q u ê , como e porq u ê?

Page 35: Revista programar 26

35

A PROGRAMAR

img.4

Uma framework tãoacessível quanto poderosae com um potencial cadavez maior

Escrito por Ricardo RodriguesÉ técnico Nível I I I em Informática/Gestão pela Fundação Escola Profissional de Setúbal, tendo ingressadoapós na FCT da Universidade Nova de Lisboa.Posteriormente frequentou vários cursos da Microsoft em diversas áreas como Windows Forms,ASP.NET,Securing .NET Applications, WCF, WWF, Web Services e COM+ tendo obtido as certificações MCP .NET2.0, MCAD .NET 1 .1 , MCSD .NET 1 .1 , MCPD Windows, Web e Distributed Applications e MCPD -Enterprise Applications Developer.(MCP Profi le)Contribui activamente em comunidades como StackOverflow e também possui um blog/twitter comotemática relacionada: Blog / @ricmrodrigues

AUTOR

j Qu ery - O q u ê , como e porq u ê?

Page 36: Revista programar 26

36

A PROGRAMAR

Lu a – Li nguagem de Programação (Pa rte 6)usada em conjunto com outras l inguagens comose fosse um satél ite natural para essas outrasl inguagens.

Fica aqui esta questão para ser pensada.

Ambiente Interactivo

A linguagem de programação Lua possui umambiente de trabalho que pode ser usado naforma interactiva.Neste modo de operação pode-se realizaralgumas tarefas operacionais. Para tanto, nal inha de comando prompt (modo terminal) dosistema operacional em uso faça a chamada doprograma lua e accione <Enter>. Neste sentidoserá apresentada uma mensagem deidentificação semelhante a:

Para sair do prompt do ambiente Lua e retornarao terminal do sistema operacional bastaexecutar o comando os.exit() e em seguidaaccionar a tecla <Enter> ou <Return> ou aindausar as teclas de atalho <Ctrl> + <c> ou entãoas teclas de atalho <Ctrl> + <z> + <Enter>dependendo do sistema operacional em uso.

Dentro do ambiente interactivo é possível passarcomandos com o sentido de obter respostas. Porexemplo, desejando-se obter o resultado dasoma do valor 7.5 com o valor 4.8, bastaexecutar a l inha de comando:

No artigo anterior (quinto artigo desta série) foraapresentado o tema relacionado ao uso ecriação de funções. Como prometido este artigotratará do tema relacionado ao uso de arquivos.Além deste será tratado também algunsaspectos ainda não mencionado sobre oambiente interactivo da linguagem e a obtençãode tamanho de strings.

Um pouco mais sobre Lua

Na primeira parte desta série de artigos foicomentado um breve histórico sobre osurgimento da linguagem Lua. Cabe aindaacrescentar mais alguns detalhes.Antes do surgimento da linguagem Lua odepartamento de informática da PUC-Rio faziauso interno das linguagens DEL (Data-EntryLanguage) e SOL (Simple Object Language)

Cada uma das linguagens fora desenvolvidaentre 1 992 e 1 993 no sentido de adicionar maiorflexibi l idade de interactividade a dois projectosde aplicação em computação gráfica para odepartamento de engenharia da empresaPETROBRAS. Apesar da ideia arrojada, ambasas linguagens apresentavam problemas muitocomuns e foi a partir desses problemas queocorreu a junção das linguagens DEL e SOL,dando vez a linguagem Lua.

Segundo reza a lenda o nome Lua foi sugeridodevido ao uso da linguagem SOL. Mas cabeaqui um pouco de devaneio, pois me parece onome Lua bem mais sugestivo que que umaocorrência a partir da l inguagem SOL. Lua é osatél ite natural do planeta Terra.

A linguagem Lua é uma linguagem que apesarde sua independência operacional pode ser

Lua 5.1.4 Copyright (C) 1994-2008 … Rio>

print(7.5 + 4.8)

Page 37: Revista programar 26

37

A PROGRAMAR

Serão apresentados como resultados os valores6, 0.66666666666667, 5 e -1 .Os cálculos efectivados poderá trabalhar comoutros formatos numéricos, como notaçãocientifica. Por exemplo, desejando-se obter oresultado decimal do valor 9.5e2, sendo:

Que mostrará como resultado o valor 950, poiscalcula-se o valor 9.5 multipl icando-se por 1 0 eelevando-se a potência 2, ou seja, 9.5 x 1 02.Experimente =9.5e-2 para obtenção do resultado0.095.

Outra possibi l idade de operações são os usosde valores hexadecimais convertidos em valoresdecimais. Por exemplo, observe os seguintescomandos.

Ao serem executados os comandos anteriorestodos resultam na apresentação do valor 1 0 (Ahexadecimal igual a 1 0 decimal). Note que nãoimporta como é definido o valor, seja em formatode carácter maiúsculo ou formato de carácterminúsculo o resultado será sempre apresentado.

O ambiente interactivo permite a definição e usode variáveis. Por exemplo, informe as linhas decódigo seguintes accionando a tecla <Enter> ou<Return> para cada linha informada.

Após accionar a tecla <Enter> ou accionar atecla <Return> obter-se-á o resultado 1 2.3.

Veja a seguir uma série de operações comcálculos matemáticos que podem serefectivadas junto ao ambiente interactivo.

Os exemplos apresentados anteriormenteresultam respectivamente nos valores: -5, 6, 2.5,2, 8, 1 7, 1 7 e 21 .

O ambiente interactivo retorna mensagens deerro quando alguma coisa não é escrita dentrodas regras sintácticas do ambiente. Porexemplo, execute o código.

Ocorrerá a apresentação da mensagem de errostdin:1: unexpected symbol near '+' informandoque um dos símbolos “+” é desconhecido.

Para a obtenção de resultados de cálculosmatemáticos pode-se substituir o comandoprint() pelo símbolo “=” igual a. Desta forma,podem ser definidos os seguintes cálculos.

print(-2 + -3)print(2 * 3)print(10 / 4)print(10 % 4)print(2 ^ 3)print(2 + 5 * 3)print(2 + (5 * 3))print((2 + 5) * 3)

print(2 + + 3)

=2*3=2/3=2+3=2-3

=9.5e2

=0xa=0xA=0Xa=0XA

A = 2B = 3print(A + B)

Lu a – Li nguagem de Programação (Pa rte 6)

Page 38: Revista programar 26

38

A PROGRAMAR

Observe o surgimento do valor 5 como resultadoda operação.

Um cuidado que se deve tomar na definição devariáveis é com relação ao nome atribuído. Porexemplo as seguintes variáveis não são asmesmas variáveis, pois a l inguagem Lua é dotipo case sensitive.

Outro detalhe no uso e definição de variáveis é apossibi l idade de se efectivar a criação demúltiplas variáveis. Por exemplo, observe ocódigo seguinte:

Observe que serão apresentados os valores 1 23e Paulo. O símbolo “=” separa os conteúdos dasvariáveis (1 23 e Paulo) das variáveis (CODIGOe NOME).

Detecção de Tamanho de String

Vagarosamente a cada artigo estão sendoapresentados diversos recursos operacionaisque podem ser uti l izados junto a linguagem deprogramação Lua. Entre os recursos explanadoscabe neste instante abordar o operador “#” deobtenção de tamanho de um string.Observe a seguir as l inhas de código que podemser executados no ambiente interactivo.

Após executar as l inhas de código anterioresserão apresentados os valores 1 e 1 3 que sãorespectivamente o tamanho das mensagens umespaço e Linguagem Lua.

Arquivos

Um dos recursos mais úteis e importantes a seroferecido por uma linguagem de programaçãode computadores á a capacidade destal inguagem permitir a manipulação de arquivos.A linguagem Lua oferta para o programador umabibl ioteca de entrada e de saída para o controlodas operações de arquivos. A abordagem desteartigo se restringirá em aplicações básicas.O programa seguinte apresenta um exemplo deprograma que cria um arquivo contendo valoresnuméricos pares situados na faixa de valoresentre 1 um) e 200 (duzentos).

COR = 1COr = 2Cor = 3cor = 4Cor = 5cOr = 6CoR = 7coR = 8print(COR)print(COr)print(Cor)print(cor)print(Cor)print(cOr)print(CoR)print(coR)

CODIGO, NOME = 123, "Paulo"print(CODIGO)print(NOME)

print(#" ")print(#"Linguagem Lua")

-- inicio do programa ARQ01

ARQ = io.open("pares.txt","w")

for N = 1, 200 doR = N % 2if (R == 0) then

ARQ:write(N.."\n")end

end

Lu a – Li nguagem de Programação (Pa rte 6)

Page 39: Revista programar 26

39

A PROGRAMAR

Em seguida escreva o código de programa emum editor de texto, gravando-o com o nomearq01 .lua e execute-o com a linha de comandolua 5.1 arq01 .lua.

O programa estabelece para a variável ARQestá sendo atribuída pela função io.open() quetem por final idade abrir um arquivo para escrita,leitura ou adição. Caso o arquivo não exista omesmo é automaticamente criado. A funçãoio.open() uti l iza entre aspas inglesas doisargumentos para sua operação:

nome (primeiro argumento); modo (segundo argumento).

O argumento nome caracteriza-se por ser onome do arquivo a ser aberto ou criado, nestecaso pares.txt e o argumento modo indica aforma de operação sobre o arquivo, podendoser:

r – modo leitura (forma padrão); w – modo escrita; a – modo adição (inserção); r+ – modo actual ização, todos os registosexistentes são preservados; w+ – modo actual ização, todos os registosexistentes são apagados; a+ – modo actual ização de adição, todos osregistos existentes são preservados e as novasinserções ocorrem após o final do arquivo; b – modo de operação para manipulação dearquivos binários, usado ao lado direito dadefinição dos modo “r”, “w” e “a”.

A l inha de instrução R = N % 2 obtém o valor doresto da divisão do valor da variável N por 2.

Este valor poderá ser 1 (se o valor for ímpar) ou0 (se o valor for par).

A instrução if (R == 0) then verifica se o valor doresto da divisão é zero, sendo executa ainstrução ARQ:write() que escreve no arquivo ovalor par obtido. O indicativo “\n” está sendousado para armazenar no arquivo um valornumérico por l inha. Sem este recurso os valoresnuméricos seriam armazenados um ao lado dooutro.

Ao final a instrução ARQ:close() efectua ofechamento do arquivo.

Se quiser ver o conteúdo do arquivo basta pedirpara l istar seu conteúdo directamente na linhade comando do sistema.

O programa seguinte efectua a leitura do arquivopares.txt e faz o somatório do valores e mostraseu resultado.

Em seguida escreva o código de programa emum editor de texto, gravando-o com o nomearq02.lua e execute-o com a linha de comandolua 5.1 arq02.lua.

ARQ:close()

-- fim do programa ARQ01

-- inicio do programa ARQ02

ARQ = io.open("pares.txt","r")

SOMA = 0for VALOR in ARQ:lines() do

SOMA = SOMA + tonumber(VALOR)end

ARQ:close()

print(SOMA)

-- fim do programa ARQ02

Lu a – Li nguagem de Programação (Pa rte 6)

Page 40: Revista programar 26

40

A PROGRAMARO programa anterior faz uso do argumento demodo r (para leitura) quando da abertura doarquivo pares.txt por parte da instruçãoio.open().

Quando da explanação do uso de laços ainstrução for foi apresentada na sua forma maissimples. Note que neste exemplo a instrução forfaz uso do comando in definida como for VALORin ARQ:lines() do. Esta forma de uso dainstrução for denomina-se uso genérico.

Neste caso, a instrução for faz com que avariável VALOR seja atribuída com o conteúdo(in) existente no arquivo pares.txt representadopela variável ARQ. Note o uso da função l ines()anexa a variável ARQ que permite avançar noarquivo uma linha a frente posicionando-sesobre cada um dos registos.

A função tonumber() faz com que cada valornumérico armazenado no arquivo na forma destring quando capturado seja convertido parasua forma numérica. Apesar da linguagem Luafazer este tipo de conversão automaticamente éfortemente recomendado que se defina este tipode operação de forma explicita como feira noprograma arq02.lua.

O próximo programa tem por objectivo fazer aentrada de dados com nome e telefone earmazenar os dados em uma agenda.

Em seguida escreva o código de programa emum editor de texto, gravando-o com o nomearq03.lua e execute-o com a linha de comandolua 5.1 arq03.lua.

O programa usa na função io.open() o modo deacção a+ para permitir a inserção de novosregistos ao arquivo.

Um novidade neste programa é a funçãostring.upper() que transforma em maiúsculo asentradas efectuadas junto as variáveis NOME eRESP.

O programa seguinte efectua a leitura dos dadosdo arquivo agenda.txt.

Em seguida escreva o código de programa emum editor de texto, gravando-o com o nomearq04.lua e execute-o com a linha de comandolua 5.1 arq04.lua.

-- inicio do programa ARQ03

ARQ = io.open("agenda.txt","a+")

RESP = "S"while (RESP == "S") do

io.write("Nome .......: ")NOME = string.upper(io.read())io.write("Telefone ...: ")TELE = io.read();REGISTO = NOME.." "..TELE

ARQ:write(REGISTO.."\n")io.write("[+]registo? S/N ")RESP = string.upper(io.read())

end

ARQ:close()

-- fim do programa ARQ03

-- inicio do programa ARQ04

ARQ = io.open("agenda.txt","r")

for REGISTO inio.lines("agenda.txt") doio.write(REGISTO.."\n")

end

ARQ:close()

-- fim do programa ARQ04

Lu a – Li nguagem de Programação (Pa rte 6)

Page 41: Revista programar 26

41

A PROGRAMAR

O programa usa a função l ines() um poucodiferente do que fora uti l izada no programaarq02.lua. Neste versão usa-se a função comoio.lines() com o nome do arquivo agenda.txtcomo argumento.

Quando se uti l iza arquivos na linguagem Luapode-se fazer uso de duas abordagens deacesso aos seus descritores, que pode serimplícito ou explicito.

Quando se faz uso de descritores implícitos,todas as operações de acesso ocorrem com ouso dos recursos da tabela io. Quando se fazuso de descritores explícitos, todas asoperações são providas como métodos dodescritor de arquivo.

É possível com a linguagem Lua criar umprograma que efectue a criação automática depáginas HTML/XHTML.

O programa a seguir cria uma página em códigoXHTML.

Em seguida escreva o código de programa emum editor de texto, gravando-o com o nomearq05.lua e execute-o com a linha de comandolua 5.1 arq05.lua. Observe junto ao programa asdefinições das tags XHTML para criação dapágina com o nome teste.html.

Conclusão

Neste artigo foi dado atenção as acções de usode arquivos em modo texto na linguagem Lua.Foi também fornecido informações sobre o usodo ambiente em modo interactivo.No próximo artigo será tratado o uso de funçõespara acesso em tabelas, escopos de variáveis,descrição de dados, meta-tabelas e orientação aobjectos em Lua.

Errata

No primeiro artigo desta série foi informadoequivocadamente que o resto de divisão entredois valores poderia ser obtido a partir da funçãomod(). De fato, pode-se fazer uso desta funçãopara se obter o valor do resto de uma divisãodesde que esta função esteja associada a suabibl ioteca, neste caso, a bibl ioteca math, pormeio da sintaxe math.mod() ou então pode-sefazer uso do operador % mostrado neste artigo.

-- inicio do programa ARQ04

ARQ = io.open("agenda.txt","r")

for REGISTO inio.lines("agenda.txt") doio.write(REGISTO.."\n")

end

ARQ:close()

-- fim do programa ARQ04

Escrito porAugusto ManzanoNatural da Cidade de São Paulo, tem experiência em ensino e desenvolvimento de programação desoftware desde 1 986. É professor da rede federal de ensino no Brasil , no Instituto Federal de Educação,Ciência e Tecnologia. É também autor, possuindo na sua carreira várias obras publicadas na área dacomputação.

AUTOR

Lu a – Li nguagem de Programação (Pa rte 6)

Page 42: Revista programar 26

42

MAC ADDRESS

E se amanhã a App l e d om i na r?conceitos. . .

Ipod, iPhone, iPad são apenas os três últimosexemplos do que acabei de tentar demonstrar.

O caso do iPod é paradigmático na minha linhade pensamento: Não é a criação do hardware,não é a criação do software (que, recordo, foiMac only durante um ano e alguns meses. . . ) quefazem (ou fizeram) a revolução. É a experiênciado uti l izador. Pela primeira vez, um ecossistemapermitia ao cliente não "power user", umaexperiência de uso integrada, pacífica etotalmente tranquila. Esse é um dos grandescapitais da Apple. Colocar no mercado produtospensados (verdadeiramente pensados) para outi l izador comum, que de uma forma tranquila sevai rendendo aos encantos desse esforço. Sim,a Apple fez de um mercado que não existia(Napster. Anyone?), um império colossal querende milhões de dólares. Artistas, compositorese músicos querem hoje cortar o "middleman" eestar de forma directa na Store. Meia dúzia deanos passados, quem se lembra de como eramas coisas anteriormente?

Replicar a experiência noutras plataformas foiapenas uma questão de poucos anos. Nãopassa nenhuma semana no meu calendário quenão tenha contactos de programadores

Já tenho idade e experiência suficiente parapoder ter uma perspectiva sólida sobre aevolução de plataformas computacionais dedesenvolvimento. Já percorri parte da "travessiado deserto" que a Apple efectuou no início dosanos noventa, altura em que mesmo os maiscépticos se questionavam sobre o futuro daCompanhia. Se é verdade que a imprensaanunciou várias vezes a "morte" da marca deCupertino (notícias que fel izmente se veio aconcluir serem manifestamente exageradas),não é menos verdade que embora umaplataforma nicho, esteve sempre muito à frente(e por vezes demasiado na vanguarda), dainovação e na capacidade de se recompor decada desaire.

Sejamos francos, hoje a marca Apple é "trendy","fashionable" e mais umas dúzias de palavrõesdo jargão IT. Arrasta multidões (e você podemuito bem ser um deles. . . ) como uma lâmpadaacesa atrai mosquitos. Nem sempre foi assim.Reduzidos a uma franja residual de uti l izadores,autênticos gauleses irredutíveis na sua aldeia, aApple sobreviveu graças à capacidade de visãodos que presidiram aos seus destinos (SteveJobs, anyone?), mas também graças a umacapacidade inigualável de R&D (que tambémteve as suas nódoas negras no caminho), e aum desempenho industrial quase irrepreensível.

Se uma nuvem de "copycats" me irritou nopassado, hoje isso quase que se tornou banal.Todos os trimestres se perfi lam no mercado"Kil lers" de isto e daquilo. A maioria delespretende ser "ki l ler" de um produto Apple, masnão é menos verdade que há cemitérios inteiroscheios de produtos que se arrogam a ser apróxima grande descoberta. O verdadeiro "ki l ler"está ainda, penso eu, nos estiradores dos

a Apple fez de ummercado que não existia(. . . ) um império colossalque rende milhões dedólares

Page 43: Revista programar 26

43

MAC ADDRESS

.experientes ou simples iniciantes que mecontactam em busca desse Santo Graal que é ainiciação ao desenvolvimento para iPhone. Sim,disse apenas iPhone; foi com este produto quetudo realmente começou. E ao longo dos últimostrês anos, no início dos quais se contavam pelosdedos de ambas as mãos de um lançador defoguetes destreinado, a quantidade de genteportuguesa envolvida no desenvolvimento,passámos a contá-los por centenas eposteriormente já na casa do milhar.

É divertido. Divertido e reconfortante assistir aesta corrida ao ouro. Numa Store que todosinvejam e tentam copiar (por vezes demasiadomal), há espaço para todos e todos são tratadospor igual. É o mercado a funcionar. Destacam-seos bons dos medianos e maus, ninguém ficaverdadeiramente prejudicado pois a escolha(compra) do cliente final é que éverdadeiramente decisória. Vingam as boasideias. E essas, reconhecidamente temo-las emPortugal com programadores portugueses.Alguns deles já reconhecidos internacionalmentecom prémios do próprio fabricante.

Quem sabe, se uma das suas ideias não chegaao top da AppStore?

Sim, disse apenasiPhone; foi com esteproduto que tudo começou

Escrito por Pedro AnicetoPedro Aniceto, é Gestor de Produto Apple desde 1 998 e uti l izador da marca desde bem mais cedo. Nãoacredita em monstros, mas espreita de quando em vez para debaixo da secretária.

AUTOR

E se amanhã a App l e d om i na r?

Page 44: Revista programar 26

44

A PROGRAMAR

SQL em Orac l ecérebro da base de dados). Alguns dessesdados variam ao longo do tempo. Por isso, ou ooptimizador é intel igente ao ponto de escolhersempre o melhor caminho, ou teremos de sernós – programadores - a ensiná-lo.

As bases de dados recentes, e em especial aOracle, já têm algoritmos bastante poderososque cobrem a maioria das situações. No entanto,há ainda alguma margem de “invenção” para oprogramador poder influenciar o desempenho doSQL.

Estrutura ultra simplificada de umaBD Oracle

Para sabermos o que optimizar e comooptimizar, há que conhecer a estrutura interna deuma base de dados Oracle.

Como este artigo não pretende ser exaustivo,mostra-se apenas uma visão muito simplista do

Introdução

Quando desenvolvemos uma aplicação assentenuma base de dados, um dos processos quenormalmente nos passa ao lado é a optimizaçãode queries.

Preocupamo-nos com a interacção da aplicaçãocom o uti l izador ou com questões de segurança,não dando importância a pormenores de SQLque podem, muitas vezes, condicionar aperformance da aplicação. O tempo de esperana execução de uma query pode arruinar umaaplicação e, em última instância, uma base dedados inteira.

A solução passa, muitas vezes, por melhorar ohardware, culpando-o da baixa performance dasnossas queries. Mas, nem sempre o problemareside no hardware. Aliás, muitas vezes, alentidão de uma aplicação com acessos à basede dados resulta de SQL mal construído ou deestruturas de dados desadequadas ao nossoprojecto.

Não existe uma fórmula para optimizar SQL.Cada caso é um caso. A estrutura de dados, aquantidade ou a qualidade dos dados sãofactores que influenciam o optimizador (o

O tempo de espera naexecução de uma querypode arruinar umaaplicação e, em últimainstância, uma base dedados inteira

a lentidão de umaaplicação com acessos àbase de dados resulta deSQL mal construído ou deestruturas de dadosdesadequadas

Page 45: Revista programar 26

45

A PROGRAMAR

1. O cliente envia a instrução SQL para oservidor.

2. O server process procura na shared pooluma instrução igual à solicitada. Se nãoencontrar, compila a nova instrução (parsing) earmazena-a na shared pool.3. O server process procura na buffer cacheos blocos de dados que necessita. Se nãoencontrar, faz uma consulta aos data files.4. Os dados são enviados para o cliente.

Se repetirmos a mesma query, de seguida, oprocesso será o seguinte:

1. O cliente envia a instrução SQL para oservidor.

2. O server process procura na shared pooluma instrução igual à solicitada. Encontra-a e jásabe como encontrar os dados.

3. O server process procura na buffer cacheos blocos de dados que necessita. Acabaram deser requisitados na query anterior. Ainda láestão. Não é necessário recorrer aos datafi les,pois os dados encontram-se todos em memória.

4. Os dados são enviados da SGA para ocliente.

Por onde começar?

Verificámos que o Oracle guarda as queriespedidas em memória com a informação do

modo de funcionamento de uma base de dadosOracle, o suficiente para perceber os conceitosaqui referidos:

Cliente – a “nossa” aplicação que comunica coma base de dados.

Oracle Server Process – processo que recebeas instruções do cliente e as executa.

Datafiles – ficheiros onde é armazenada aestrutura e os dados de uma BD.

SGA – zona de memória uti l izada para guardardados parti lhados pelos váriosuti l izadores/aplicações da BD. Armazena dadosno Buffer Cache e instruções SQL na SharedPool.As instruções SQL e os dados solicitadosatravés de queries são guardados na SGA,poupando tempos de processamento e acessosao disco, em futuras chamadas da mesmaquery.

Como o Oracle processa um comando

Tomemos como exemplo o seguinte query:

select nome, morada, telefone from t_clienteswhere nif = 12345;

SQL em Orac l e

Page 46: Revista programar 26

46

A PROGRAMAR

melhor percurso para obter os dados.Imaginemos uma aplicação que executa,sistematicamente, esta query com diferentescondições:

As queries são todas diferentes. Logo, o Oraclevai armazenar cada uma delas na shared pool.Mas, na prática, o processo de obtenção dosdados é sempre o mesmo.

Na verdade, as queries são todas iguais,excepto o critério da condição where. Ooptimizador não é suficientemente esperto aoponto de perceber que o processo é sempre omesmo.

Poderíamos, facilmente, encontrar estas queriesem memória, na SGA, executando a seguinteconsulta:

Verificaríamos inúmeras queries similares, comvariância no parâmetro nif.

Uma funcionalidade do Oracle e que permiteoptimizar a uti l ização repetida de queries iguaissão as bind variables. Estas variáveis permitemexecutar a instrução da seguinte forma:

Agora, sim, a query é sempre igual, aos olhos dooptimizador Oracle e, em vez de guardarinúmeras queries iguais em memória, guardaapenas uma:

Estas situações tomam especial importância embases de dados onde a mesma query é repetidamilhares de vezes ficando a memória entupidacom instruções iguais.

A repetição da mesma query milhares de vezespode rapidamente ocupar toda a memóriadisponível. Ao uti l izarmos bind variables,estamos a poupar CPU no parsing e RAM nashared pool.Como caso prático da uti l ização de bind

variables podemos referir um website de vendade automóveis usados.

select nome, morada, telefone from t_clienteswhere nif = 12345;

select nome, morada, telefone from t_clienteswhere nif = 12346;

select nome, morada, telefone from t_clienteswhere nif = 23245;(...)

select hash_value,sql_text, parse_calls,loads, executionsfrom v$sqlareawhere sql_text like 'select nome, morada,telefone from t_clientes where nif =%';

variable nif_n number;exec :nif_n := 12345;

query -> select nome, morada,telefone from t_clientes where nif =:nif_n;

exec :nif_n := 12346;query -> select nome, morada,telefone from t_clientes where nif =:nif_n;

select nome, morada, telefone fromt_clientes where nif = :nif_n;

SQL em Orac l e

Page 47: Revista programar 26

47

A PROGRAMAR

Se o campo de pesquisa for a marca, modelo eano, estaremos a executar uma query queprocura numa tabela os automóveis com amarca X, modelo Y e ano Z, que podem serseleccionados recorrendo a bind variables,evitando assim milhares de queries similares.

Conclusão

A uti l ização de bind variables é uma prática quedeve ser adoptada sempre que possível. Se anossa aplicação já está em produção, umaanálise à vista dinâmica v$sqlarea permitedetectar as instruções SQL similares que podemser reduzidas a uma só.

Para isso, podemos olhar para as colunasparse_calls e executions.Uma query muito frequente está optimizada

quando tem apenas uma parse_calls e muitasexecutions.Naturalmente que, em queries pouco frequentes,não é necessário preocuparmo-nos com estaoptimização e nem devemos general izar aoptimização somente às bind variables.

Existem muitas maneiras de tornar o código SQLmais eficiente e esta é apenas uma delas e defácil implementação.

Uma análise mais aprofundada da estrutura deuma base de dados Oracle permite umconhecimento mais vasto sobre o modo como oOracle processa os pedidos de informação.

Na prática, os conceitos aqui referidos são bemmais complexos. No entanto, a nível doprogramador que estrutura o SQL e que,eventualmente, cria a estrutura de dados, estesconceitos são suficientes para este tipo deoptimização.

O detalhe vai interessar mais ao DBA quetambém poderá fazer “maravilhas” no tunning dabase de dados.

A uti l ização de bindvariables é uma práticaque deve ser adoptadasempre que possível

Escrito por Ricardo TrindadeÉ actualmente o responsável pela área informática dos Serviços Sociais da Câmara Municipal de Lisboaonde efectua, desde administração de sistemas, até programação em .NET. Está também ligado aoprojecto N-Ideias na área da consultoria, webdesign e software, trabalhando essencialmente com BD'sOracle, PostgreSQL e SQL Server.

AUTOR

SQL em Orac l e

Page 48: Revista programar 26

48

A PROGRAMAR

Aspectos l ow- l eve l d e 3D(normalmente implementada nos drivers) e aplaca gráfica?

Pensem na pipel ine 3D como uma linha deexecução de uma fábrica. Os materiais sãointroduzidos, processados em várias fases, eobtemos o produto final. Convém também ficarclaro que existem vários métodos diferentespara fazer render de gráficos 3D. O que asplacas gráficas actuais usam (e os primeirosjogos 3D que funcionavam apenas por software)é chamado de rasterisation. Existem outrosmétodos como ray tracing, mas não vão serexplicados.

As primeiras gerações de placas gráficas apenasexecutavam a fase Rasterizer, sendo que a fasede Geometry era totalmente processada peloCPU. Devido à crescente complexidade dasaplicações 3D, o CPU não conseguia processartoda a informação em tempo úti l , e a faseGeometry passou a ser implementada no GPU.Esta capacidade é normalmente referida nasfuncionalidades das placas gráficas porhardware T&L (Transform & Lighting).

Esta pipel ine está de acordo com um modeloconhecido por Fixed-function pipel ine. As placasgráficas modernas são muito mais flexíveis edispõem de uma pipel ine programável, uti l izandoshaders. Ainda é possível programar com este

Introduçao ao 3D

Este artigo explica alguma da teoria relacionadacom o funcionamento de baixo nível de gráficos3D, desde a placa gráfica, às bibl iotecas que seusam para as programar, e alguma da magia(matemática) necessária para que tudo funcione.Recomenda-se alguma experiência básica comconceitos 3D.

Quem não se lembra de jogos como Quake eDuke Nukem 3D? Estes jogos (pelo menos asversões originais), eram "renderizados"(transformados numa imagem para mostrar noecrã) completamente por software, ou seja, semrecurso a aceleração por hardware.

Só anos depois, com a popularidade dos jogosna plataforma PC, é que as placas gráficascomeçaram a ser vendidas e distribuídas com oscomputadores. As placas gráficas (GPU) sãouti l izadas para acelerar os cálculos necessáriospara representar realisticamente os objectos em3D.

As placas são constituídas por processadoresespecial izados, e com grande capacidade deparalel ização, em contraste com umprocessador normal (CPU), que está preparadopara executar os mais variados tipos deaplicações.

Com o aparecimento das primeiras placasgráficas surge a necessidade de criar APIs paratirar proveito das capacidades deprocessamento do hardware. As bibl iotecas maisconhecidas são o OpenGL e o Direct3D, emboraalguns talvez ainda se lembrem do Glide, quehoje em dia não passa de um artefacto histórico.Como funcionam e qual a relação entre a API

Page 49: Revista programar 26

49

A PROGRAMAR

Por questões de optimização todos os cálculosinternos são feitos em triângulos, por ser umarepresentação simples. Consequentemente,todas as outras formas de representação sãoconvertidas para triângulos, usando umprocesso chamado tessellation (ou Polygontriangulation).

Realizada esta conversão os dados sãoenviados pelo bus (AGP ou PCI-Express) para aplaca gráfica.

Geometry stage

Esta fase recebe os vértices3D enviados para a placagráfica pela fase anterior, eexecuta uma série detransformações necessáriaspara adaptar estes dadosnum formato adequado parao processamento dapróxima fase. Esta é a partemais importante da pipel ine,e onde são efectuados amaior parte dos cálculos.

Antes de analisarmos emmais detalhe cada uma das transformaçõesdesta etapa, vamos ver o que são espaços decoordenadas e como são representados osvértices.

Em 3D é comum uti l izarmos vários espaços decoordenadas pois faz sentido falar de diferentescoordenadas dependendo do objecto oureferência que estejamos a considerar. Osespaços fundamentais são denominados porModel/Object Space, World Space eCamera/Eye Space, pela ordem que sãoprocessados na pipel ine.

Inicialmente um objecto em 3D reside numespaço chamado Model Space, que significa que

modelo não-programável nas placas gráficasmais recentes, mas o seu funcionamento é"emulado" pela API gráfica.

A esmagadora maioria dos chipsets gráficosproduzidos hoje em dia são programáveis,sendo a excepção mais notável a consola Wii daNintendo. Os dispositivos móveis tambémdemoraram um pouco a adoptar este novomodelo, mas as novas versões do iPhone edispositivos Android também já suportamshaders (através do OpenGL ES 2). A webtambém está a caminhar para este modelo, coma adopção do WebGL por vários browsers.

Application stage

Tal como o nome implica, a primeira fase ocorrena aplicação desenvolvida pelo programador, e éprocessada apenas no CPU. Nesta etapa, sãonormalmente processadas tarefas comodetecção de colisão (Coll ision detection),animação, simulação de física, algoritmos deaceleração (Space partitioning, Cull ing), entreoutros, dependendo do tipo de aplicação.

A aplicação é também responsável por enviar osdados dos objectos 3D para a API . Os objectosem 3D são geralmente representados porpolígonos: triângulos e quadri láteros. Existemoutras formas de representação, comocurvas/superfícies NURBS (Non-uniformRational B-spl ines), mas apesar de permitirem amodelação de alguns tipos de objectos de formamais precisa (através de modelos matemáticos)precisam de ser convertidas noutrasrepresentações.

Aspectos l ow- l eve l d e 3D

Page 50: Revista programar 26

50

A PROGRAMAR

o objecto ainda não foi transformado e seencontra no seu próprio espaço de coordenadas.É importante que cada objecto defina o seupróprio espaço, pois podemos associar váriastransformações a um objecto inicial , obtendovárias cópias no objecto no mundo comlocalizações, orientações e tamanhos diferentes,sem ser necessário enviar todos estes objectosdiferentes para a placa gráfica (esta técnica éconhecida por Instancing). Neste caso osobjectos estão normalmente posicionados naorigem para fácil manipulação.

World Space é um espaço de coordenadas“especial” pois todos os outros espaços vão serreferenciados em relação a este. Em outraspalavras este é o “maior” espaço decoordenadas no mundo.

É mais fácil perceber a relação entre estesdiferentes espaços uti l izando um exemplo.Todos nós temos o nosso próprio espaço decoordenadas. Se eu vos disser para darem umpasso em frente (Object Space), não faço ideiase vão para Norte, Sul, Este ou Oeste (WorldSpace).

Antes de estudarmos os diferentes tipos detransformações que os objectos sofrem, énecessário um modelo que possa ser facilmentetrabalhado. Os pioneiros em computação gráficaescolheram vectores como a forma derepresentação dos vértices. Esta representaçãopermite reuti l izar todo o conhecimento da áreamatemática conhecida por álgebra l inear. Estaárea estuda as propriedades dos vectores e dosconceitos associados (espaços vectoriais).

Esta representação vai permitir o uso dematrizes (que podem ser visual izadas como umconjunto de vectores) para a manipulação dosvértices.

As matrizes vão corresponder a transformaçõesde um espaço de coordenadas para outrodiferente. Exemplos de transformaçõesrepresentáveis com matrizes são translações,rotações, escalamentos ou redimensionamentos,reflexões, projecções, entre outros.

Existem várias formas de representar matrizesna memória: row-major order e column-majororder. É fundamental que não se misturem osdois tipos de representações, pois a ordem damultipl icação para a concatenação detransformações é diferente.

Com o uso de matrizes também se tornapossível a concatenação de diferentes tipos detransformações (representadas em diferentesmatrizes) numa únicamatriz. Isto é bastanteúti l , pois apenastemos de multipl icaros vértices por essamatriz composta eobtemos logo oresultado equivalentea multipl icar o vértice por cada transformaçãoem separado.

Aspectos l ow- l eve l d e 3D

Page 51: Revista programar 26

51

A PROGRAMAR

Existem bastantes mais detalhes sobre matrizesque convém estudar para se conseguir perceberdetalhadamente como a teoria (e a prática!)funciona. Mais concretamente, é fortementerecomendada a leitura sobre coordenadashomogéneas, transformações lineares etransformações afins.

É bom que estudem também como as diferentestransformações funcionam em termos deoperações matriciais. Como exemplo, vejamuma matriz de translação (apresentada nafigura) e tentem multipl icar um vector pelamatriz.

As diferentes APIs gráficas usam diferentesconvenções para a representação de matrizes evectores em memória. Vamos ver as diferenças:

Convém também perceber as convenções deeixos usadas nas principais APIs gráficas podemser vistas de diferentes formas. É preciso tercuidado se temos um sistema de coordenadasleft-handed ou um sistema de coordenadas right-handed.

Em relação à correspondência dos eixos, aconvenção usada é que o Y corresponde acima/baixo, o X a esquerda/direita e o Z afrente/trás (ver imagens), embora isto possa seralterado.

Agora que já vimos o modelo usado paratrabalhar os vértices, e como eles sãorepresentados no computador, vamos analisaras transformações principais que aconteceminternamente na pipel ine (não se preocupem senão perceberem os diferentes espaços decoordenadas, vão ser explicados mais à frente):

1 . Model transform, transformação deModel Space para World Space.2. View transform, transformação de WorldSpace para Camera Space.3. Projection transform, transformação deCamera Space para Clip Space.

Usando notação matemática, podemosrepresentar estas transformações pela seguintemultipl icação de matrizes:

Model & View Transform

A primeira transformação que ocorre é atransformação designada por Model. Estatransformação é usada para colocar os objectosna sua posição do mundo. Como já vimos, osobjectos começam com o seu próprio espaço decoordenadas, e normalmente estão centrados naorigem. Se quisermos colocar dois cubos nomundo 3D (definidos num ficheiro externo ecentrados na origem), vamos ter duas matrizesde model diferentes, que os colocam emposições diferentes, e que também permitemque eles tenham tamanhos diferentes ou quenão estejam orientados da mesma forma.

A transformação View vai colocar os objectoscentrados no espaço da câmara. Ou seja,objectos mesmo à frente da lente da câmara vãoestar na origem desse novo espaço. Ao iníciopode parecer confuso, pois ao contrário do queestamos habituado no mundo real (onde osobjectos não mudam de sítio), em 3D são osvértices dos objectos que são multipl icados por

Aspectos l ow- l eve l d e 3D

Page 52: Revista programar 26

52

A PROGRAMAR

uma matriz, e é normal que sejam os objectosque mudam de sitio para serem vistos dediferentes posições.

Projection

Depois de os objectos estarem posicionados noespaço da câmara, é necessário que eles sejamprojectados. A projecção consiste nomapeamento dos vértices (em 3D) para um certoplano com representação bi-dimensional (2D).Podemos considerar dois tipos de projecções:

• Ortogonais (ortographic projection)• Perspectivas (perspective projection).

Tal como representado na figura, podemos veruma projecção perspectiva na esquerda. Aslinhas, quando vistas no horizonte, focam-senum ponto (vanishing point). A este efeitochama-se foreshortening. Tem a característicaque objectos mais longe parecem maispequenos. Este é o tipo de projecção a queestamos habituados a ver no dia-a-dia.

Outro tipo de projecção, apresentado na direita,é a projecção ortográfica. Esta projecção tem acaracterística que linhas paralelas continuamparalelas depois da projecção. Por exemplo,estamos habituados a ver este tipo de projecçãoem plantas de edifícios.

No final da projecção, o resultado de multipl icartodos os vértices pelas matrizes detransformação e projecção vai ser diferente,dependendo do tipo de projecção escolhido. Nocaso da projecção ortográfica, o resultado vaiser um paralelepípedo, enquanto no caso daprojecção perspectiva vai ser uma pirâmideinvertida com o topo truncado, a que se dá onome de frustum (exemplo na figura).

No final da projecção, o resultado de multipl icartodos os vértices pelas matrizes detransformação e projecção vai ser diferente,dependendo do tipo de projecção escolhido. Nocaso da projecção ortográfica, o resultado vaiser um paralelepípedo, enquanto no caso daprojecção perspectiva vai ser uma pirâmideinvertida com o topo truncado, a que se dá onome de frustum (exemplo na figura).

As APIs gráficas normalizam o resultado detodos os tipos de projecção num cubo centradona origem com dimensões que variam de (-1 ,1 )no eixo X, Y e Z. Isto permite que os restantes

Aspectos l ow- l eve l d e 3D

Page 53: Revista programar 26

53

A PROGRAMAR

passos da pipel ine sejam executados de formauniforme. O espaço resultante é chamado de clipspace pois nesta mesma fase todos os vérticesque estejam fora do espaço definido pelo cubo,são ignorados (também conhecido por cl ipping).

É de notar que o funcionamento apresentadopode ser l igeiramente diferente entre o OpenGLe o Direct3D, mas a teoria é equivalente entre osdois. Normalmente só alguns pormenoresvariam, sendo recomendada a consulta dadocumentação oficial de cada API para sabermais concretamente de como são executadostodos estes passos. Alguns pequenospormenores também foram omitidos poisrequerem conhecimento mais avançado sobre arepresentação de coordenadas homogéneas emmatrizes (perspective divide e normalized devicecoordinates).

Viewport Mapping

As APIs gráficas normalmente permitem adefinição de uma sub-região da janela onde ooutput final é mostrado. Imaginem por exemploum jogo de carros, com suporte para 2jogadores no mesmo ecrã (o que os jogosnormalmente chamam de split-screen).Normalmente o ecrã é dividido ao meio e émostrada a área de jogo de cada jogador emcada uma dessas regiões. Nas APIs gráficas,cada uma dessas regiões é conhecida porviewport.

Depois de obter as coordenadas normalizadasno cubo, é feito o mapeamento para o espaço decoordenadas da janela, ou Window Space. Esteprocesso é conhecido por Viewport Mapping,pois tem em conta as definições do viewportactual, para permitir que diferentes imagenssejam mostradas na mesma janela.

Rasterizer stage

Esta fase uti l iza as primitivas geradas na faseanterior para determinar os píxeis finais que vãoser escritos no framebuffer. O primeiro passo aser processado é conhecido por Scanconversion. Este passo transforma os triângulos2D (mais a sua profundidade) em fragmentos.Fragmentos são potenciais píxeis que vão serescritos no framebuffer. Têm associadosinformação como localização, cor, coordenadasde texturação e profundidade.

A informação que está associada aosfragmentos é usada para determinar a sua cor. Acor de um fragmento pode depender de váriosfactores, por exemplo, se existem luzes queafectam o fragmento, ou se o fragmento faz usode texturas. Esta fase é chamada de shading eexistem vários algoritmos de diferentescomplexidades que dão resultados melhores oupiores de acordo com o seu custo deprocessamento.

Nos primeiros jogos as fórmulas uti l izadassimplificavam bastante as equações necessáriaspois ainda não existia poder de processamentosuficiente para uti l izar técnicas mais avançadas.A informação era normalmente processada paracada vértice (per-vertex shading) e depoisinterpolada em cada fragmento (Gouraudshading). Hoje em dia já temos poder deprocessamento suficiente para calcular ainformação da cor por cada fragmento (per-pixelshading) com técnicas como o Phong shading.Esta fase é normalmente implementada nasplacas modernas com shaders, que permitemtotal controlo e flexibi l idade sobre o algoritmouti l izado já que são escritos pelo uti l izador.

Depois de calculada a cor de cada fragmento,essa cor pode ser misturada com a já existente

Aspectos l ow- l eve l d e 3D

Page 54: Revista programar 26

54

A PROGRAMAR

no framebuffer (de fragmentos anteriores queocupam a mesma posição). Esta técnica échamada deblending e oOpenGL porexemplo permite ocontrolo dasequaçõesuti l izadas paraefectuar a mistura.É possível assimobter efeitos comotransparências parciais ou totais.

O que vemos na figura é um exemplo deblending por adição. Os fragmentos do quadradoverde são misturados com os já existentes doquadrado vermelho, dando origem ao amarelo.

Uti l izando a mesma figura, outro conceitoimportante a perceber é o controlo daprofundidade dos objectos. Por exemplo, setiverem um quadrado à frente de outro, sóquerem que o quadrado mais próximo da

câmara sejamostrado, pois está atapar o quadrado detrás. A profundidade écontrolada com ovalor de profundidadedo vértice quandoprojectado no espaçode coordenadas dacâmara (eixo dos Z).

Para controlar e saber quais os objectos a

mostrar, o OpenGL podia ordenar os objectos edesenhar os que estão mais longe primeiro (ochamado Painter's algorithm), mas isso causaproblemas com objectos que se intersectam (verfigura). A solução uti l izada pelo OpenGL eDirect3D é ordenar os objectos ao nível do pixel,uti l izando uma zona de memória que armazenaa profundidade de cada pixel (chamado dedepth- ou Z-buffer).

Depois de conhecida então a cor do fragmento,quando um fragmento está para ser escrito noframebuffer, a sua profundidade é comparadacom a do fragmento que está no buffer (depthbuffer test). Só se o fragmento novo estiver maisperto (se o seu valor for menor) é que o novovalor de cor é escrito no framebuffer.

No fim do processamento de todos osfragmentos, a aplicação mostra o conteúdo doframebuffer no ecrã (normalmente numa janela)ou grava o conteúdo para uma imagem.

Chegamos ao fim do artigo! Embora este artigojá dê uma pequena ideia sobre o mundo que é o3D, foi apenas uma pequena introdução sobre otema. Espero que tenham gostado e aprendidocom o artigo, e se quiserem aprender mais,podem consultar os seguintes recursos.

Real-Time RenderingEssential Math for Game DevelopersGameDev.net

Escrito por João Matos

Também conhecido por triton, frequenta o segundo ano do curso de Engenharia Informática e

Computadores no IST. Tem como principais interesses as áreas de Sistemas Operativos, Computação

Gráfica e Arquitectura de Computadores.

AUTOR

Aspectos l ow- l eve l d e 3D

Page 55: Revista programar 26

55

CORE DUMP

Quand o se é ! Prod u t i voacusadas cai por terra. Muitas das vezes até épossível mostrar que a verdadeira razão da faltade produtividade vem da equipa de gestão.

Mas então, como encontrar e medir essasineficiências? É aqui que entra o poder deobservação e o cérebro.

O primeiro passo é identificar todas as causasque nos levam ao desespero quando fazemosdesenvolvimento. Já me deparei com coisas tãovariadas como intromissões de anti-vírus, faltade permissões no sistema de desenvolvimento,ou uso de máquinas virtuais.

Para exemplificar, no caso do anti-vírus omesmo não podia ser configurado pelo uti l izadorpara não verificar os directórios referentes aocódigo fonte, ao código compilado, às bibl iotecasusadas, etc. ; enquanto que o clássico caso defalta de permissões, faz com que qualqueralteração necessite de uma longa interacçãoentre efectuar um pedido para a alteração e omesmo ser satisfeito; já o caso da máquinavirtual, há quem tenha de desenvolver usandouma máquina virtual que sub-aproveita osrecursos da máquina física e, devido àquantidade de camadas intermédias envolvidas,torna toda a interacção com o sistema muitomais lenta.

O segundo passo é encontrar uma forma demedir os problemas identificados e convertê-losnuma medida que a gestão compreenda.

Neste caso o tempo é uma das escolhasnaturais. Por exemplo, no caso do anti-vírus, otempo de compilação da aplicação sofreu umaumento significativo, que somado ao longo deuma semana resultava em, aproximadamente,

Quem ganha a vida a bater código estáhabituado a ver a sua produtividade medida. Porvezes essa medição não é efectuada de formacorrecta e, pior, muitas vezes não é sequerefectuada de forma justa. O resultado é, muitasvezes, uma enorme irritação para com a gestãopor esta se refugiar em frases, quaseinfindáveis, como “Estás quase sempre atrasadonos prazos de entrega”, ou “O desenvolvimentonunca entrega as coisas a tempo e horas”.

As desculpas, ou justificações, por quem fazdesenvolvimento são também elas inúmeras,vão do simples “O servidor é muito lento” ao“Estão sempre a mudar as especificações doproduto”.

Esta parece uma luta desigual, entre odesenvolvimento e a gestão, mas na verdadeapenas o é porque tipicamente odesenvolvimento não faz uso daquilo que melhortem ao seu alcance: o seu cérebro e o poder deobservação.

Se a produtividade pode ser medida, aineficiência também. E quando se mede aineficiência então há factos que sustentam afalta de produtividade e que, por sua vez, trazemluz à verdadeira causa dessas ineficiências.

Quando fazemos este exercício de medir aineficiência, posso assegurar-vos que a largamaioria das vezes a tal falta de produtividade deque as equipas de desenvolvimento são

Se a produtividadepode ser medida, aineficiência também

Page 56: Revista programar 26

56

CORE DUMP

duas horas de inactividade, ou seja um dia pormês de inactividade só devido ao facto do anti-vírus estar incorrectamente configurado.

Esta situação levou-me a questionar a gestão seeu podia configurar o anti-vírus correctamente etirar um dia de folga a mais por mês, afinal oresultado seria exactamente o mesmo.

No caso das máquinas virtuais voltei a medir otempo, mas desta vez as coisas foram maisdrásticas. E não era só pelo facto da mesmamáquina física ter de correr dois sistemasoperativos com dois anti-vírus e desperdiçar500MB de RAM porque a máquina virtualapenas conseguia alocar 1 .5GB de RAM.. .

Era um conjunto de situações que somadoresultava num aumento de quatro vezes o tempode espera na operação de compilação e deployda aplicação.

Sim, a produtividade caiu para valores críticos.

Após efectuar esta medição, a extrapolação dosvalores obtidos mostrou 33 horas de inactividademensal. Trinta e três horas por mês num mêsque tem quarenta horas de trabalho semanalresulta quase numa semana de inactividade.

O caso tomou proporções interessantes uma vezque esta situação se passou num cliente quetinha mais de oitenta pessoas externas a fazerdesenvolvimento nestas condições. Quando se

tem oitenta pessoas em regime de outsourcing aquem se pagam 4 semanas de trabalho paratrabalharem pouco mais de 3 semanas, oresultado financeiro é desastroso.

Tudo pode ser medido, pelo que o desafio estáem encontrar uma forma intel igente de medir oque está mal e apresentar esses resultados.

Certamente que não é o desenvolvimento quenão é produtivo quando um bug ocorreu devidoa um requisito mal especificado, ou quandoexiste um processo moroso para satisfazer umasolicitação, ou quando ocorre uma alteração naespecificação do sistema.

Da próxima vez, não se queixem, identifiquem aineficiência, meçam a ineficiência e apresentemessa ineficiência à vossa gestão.

Após efectuar estamedição, a extrapolaçãodos valores obtidosmostrou 33 horas deinactividade mensal

Escrito por Fernando MartinsFaz parte da geração que se iniciou nos ZX Spectrum 48K. Tem um Mestrado em Informática e mais deuma década de experiência profissional nas áreas de Tecnologias e Sistemas de Informação. Criou a suaprópria consultora sendo a sua especial idade a migração de dados.

AUTOR

Quand o se é ! Prod u t i vo

Page 57: Revista programar 26

57

COMUNIDADE SHAREPOINTPT

C l i en t Ob j ect Mode l p a ra S i l ve rl i gh tcrescido a nível de serviço e a nível deimportância nas instituições empresariais,tornando uma aposta mais que decisiva daMicrosoft, com a sua implementação eintegração de todos os seus produtos nestaplataforma, tornando-se o sistema operativo dasempresas.

Uma das suas vantagens é a capacidade deintegração entre as diversas tecnologiasMicrosoft e a capacidade de integrações deplataformas externas, como SAP, Oracle entreoutras, de forma a torna um ponto de parti lhaúnica da Informação da empresa, sendoconstruido numa plataforma Web o que tornabastante acessível o seu acesso.

No próximo quadro encontram-se os serviçosque estão disponíveis para o SharePoint 201 0.

Com o lançamento do SharePoint 201 0 foramdisponibi l izados múltiplos novos serviços comoLINQ, novas API ’s para acesso a dados(uti l izando o Client Object Model), uti l ização deREST - ADO.NET Data Services e uti l ização deAjax em webParts com processos Asynchronous(sem uti l ização de postback nas páginas) entreoutros novos serviços.O SharePoint 201 0 apresenta 3 novas Client

Com o lançamento da nova versão doSharePoint, mais propiamente SharePoint 201 0no início deste ano, e o seu sucesso a nívelmundial da sua adopção como uma dasferramenta empressariais de Portais eColaboração, este artigo tem como prespectiva asua demostração como ferramenta dedesenvolvimento para Soluções empresariais.

Neste artigo irei ainda dar atenção a um dosnovos serviços disponibi l izados pelo SharePoint201 0 que é o Client Object Model paraSilverl ight, com a criação de um projecto echamada de métodos para demostrar a suacapacidade de acesso a conteudos existentenos sites em SharePoint.

A plataforma SharePoint é um conjunto integradode recursos que pode ajudar a melhorar aeficácia organizacional fornecendo uma gestãode conteúdo abrangente e pesquisa empresarial ,acelerando os processos comerciaiscomparti lhados e facil itando a parti lha deinformações para uma melhor visão dosnegócios.

Os serviços disponibi l izados vão desde Gestãode Conteúdos, Gestão Documental, BusinessIntel l igence, Comunidades, Integração dePlataforma externas a Microsoft através dosBCS(Business Connectivity Services),Workflows, Office Web app (Integração dasferramentas Microsoft Office em formato Web),SharePoint Designer 201 0, Gestão de Projectos,Serviços de Pesquisa de Portal e ConteúdosExterno, com diversos tipos de autenticaçãouti l ização de federações entre outros serviços.Enfim uma plataforma bastante completa.

Durante os últimos anos a plataforma tem

Page 58: Revista programar 26

58

COMUNIDADE SHAREPOINTPT

no Visual Studio 201 0, com uma aplicação emSilverl ight 4, uti l izando a API do SharePoint eintegrando do SharePoint 201 0.

Para suporte da nossa solução em SharePointeu criei uma Lista chamada “Geral” com umconjunto de dados para teste.Criar um novo Projecto com o Visual Studio

201 0 no Template “Silverl ight” e seleccionar aopção para associar a um novo Web site com aversão do Silverl ight 4:

API ’s para interagir com conteúdos dos sites deSharePoint:• A partir de aplicações .Net “nunca inferiores aFramework 3.5”;• A partir de aplicações Silverl ight “nuncainferiores a Silverl ight 2.0”• A partis de ECMAScript ou seja de Javascript,Jscript

Arquitectura do Client Object Model

Estas novas API em Client Object Modelfornecem um sistema orientado a objectos parainteragir com os dados do SharePointremotamente, sendo bastante fáceis de uti l izarporque a sua nomenclatura é bastante parecidado Server Object Model do SharePoint.

Para demostrar a forma de acesso aos Objectosda API na próxima tabela mostra a diferentesAPI ’s para as diversas plataformas e a formaidêntica da uti l ização do Object Model.Neste exemplo, irei criar um pequeno Projecto

C l i en t Ob j ect Mode l p a ra S i l ve rl i gh t

Page 59: Revista programar 26

59

COMUNIDADE SHAREPOINTPT

Método 1 :Retorna o nome das Listas existentes no site deSharePoint uti l izando o Client Object Mode. Foiuti l izado uma expressão Lambda para retornaras l istas e o Titulo associado.

Para realizar as chamadas ao conteúdo doSharePoint, através da API em Silverl ight, seránecessário adicionar como referencias as DLL’sque se encontram na pasta da instalação doSharePoint 201 0(Microsoft.SharePoint.Cl ient.Si lverl ight eMicrosoft.SharePoint.Cl ient.Si lverl ight.Runtime),tipicamente em C:\Program Files\CommonFiles\Microsoft Shared\Web ServerExtensions\1 4\TEMPLATE\LAYOUTS\ClientBin.

Futuramente, a Microsoft irá disponibi l izar umpackage com as DLLs em SharePoint .NETClient Object Model, onde se poderá realizar odownload e a sua distribuição ao cliente.

Com a uti l ização do Visual Studio 201 0 existe apossibi l idade de integrar o Microsoft ExpressionBlend 4 com as nossas aplicaçõesdesenvolvidas em Silverl ight.

Depois de termos realizado a nossacustomização podemos voltar à nossa soluçãoem Visual Studio 201 0 e começar a criar osnosso métodos para retornar conteúdo do Site.Para isso criei 2 métodos, um para retornar al istas do nosso site em SharePoint e outro pararetornar o conteúdo de uma Lista numaDatagrid.

private void LoadLists()

ClientContext clientContext =new ClientContext("http://[Site]");

oWebsite = clientContext.Web;collList = oWebsite.Lists;

clientContext.Load(oWebsite,website => website.Title);

//Lambda expression para retornar as ListaslistInfo = clientContext.LoadQuery(

collList.Include(list => list.Title,list => list.Fields.Include(field => field.Title).Where(field => field.Required == true

&& field.Hidden != true)));

clientContext.ExecuteQueryAsync(onQuerySucceeded, onQueryFailed);

private void onQuerySucceeded(object sender,

ClientRequestSucceededEventArgs args)

UpdateUIMethod updateUI = DisplayInfo;this.Dispatcher.BeginInvoke(updateUI);

private void onQueryFailed(object sender,ClientRequestFailedEventArgs args)

MessageBox.Show("Request failed. " +

args.Message +"\n" + args.StackTrace);

C l i en t Ob j ect Mode l p a ra S i l ve rl i gh t

Page 60: Revista programar 26

60

COMUNIDADE SHAREPOINTPT

No seguinte exemplo foi criado um pequenoformulário no Silverl ight para a lista “Anuncios”.Esta l ista tem um conjunto de artigos dereferência ao Site e este método mostra comose consegue criar um formulário de uma formasimples, sem ter a necessidade de realizar

Exemplo:http: //msdn.microsoft.com/en-us/l ibrary/ee538971 .aspx

Método 2:Retorna dados da Lista “Geral” para umaDataGrid uti l izando CAML para realizar os fi ltrosdos conteúdos a retornar:

private void DisplayInfo()

collList = oWebsite.Lists;listBox1.ItemsSource = listInfo;listBox1.DisplayMemberPath = "Title";

private delegate void UpdateUIMethod();

private void LoadGrid()

//Contexto do site em SharePoint a chamarvar context = new

ClientContext("http://[Site]");context.Load(context.Web);

//retornar o objecto List com o nome“Geral”

List projects =context.Web.Lists.GetByTitle("Geral");

context.Load(projects);

//CAML Query para Filtar os valores danossa Lista

CamlQuery camlQuery = new CamlQuery();camlQuery.ViewXml =

"<View><Query><Where><Geq><FieldRefName='ID'/>" +

"<ValueType='Number'>0</Value></Geq></Where></Query><RowLimit>100</RowLimit></View>";

_projectItems =projects.GetItems(camlQuery);

context.Load(_projectItems);

context.ExecuteQueryAsync(OnRequestSucceeded,null);

#region Methods

private void OnRequestSucceeded(Objectsender, ClientRequestSucceededEventArgs args)

Dispatcher.BeginInvoke(BindData);

private void BindData()

//Utilizando o conteúdo numa lista deObjecto do tipo Geral como a Lista

var list = new List<Geral>();foreach (var li in _projectItems)

list.Add(new Geral

Title = li["Title"].ToString(),Nome = li["Nome"].ToString(),

Activo =Convert.ToBoolean(li["Activo"].ToString())

);

//adicionar os Dados da Lista naDatagrid

dataGrid1.ItemsSource = list;

C l i en t Ob j ect Mode l p a ra S i l ve rl i gh t

Page 61: Revista programar 26

61

COMUNIDADE SHAREPOINTPT

Com a criação deste 2 pequenos exemplospodemos criar a nossa solução“AccessData.XAP”.

SharePoint Silverlight Web Part

SharePoint disponibi l iza ferramentas paraintegrar o projecto desenvolvido em Silverl ight eadicionar nos nossos sites em SharePoint deuma forma bastante simples.O primeiro passo será adicionar o nosso projectoem Silverl ight, neste caso “AccessData.XAP” eadicionar no nosso site em SharePoint, podendoser uma Folder, uma Document Library ou até na

customização de páginas em aspx.

Foram adicionadas na Tab “formulário” doSilverl ight, 3 campos de preenchimento donosso Artigo, como o Url do site onde se destina,Titulo e corpo.

Método 3:Este método ira criar uma nova entrada na Listade SharePoint de um novo anúncio.

if (!TxtTitle.Text.Equals(""))

ClientContext clientContext =new ClientContext(TxtUrl.Text);

Web oWebsite =clientContext.Web;

ListCollection collList =oWebsite.Lists;

oList =clientContext.Web.Lists.GetByTitle("Anuncios");

ListItem oListItem =oList.AddItem(newListItemCreationInformation());

oListItem["Title"] =TxtTitle.Text;

oListItem["Body"] =TxtBody.Text;

oListItem.Update();

clientContext.Load(oList,list => list.Title);

clientContext.ExecuteQueryAsync(onQueryInsertSucceeded, onQueryInsertFailed);

else

MessageBox.Show("Vazio!!");

C l i en t Ob j ect Mode l p a ra S i l ve rl i gh t

Page 62: Revista programar 26

62

COMUNIDADE SHAREPOINTPT

Quando nos encontramos a trabalhar emambiente Web a aplicação Fiddler é umaferramenta essencial para captura e validaçãodo nosso tráfego na Web. Estando ela emfuncionamento podemos encontrar astransacções realizadas, através da Client OM, eencontramos uma chamada ao WCF WebService “cl ient.svc” e um Web Service XML paracomunicação e transacção das operações.

Existem outra forma de poder interagir com osdados em SharePoint, com o Silverl ight atravésdos “REST” em WCF e com todas as suaspotencial idades.

Conclusão

Este foi um pequeno exemplo de como o Client

directoria ou pasta “Hive” onde se encontrainstalado o SharePoint no servidor. Neste casocriei uma Folder dentro do site em SharePoint.Estas pastas não são visíveis aos uti l izadoresfinais, garantido que o ficheiro não é apagadoacidentalmente.

Depois de adicionado a nossa solução emSilverl ight, acedemos ao nosso site emSharePoint e adicionamos uma Web Part que seencontra por defeito no SharePoint “Silverl ightWeb Part”. Um dos parâmetros que é requisitadoé o caminho de onde se encontra a nossasolução em Silverl ight.

Assim que esteja tudo correctamenteadicionado, irá ser disponibi l izado na nossapágina de internet a nossa solução de Silverl ight,dentro do SharePoint, numa WebPart podendotrabalhar e interagir com o conteúdo do Siteonde se encontra.

C l i en t Ob j ect Mode l p a ra S i l ve rl i gh t

Page 63: Revista programar 26

63

COMUNIDADE SHAREPOINTPT

Create a Silverl ight 4 Web Part for SharePoint201 0http: //msdn.microsoft.com/en-us/magazine/ff956224.aspxPágina Oficial do SharePoint 201 0http: //sharepoint.microsoft.com/pt-pt/Pages/default.aspx

Este e outros artigos relacionados com aTecnologia Microsoft SharePoint estãodisponibi l izados pelo site da ComunidadePortuguesa de SharePoint. Podem tornar-semembros activos, criando artigos e aparticipando em eventos mensais daComunidade sobre a tecnologia SharePoint.

Comunidade Portuguesa de SharePointhttp: //www.sharepointpt.org/

Object Model e como o SharePoint 201 0consegue fornecer informação e integração comSilverl ight.Teria muita mais que falar, isto é um tema paradiversos subtópicos e com múltiplas formas detratar, apenas quero demostra as portas quepodem ser abertas e como o SharePoint 201 0 éuma ferramenta de integração com todas asdiversas Tecnologias Microsoft.

Alguns l inks úteis:Using the Silverl ight Object Modelhttp: //msdn.microsoft.com/en-us/l ibrary/ee538971 .aspxUsing the SharePoint Foundation 201 0 ManagedClient Object Modelhttp: //msdn.microsoft.com/en-us/l ibrary/ee857094.aspxUsing the SharePoint Foundation 201 0 ManagedClient Object Model with the Open XML SDK 2.0http: //msdn.microsoft.com/en-us/l ibrary/ee956524.aspxSharePoint 201 0 Reference: SoftwareDevelopment Kithttp: //www.microsoft.com/downloads/en/detai ls.aspx?FamilyID=f0c9daf3-4c54-45ed-9bde-7b4d83a8f26f&displaylang=en

Escrito porAndré Lage

Microsoft SharePoint MVP, trabalhando na Suiça em empresa Farmaceutica e Banca.

Apoiando as diversas Comunidades em SharePoint pelo mundo com participaçoes em eventos como

speaker e efectuando artigos com focus nas tecnologias SharePoint. Um dos administradores da

Comunidade Portuguesa de SharePoint, Co-fundada por Rodrigo Pinto, www.Sharepointpt.org. Blog

pessoal http: //aaclage.blogspot.com/

AUTOR

C l i en t Ob j ect Mode l p a ra S i l ve rl i gh t

Page 64: Revista programar 26