Você está na página 1de 64

Editorial

EDITORIAL
EQUIPA PROGRAMAR
Coordenadores Antnio Silva Fernando Martins Editor Antnio Silva Design Srgio Alves (@scorpion_blood) Redaco Andr Lage, Augusto Manzano, Diogo Constantino, Fernando Martins, Joo Mares, Joo 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

Sempre em movimento
Porque sabemos que parar morrer, nesta edio da Revista PROGRAMAR introduzimos vrias alteraes que achamos importantes para continuidade deste projecto. Das vrias alteraes introduzidas, a salta imediatamente vista, mesmo ao leitor que ainda est somente a ler a pgina do editorial, a mudana de design . Em qualquer tipo de publicao 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 Srgio Alves por toda a parte da idealizao e desenho do novo design. Outra alterao, que todavia no ser to notada pelos leitores a alterao do software de paginao. Chegamos concluso que o Scribus j evoluiu bastante desde a ltima vez que foi utilizado para paginar a Revista PROGRAMAR e est altura das nossas necessidades. Assim decidimos que no havia necessidade de continuarmos a utilizar um software pago e que trazia vrios problemas de leitura a alguns utilizadores (dos quais chegamos a receber comentrios). Tambm fizemos vrias parcerias com algumas comunidades portuguesas que esto de algum modo relacionadas com programao, de modo a obter mais e melhores artigos para si. Todavia no estamos fechados a mais parcerias, continuamos abertos a futuros contactos para o nosso endereo de correio electrnico, que sero posteriormente analisados por toda a equipa. Trazemos tambm at si, colunas de opinio e colunas direccionadas a um tema especfico. Assim poder contar que surgiro artigos desse assunto com uma periodicidade especfica 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 prxima edio dever sair em Fevereiro ao invs de Maro como estava programado. Tudo isto para si, que est ler. Espermos que as alteraes sejam bem recebidas por todos, mas tambm espermos opinies sobre todas estas alteraes, mesmo porque as novidades podero no ficar por aqui, contmos ter mais novidades na prxima edio. Por isso no tenha medo de nos contactar para revistaprogramar@portugal-a-programar.org a dizer o que acha de todas estas alteraes. Porque voc importante para ns, quer as suas opinies, quer o seu trabalho a divulgar o nosso projecto aos seus amigos e colegas, e mais importante a sua preferncia que nos permite crescer para lhe oferecer algo maior e melhor. A equipa da Revista PROGRAMAR

INDICE
4 11 18 23 26 31 35 41 43 47 54 56

Tema de Capa - LINQ BYACC Introduo ao Entity Framework Programao 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 Silverlight

A revista PROGRAMAR um projecto voluntrio, sem fins lucrativos. Todos os artigos so da responsabilidade dos autores, no podendo a revista ou a comunidade ser responsabilizada por alguma impreciso ou erro. Para qualquer dvida ou esclarecimento poder sempre contactar-nos.
2

Noticias

NOTICIAS
U p l o a d Li s b o a e U p l o a d Li s b o a Pro 2 0 1 0
O Upload Lisboa um evento que por si s nomeia a era em que estamos. A era da nova comunicao, da troca de informao no momento, de forma prtica e natural, e da partilha de conhecimentos em rede. O Upload Lisboa pretende, mais uma vez, passar a esfera da rede interior e global para a esfera da partilha conjunta, fsica. Este evento nasce da necessidade crescente de debate e partilha de conhecimentos sobre a web 2.0, numa altura em que as novas plataformas de comunicao e informao assumem um lugar cada vez mais central na vida de pessoas e empresas. Hoje, mais que nunca, a partilha atravs das plataformas sociais na web ocupam um lugar de destaque na influncia na opinio pblica e na formao de critrios de anlise ao que se passa no pas e no mundo. So dois dias, 11 e 1 5 de Dezembro, que certamente no ir perder! Mais informaes: http://uploadlisboa.com/

Se m i n ri o Po c ke tPT s o b re te c n o l o gi a s Wi n d o ws Ph o n e
Encontram-se abertas as inscries para o 6 Seminrio PocketPT sobre tecnologias mveis Windows Phone. Este ano o seminrio ser dedicado nova plataforma mvel da Microsoft, e ir incluir vrias sesses que iro dar a conhecer as funcionalidades do mesmo. Ser ainda uma excelente oportunidade para os participantes testarem e verem em primeira mo os novos equipamentos. Como tem vindo a acontecer nos anos anteriores a inscrio este ano gratuita e ir ter lugar no auditrio da Microsoft Portugal no TagusPark em Porto Salvo no prximo dia 1 8 de Dezembro pelas 1 0h. Mais informaes e inscries: http://www.mtechseminar.com/201 0/index.htm

SAPO C o d e B i ts 2 0 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 (infelizmente no foi possvel juntar todos):

1 6 a R e u n i o Pre s e n c i a l d a C o m u n i d a d e N e tPo n to
No dia 11 /1 2/201 0 ser realizada a 1 6 reunio presencial da comunidade NetPonto, em Lisboa. Nesta sesso, poder ver duas apresentaes presenciais sobre Domain Driven Design e WP7 & XNA Lets play? Para participar, basta efectuar a inscrio atravs do site http://netponto-lisboa-dezembro-201 0.eventbrite.com/ A entrada gratuita e so realizadas reunies todos os meses. Para mais informaes, consulta de prximas sesses e inscrio: http://netponto.org/

TEMA DE CAPA
LI N Q: I m p l e m e n ta o d o s o p e ra d o re s Ta ke La st, Ta ke La stWh i l e , Ski p La st e S ki p La stWh i l e
H algum tempo necessitei de obter os ltimos itens de uma sequncia que satisfaziam um determinado critrio e, olhando para os operadores disponveis na classe Enumerable, apercebi-me de que tal operador no existia.

original uma vez e mais trs vezes sobre os itens que satisfazem o critrio. Se a sequncia original for grande, isto pode consumir muita memria e tempo. Existe ainda um problema adicional quando se usa a variante que usa o ndice de item na sequncia original na avaliao do critrio de seleco (>). Quando se inverte a ordem dos itens, os ndices destes sero invertidos e o predicado de avaliao do critrio de seleco ter de ter isso em considerao, o que poder no ser possvel se no se souber o nmero de itens na sequncia original. Tinha de haver uma soluo melhor, e por isso que eu implementei os Operadores Take Last:

A nica forma de obter o resultado pretendido era inverter a ordem dos itens na sequncia, obter os itens que satisfaziam o critrio e inverter os itens da sequncia resultante. Algo como isto:
Sequence .Reverse()

.TakeWhile(criteria) .Reverse();

Parece simples, certo? Primeiro chamamos o mtodo Reverse para produzir uma nova sequncia com os mesmos itens mas na ordem inversa da sequncia original, depois chamamos o mtodo TakeWhile para obter os primeiros itens que satisfazem o critrio e, finalmente, chamamos novamente o mtodo Reverse para recuperar a ordem original dos itens. O problema desta aproximao que o mtodo rev memoriza toda a sequncia antes de iterar sobre os seus itens na ordem inversa e o cdigo acima usa-o duas vezes. Isto significa iterar sobre todos os itens da sequncia original e memoriza-los, iterar sobre os primeiros itens que satisfazem o critrio e memoriza-los e, finalmente, iterar sobre estes itens para produzir a sequncia final. Se estiveram a contar, chegaram concluso de que se iterou sobre todos os itens da sequncia
4

TakeLast<TSource>(IEnumerable<TSource>)
Retorna o nmero especificado de elementos contnuos no fim da sequncia.
int[] grades = { 59, 82, 70, 56, 92, 98, 85 };

var topThreeGrades = grades .TakeLast(3); Console.WriteLine("As so:");

.OrderBy(grade => grade)

notas

mais

altas

foreach (int grade in topThreeGrades) { } Console.WriteLine(grade);

TEMA DE CAPA
LI N Q: I m p l e m e n ta o d o s o p e ra d o re s Ta ke La st, Ta ke La stWh i l e , Ski p La st e Ski p La stWh i l e
/* Este cdigo produz o seguinte resultado: As notas mais altas so: 98 92 85 */ 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);

TakeLastWhile<TSource>(IEnumerable<TSou rce>, Func<TSource, Boolean>)


Retorna os elementos do fim da sequncia para os quais a condio especificada verdadeira.
string[] fruits = { "ma", "maracuj","banana", "manga", };

Este cdigo produz o seguinte resultado: morango */

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

var query = fruits

.TakeLastWhile(fruit => fruit, true) != 0);

string.Compare("laranja",

Tendo introduzido os operadores TakeLast, faz todo o sentido introduzido os seus duais: os operadores SkipLast:

SkipLast<TSource>(IEnumerable<TSource>)
Retorna todos os elementos da sequncia excepo do nmero especificado de elementos contnuos no fim da sequncia.
int[] grades = { 59, 82, 70, 56, 92, 98, 85 }; .OrderBy(g => g) .SkipLast(3);

foreach (string fruit in query) { } /* Console.WriteLine(fruit);

Este cdigo produz o seguinte resultado: maracuj uva */ morango

var lowerGrades = grades

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

TakeLastWhile<TSource>(IEnumerable<TSou rce>, Func<TSource, Int32, Boolean>)


Retorna os elementos do fim da sequncia para os quais a condio especificada verdadeira.
5

foreach (int grade in lowerGrades) { } Console.WriteLine(grade);

TEMA DE CAPA
LI N Q: I m p l e m e n ta o d o s o p e ra d o re s Ta ke La st, Ta ke La stWh i l e , Ski p La st e Ski p La stWh i l e
/* Este cdigo produz o seguinte resultado: As notas mais altas, excepto: 56 59 70 82 */

SkipLastWhile<TSource>(IEnumerable<TSour ce>, Func<TSource, Int32, Boolean>)


Retorna todos os elementos da sequncia excepo dos elementos do fim da sequncia para os quais a condio especificada verdadeira.
int[] amounts = { 5000, 2500, 9000, 8000, 6500, 4000, 1500, 5500

SkipLastWhile<TSource>(IEnumerable<TSour ce>, Func<TSource, Boolean>)


Retorna todos os elementos da sequncia excepo dos elementos do fim da sequncia para os quais a condio especificada verdadeira.
int[] grades = { 59, 82, 70, 56, 92, 98, 85 }; .OrderBy(grade => grade) .SkipLastWhile(grade => grade >= 80);

};

var query = amounts index * 1000);

.SkipWhile((amount, index) => amount >

foreach (int amount in query) { } /* Console.WriteLine(amount);

var lowerGrades = grades

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

Este cdigo produz o seguinte resultado: 5000 2500 */

foreach (int grade in lowerGrades) { } /* Console.WriteLine(grade);

IMPLEMENTADO OS OPERADORES TAKELAST


I mplementando O Operador TakeLast O operador TakeLast retorna o nmero especificado de elementos contnuos do fim de uma sequncia e implementado como o mtodo de extenso TakeLast. Para implementar este operador, primeiro comeamos por memorizar, pelo menos, o nmero requerido (count) de itens da sequncia
6

Este cdigo produz o seguinte resultado: Todas as notas menores que 80: 56 59 70 */

TEMA DE CAPA
LI N Q: I m p l e m e n ta o d o s o p e ra d o re s Ta ke La st, Ta ke La stWh i l e , Ski p La st e Ski p La stWh i l e

fonte (source) num array que funciona como uma memria intermdia (buffer) circular:
var sourceEnumerator = source.GetEnumerator(); var numOfItems = 0; int idx; var buffer = new TSource[count];

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

yield return buffer[idx];

H duas optimizaes que ainda podemos fazer. A primeira bvia, se o nmero de itens requerido for 0 (zero), retornamos uma sequncia vazia:
if (count <= 0) { return

for (idx = 0; (idx < count) && numOfItems++) {

sourceEnumerator.MoveNext(); idx++,

buffer[idx] = sourceEnumerator.Current;

Se o nmero de itens memorizados (numOfItems) for inferior ao nmero requerido (count), produzimos os itens memorizados:
if (numOfItems < count) { for (idx = 0; idx < numOfItems; idx++) { } } yield return buffer[idx];

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

yield break;

A segunda se a sequncia fonte (source) implementar a interface IList<T>. Os objectos que implementam esta interface tm uma propriedade Count e acesso indexado aos seus itens que nos permite optimizar a produo da sequncia final. A produo da sequncia final passa por produzir o nmero de itens requeridos do fim da lista (ou todos se a lista contiver menos que os itens requeridos):
int listCount = list.Count; for (int idx = listCount - ((count < listCount; idx++) { }

Em seguida, iteramos pelos restantes itens e vamos os armazenando, de forma circular, na memria intermdia:
for { idx = (idx + 1) % count) (idx = 0; sourceEnumerator.MoveNext();

listCount) ? count : listCount); idx < buffer[idx] =

sourceEnumerator.Current; }

yield return list[idx];

E finalmente, iteramos sobre os itens memorizados para produzir a sequncia final:

Implementando os Operadores TakeLastWhile


O operador TakeLastWhile retorna os ltimos
7

TEMA DE CAPA
LI N Q: I m p l e m e n ta o d o s o p e ra d o re s Ta ke La st, Ta ke La stWh i l e , Ski p La st e Ski p La stWh i l e

elementos contguos que satisfazem o critrio especificado e implementado como os mtodos de extenso TakeLastWhile. Para implementar este operador, primeiro comeamos com uma memria intermdia (buffer) vazia e, para cada item que satisfaa o critrio implementado pelo predicado (predicate), memorizamos esse item. Sempre que ocorrer um item que no satisfaa o critrio de seleco, a memria intermdia limpa:
var buffer = new List<TSource>(); foreach (var item in source) { if (predicate(item)) { } { } buffer.Add(item);

} { }

buffer.Add(item);

else buffer.Clear();

foreach (var item in buffer) { } yield return item;

IMPLEMENTANDO OS OPERADORES SKIPLAST Implementando o Operador SkipLast

else buffer.Clear();

O operador SkipLast retorna o nmero especificado de elementos contnuos do fim de uma sequncia e implementado como o mtodo de extenso SkipLast. Para implementar este operador, comeamos por memorizar, pelo menos, o nmero requerido (count) de itens da sequncia fonte (source) num array que funciona como uma memria intermdia (buffer) circular:
var sourceEnumerator = source.GetEnumerator(); int idx; var buffer = new TSource[count];

Depois de percorrer toda a sequncia fonte (source), produzimos todos os itens, se existirem, da memria intermdia:
foreach (var item in buffer) { } yield return item;

A diferena para o mtodo que tem em conta o ndice do item no predicado (predicate) de seleco apenas na invocao deste:
var buffer = new List<TSource>(); var idx = 0;

for (idx = 0; (idx < count) && { }

sourceEnumerator.MoveNext(); idx++) buffer[idx] = sourceEnumerator.Current;

foreach (var item in source) { if (predicate(item, idx++)) {

Em seguida, iteramos pelos restantes itens da sequncia fonte (source) memorizando


8

TEMA DE CAPA
LI N Q: I m p l e m e n ta o d o s o p e ra d o re s Ta ke La st, Ta ke La stWh i l e , Ski p La st e Ski p La stWh i l e

circularmente cada item e produzindo o item armazenado anteriormente na mesma posio:


idx = 0; while (sourceEnumerator.MoveNext()) { var item = buffer[idx];

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

if (count >= list.Count) { return

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

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

// ...

Se o nmero de itens a excluir for igual ou superior ao nmero de itens existentes na sequncia fonte (source), o mtodo sourceEnumerator.MoveNext() retornar false na primeira iterao do ciclo while e ser produzida uma sequncia vazia. Tal como acontecia com o operador TakeLast, podem-se fazer algumas optimizaes. A primeira bvia, se o nmero de itens requeridos for 0 (zero) ou inferior, retornamos uma sequncia equivalente fonte (source):
if (count <= 0) { } return source.Select(i => i);

Se o nmero de itens da sequncia fonte (source) for superior ao nmero de itens a excluir, produzir a sequncia final consiste em produzir todos os itens da sequncia fonte (source) excepto os ltimos count itens:
int returnCount = list.Count - count; for (int idx = 0; idx < returnCount; idx++) { } yield return list[idx];

Implementando os Operadores SkipLastWhile


O operador SkipLastWhile retorna os ltimos elementos contguos que satisfazem o critrio especificado e implementado como os mtodos de extenso SkipLastWhile. Para implementar este operador, primeiro comeamos com uma memria intermdia (buffer) vazia e, para cada item que satisfaa o critrio implementado pelo predicado (predicate), memorizamos esse item. Sempre que ocorrer um item que no satisfaa o critrio de seleco, a memria intermdia limpa e o item que no satisfaz o critrio produzido:
9

A segunda se a sequncia fonte (source) implementar a interface IList<T>. Os objectos que implementam esta interface tm uma propriedade Count e acesso indexado aos seus itens que nos permite optimizar a produo da sequncia final. Se o nmero de itens a excluir for igual ou superior ao nmero de itens da sequncia fonte (source), retornamos uma sequncia vazia:

TEMA DE CAPA
LI N Q: I m p l e m e n ta o d o s o p e ra d o re s Ta ke La st, Ta ke La stWh i l e , Ski p La st e Ski p La stWh i l e
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) { } if (buffer.Count > 0) { foreach (var bufferedItem in buffer) { } } } yield return bufferedItem; } } yield return bufferedItem;

else

buffer.Clear();

yield return item;

buffer.Clear();

Concluso
Como podem ver, implementar este tipo de operadores muito fcil, pelo que, no se deve evitar a sua implementao sempre que se justifique. Implementar um especfico para a nossa aplicao pode significar uma melhor legibilidade do cdigo e at um aumento de performance. Podem encontrar a implementao completa destes operadores (e outros) no meu projecto de utilitrios e operadores para LINQ no CodePlex: PauloMorgado.Linq.

yield return item;

A diferena para o mtodo que tem em conta o ndice do item no predicado (predicate) de seleco apenas na invocao deste:
var buffer = new List<TSource>(); var idx = 0;

foreach (var item in source) { if (predicate(item, idx++)) { } buffer.Add(item);

Recursos

O meu website: http://PauloMorgado.NET/ Livro LINQ Com C# PauloMorgado.Linq Classe Enumerable Mtodos de extenso

AUTOR
Escrito por Paulo Morgado licenciado em Engenharia Electrnica e Telecomunicaes (Sistemas Digitais) pelo Instituto Superior de Engenharia de Lisboa e Licenciado em Engenharia Informtica pela Faculdade de Cincias e Tecnologia da Universidade Nova de Lisboa. Pelo seu contributo para a comunidade de desenvolvimento em .NET em lngua Portuguesa, a Microsoft premeia-o com o prmio MVP (C#) desde 2003. ainda co-autor do livro LINQ Com C# da FCA.

10

A PROGRAMAR
BYAC C
No artigo anterior adquirimos algumas noes sobre flex e vimos como implementar um scanner simples. Relembrando, o flex um gerador de analisadores lexicais ou scanners, e o byacc um gerador de parsers. Usados em conjunto permitem escrever aplicaes bastante sofisticadas, mas no nosso artigo limitamo-nos a considerar uma calculadora simples, servindo como exemplo introdutrio. Agora que temos o scanner para a nossa calculadora escrito podemos comear a considerar o parser. Um ficheiro byacc tem a mesma estrutura que o flex, j que o analisador lexical em que o flex se baseia, o lex, copiou a sua estrutura do yacc, o gerador de parsers em que o byacc se baseia. Como tal o nosso ficheiro byacc vai ser algo deste gnero:
definies %% gramtica %% int main() { } yyparse();

eles seguem a gramtica que ele define. Se o objectivo do parser for s verificar que um certo ficheiro, por exemplo um ficheiro xml, segue a especificao da linguagem, podemos no ter interesse nenhum em saber o valor de qualquer token. A nossa calculadora no entanto, precisa de produzir resultados, portanto necessita de saber o valor de cada token NUMBER que recebe. O parser define os tokens e o tipo de valores que lhes podem estar associados na zona das definies, sempre que precisa de um token novo ele chama o scanner com o resto do input que falta analisar. Vejamos a definio dos tokens para a nossa calculadora:
%union { }; double d;

%token<d> NUMBER %token NL

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

%% ... %% int main() { } yyparse();

Comecemos por considerar como que o parser e o scanner funcionam em conjunto. Um parser recebe tokens e verifica se esses tokens esto a seguir uma gramtica. O que ns estvamos a retornar no scanner, o NUMBER e o NL so esses tokens. Os tokens podem ter um valor associado ou no. O que o parser faz ver se
11

A PROGRAMAR
BYAC C

A primeira coisa que encontramos uma %union, seguida da declarao de dois tokens, NUMBER e NL. A %union serve para indicar tipos que queiramos associar a tokens e eventualmente a elementos da gramtica. Ao escrevermos %token<d> NUMBER estamos a indicar que para alm de NUMBER ser um token, tem um valor associado do tipo d, neste caso double. Isto vai ser importante quando passarmos para a gramtica e por esta razo que no scanner passvamos o nmero que tnhamos lido ao yylval.d antes de retornarmos o token. A informao da union e dos tokens que escrevermos nesta seco vai servir para o byacc gerar o header ao qual o nosso scanner fez #include e que permite ao scanner e ao parser comunicarem entre si. O '+', '-', '*', '/', '^' e UMINUS tambm so tokens mas aqui para alm de indicarmos que so tokens estamos a indicar a associatividade dos operadores, um conceito que o leitor dever conhecer, mas que abordaremos com maior profundidade na gramtica.
%{ #include <iostream> #include <cmath> %}

%%

expr_list

<< $1 << std::endl; } | ;

: expr NL expr_list expr

{ std::cout NL {

std::cout << $2 << std::endl; }

expr -$2; }

: NUMBER

| '-' expr %prec UMINUS | expr '+' expr | expr '-' expr | expr '*' expr | expr '/' expr | expr '^' expr | '(' expr ')' ;

{ $$ = $1; }

{ $$ = { $$ = { $$ = $1{ $$ = { $$ = { $$ = { $$ = $2;

$1+$3; } $3; }

$1*$3; } $1/$3; }

pow($1, $3); } }

%% int main()

%union { };

{ }

double d;

yyparse();

%token<d> NUMBER %token NL

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

Esta verso do parser introduz a gramtica, mas comecemos por observar as diferenas na seco das definies. Podemos ver primeiro que a introduo de cdigo C/C++ se processa da mesma forma que no scanner. Em seguida temos a instruo, %type<d> expr, expr no um token, outro smbolo da gramtica mas ainda assim tem um tipo, portanto temos que o indicar. Uma gramtica, tal como a gramtica da lngua
12

A PROGRAMAR
BYAC C

portuguesa, serve para nos indicar a estrutura da linguagem, quais as composies de elementos que so vlidas ou no de acordo com a linguagem. fcil de ver como isto til para um compilador. A nossa calculadora tem uma gramtica muito simples, mas ainda assim tem-la, portanto temos que compreender alguns princpios sobre gramticas. As gramticas so um conjunto de regras, s quais chamamos produes, constitudas por uma cabea e um corpo. Por exemplo,
stmt : WHILE expression stmt;

faz sentido criar vrias produes para um stmt, j que um stmt pode ser vrias coisas. Neste caso, um while, um if, um bloco, e continuando teramos um for, um switch, um do while, etc. Sendo usual a existncia de vrias produes com a mesma cabea, o byacc permite usar a seguinte sintaxe, com significado equivalente, para aumentar a legibilidade:
stmt : WHILE expression stmt | IF expression stmt | block ; | IF expression stmt ELSE stmt ...

uma produo, com cabea stmt e corpo WHILE expression stmt. A cabea indica-nos uma construo da gramtica e o corpo como ela composta. Os elementos duma gramtica dividem-se em smbolos terminais e no terminais, sendo os terminais, para efeitos deste artigo, os tokens que o scanner envia e os noterminais as cabeas de produes, ou seja smbolos que podem ser produzidos atravs doutros smbolos. Por clareza, usamos maisculas para representar terminais e minsculas para no terminais, logo, no exemplo acima, stmt e expression so smbolos no terminais enquanto que o WHILE terminal. Um smbolo terminal no pode ser obtido atravs da juno de outros smbolos, portanto s pode aparecer em corpos de produes. Um no terminal por outro lado pode ser derivado de terminais e outros no terminais, logo pode aparecer tanto na cabea como no corpo duma produo. Um smbolo no terminal pode, e habitualmente, tem vrias definies. Pegando no exemplo anterior e expandindo, obtemos,
stmt : WHILE expression stmt; stmt : IF expression stmt; stmt : block; ... stmt : IF expression stmt ELSE stmt;

Se quisssemos escrever um parser para uma linguagem de programao, tnhamos de ter uma forma de relacionar as vrias regras, por outras palavras uma gramtica necessita de uma estrutura. A forma de criar essa estrutura criando um smbolo no terminal inicial ao qual todos os outros esto subordinados. Pode ajudar pensar na estrutura da gramtica como uma rvore na qual o smbolo no terminal inicial a raiz, os outros no terminais so ns e os terminais so as folhas.
%% program : list ;

list

: statement ;

| list statement

statement : declaration | function ;

declaration : type identifier expression | ; type

identifier

'='

13

A PROGRAMAR
BYAC C
s : x type : INT | y ; | DOUBLE | CHAR ;

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

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

Este caso bvio, temos duas produes diferentes com o mesmo corpo, o parser no sabe qual deve usar quando recebe os trs tokens. O mesmo se passa nos casos seguintes.
s : x | y ;

block : '{' stmt_list '}' ;

stmt_list : stmt ;

| stmt_list stmt

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

... %%

Acima temos um esqueleto de uma linguagem muito simplificada, ainda com vrios no terminais sem produes associadas, mas basta para termos uma noo da estrutura duma gramtica. Qualquer que seja o programa escrito para esta linguagem, se ele estiver sintacticamente correcto deve ser possvel partir de program e derivar todos os elementos que o compem. Neste caso program o smbolo inicial da gramtica, e indicamos isso ao byacc colocando-o como a primeira produo do ficheiro. J vimos nos exemplos anteriores que as produes podem ser recursivas, o corpo duma produo pode conter o mesmo no terminal que a cabea. A recursividade necessria e algo que o byacc processa muito eficientemente, mas usada sem cuidado uma das coisas que introduz conflictos na gramtica. Um conflicto surge quando o parser no sabe que regra usar para uma determinada sequncia de tokens. Um exemplo segue-se:

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

O byacc s tem um token de lookahead, ou seja, no caso abaixo ele no consegue decidir se o que recebeu foi o x ou o y porque no momento de escolher a produo ele s sabe que o se segue o token C. Como existem dois casos com o token C, ele no sabe o que fazer. Isto no um problema com a gramtica, uma limitao do byacc.
s : x C D | y C F ;

x : A B; y : A B;

O mesmo no ocorre no caso seguinte. Nesta situao ele consegue saber que produo usar vendo se o lookahead D ou F.
14

A PROGRAMAR
BYAC C
s : x D | y F ; %nonassoc IFX %token ELSE ... %% ... stmt : IF expression stmt ; ... %% %prec IFX

x : A B; y : A B;

A existncia de conflictos na gramtica no impede o parser de ser gerado, j que o byacc tem comportamentos default quando no sabe que produo usar, mas claro que o comportamento default pode no ser o que o programador tinha em mente quando escreveu a gramtica portanto convm eliminar os conflictos antes de gerar o parser. Os conflictos so introduzidos na escrita da gramtica e podem sempre ser eliminados reescrevendo-a, mas por vezes prefervel elimin-los usando precedncias. Tomemos o seguinte exemplo clssico, o dangling else:
stmt : IF expression stmt ; | IF expression stmt ELSE stmt

| IF expression stmt ELSE stmt

Para o seguinte input:


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

O problema que nos surge que o parser no sabe se o que ele tem um IF expression stmt com expression igual a (a) e o stmt igual a if(b) c = a + b; else c = a; ou se em vez disso tem um IF expression stmt ELSE stmt com expression tambm igual a (a), o primeiro stmt igual a if(b) c = a + b; e o segundo stmt igual a c = a;. O que queremos que o parser faa? Associe o else ao primeiro if ou ao segundo? O comportamento que esperamos que associe ao segundo, portanto para o conseguir vamos usar precedncias.

Introduzimos o token IFX - o token ELSE j tem de estar definido, tal como o IF se o estamos a usar na gramtica - que no retornado pelo scanner. O IFX s existe dentro do parser e serve apenas para indicar o nvel de precedncia de uma produo. Indicamos ao byacc o nvel de precedncia dos tokens pela ordem em que os declaramos, tendo os ltimos maior precedncia que os primeiros. A precedncia de um token determina a precedncia da produo em que ele se encontra, numa situao em que duas produes so viveis como no exemplo anterior a produo com maior precedncia usada. Se quisermos modificar a precedncia de uma produo sem afectar a precedncia de nenhum dos seus tokens, podemos, como mencionado previamente, criar um token falso como o IFX e escrever %prec IFX no fim da produo para o conseguir. Usando o token IFX no primeiro IF estamos a dizer que aquele tipo de if tem menos precedncia que o segundo IF,j que o token IFX declarado antes do token ELSE, portanto quando existem as duas hipteses o parser escolhe sempre a segunda, o que o comportamento que desejvamos.
15

A PROGRAMAR
BYAC C
expr : expr '*' expr | NUMBER ; | expr '^' expr | '(' expr ')' ;

Neste caso para o input NUMBER * NUMBER * NUMBER por exemplo, o parser no sabe se hde fazer (NUMBER * NUMBER) * NUMBER ou NUMBER * (NUMBER * NUMBER). Para resolver este problema precisamos de indicar a associatividade do operador binrio '*' ao byacc. Um operador com associatividade esquerda para o input NUMBER * NUMBER * NUMBER * NUMBER faz ((NUMBER * NUMBER) * NUMBER) * NUMBER, um operador com associatividade direita faz NUMBER * (NUMBER * (NUMBER * NUMBER)) para o mesmo input. A forma de indicar a associatividade de um token ao byacc escrever %left ou %right em vez de %token quando o declaramos. Para declarar um operador unrio no associativo (ou seja um operador que no se pode encadear) escrevemos %nonassoc em vez de %token. Entendendo associatividade e precedncias podemos comear a compreender a gramtica da nossa calculadora.
%token NUMBER %left '+' '-' %left '*' '/' %right '^' %nonassoc UMINUS %% expr : NUMBER

Dizemos que os operadores binrios '+' e '-' so associativos esquerda e tm a mesma precedncia. Os operadores '*' e '/' funcionam de forma idntica mas tm maior precedncia. O operador de potncia '^' associativo direita e tem a maior precedncia de todos os operadores binrios. O UMINUS indica que uma expresso negada tem a maior precedncia e que no se pode negar uma negao. Os parnteses foram a avaliao de qualquer que seja a expresso que estiver dentro deles, contornando as precedncias caso seja necessrio. Para o input, -1 ^2 + 5 + 3 - 2 * 3 ^ 4 ^ 5 / -6 / 2 - 5 a nossa gramtica vai fazer (((((-1 )^2) + 5) + 3) - (((2 * (3 ^ (4 ^ 5))) / (-6)) / 2)) - 5 como seria de esperar. Podemos associar aces a cada produo, para serem executadas quando o parser acaba de processar o corpo de uma produo e o substitui pela cabea. As aces indicam-se da mesma forma que no scanner, e possvel usar elementos da produo dentro delas desde que eles tenham valores associados. Para indicar o valor da cabea usamos $$, para os membros do corpo usamos $1 , $2, $n de acordo com a ordem em que eles aparecem. Um no terminal tem por default associado um int. Se quisermos associar um tipo diferente declaramos %type<tipo-do-valor-associado> nome-dosmbolo-no-terminal na primeira seco do ficheiro. Vejamos ento o ficheiro inteiro:
%% %{ #include <iostream> #include <cmath> %}

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

16

A PROGRAMAR
BYAC C
%union { }; double d;

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

expr_list

: expr NL ;

| expr_list expr NL

{ std::cout << $1 << std::endl; }

{ std::cout << $2 << std::endl; }

expr : NUMBER

| '-' expr %prec UMINUS | expr '+' expr | expr '-' expr | expr '*' expr | expr '/' expr | expr '^' expr | '(' expr ')' ;

{ $$ = $1; }

{ $$ = -$2; }

{ $$ = $1+$3; } { $$ = $1-$3; } { $$ = $1*$3; } { $$ = $1/$3; } { $$ = $2; } { $$ = pow($1, $3); }

%% { }

tipos associados, associatividade e precedncia. Conclumos a primeira seco com a declarao que o smbolo no terminal expr tem um valor associado do tipo double. Isto essencial porque as nossas operaes no esto a receber tokens NUMBER como argumentos mas sim no terminais expr. O smbolo inicial da nossa gramtica expr_list e est definido como uma sequncia de um ou mais no terminais expr, separados por mudanas de linha. Associamos a cada produo de expr_list a aco da impresso do valor de expr. As produes com cabea expr tem associadas as aces que realizam os clculos, guardando os valores na cabea. Na terceira seco temos um main que chama o yyparse().

int main() yyparse();

O ficheiro comea com os #includes de C++ que precisamos, seguidos da %union com o nico tipo que a nossa calculadora necessita, um double. Lemos a declarao dos tokens, com os
AUTOR

Neste momento temos um parser e um scanner para a nossa calculadora, no prximo artigo veremos como lig-los e como modificar o scanner e o parser em conjunto de forma a adicionar mais funcionalidades calculadora.

Escrito por Joo Mares Estando actualmente no terceiro ano de LEIC no IST, interssa-se preferencialmente por arquitectura de computadores e computao grfica.

17

VISUAL (NOT) BASIC


I n tro d u o a o E n ti ty Fra m e wo rk
O ADO.NET Entity Framework permite criar aplicaes em que o acesso a dados feito com base em um modelo conceitual e no utilizando comandos directos base de dados. Isto permite que o programador se abstraia totalmente da base de dados (criao de ligaes de acesso, comandos, parmetros, etc.) e utilize apenas objectos durante o desenvolvimento. A verso 4.0 do Entity Framework (actual), que est disponvel na .NET Framework 4.0, tem um conjunto de novas funcionalidades e melhorias, como o caso de suporte a POCO - Plain Old CLR Objects (permite criar classes que no herdam, nem implementam nenhuma outra classes ou interface), abordagem Model-First (permite criar primeiro o modelo conceptual e, com base nele, criar a base de dados), suporte para o uso de funes em LINQ-to-Entities, Complex Types (criao de tipos de dados complexos), Deferred Loading ou Lazy Loading (capacidade de carregar as propriedades de associao das entidades no momento em so chamadas, se forem chamadas), etc. No especifica apenas para o SQL Server, pois existem providers que permitem usar outras bases de dados, como Oracle, MySql, PostgreSQL, DB2, SQL Anywhere, Ingres, Progress, Firebird, Synergy, etc. Existem vrias vantagens na utilizao de um ORM (Object-relational mapping), que tornam a sua adopo quase inevitvel, mas vejamos o seguinte exemplo:
SELECT * FROM utilizadores WHERE nome = Jorge AND morada = Moita

tenham como nome Jorge e que tenham como morada a Moita. Imaginemos que o programador ou o DBA (database administrator) altera o campo nome para nomecompleto, pois quer que se registe o nome completo do utilizador e, desta forma, o nome do campo fica mais coerente. Se aplicao for compilada no detectado qualquer problema e s no momento de execuo ir ocorrer um erro. Situaes como estas so muito frequentes e podem representam vrios erros na aplicao. Este apenas um exemplo de como se pode beneficiar, e muito, da utilizao do Entity Framework, mas existem muito mais vantagens como a utilizao de LINQ to Entities, intellisense no momento em que se est a escrever o cdigo, cdigo mais fcil de manter e actualizar, etc, etc. Neste artigo, que ser uma breve introduo ao Entity Framework, ir apenas mostrar como construir um modelo relacional de uma base de dados SQL, uma abordagem database-first, e como executar algumas operaes CRUD.

CRIAO DO (database-first)

MODELO

RELACIONAL

Para criao de um modelo relacional iremos usar a seguinte base de dados SQL:

Este exemplo ir listar todos os utilizadores que


18

VISUAL (NOT) BASIC


I n tro d u o a o E n ti ty Fra m e wo rk

Como possvel ver nesta imagem, existem apenas 3 tabelas, com as respectivas chaves primrias/estrangeiras: produtos, clientes e uma terceira tabela onde se registam os movimentos. O primeiro passo adicionar um novo item ao projecto (menu Project Add New Item), e seleccionar no grupo de templates Data o item ADO.NET Entity Data Model. Isto ir iniciar um Wizard que permitir criar o modelo final.

Para o nome da ligao, e para este exemplo, utilize vendasEntities. A ltima opo deste Wizard onde so seleccionados os objectos a utilizar no modelo. Neste exemplo so escolhidas as trs tabelas j referidas.

De seguida seleccionar Generate database e carregar em Next.

from Aps este processo est criado o ficheiro EDMX, que no mais do que um conjunto de classes e mtodos que nos permitir aceder base de dados de uma forma simples, como iremos ver de seguida.

A prxima opo permite fazer a ligao base de dados, escolhendo uma j existente ou criando uma nova ligao.

OPERAES CRUD

As operaes CRUD (acrnimo de Create, Read, Update e Delete em Ingls) so quatro operaes bsicas e fundamentais para a manipulao de bases de dados. So por isso
19

VISUAL (NOT) BASIC


I n tro d u o a o E n ti ty Fra m e wo rk

bastante importantes e requerem, sem a utilizao 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 de cdigo, com recurso a IntelliSense, para as executar. O funcionamento para todas as operaes semelhante: criada uma nova instncia da nossa entidade (neste exemplo vendasEntities) que herda de uma classe da EntityFramework chamada ObjectContext, que a classe primria e responsvel de gerir a informao como objectos e a ligao dos objectos aos dados.

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

' Podemos verificar logo o nmero Debug.WriteLine("Nmero de registo: " & cliente.id.ToString()) ' (ID) do registo inserido

End Using

Apagar registos
Para apagar um registo necessrio seleccionar o registo correcto, neste caso usando uma Lambda Expression, e caso o resultado seja vlido, executamos o mtodo DeleteObject(), indicando o registo a apagar. Finalmente gravamos as alteraes na base de dados.

Inserir registos
Para inserir novos registos, neste caso um novo cliente, criamos uma nova instncia da respectiva classe, definindo as suas propriedades, que correspondem aos respectivos campos. Depois adicionamos o objecto atravs do mtodo AddObject() e, finalmente, executamos o mtodo SaveChanges() que ir efectuar as respectivas alteraes, neste caso inserir um registo, na base de dados.

Using context As New vendasEntities ' Procura o registo com o nmero de Dim cliente = context.clientes.Where( Function(c) c.id = 1). FirstOrDefault() ' cliente (ID) igual a 1

Using context As New vendasEntities ' Cria um novo cliente {

If cliente IsNot Nothing Then context.SaveChanges() MessageBox.Show(

context.clientes.DeleteObject(cliente)

Dim cliente As New clientes With .nome = "Rui Paulo", .morada = "Lisboa", .datanascimento = }

Else

End If End Using

"Nmero de cliente invlido")

New DateTime(1980, 10, 31)

20

VISUAL (NOT) BASIC


I n tro d u o a o E n ti ty Fra m e wo rk

Modificar Registos
Para modificar um registo, e semelhana da operao anterior, necessrio seleccionar o registo. Neste exemplo utilizamos LINQ to Entities para fazer essa seleco. Depois, modificamos o que for para modificar e finalmente gravamos as alteraes.
Using context As New vendasEntities Dim cliente =

Using context As New vendasEntities Dim listaClientes =

Where c.morada.Contains("Lisboa") And c.datanascimento < Select c New DateTime(1985, 1, 1)

From c In context.clientes

For Each c As clientes In listaClientes Next Debug.WriteLine(c.nome)

(From c In context.clientes Where c.id = 1 Select c).FirstOrDefault()

End Using

If cliente IsNot Nothing Then With cliente .nome = "Rui Paulo" .morada = "Setbal" .datanascimento = End With Else New DateTime(1979, 10, 31)

context.SaveChanges() MessageBox.Show(

Entre entidades existir normalmente associaes, e essas associaes (tambm representadas na ltima imagem), tm algo que se designa por Navigation Properties. As Navigation Properties permitem uma navegao bidireccional entre entidades, de acordo com as suas associaes. Isto algo bastante prtico pois permite-nos criar queries entre vrias entidades usando LINQ to Entities. O seguinte exemplo mostra esta abordagem, definindo depois o resultado como DataSource num controlo DataGridView.
NOTA: Se utilizar uma base de dados anexa ao
Using context As New vendasEntities

End If End Using

"Nmero de cliente invlido")

Listar Registos
A listagem de registo tambm muito semelhante s operaes anteriores. Neste exemplo, usando LINQ to Entities, vamos seleccionar todos os registo com base num critrio, para uma varivel do tipo IQueryable(Of T), e depois efectuamos um ciclo para mostrar os resultados obtidos.
21

Dim listaClientes =

From c In context.clientes

Join m In context.movimentos Join p In context.produtos Select m.datavenda,

On m.clienteid Equals c.id On m.produtoid Equals p.id

VISUAL (NOT) BASIC


I n tro d u o a o E n ti ty Fra m e wo rk
Select m.datavenda, c.nome, m.preco p.produto,

especiais), etc Estas so apenas algumas, das muitas vantagens, que nos devem fazer de uma vez por todas, deixar de usar SqlCommands, SqlConnections, DataSets, etc.

Me.DataGridView1.DataSource = listaClientes End Using

projecto (AttachDb), a base de dados copiada para as pastas Debug/Release. Pode seleccionar no menu Project a opo Show All Files e verificar as alteraes nessa localizao.

Alguns recursos interessantes: Data Developer Center http://msdn.microsoft.com/en-us/data/ef.aspx Data Access Hands-on Labs http://msdn.microsoft.com/enus/data/gg427655.aspx ADO.NET team blog http://blogs.msdn.com/b/adonet/ Julie Lerman's Blog http://thedatafarm.com/blog/

CONCLUSO
Como foi possvel ver ao longo do artigo, que abordou de uma forma muito superficial algumas das funcionalidades deste ORM, o Entity Framework uma excelente opo para se trabalhar com bases de dados. simples de utilizar, permite-nos trabalhar apenas com objectos e com intellisense, resolve inmeros problemas que so habituais quando trabalhamos directamente com a base de dados (formatos de datas, nmeros, caracteres

AUTOR
Escrito por Jorge Paulino Exerce funes de analista-programador numa multinacional sediada em Portugal. formador e ministra cursos de formao em tecnologias Microsoft .NET e VBA. Microsoft Most Valuable Professional (MVP), em Visual Basic, pela sua participao nas comunidades tcnicas . administrador da Comunidade Portugal-a-Programar e membro de vrias comunidades (PontoNetPT, NetPonto, MSDN, ExpertsExchange, CodeProject, etc). autor do blog http://vbtuga.blogspot.com - twitter @vbtuga

22

A PROGRAMAR
Pro gra m a o Fu n c i o n a l c o m Pe rl ( p a rte I )
Comeo com este artigo uma srie de artigos relacionados com a Programao Funcional em Perl. Nesta srie de artigos pretendo demonstrar algumas das capacidades do Perl para utilizao com o paradigma de Programao Funcional. No pretendo ensinar nem as bases da Programao Funcional, nem do Perl. Vou abrir excepes quando se tratarem de aspectos mais avanados e/ou muito relacionados com a prpria Programao Funcional. A compreenso elementar do Perl e da Programao Funcional um requisito para a compreenso destes artigos contudo tudo ser explicado de forma a permitir que um principiante possa compreender tudo e quem tiver dvidas poder contactar-me para as esclarecer. Umas das principais caractersticas do Perl, em seguimento do mantra da sua comunidade (There's more than one way to do it), no obrigar o programador a utilizar, ou escolher um paradigma de programao, mas sim permitir ao programador utilizar o que quiser quando quiser, ficando ao cuidado dele ter os cuidados necessrios para que o cdigo seja til e siga boas prticas de programao. H quem concorde com esta filosofia, h quem no concorde, mas a filosofia do Perl e da sua comunidade no o mbito deste artigo. Um dos muitos paradigmas de programao que so possveis utilizar em Perl a Programao Funcional (PF). Contudo no cabe a este artigo explicar a PF. Por isso sugiro que antes de prosseguirem na leitura deste artigo leiam pelo menos uma curta explicao do que PF (os primeiros pargrafos do artigo da Wikipedia
23

sobre PF por exemplo). Como j h vrios artigos sobre PF em diversas linguagens, como Python, Scheme, Haskell (recomendo que os leiam), deixo aqui a sugesto a algum, para redigir um artigo terico e agnstico (em relao a linguagens de programao) sobre Programao Funcional.

Umas das principais caractersticas do Perl (...) no obrigar o programador a utilizar (...) mas sim permitir ao programador utilizar o que quiser quando quiser

Algumas das funcionalidades elementares das linguagens funcionais so as funes annimas e as closures. O Perl tem ambas as features. Uma das alteraes que o Perl 5.1 2 trouxe foi uma funo chamada say. O say basicamente um print que adiciona um newline string que queremos imprimir (poupa-nos pelo menos 4 caracteres). Qualquer uma das seguintes linhas de cdigo vai imprimir isolado numa linha a string: Hello world!:
print "Hello world!\n"; print "Hello world!"."\n"; say "Hello world!";

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

A PROGRAMAR
Pro gra m a o Fu n c i o n a l c o m Pe rl ( p a rte I )

Para demonstrar a utilizao de funes annimas decidi criar uma implementao da funo say que permite definir antes da sua utilizao como queremos que a string seja formatada:
sub say { my ($string, $format) = @_; print $str; $format = #definio da funo say

utilizao nas "dispach tables":


my %lingua = ( "pt" => sub { return "Ol mundo!" }, #dispach table

"es" => sub { return "Hola mundo!" },

"en" => sub { return "Hello world!" }, );

"fr" => sub { return "Bonjour monde!" },

my $str = $format->($string); }

sub dispach { annima de

my

formatao da string

sub

#funo

my $l = shift;

my $str = shift;

$lingua{$l}) {

if(defined

$lingua{$l}

&&

exists

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

};

return $str."\n";

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

else { }

print "Erro: lingua desconhecida!\n";

Explicao do cdigo do exemplo anterior: Primeiro comeamos por definir a funo say, como definiramos qualquer outra funo em Perl. Depois definimos a funo annima de formatao, e atribumos essa funo a uma varivel (que guarda uma referncia para cdigo) para que possa ser passada de forma visualmente mais limpa funo say (poderamos tambm ter definido a funo annima, na invocao de say mas faria com que o cdigo fosse muito menos legvel). Qual a utilidade das funes annimas? As utilidades so diversas. E vo desde a utilizao das funes annimas para poder modificar o comportamento de uma funo que tenha sido criada para poder permitir essa alterao. H quem utilize isto para poder por exemplo poder voltar a correr cdigo que tinha sido serializado. E passam pela utilizao em "dispach tables". Uma outra utilidade a
24

dispach("fr");

Explicao do cdigo do exemplo anterior: Comeou por ser definido uma hash table que, como chaves contm, as opes vlidas de lnguas que queremos utilizar na impresso de uma saudao e como valores, tem funes annimas que imprimem uma saudao na lngua representada pela sua chave na hash table. Isto poderia ter sido feito definindo individualmente funes "regulares", criando variveis que eram referncias para cada uma dessas funes e utilizando essas variveis como valores a utilizar na hash table. Mas isso traria imediatamente dois problemas: aumentaria a quantidade de cdigo necessrio e este artigo tem um limite de caracteres; no

A PROGRAMAR
Pro gra m a o Fu n c i o n a l c o m Pe rl ( p a rte I )

utilizaria funes annimas, que o objectivo deste exemplo ;). Para alm de isso, o que pretendido neste exemplo, algo tremendamente simples que pode perfeitamente ser feito utilizando funes annimas, sem se aumentar a dificuldade relevante da sua compreenso como um todo e em parte. A opo por esta soluo, em vez de a utilizao de um encadeamento maior de if-elsif, ou de um switch-case (tambm maior) permite que a

soluo escale para mais opes de lnguas, sem qualquer alterao e atinge melhor vrios dos objectivos da utilizao de funes na programao: conter/isolar os problemas de forma a simplificar a sua resoluo, facilitar a compreenso do cdigo. No prximo, artigo vou falar da segunda das principais capacidades do Perl para a Programao Funcional de que falei antes, as closures.

(...) permite que a soluo escale para mais opes de lnguas, sem qualquer alterao e atinge melhor vrios dos objectivos da utilizao de funes na programao (...)
AUTOR
Escrito por Diogo Constantino Consultor na rea as tecnologias licenciadas como Software Livre, com aproximadamente vrios anos de experincia profissional, especializado em desenvolvimento com Perl. Larga experincia na rea de sistemas, engenharia e de operaes de redes de telecoms, tendo desenvolvido, mantido e utilizado 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 de routing, firewalling e switching de diversos fabricantes, diversos sistemas *nix e diversas outras ferramentas e tecnologias comuns em sistemas *nix e/ou utilizadas em empresas de telecomunicaes, redes e web. Relativamente conhecido advogado da causa do Software Livre em diversas comunidades. Scio da Associao Nacional para o Software Livre e da Associao Portuguesa de Programadores de Perl.

25

COMUNIDADE NETPONTO
B a c kgro u n d Wo rke rs - I m p l e m e n ta o p r ti c a e m Wi n d o ws Pre s e n ta ti o n Fo u n d a ti o n ( WPF)
Neste artigo pretendo mostrar o que o BackgroundWorker e vou exemplificar como se deve proceder sua implementao usando a tecnologia WPF na verso .Net Framework 4. Suponhamos:
Tenho um algoritmo complexo de Optimizao Combinatria que ir ter como parmetro de entrada um objecto do tipo World. Classe que define toda a estrutura de dados da minha aplicao e no final retorna o objecto World com as alteraes realizadas pelo algoritmo.

System.ComponentModel. Esta classe permitenos ajudar a gerir uma tarefa numa thread separada da thread principal sem termos de nos preocupar com a inicializao e gesto da thread onde vamos executar a tarefa.

As propriedades a ter em conta so:


CancellationPending

Permite obter se a tarefa foi cancelada.


WorkerReportsProgress

Esta gerao vai implicar que tenhamos pelo menos trs passos: 1 . A partir do objecto World vamos criar a estrutura de dados do algoritmo; 2. Gera-se o algoritmo a partir dos dados recebidos; 3. Depois de gerar o algoritmo preciso converter o resultado de forma a reflectir no World o resultado do algoritmo; Enquanto estes trs passos esto a decorrer, eu quero ser informada sobre o progresso da gerao do algoritmo e pretendo ter a capacidade de a cancelar. Este cenrio um dos muitos cenrios onde o BackgroundWorker pode ser implementado. Outros exemplos reais so a leitura de ficheiros extensos, aceder a base de dados para efectuar o carregamento de dados, fazer o load de imagens e gerar relatrios. Antes de passarmos implementao vou dar uma breve apresentao terica: Um BackgroundWorker uma classe contida no
26

Permite obter e definir se o BackgroundWorker vai reportar o seu progresso da tarefa.


WorkerSupportsCancellation

Permitir obter e definir se o BackgroundWorker vai permitir cancelar a tarefa.

Os mtodos a ter em conta so:


RunWorkerAsync

Permite iniciar a tarefa. Existem duas assinaturas deste mtodo. Uma delas no tem argumento, a outra que o tem utiliza-o na execuo da tarefa.
CancelAsync

Permite cancelar a tarefa e consequentemente o BackgroundWorker ir terminar. Para que seja possvel cancelar a tarefa necessrio que a propriedade WorkerSupportsCancellation tenha o valor de verdade true.
ReportProgress

Permite reportar o progresso da tarefa em dado momento. Para que o progresso seja reportado necessrio que o WorkerReportsProgress tenha

COMUNIDADE NETPONTO
B a c kgro u n d Wo rke rs - I m p l e m e n ta o p r ti c a e m Wi n d o ws Pre s e n ta ti o n Fo u n d a ti o n ( WPF)

o valor de verdade true. Este mtodo apresenta duas assinaturas, ReportProgress(int percentProgress) e ReportProgress(int percentProgress, object userState). Ambas permitem reportar a percentagem da tarefa que j foi realizada. Na ltima assinatura possvel enviar mais informao sobre o estado da tarefa.

trs propriedades relevantes. So a propriedade Cancelled - que nos informa se a tarefa foi cancelada, a propriedade Error que nos reporta a excepo que fez terminar a tarefa e a propriedade Result - que representa o resultado da execuo da tarefa.

Os eventos a ter em conta:


Ocorre quando o mtodo RunWorkerAsync chamado. Ao subscrever este evento definido um handler que recebe dois parmetros: - Um parmetro do tipo object que representa o objecto que subscreveu o evento. - Um parmetro do tipo DoWorkEventArgs que contm informao respeitante ao parmetro de entrada e permite devolver o resultado da tarefa. De referir ainda que este parmetro possui duas propriedades relevantes. Sendo elas, a propriedade Argument - que representa o objecto que enviado como parmetro do mtodo RunWorkerAsync e a propriedade Result - que representa o resultado do DoWork.
ProgressChanged DoWork

Vamos agora passar implementao prtica, 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 detalhes do progresso.

Ocorre quando o mtodo ReportProgress chamado. Um dos parmetros do handler deste evento um objecto do tipo ProgressChangedEventArgs, que contm duas propriedades relevantes, que so o ProgressPercentage e UserState, cujos valores foram enviados pelo mtodo ReportProgress;
RunWorkerCompleted

Toda a interface definida no ficheiro .xaml. Em Code Behind iremos proceder implementao de toda a funcionalidade para resolver o problema em causa.
1. Comecemos ento por definir uma varivel global:
private BackgroundWorker _backgroundWorker;

Ocorre quando a tarefa terminada, cancelada ou lanada uma excepo. Um dos parmetros do handler deste evento um objecto do tipo RunWorkerCompletedEventArgs, que contm
27

2. De seguida vamos criar um mtodo onde vamos fazer a inicializao desta varivel e definir as suas propriedades e subscrever os eventos:

COMUNIDADE NETPONTO
B a c kgro u n d Wo rke rs - I m p l e m e n ta o p r ti c a e m Wi n d o ws Pre s e n ta ti o n Fo u n d a ti o n ( WPF)
private void InitializeBackgroundWorker() { _backgroundWorker = new BackgroundWorker(); _backgroundWorker.DoWork += new DoWorkEventHandler(DoWork); private void RunBackground_Click( object sender, RoutedEventArgs e) { ClearProgress(); _backgroundWorker.RunWorkerAsync( (object)_world); btnCancel.IsEnabled = true; btnRunBackground.IsEnabled=false;

_backgroundWorker.ProgressChanged += new ProgressChangedEventHandler( ProgressChanged);

_backgroundWorker.WorkerReportsProgress = true;

_backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler( RunWorkerCompleted);

_backgroundWorker.WorkerSupportsCancellation = true; }

Caso no pretendssemos enviar parmetros usvamos a assinatura do RunWorkerAsync sem parmetros.


5. No handler do evento do Click do btnCancel vamos mandar cancelar a tarefa, chamando o mtodo CancelAsync.
private void btnCancel_Click( object sender, RoutedEventArgs e) { _backgroundWorker.CancelAsync(); btnCancel.IsEnabled = false; btnRunBackground.IsEnabled = true; }

De notar que j estou a definir que o meu objecto _backgroundWorker vai permitir que a tarefa seja cancelada a meio e que o progresso da tarefa possa ser reportado.
3. Agora vamos definir os handler dos eventos:
private void DoWork (object sender, DoWorkEventArgs e) {}

6. Neste momento estamos prontos para definir a tarefa (handler): private void DoWork(object DoWorkEventArgs e){} sender,

private void ProgressChanged (object sender, ProgressChangedEventArgs args) {} private void RunWorkerCompleted (object sender, RunWorkerCompletedEventArgs e) {}

executado quando o mtodo RunWorkerAsync chamado. Consideremos a seguinte poro de cdigo:


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;

4. No handler do evento do Click do btnRunBackground vamos mandar executar a tarefa e como parmetro vamos enviar o objecto _world.

28

COMUNIDADE NETPONTO
B a c kgro u n d Wo rke rs - I m p l e m e n ta o p r ti c a e m Wi n d o ws Pre s e n ta ti o n Fo u n d a ti o n ( WPF)

Note-se que vou obter o objecto do tipo World que foi enviado por parmetro e em seguida vou iterar pelos vrios passos do algoritmo. Por fim vou devolver o resultado da tarefa. Aparentemente posso pensar que j defini a minha tarefa, no entanto, ainda no estou a ter em conta que poderei cancelar a execuo do algoritmo nem estou a reportar o progresso.
private void DoWork( object sender, DoWorkEventArgs e) { Algorithm algorithm = new Algorithm(); World world = (World)e.Argument; foreach (IAlgorithmStep step in algorithm.Steps) { if (_backgroundWorker.CancellationPending) { e.Cancel = true; return; } else { stepValue = step.DoWork(stepValue); } } e.Result = stepValue; } 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);

object stepValue = world;

_backgroundWorker.ReportProgress(20, string.Format( "{0} is finished.", step.Name));

e.Result = stepValue;

_backgroundWorker.ReportProgress(5, "Finished.");

Neste momento j temos a nossa tarefa definida tendo em conta as operaes que pretendamos.
7. Para que o progresso seja apresentado na interface com o utilizador preciso definir o seguinte handler: private void ProgressChanged(object sender, ProgressChangedEventArgs args){}

A cada passo do algoritmo vou verificar se a tarefa foi cancelada atravs da propriedade CancellationPending e consoante o valor de verdade desta propriedade a tarefa continua ou no. Por fim temos que reportar o progresso de cada passo e para isso vamos recorrer ao mtodo ReportProgress.
private void DoWork( object sender, DoWorkEventArgs e) { Algorithm algorithm = new Algorithm(); World world = (World)e.Argument; _backgroundWorker.ReportProgress( 5, "Is starting...");

Que executado quando ReportProgress chamado.

mtodo

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

29

A PROGRAMAR
B a c kgro u n d Wo rke rs - I m p l e m e n ta o p r ti c a e m Wi n d o ws Pre s e n ta ti o n Fo u n d a ti o n ( WPF)

Desta forma actualizamos o progresso na interface com o utilizador.


8. Para terminar, vejamos o handler: private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){}

tarefa. Caso tenha ocorrido um erro, este ser apresentado ao utilizador. Em concluso, a implementao de um BackgroundWorker permite-nos correr uma tarefa numa thread separada sem que esta interfira com a interface com o utilizador. Permite-nos ainda ter a capacidade de: - Cancelar a tarefa; - Reportar o progresso da tarefa; - Actualizar os controlos de WPF enquanto a tarefa decorre.

Que executado depois do DoWork ter terminado, ter ocorrido uma excepo ou a tarefa ter sido cancelada.
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;

A comunidade NetPonto uma iniciativa independente e sem fins lucrativos, que tem como simples e nico objectivo a partilha de conhecimento na rea de arquitectura e desenvolvimento de software na plataforma .NET, na tentativa de disseminar o conhecimento diferenciado de cada um de seus membros. Cada um de ns tem diferentes talentos, e com as dezenas de tecnologias que so lanadas todos os dias, muito difcil (para no dizer impossvel) estar por dentro de tudo, e essa uma das principais vantagens em fazer parte de uma comunidade de pessoas ligadas nossa rea. Podemos aprender mais, e mais rpido, com as experincias de cada um. Visite-nos em http://netponto.org

Vou verificar se a tarefa foi cancelada ou no. Em caso de sucesso posso obter o resultado da
AUTOR

Escrito por Sara Silva licenciada em Matemtica Especialidade em Computao, pela Universidade de Coimbra, actualmente Software Developer no Porto. O entusiasmo pela rea resultou na obteno dos ttulos de Microsoft Certified Profissional Developer Windows 3.5, Microsoft Certified Tecnology Specialist WPF 3.5, WPF 4 e Windows Forms. Faz parte de vrias comunidades, tendo uma participao activa na Comunidade NetPonto e no P@P.

30

A PROGRAMAR

31

A PROGRAMAR
j Qu e ry - O q u , c o m o e p o rq u ?
O objectivo deste artigo dar a conhecer as principais funcionalidades do jQuery, um pouco da sua histria e motivaes e fornecer exemplos da sua utilizao. O jQuery, existente desde 26 de Agosto de 2006, criado por John Resig, uma cross-browser JavaScript library (embora considerado uma verdadeira framework), licenciado ao abrigo do MIT e GNU, fazendo dele software livre, e o mais usado mundialmente face aos seus concorrentes (Dojo, MooTools, Prototype). Os seus objectivos so simplificar a interaco com o DOM (Document Object Model), handling de eventos, criao de animaes, interaco AJAX (Asynchronous JavaScript and XML), e, last but not least, ser cross-browser, que foi o factor decisivo para John Resig o criar. O jQuery tem uma sub-library de nome jQuery UI, que um subset do jQuery especfico para animaes e interface visual, fornecendo muitas funcionalidades out-of-the-box, como vrios controlos, um motor de estilos visuais para estes (theme roller), vrias funcionalidades utilizadas em interfaces ricos como drag & drop, dialogs, tabs, sliders, entre muitos outros. O projecto jQuery gerou um spin-off de nome Sizzle, que um motor de selectores CSS em JavaScript, sendo naturalmente utilizado no jQuery, a partir do qual foi gerado. Actualmente a verso do jQuery a 1 .4.3 e do jQuery UI 1 .8.5. Para o futuro, a grande novidade o jQuery Mobile (do qual j foi feita uma release 1 .0 alpha 1 em 1 6 de Outubro de 201 0), que ir revolucionar o desenvolvimento a nvel de
32

dispositivos mveis, pois o seu grande trunfo ser cross-browser entre as vrias plataformas mveis e alm disso as prprias themes serem adaptadas ao aspecto do dispositivo em uso, fazendo com que o aspecto e usabilidade (look & feel) das aplicaes desenvolvidas com este plugin no se distingam das aplicaes nativas do dispositivo, o que um avano enorme no desenvolvimento de aplicaes web para dispositivos mveis. Pode-se acrescentar que tanto o jQuery como o jQuery UI tm um mecanismo de extensibilidade que permite aos programadores criarem plugins completamente integrados na API, fazendo com que actualmente existam cerca de 4000 plugins na pgina oficial de plugins do jQuery. De seguida irei apresentar um tutorial muito bsico de como desenvolver com jQuery que irei aprofundar em futuras edies. Para iniciar o desenvolvimento, deve-se adicionar uma referncia ao ficheiro js que contm o jQuery (minificado) na head do nosso html document: (img.1 )
<html> <head>

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

<script

type="text/javascript"

</head> <a <body>

programar.org/">PaP</a> </html> </body>

href="http://www.portugal-a-

A PROGRAMAR
j Qu e ry - O q u , c o m o e p o rq u ?
$(document).ready(function() { $(a).bind(click, function(event) { alert("Aceder ao site da comunidade Portugal a Programar) }) })

img.1

Para cdigo assim que o nosso documento estiver no estado ready (on document ready), antes do jQuery, o natural seria ter algum cdigo:
window.onload = function() { alert("on doc ready"); }

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


$(document).bind(ready, function() {})

e o modo mais abreviado e mais utilizado:


$(function() { })

O problema de executar cdigo neste evento que este s executado quando o DOM est completamente carregado e todas as referncias externas j foram descarregadas do servidor (imagens, js, css), o que no nada agradvel para o programador. Por este motivo, o jQuery tem um evento que despoletado logo que o DOM est carregado, no esperando pelos recursos externos:
$(document).ready(function() { //cdigo aqui })

Neste momento podemos gravar o nosso ficheiro HTML com todo o cdigo e testar: Ao testarmos clicar no link, a popup aparece, e de seguida entramos na pgina Portugal a Programar.
<html> <head> <script type="text/javascript" src="jquery1.4.3.min.js"> </script> <script type="text/javascript"> $(document).ready(function() { $(a).bind(click, function(event) { </html> alert("Aceder ao site da comunidade Portugal a Programar) img.2 })

Podemos adicionar cdigo para ao clicarmos no link, mostrar um alert:

33

A PROGRAMAR
j Qu e ry - O q u , c o m o e p o rq u ?
}) </script> </head> $(document).ready(function() { $(a).bind(click, function(event) { alert("Deste modo, j no somos direccionados para o site Portugal a Programar) event.preventDefault() }) })

<body> <ahref="http://www.portugala programar.org/">PaP</a> </body> </html>

Se quisermos prevenir o comportamento por omisso (default) do nosso clique sobre a ncora, podemos faz-lo, chamando a funo preventDefault do objecto event, que recebido no handler de qualquer evento: img. 4

Para carregarmos o jQuery, a melhor opo utilizar um CDN (Content Delivery Network, que fornece contedos na rea geogrfica do utilizador, de alta disponibilidade e a alta velocidade) da Microsoft ou da Google. Quanto ao script includo inline, o ideal ser colocado num ficheiro externo, de modo a no poluir o html. Como pude demonstrar neste pequeno tutorial bsico, de iniciao ao jQuery, ele uma framework to acessvel quanto poderosa e com um potencial cada vez maior e com cada vez mais funcionalidade, por isso, irei continuar em artigos subsequentes, a aprofundar cada vez mais as suas funcionalidades, truques e dicas, assim como partilhar boas prcticas de desenvolvimento, por isso no percam os prximos artigos!

img.2

img.3

Actualmente existem cerca de 4000 plugins na pgina oficial !

34

A PROGRAMAR
j Qu e ry - O q u , c o m o e p o rq u ?

Uma framework to acessvel quanto poderosa e com um potencial cada vez maior
img.4

AUTOR
Escrito por Ricardo Rodrigues tcnico Nvel III em Informtica/Gesto pela Fundao Escola Profissional de Setbal, tendo ingressado aps na FCT da Universidade Nova de Lisboa. Posteriormente frequentou vrios cursos da Microsoft em diversas reas como Windows Forms,ASP.NET, Securing .NET Applications, WCF, WWF, Web Services e COM+ tendo obtido as certificaes MCP .NET 2.0, MCAD .NET 1 .1 , MCSD .NET 1 .1 , MCPD Windows, Web e Distributed Applications e MCPD Enterprise Applications Developer. (MCP Profile) Contribui activamente em comunidades como StackOverflow e tambm possui um blog/twitter como temtica relacionada: Blog / @ricmrodrigues

35

A PROGRAMAR
Lu a Li n gu a ge m d e Pro gra m a o ( Pa rte 6 )
No artigo anterior (quinto artigo desta srie) fora apresentado o tema relacionado ao uso e criao de funes. Como prometido este artigo tratar do tema relacionado ao uso de arquivos. Alm deste ser tratado tambm alguns aspectos ainda no mencionado sobre o ambiente interactivo da linguagem e a obteno de tamanho de strings. usada em conjunto com outras linguagens como se fosse um satlite natural para essas outras linguagens. Fica aqui esta questo para ser pensada.

Ambiente Interactivo
A linguagem de programao Lua possui um ambiente de trabalho que pode ser usado na forma interactiva. Neste modo de operao pode-se realizar algumas tarefas operacionais. Para tanto, na linha de comando prompt (modo terminal) do sistema operacional em uso faa a chamada do programa lua e accione <Enter>. Neste sentido ser apresentada uma mensagem de identificao semelhante a:
Lua 5.1.4 > Copyright (C) 1994-2008 Rio

Um pouco mais sobre Lua


Na primeira parte desta srie de artigos foi comentado um breve histrico sobre o surgimento da linguagem Lua. Cabe ainda acrescentar mais alguns detalhes. Antes do surgimento da linguagem Lua o departamento de informtica da PUC-Rio fazia uso interno das linguagens DEL (Data-Entry Language) e SOL (Simple Object Language) Cada uma das linguagens fora desenvolvida entre 1 992 e 1 993 no sentido de adicionar maior flexibilidade de interactividade a dois projectos de aplicao em computao grfica para o departamento de engenharia da empresa PETROBRAS. Apesar da ideia arrojada, ambas as linguagens apresentavam problemas muito comuns e foi a partir desses problemas que ocorreu a juno das linguagens DEL e SOL, dando vez a linguagem Lua. Segundo reza a lenda o nome Lua foi sugerido devido ao uso da linguagem SOL. Mas cabe aqui um pouco de devaneio, pois me parece o nome Lua bem mais sugestivo que que uma ocorrncia a partir da linguagem SOL. Lua o satlite natural do planeta Terra. A linguagem Lua uma linguagem que apesar de sua independncia operacional pode ser
36

Para sair do prompt do ambiente Lua e retornar ao terminal do sistema operacional basta executar o comando os.exit() e em seguida accionar a tecla <Enter> ou <Return> ou ainda usar as teclas de atalho <Ctrl> + <c> ou ento as teclas de atalho <Ctrl> + <z> + <Enter> dependendo do sistema operacional em uso. Dentro do ambiente interactivo possvel passar comandos com o sentido de obter respostas. Por exemplo, desejando-se obter o resultado da soma do valor 7.5 com o valor 4.8, basta executar a linha de comando:
print(7.5 + 4.8)

A PROGRAMAR
Lu a Li n gu a ge m d e Pro gra m a o ( Pa rte 6 )

Aps accionar a tecla <Enter> ou accionar a tecla <Return> obter-se- o resultado 1 2.3. Veja a seguir uma srie de operaes com clculos matemticos que podem ser efectivadas junto ao ambiente interactivo.
print(-2 + -3) print(2 * 3) print(10 / 4) print(10 % 4) print(2 ^ 3) print(2 + 5 * 3)

Sero apresentados como resultados os valores 6, 0.66666666666667, 5 e -1 . Os clculos efectivados poder trabalhar com outros formatos numricos, como notao cientifica. Por exemplo, desejando-se obter o resultado decimal do valor 9.5e2, sendo:
=9.5e2

print(2 + (5 * 3)) print((2 + 5) * 3)

Que mostrar como resultado o valor 950, pois calcula-se o valor 9.5 multiplicando-se por 1 0 e elevando-se a potncia 2, ou seja, 9.5 x 1 02. Experimente =9.5e-2 para obteno do resultado 0.095. Outra possibilidade de operaes so os usos de valores hexadecimais convertidos em valores decimais. Por exemplo, observe os seguintes comandos.
=0xa =0xA =0Xa =0XA

Os exemplos apresentados anteriormente resultam respectivamente nos valores: -5, 6, 2.5, 2, 8, 1 7, 1 7 e 21 . O ambiente interactivo retorna mensagens de erro quando alguma coisa no escrita dentro das regras sintcticas do ambiente. Por exemplo, execute o cdigo.
print(2 + + 3)

Ocorrer a apresentao da mensagem de erro stdin:1: unexpected symbol near '+' informando que um dos smbolos + desconhecido. Para a obteno de resultados de clculos matemticos pode-se substituir o comando print() pelo smbolo = igual a. Desta forma, podem ser definidos os seguintes clculos.
=2*3 =2/3 =2+3 =2-3

Ao serem executados os comandos anteriores todos resultam na apresentao do valor 1 0 (A hexadecimal igual a 1 0 decimal). Note que no importa como definido o valor, seja em formato de carcter maisculo ou formato de carcter minsculo o resultado ser sempre apresentado. O ambiente interactivo permite a definio e uso de variveis. Por exemplo, informe as linhas de cdigo seguintes accionando a tecla <Enter> ou <Return> para cada linha informada.
A = 2 B = 3 print(A + B)

37

A PROGRAMAR
Lu a Li n gu a ge m d e Pro gra m a o ( Pa rte 6 )

Observe o surgimento do valor 5 como resultado da operao. Um cuidado que se deve tomar na definio de variveis com relao ao nome atribudo. Por exemplo as seguintes variveis no so as mesmas variveis, pois a linguagem Lua do tipo case sensitive.
COR = 1 COr = 2 Cor = 3 cor = 4 Cor = 5 cOr = 6 CoR = 7 coR = 8 print(COR) print(COr) print(Cor) print(cor) print(Cor) print(cOr) print(CoR) print(coR)

Vagarosamente a cada artigo esto sendo apresentados diversos recursos operacionais que podem ser utilizados junto a linguagem de programao Lua. Entre os recursos explanados cabe neste instante abordar o operador # de obteno de tamanho de um string. Observe a seguir as linhas de cdigo que podem ser executados no ambiente interactivo.
print(#" ") print(#"Linguagem Lua")

Aps executar as linhas de cdigo anteriores sero apresentados os valores 1 e 1 3 que so respectivamente o tamanho das mensagens um espao e Linguagem Lua.

Arquivos
Um dos recursos mais teis e importantes a ser oferecido por uma linguagem de programao de computadores a capacidade desta linguagem permitir a manipulao de arquivos. A linguagem Lua oferta para o programador uma biblioteca de entrada e de sada para o controlo das operaes de arquivos. A abordagem deste artigo se restringir em aplicaes bsicas. O programa seguinte apresenta um exemplo de programa que cria um arquivo contendo valores numricos pares situados na faixa de valores entre 1 um) e 200 (duzentos).
-- inicio do programa ARQ01 ARQ = io.open("pares.txt","w") for N = 1, 200 do R = N % 2 if (R == 0) then end

Outro detalhe no uso e definio de variveis a possibilidade de se efectivar a criao de mltiplas variveis. Por exemplo, observe o cdigo seguinte:
CODIGO, NOME = 123, "Paulo" print(CODIGO) print(NOME)

Observe que sero apresentados os valores 1 23 e Paulo. O smbolo = separa os contedos das variveis (1 23 e Paulo) das variveis (CODIGO e NOME).

Deteco de Tamanho de String

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

end

38

A PROGRAMAR
Lu a Li n gu a ge m d e Pro gra m a o ( Pa rte 6 )
ARQ:close() -- fim do programa ARQ01

Este valor poder ser 1 (se o valor for mpar) ou 0 (se o valor for par). A instruo if (R == 0) then verifica se o valor do resto da diviso zero, sendo executa a instruo ARQ:write() que escreve no arquivo o valor par obtido. O indicativo \n est sendo usado para armazenar no arquivo um valor numrico por linha. Sem este recurso os valores numricos seriam armazenados um ao lado do outro. Ao final a instruo ARQ:close() efectua o fechamento do arquivo. Se quiser ver o contedo do arquivo basta pedir para listar seu contedo directamente na linha de comando do sistema. O programa seguinte efectua a leitura do arquivo pares.txt e faz o somatrio do valores e mostra seu resultado.
-- inicio do programa ARQ02 ARQ = io.open("pares.txt","r") SOMA = 0

Em seguida escreva o cdigo de programa em um editor de texto, gravando-o com o nome arq01 .lua e execute-o com a linha de comando lua 5.1 arq01 .lua. O programa estabelece para a varivel ARQ est sendo atribuda pela funo io.open() que tem por finalidade abrir um arquivo para escrita, leitura ou adio. Caso o arquivo no exista o mesmo automaticamente criado. A funo io.open() utiliza entre aspas inglesas dois argumentos para sua operao: nome (primeiro argumento); modo (segundo argumento). O argumento nome caracteriza-se por ser o nome do arquivo a ser aberto ou criado, neste caso pares.txt e o argumento modo indica a forma de operao sobre o arquivo, podendo ser: r modo leitura (forma padro); w modo escrita; a modo adio (insero); r+ modo actualizao, todos os registos existentes so preservados; w+ modo actualizao, todos os registos existentes so apagados; a+ modo actualizao de adio, todos os registos existentes so preservados e as novas inseres ocorrem aps o final do arquivo; b modo de operao para manipulao de arquivos binrios, usado ao lado direito da definio dos modo r, w e a. A linha de instruo R = N % 2 obtm o valor do resto da diviso do valor da varivel N por 2.
39

for VALOR in ARQ:lines() do end

SOMA = SOMA + tonumber(VALOR)

ARQ:close() print(SOMA) -- fim do programa ARQ02

Em seguida escreva o cdigo de programa em um editor de texto, gravando-o com o nome arq02.lua e execute-o com a linha de comando lua 5.1 arq02.lua.

A PROGRAMAR
Lu a Li n gu a ge m d e Pro gra m a o ( Pa rte 6 )

O programa anterior faz uso do argumento de modo r (para leitura) quando da abertura do arquivo pares.txt por parte da instruo io.open() . Quando da explanao do uso de laos a instruo for foi apresentada na sua forma mais simples. Note que neste exemplo a instruo for faz uso do comando in definida como for VALOR in ARQ:lines() do. Esta forma de uso da instruo for denomina-se uso genrico. Neste caso, a instruo for faz com que a varivel VALOR seja atribuda com o contedo (in) existente no arquivo pares.txt representado pela varivel ARQ. Note o uso da funo lines() anexa a varivel ARQ que permite avanar no arquivo uma linha a frente posicionando-se sobre cada um dos registos. A funo tonumber() faz com que cada valor numrico armazenado no arquivo na forma de string quando capturado seja convertido para sua forma numrica. Apesar da linguagem Lua fazer este tipo de converso automaticamente fortemente recomendado que se defina este tipo de operao de forma explicita como feira no programa arq02.lua. O prximo programa tem por objectivo fazer a entrada de dados com nome e telefone e armazenar os dados em uma agenda.
-- inicio do programa ARQ03 ARQ = io.open("agenda.txt","a+") RESP = "S"

ARQ:write(REGISTO.."\n")

io.write("[+]registo? S/N ") end

RESP = string.upper(io.read())

ARQ:close() -- fim do programa ARQ03

Em seguida escreva o cdigo de programa em um editor de texto, gravando-o com o nome arq03.lua e execute-o com a linha de comando lua 5.1 arq03.lua. O programa usa na funo io.open() o modo de aco a+ para permitir a insero de novos registos ao arquivo. Um novidade neste programa a funo string.upper() que transforma em maisculo as entradas efectuadas junto as variveis NOME e RESP. O programa seguinte efectua a leitura dos dados do arquivo agenda.txt.
-- inicio do programa ARQ04 ARQ = io.open("agenda.txt","r") for REGISTO in

io.lines("agenda.txt") do io.write(REGISTO.."\n")

end

ARQ:close() -- fim do programa ARQ04

while (RESP == "S") do

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

NOME = string.upper(io.read())

Em seguida escreva o cdigo de programa em um editor de texto, gravando-o com o nome arq04.lua e execute-o com a linha de comando lua 5.1 arq04.lua.
40

A PROGRAMAR
Lu a Li n gu a ge m d e Pro gra m a o ( Pa rte 6 )

O programa usa a funo lines() um pouco diferente do que fora utilizada no programa arq02.lua. Neste verso usa-se a funo como io.lines() com o nome do arquivo agenda.txt como argumento. Quando se utiliza arquivos na linguagem Lua pode-se fazer uso de duas abordagens de acesso aos seus descritores, que pode ser implcito ou explicito. Quando se faz uso de descritores implcitos, todas as operaes de acesso ocorrem com o uso dos recursos da tabela io. Quando se faz uso de descritores explcitos, todas as operaes so providas como mtodos do descritor de arquivo. possvel com a linguagem Lua criar um programa que efectue a criao automtica de pginas HTML/XHTML. O programa a seguir cria uma pgina em cdigo XHTML.
-- inicio do programa ARQ04 ARQ = io.open("agenda.txt","r") for REGISTO in

ARQ:close() -- fim do programa ARQ04

Em seguida escreva o cdigo de programa em um editor de texto, gravando-o com o nome arq05.lua e execute-o com a linha de comando l ua 5.1 arq05.lua. Observe junto ao programa as definies das tags XHTML para criao da pgina com o nome teste.html.

Concluso
Neste artigo foi dado ateno as aces de uso de arquivos em modo texto na linguagem Lua. Foi tambm fornecido informaes sobre o uso do ambiente em modo interactivo. No prximo artigo ser tratado o uso de funes para acesso em tabelas, escopos de variveis, descrio de dados, meta-tabelas e orientao a objectos em Lua.

Errata
No primeiro artigo desta srie foi informado equivocadamente que o resto de diviso entre dois valores poderia ser obtido a partir da funo mod(). De fato, pode-se fazer uso desta funo para se obter o valor do resto de uma diviso desde que esta funo esteja associada a sua biblioteca, neste caso, a biblioteca math, por meio da sintaxe math.mod() ou ento pode-se fazer uso do operador % mostrado neste artigo.

io.lines("agenda.txt") do io.write(REGISTO.."\n")

end

AUTOR
Escrito por Augusto Manzano Natural da Cidade de So Paulo, tem experincia em ensino e desenvolvimento de programao de software desde 1 986. professor da rede federal de ensino no Brasil, no Instituto Federal de Educao, Cincia e Tecnologia. tambm autor, possuindo na sua carreira vrias obras publicadas na rea da computao.

41

MAC ADDRESS
E s e a m a n h a Ap p l e d o m i n a r?
J tenho idade e experincia suficiente para poder ter uma perspectiva slida sobre a evoluo de plataformas computacionais de desenvolvimento. J percorri parte da "travessia do deserto" que a Apple efectuou no incio dos anos noventa, altura em que mesmo os mais cpticos se questionavam sobre o futuro da Companhia. Se verdade que a imprensa anunciou vrias vezes a "morte" da marca de Cupertino (notcias que felizmente se veio a concluir serem manifestamente exageradas), no menos verdade que embora uma plataforma nicho, esteve sempre muito frente (e por vezes demasiado na vanguarda), da inovao e na capacidade de se recompor de cada desaire. Sejamos francos, hoje a marca Apple "trendy", "fashionable" e mais umas dzias de palavres do jargo IT. Arrasta multides (e voc pode muito bem ser um deles...) como uma lmpada acesa atrai mosquitos. Nem sempre foi assim. Reduzidos a uma franja residual de utilizadores, autnticos gauleses irredutveis na sua aldeia, a Apple sobreviveu graas capacidade de viso dos que presidiram aos seus destinos (Steve Jobs, anyone?), mas tambm graas a uma capacidade inigualvel de R&D (que tambm teve as suas ndoas negras no caminho), e a um desempenho industrial quase irrepreensvel. Se uma nuvem de "copycats" me irritou no passado, hoje isso quase que se tornou banal. Todos os trimestres se perfilam no mercado "Killers" de isto e daquilo. A maioria deles pretende ser "killer" de um produto Apple, mas no menos verdade que h cemitrios inteiros cheios de produtos que se arrogam a ser a prxima grande descoberta. O verdadeiro "killer" est ainda, penso eu, nos estiradores dos
42

conceitos... Ipod, iPhone, iPad so apenas os trs ltimos exemplos do que acabei de tentar demonstrar.

a Apple fez de um mercado que no existia (...) um imprio colossal que rende milhes de dlares
O caso do iPod paradigmtico na minha linha de pensamento: No a criao do hardware, no a criao do software (que, recordo, foi Mac only durante um ano e alguns meses...) que fazem (ou fizeram) a revoluo. a experincia do utilizador. Pela primeira vez, um ecossistema permitia ao cliente no "power user", uma experincia de uso integrada, pacfica e totalmente tranquila. Esse um dos grandes capitais da Apple. Colocar no mercado produtos pensados (verdadeiramente pensados) para o utilizador comum, que de uma forma tranquila se vai rendendo aos encantos desse esforo. Sim, a Apple fez de um mercado que no existia (Napster. Anyone?), um imprio colossal que rende milhes de dlares. Artistas, compositores e msicos querem hoje cortar o "middleman" e estar de forma directa na Store. Meia dzia de anos passados, quem se lembra de como eram as coisas anteriormente? Replicar a experincia noutras plataformas foi apenas uma questo de poucos anos. No passa nenhuma semana no meu calendrio que no tenha contactos de programadores

MAC ADDRESS
E s e a m a n h a Ap p l e d o m i n a r?

experientes ou simples iniciantes que me contactam em busca desse Santo Graal que a iniciao ao desenvolvimento para iPhone. Sim, disse apenas iPhone; foi com este produto que tudo realmente comeou. E ao longo dos ltimos trs anos, no incio dos quais se contavam pelos dedos de ambas as mos de um lanador de foguetes destreinado, a quantidade de gente portuguesa envolvida no desenvolvimento, passmos a cont-los por centenas e posteriormente j na casa do milhar. divertido. Divertido e reconfortante assistir a esta corrida ao ouro. Numa Store que todos invejam e tentam copiar (por vezes demasiado mal), h espao para todos e todos so tratados por igual. o mercado a funcionar. Destacam-se os bons dos medianos e maus, ningum fica verdadeiramente prejudicado pois a escolha (compra) do cliente final que verdadeiramente decisria. Vingam as boas ideias. E essas, reconhecidamente temo-las em Portugal com programadores portugueses. Alguns deles j reconhecidos internacionalmente com prmios do prprio fabricante. Quem sabe, se uma das suas ideias no chega ao top da AppStore?

Sim, disse apenas iPhone; foi com este produto que tudo comeou

AUTOR
Escrito por Pedro Aniceto Pedro Aniceto, Gestor de Produto Apple desde 1 998 e utilizador da marca desde bem mais cedo. No acredita em monstros, mas espreita de quando em vez para debaixo da secretria.

43

A PROGRAMAR
S QL e m O ra c l e
Introduo
Quando desenvolvemos uma aplicao assente numa base de dados, um dos processos que normalmente nos passa ao lado a optimizao de queries. Preocupamo-nos com a interaco da aplicao com o utilizador ou com questes de segurana, no dando importncia a pormenores de SQL que podem, muitas vezes, condicionar a performance da aplicao. O tempo de espera na execuo de uma query pode arruinar uma aplicao e, em ltima instncia, uma base de dados inteira. crebro da base de dados). Alguns desses dados variam ao longo do tempo. Por isso, ou o optimizador inteligente ao ponto de escolher sempre o melhor caminho, ou teremos de ser ns programadores - a ensin-lo.

a lentido de uma aplicao com acessos base de dados resulta de SQL mal construdo ou de estruturas de dados desadequadas
As bases de dados recentes, e em especial a Oracle, j tm algoritmos bastante poderosos que cobrem a maioria das situaes. No entanto, h ainda alguma margem de inveno para o programador poder influenciar o desempenho do SQL.

O tempo de espera na execuo de uma query pode arruinar uma aplicao e, em ltima instncia, uma base de dados inteira
A soluo passa, muitas vezes, por melhorar o hardware, culpando-o da baixa performance das nossas queries. Mas, nem sempre o problema reside no hardware. Alis, muitas vezes, a lentido de uma aplicao com acessos base de dados resulta de SQL mal construdo ou de estruturas de dados desadequadas ao nosso projecto. No existe uma frmula para optimizar SQL. Cada caso um caso. A estrutura de dados, a quantidade ou a qualidade dos dados so factores que influenciam o optimizador (o
44

Estrutura ultra simplificada de uma BD Oracle

Para sabermos o que optimizar e como optimizar, h que conhecer a estrutura interna de uma base de dados Oracle. Como este artigo no pretende ser exaustivo, mostra-se apenas uma viso muito simplista do

A PROGRAMAR
SQL e m O ra c l e

modo de funcionamento de uma base de dados Oracle, o suficiente para perceber os conceitos aqui referidos:

select nome, morada, telefone from t_clientes where nif = 12345;

1. 2.

O cliente envia a instruo SQL para o servidor. O server process procura na shared pool uma instruo igual solicitada. Se no encontrar, compila a nova instruo (parsing) e armazena-a na shared pool.
3.

Cliente a nossa aplicao que comunica com


a base de dados.

O server process procura na buffer cache os blocos de dados que necessita. Se no encontrar, faz uma consulta aos data files.
4.

Os dados so enviados para o cliente.


query,

Oracle Server Process processo que recebe


as instrues do cliente e as executa. estrutura e os dados de uma BD.

Se repetirmos a mesma processo ser o seguinte:


1. 2.

de seguida, o

Datafiles ficheiros onde armazenada a SGA zona de memria utilizada para guardar
dados partilhados pelos vrios utilizadores/aplicaes da BD. Armazena dados no Buffer Cache e instrues SQL na Shared Pool. As instrues SQL e os dados solicitados atravs de queries so guardados na SGA, poupando tempos de processamento e acessos ao disco, em futuras chamadas da mesma query.

O cliente envia a instruo SQL para o servidor. O server process procura na shared pool uma instruo igual solicitada. Encontra-a e j sabe como encontrar os dados.
3.

O server process procura na buffer cache os blocos de dados que necessita. Acabaram de ser requisitados na query anterior. Ainda l esto. No necessrio recorrer aos datafiles, pois os dados encontram-se todos em memria.
4.

Como o Oracle processa um comando


Tomemos como exemplo o seguinte query:

cliente.

Os dados so enviados da SGA para o

Por onde comear?


Verificmos que o Oracle guarda as queries pedidas em memria com a informao do
45

A PROGRAMAR
SQL e m O ra c l e

melhor percurso para obter os dados. Imaginemos uma aplicao que executa, sistematicamente, esta query com diferentes condies:
select nome, morada, telefone from t_clientes where nif = 12345;

Uma funcionalidade do Oracle e que permite optimizar a utilizao repetida de queries iguais so as bind variables . Estas variveis permitem executar a instruo da seguinte forma:
variable nif_n number; query -> :nif_n; exec :nif_n := 12345; select nome, morada,

select nome, morada, telefone from t_clientes where nif = 12346;

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

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

query -> :nif_n;

telefone from t_clientes where nif =

As queries so todas diferentes. Logo, o Oracle vai armazenar cada uma delas na shared pool. Mas, na prtica, o processo de obteno dos dados sempre o mesmo. Na verdade, as queries so todas iguais, excepto o critrio da condio where. O optimizador no suficientemente esperto ao ponto de perceber que o processo sempre o mesmo. Poderamos, facilmente, encontrar estas queries em memria, na SGA, executando a seguinte consulta:
select hash_value,sql_text, parse_calls,

Agora, sim, a query sempre igual, aos olhos do optimizador Oracle e, em vez de guardar inmeras queries iguais em memria, guarda apenas uma:
select nome, morada, telefone from

t_clientes where nif = :nif_n;

Estas situaes tomam especial importncia em bases de dados onde a mesma query repetida milhares de vezes ficando a memria entupida com instrues iguais. A repetio da mesma query milhares de vezes pode rapidamente ocupar toda a memria disponvel. Ao utilizarmos bind variables, estamos a poupar CPU no parsing e RAM na shared pool. Como caso prtico da utilizao de bind variables podemos referir um website de venda de automveis usados.

loads, executions from v$sqlarea

where sql_text like 'select nome, morada, telefone from t_clientes where nif =%';

Verificaramos inmeras queries similares, com varincia no parmetro nif.


46

A PROGRAMAR
SQL e m O ra c l e

Se o campo de pesquisa for a marca, modelo e ano, estaremos a executar uma query que procura numa tabela os automveis com a marca X, modelo Y e ano Z, que podem ser seleccionados recorrendo a bind variables , evitando assim milhares de queries similares.

quando tem apenas uma executions.

parse_calls

e muitas

Naturalmente que, em queries pouco frequentes, no necessrio preocuparmo-nos com esta optimizao e nem devemos generalizar a optimizao somente s bind variables . Existem muitas maneiras de tornar o cdigo SQL mais eficiente e esta apenas uma delas e de fcil implementao. Uma anlise mais aprofundada da estrutura de uma base de dados Oracle permite um conhecimento mais vasto sobre o modo como o Oracle processa os pedidos de informao. Na prtica, os conceitos aqui referidos so bem mais complexos. No entanto, a nvel do programador que estrutura o SQL e que, eventualmente, cria a estrutura de dados, estes conceitos so suficientes para este tipo de optimizao. O detalhe vai interessar mais ao DBA que tambm poder fazer maravilhas no tunning da base de dados.

Concluso
A utilizao de bind variables uma prtica que deve ser adoptada sempre que possvel. Se a nossa aplicao j est em produo, uma anlise vista dinmica v$sqlarea permite detectar as instrues SQL similares que podem ser reduzidas a uma s.

A utilizao de bind variables uma prtica que deve ser adoptada sempre que possvel
Para isso, podemos olhar para as colunas parse_calls e executions. Uma
query

muito frequente est optimizada

AUTOR
Escrito por Ricardo Trindade actualmente o responsvel pela rea informtica dos Servios Sociais da Cmara Municipal de Lisboa onde efectua, desde administrao de sistemas, at programao em .NET. Est tambm ligado ao projecto N-Ideias na rea da consultoria, webdesign e software, trabalhando essencialmente com BD's Oracle, PostgreSQL e SQL Server.

47

A PROGRAMAR
As p e c to s l o w- l e ve l d e 3 D
Introduao ao 3D
Este artigo explica alguma da teoria relacionada com o funcionamento de baixo nvel de grficos 3D, desde a placa grfica, s bibliotecas que se usam para as programar, e alguma da magia (matemtica) necessria para que tudo funcione. Recomenda-se alguma experincia bsica com conceitos 3D. Quem no se lembra de jogos como Quake e Duke Nukem 3D? Estes jogos (pelo menos as verses originais), eram "renderizados" (transformados numa imagem para mostrar no ecr) completamente por software, ou seja, sem recurso a acelerao por hardware. S anos depois, com a popularidade dos jogos na plataforma PC, que as placas grficas comearam a ser vendidas e distribudas com os computadores. As placas grficas (GPU) so utilizadas para acelerar os clculos necessrios para representar realisticamente os objectos em 3D. As placas so constitudas por processadores especializados, e com grande capacidade de paralelizao, em contraste com um processador normal (CPU), que est preparado para executar os mais variados tipos de aplicaes. Com o aparecimento das primeiras placas grficas surge a necessidade de criar APIs para tirar proveito das capacidades de processamento do hardware. As bibliotecas mais conhecidas so o OpenGL e o Direct3D, embora alguns talvez ainda se lembrem do Glide, que hoje em dia no passa de um artefacto histrico. Como funcionam e qual a relao entre a API
48

(normalmente implementada nos drivers) e a placa grfica?

Pensem na pipeline 3D como uma linha de execuo de uma fbrica. Os materiais so introduzidos, processados em vrias fases, e obtemos o produto final. Convm tambm ficar claro que existem vrios mtodos diferentes para fazer render de grficos 3D. O que as placas grficas actuais usam (e os primeiros jogos 3D que funcionavam apenas por software) chamado de rasterisation. Existem outros mtodos como ray tracing, mas no vo ser explicados. As primeiras geraes de placas grficas apenas executavam a fase Rasterizer, sendo que a fase de Geometry era totalmente processada pelo CPU. Devido crescente complexidade das aplicaes 3D, o CPU no conseguia processar toda a informao em tempo til, e a fase Geometry passou a ser implementada no GPU. Esta capacidade normalmente referida nas funcionalidades das placas grficas por hardware T&L (Transform & Lighting). Esta pipeline est de acordo com um modelo conhecido por Fixed-function pipeline. As placas grficas modernas so muito mais flexveis e dispem de uma pipeline programvel, utilizando shaders. Ainda possvel programar com este

A PROGRAMAR
As p e c to s l o w- l e ve l d e 3 D

modelo no-programvel nas placas grficas mais recentes, mas o seu funcionamento "emulado" pela API grfica. A esmagadora maioria dos chipsets grficos produzidos hoje em dia so programveis, sendo a excepo mais notvel a consola Wii da Nintendo. Os dispositivos mveis tambm demoraram um pouco a adoptar este novo modelo, mas as novas verses do iPhone e dispositivos Android tambm j suportam shaders (atravs do OpenGL ES 2). A web tambm est a caminhar para este modelo, com a adopo do WebGL por vrios browsers.

Por questes de optimizao todos os clculos internos so feitos em tringulos, por ser uma representao simples. Consequentemente, todas as outras formas de representao so convertidas para tringulos, usando um processo chamado tessellation (ou Polygon triangulation). Realizada esta converso os dados so enviados pelo bus (AGP ou PCI-Express) para a placa grfica.

Geometry stage
Esta fase recebe os vrtices 3D enviados para a placa grfica pela fase anterior, e executa uma srie de transformaes necessrias para adaptar estes dados num formato adequado para o processamento da prxima fase. Esta a parte mais importante da pipeline, e onde so efectuados a maior parte dos clculos. Antes de analisarmos em mais detalhe cada uma das transformaes desta etapa, vamos ver o que so espaos de coordenadas e como so representados os vrtices. Em 3D comum utilizarmos vrios espaos de coordenadas pois faz sentido falar de diferentes coordenadas dependendo do objecto ou referncia que estejamos a considerar. Os espaos fundamentais so denominados por Model/Object Space, World Space e Camera/Eye Space, pela ordem que so processados na pipeline. Inicialmente um objecto em 3D reside num espao chamado Model Space, que significa que
49

Application stage
Tal como o nome implica, a primeira fase ocorre na aplicao desenvolvida pelo programador, e processada apenas no CPU. Nesta etapa, so normalmente processadas tarefas como deteco de coliso (Collision detection), animao, simulao de fsica, algoritmos de acelerao (Space partitioning, Culling), entre outros, dependendo do tipo de aplicao. A aplicao tambm responsvel por enviar os dados dos objectos 3D para a API. Os objectos em 3D so geralmente representados por polgonos: tringulos e quadrilteros. Existem outras formas de representao, como curvas/superfcies NURBS (Non-uniform Rational B-splines), mas apesar de permitirem a modelao de alguns tipos de objectos de forma mais precisa (atravs de modelos matemticos) precisam de ser convertidas noutras representaes.

A PROGRAMAR
As p e c to s l o w- l e ve l d e 3 D

o objecto ainda no foi transformado e se encontra no seu prprio espao de coordenadas. importante que cada objecto defina o seu prprio espao, pois podemos associar vrias transformaes a um objecto inicial, obtendo vrias cpias no objecto no mundo com localizaes, orientaes e tamanhos diferentes, sem ser necessrio enviar todos estes objectos diferentes para a placa grfica (esta tcnica conhecida por Instancing). Neste caso os objectos esto normalmente posicionados na origem para fcil manipulao. World Space um espao de coordenadas especial pois todos os outros espaos vo ser referenciados em relao a este. Em outras palavras este o maior espao de coordenadas no mundo. mais fcil perceber a relao entre estes diferentes espaos utilizando um exemplo. Todos ns temos o nosso prprio espao de coordenadas. Se eu vos disser para darem um passo em frente (Object Space), no fao ideia se vo para Norte, Sul, Este ou Oeste (World Space). Antes de estudarmos os diferentes tipos de transformaes que os objectos sofrem, necessrio um modelo que possa ser facilmente trabalhado. Os pioneiros em computao grfica escolheram vectores como a forma de representao dos vrtices. Esta representao permite reutilizar todo o conhecimento da rea matemtica conhecida por lgebra linear. Esta rea estuda as propriedades dos vectores e dos conceitos associados (espaos vectoriais). Esta representao vai permitir o uso de matrizes (que podem ser visualizadas como um conjunto de vectores) para a manipulao dos vrtices.

As matrizes vo corresponder a transformaes de um espao de coordenadas para outro diferente. Exemplos de transformaes representveis com matrizes so translaes, rotaes, escalamentos ou redimensionamentos, reflexes, projeces, entre outros. Existem vrias formas de representar matrizes na memria: row-major order e column-major order. fundamental que no se misturem os dois tipos de representaes, pois a ordem da multiplicao para a concatenao de transformaes diferente. Com o uso de matrizes tambm se torna possvel a concatenao de diferentes tipos de transformaes (representadas em diferentes matrizes) numa nica matriz. Isto bastante til, pois apenas temos de multiplicar os vrtices por essa matriz composta e obtemos logo o resultado equivalente a multiplicar o vrtice por cada transformao em separado.

50

A PROGRAMAR
As p e c to s l o w- l e ve l d e 3 D

Existem bastantes mais detalhes sobre matrizes que convm estudar para se conseguir perceber detalhadamente como a teoria (e a prtica!) funciona. Mais concretamente, fortemente recomendada a leitura sobre coordenadas homogneas, transformaes lineares e transformaes afins. bom que estudem tambm como as diferentes transformaes funcionam em termos de operaes matriciais. Como exemplo, vejam uma matriz de translao (apresentada na figura) e tentem multiplicar um vector pela matriz. As diferentes APIs grficas usam diferentes convenes para a representao de matrizes e vectores em memria. Vamos ver as diferenas:

Agora que j vimos o modelo usado para trabalhar os vrtices, e como eles so representados no computador, vamos analisar as transformaes principais que acontecem internamente na pipeline (no se preocupem se no perceberem os diferentes espaos de coordenadas, vo ser explicados mais frente): 1. Model transform, transformao de Model Space para World Space. 2. View transform, transformao de World Space para Camera Space. 3. Projection transform, transformao de Camera Space para Clip Space. Usando notao matemtica, podemos representar estas transformaes pela seguinte multiplicao de matrizes:

Model & View Transform


A primeira transformao que ocorre a transformao designada por Model. Esta transformao usada para colocar os objectos na sua posio do mundo. Como j vimos, os objectos comeam com o seu prprio espao de coordenadas, e normalmente esto centrados na origem. Se quisermos colocar dois cubos no mundo 3D (definidos num ficheiro externo e centrados na origem), vamos ter duas matrizes de model diferentes, que os colocam em posies diferentes, e que tambm permitem que eles tenham tamanhos diferentes ou que no estejam orientados da mesma forma. A transformao View vai colocar os objectos centrados no espao da cmara. Ou seja, objectos mesmo frente da lente da cmara vo estar na origem desse novo espao. Ao incio pode parecer confuso, pois ao contrrio do que estamos habituado no mundo real (onde os objectos no mudam de stio), em 3D so os vrtices dos objectos que so multiplicados por
51

Convm tambm perceber as convenes de eixos usadas nas principais APIs grficas podem ser vistas de diferentes formas. preciso ter cuidado se temos um sistema de coordenadas left-handed ou um sistema de coordenadas righthanded. Em relao correspondncia dos eixos, a conveno usada que o Y corresponde a cima/baixo, o X a esquerda/direita e o Z a frente/trs (ver imagens), embora isto possa ser alterado.

A PROGRAMAR
As p e c to s l o w- l e ve l d e 3 D

uma matriz, e normal que sejam os objectos que mudam de sitio para serem vistos de diferentes posies.

Projection
Depois de os objectos estarem posicionados no espao da cmara, necessrio que eles sejam projectados. A projeco consiste no mapeamento dos vrtices (em 3D) para um certo plano com representao bi-dimensional (2D). Podemos considerar dois tipos de projeces: Ortogonais (ortographic projection) Perspectivas (perspective projection). No final da projeco, o resultado de multiplicar todos os vrtices pelas matrizes de transformao e projeco vai ser diferente, dependendo do tipo de projeco escolhido. No caso da projeco ortogrfica, o resultado vai ser um paraleleppedo, enquanto no caso da projeco perspectiva vai ser uma pirmide invertida com o topo truncado, a que se d o nome de frustum (exemplo na figura). No final da projeco, o resultado de multiplicar todos os vrtices pelas matrizes de transformao e projeco vai ser diferente, dependendo do tipo de projeco escolhido. No caso da projeco ortogrfica, o resultado vai ser um paraleleppedo, enquanto no caso da projeco perspectiva vai ser uma pirmide invertida com o topo truncado, a que se d o nome de frustum (exemplo na figura).

Tal como representado na figura, podemos ver uma projeco perspectiva na esquerda. As linhas, quando vistas no horizonte, focam-se num ponto (vanishing point). A este efeito chama-se foreshortening. Tem a caracterstica que objectos mais longe parecem mais pequenos. Este o tipo de projeco a que estamos habituados a ver no dia-a-dia. Outro tipo de projeco, apresentado na direita, a projeco ortogrfica. Esta projeco tem a caracterstica que linhas paralelas continuam paralelas depois da projeco. Por exemplo, estamos habituados a ver este tipo de projeco em plantas de edifcios.

As APIs grficas normalizam o resultado de todos os tipos de projeco num cubo centrado na origem com dimenses que variam de (-1 ,1 ) no eixo X, Y e Z. Isto permite que os restantes
52

A PROGRAMAR
As p e c to s l o w- l e ve l d e 3 D

passos da pipeline sejam executados de forma uniforme. O espao resultante chamado de clip space pois nesta mesma fase todos os vrtices que estejam fora do espao definido pelo cubo, so ignorados (tambm conhecido por clipping). de notar que o funcionamento apresentado pode ser ligeiramente diferente entre o OpenGL e o Direct3D, mas a teoria equivalente entre os dois. Normalmente s alguns pormenores variam, sendo recomendada a consulta da documentao oficial de cada API para saber mais concretamente de como so executados todos estes passos. Alguns pequenos pormenores tambm foram omitidos pois requerem conhecimento mais avanado sobre a representao de coordenadas homogneas em matrizes (perspective divide e normalized device coordinates).

Rasterizer stage
Esta fase utiliza as primitivas geradas na fase anterior para determinar os pxeis finais que vo ser escritos no framebuffer. O primeiro passo a ser processado conhecido por Scan conversion. Este passo transforma os tringulos 2D (mais a sua profundidade) em fragmentos. Fragmentos so potenciais pxeis que vo ser escritos no framebuffer. Tm associados informao como localizao, cor, coordenadas de texturao e profundidade. A informao que est associada aos fragmentos usada para determinar a sua cor. A cor de um fragmento pode depender de vrios factores, por exemplo, se existem luzes que afectam o fragmento, ou se o fragmento faz uso de texturas. Esta fase chamada de shading e existem vrios algoritmos de diferentes complexidades que do resultados melhores ou piores de acordo com o seu custo de processamento. Nos primeiros jogos as frmulas utilizadas simplificavam bastante as equaes necessrias pois ainda no existia poder de processamento suficiente para utilizar tcnicas mais avanadas. A informao era normalmente processada para cada vrtice (per-vertex shading) e depois interpolada em cada fragmento (Gouraud shading). Hoje em dia j temos poder de processamento suficiente para calcular a informao da cor por cada fragmento (per-pixel shading) com tcnicas como o Phong shading. Esta fase normalmente implementada nas placas modernas com shaders, que permitem total controlo e flexibilidade sobre o algoritmo utilizado j que so escritos pelo utilizador.

Viewport Mapping
As APIs grficas normalmente permitem a definio de uma sub-regio da janela onde o output final mostrado. Imaginem por exemplo um jogo de carros, com suporte para 2 jogadores no mesmo ecr (o que os jogos normalmente chamam de split-screen). Normalmente o ecr dividido ao meio e mostrada a rea de jogo de cada jogador em cada uma dessas regies. Nas APIs grficas, cada uma dessas regies conhecida por viewport. Depois de obter as coordenadas normalizadas no cubo, feito o mapeamento para o espao de coordenadas da janela, ou Window Space. Este processo conhecido por Viewport Mapping, pois tem em conta as definies do viewport actual, para permitir que diferentes imagens sejam mostradas na mesma janela.

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

A PROGRAMAR
As p e c to s l o w- l e ve l d e 3 D

no framebuffer (de fragmentos anteriores que ocupam a mesma posio). Esta tcnica chamada de blending e o OpenGL por exemplo permite o controlo das equaes utilizadas para efectuar a mistura. possvel assim obter efeitos como transparncias parciais ou totais. O que vemos na figura um exemplo de blending por adio. Os fragmentos do quadrado verde so misturados com os j existentes do quadrado vermelho, dando origem ao amarelo. Utilizando a mesma figura, outro conceito importante a perceber o controlo da profundidade dos objectos. Por exemplo, se tiverem um quadrado frente de outro, s querem que o quadrado mais prximo da cmara seja mostrado, pois est a tapar o quadrado de trs. A profundidade controlada com o valor de profundidade do vrtice quando projectado no espao de coordenadas da cmara (eixo dos Z). Para controlar e saber quais os objectos a
AUTOR

mostrar, o OpenGL podia ordenar os objectos e desenhar os que esto mais longe primeiro (o chamado Painter's algorithm), mas isso causa problemas com objectos que se intersectam (ver figura). A soluo utilizada pelo OpenGL e Direct3D ordenar os objectos ao nvel do pixel, utilizando uma zona de memria que armazena a profundidade de cada pixel (chamado de depth- ou Z-buffer). Depois de conhecida ento a cor do fragmento, quando um fragmento est para ser escrito no framebuffer, a sua profundidade comparada com a do fragmento que est no buffer (depth buffer test). S se o fragmento novo estiver mais perto (se o seu valor for menor) que o novo valor de cor escrito no framebuffer. No fim do processamento de todos os fragmentos, a aplicao mostra o contedo do framebuffer no ecr (normalmente numa janela) ou grava o contedo para uma imagem. Chegamos ao fim do artigo! Embora este artigo j d uma pequena ideia sobre o mundo que o 3D, foi apenas uma pequena introduo sobre o tema. Espero que tenham gostado e aprendido com o artigo, e se quiserem aprender mais, podem consultar os seguintes recursos. Real-Time Rendering Essential Math for Game Developers GameDev.net

Escrito por Joo Matos Tambm conhecido por triton, frequenta o segundo ano do curso de Engenharia Informtica e Computadores no IST. Tem como principais interesses as reas de Sistemas Operativos, Computao Grfica e Arquitectura de Computadores.

54

CORE DUMP
Qu a n d o s e ! Pro d u ti vo
Quem ganha a vida a bater cdigo est habituado a ver a sua produtividade medida. Por vezes essa medio no efectuada de forma correcta e, pior, muitas vezes no sequer efectuada de forma justa. O resultado , muitas vezes, uma enorme irritao para com a gesto por esta se refugiar em frases, quase infindveis, como Ests quase sempre atrasado nos prazos de entrega, ou O desenvolvimento nunca entrega as coisas a tempo e horas. As desculpas, ou justificaes, por quem faz desenvolvimento so tambm elas inmeras, vo do simples O servidor muito lento ao Esto sempre a mudar as especificaes do produto. Esta parece uma luta desigual, entre o desenvolvimento e a gesto, mas na verdade apenas o porque tipicamente o desenvolvimento no faz uso daquilo que melhor tem ao seu alcance: o seu crebro e o poder de observao. Se a produtividade pode ser medida, a ineficincia tambm. E quando se mede a ineficincia ento h factos que sustentam a falta de produtividade e que, por sua vez, trazem luz verdadeira causa dessas ineficincias. acusadas cai por terra. Muitas das vezes at possvel mostrar que a verdadeira razo da falta de produtividade vem da equipa de gesto. Mas ento, como encontrar e medir essas ineficincias? aqui que entra o poder de observao e o crebro. O primeiro passo identificar todas as causas que nos levam ao desespero quando fazemos desenvolvimento. J me deparei com coisas to variadas como intromisses de anti-vrus, falta de permisses no sistema de desenvolvimento, ou uso de mquinas virtuais. Para exemplificar, no caso do anti-vrus o mesmo no podia ser configurado pelo utilizador para no verificar os directrios referentes ao cdigo fonte, ao cdigo compilado, s bibliotecas usadas, etc.; enquanto que o clssico caso de falta de permisses, faz com que qualquer alterao necessite de uma longa interaco entre efectuar um pedido para a alterao e o mesmo ser satisfeito; j o caso da mquina virtual, h quem tenha de desenvolver usando uma mquina virtual que sub-aproveita os recursos da mquina fsica e, devido quantidade de camadas intermdias envolvidas, torna toda a interaco com o sistema muito mais lenta. O segundo passo encontrar uma forma de medir os problemas identificados e convert-los numa medida que a gesto compreenda. Neste caso o tempo uma das escolhas naturais. Por exemplo, no caso do anti-vrus, o tempo de compilao da aplicao sofreu um aumento significativo, que somado ao longo de uma semana resultava em, aproximadamente,
55

Se a produtividade pode ser medida, a ineficincia tambm


Quando fazemos este exerccio de medir a ineficincia, posso assegurar-vos que a larga maioria das vezes a tal falta de produtividade de que as equipas de desenvolvimento so

CORE DUMP
Qu a n d o s e ! Pro d u ti vo

duas horas de inactividade, ou seja um dia por ms de inactividade s devido ao facto do antivrus estar incorrectamente configurado. Esta situao levou-me a questionar a gesto se eu podia configurar o anti-vrus correctamente e tirar um dia de folga a mais por ms, afinal o resultado seria exactamente o mesmo. No caso das mquinas virtuais voltei a medir o tempo, mas desta vez as coisas foram mais drsticas. E no era s pelo facto da mesma mquina fsica ter de correr dois sistemas operativos com dois anti-vrus e desperdiar 500MB de RAM porque a mquina virtual apenas conseguia alocar 1 .5GB de RAM... Era um conjunto de situaes que somado resultava num aumento de quatro vezes o tempo de espera na operao de compilao e deploy da aplicao. Sim, a produtividade caiu para valores crticos. Aps efectuar esta medio, a extrapolao dos valores obtidos mostrou 33 horas de inactividade mensal. Trinta e trs horas por ms num ms que tem quarenta horas de trabalho semanal resulta quase numa semana de inactividade. O caso tomou propores interessantes uma vez que esta situao se passou num cliente que tinha mais de oitenta pessoas externas a fazer desenvolvimento nestas condies. Quando se
AUTOR

tem oitenta pessoas em regime de outsourcing a quem se pagam 4 semanas de trabalho para trabalharem pouco mais de 3 semanas, o resultado financeiro desastroso.

Aps efectuar esta medio, a extrapolao dos valores obtidos mostrou 33 horas de inactividade mensal
Tudo pode ser medido, pelo que o desafio est em encontrar uma forma inteligente de medir o que est mal e apresentar esses resultados. Certamente que no o desenvolvimento que no produtivo quando um bug ocorreu devido a um requisito mal especificado, ou quando existe um processo moroso para satisfazer uma solicitao, ou quando ocorre uma alterao na especificao do sistema. Da prxima vez, no se queixem, identifiquem a ineficincia, meam a ineficincia e apresentem essa ineficincia vossa gesto.

Escrito por Fernando Martins Faz parte da gerao que se iniciou nos ZX Spectrum 48K. Tem um Mestrado em Informtica e mais de uma dcada de experincia profissional nas reas de Tecnologias e Sistemas de Informao. Criou a sua prpria consultora sendo a sua especialidade a migrao de dados.

56

COMUNIDADE SHAREPOINTPT
C l i e n t O b j e c t M o d e l p a ra S i l ve rl i gh t
Com o lanamento da nova verso do SharePoint, mais propiamente SharePoint 201 0 no incio deste ano, e o seu sucesso a nvel mundial da sua adopo como uma das ferramenta empressariais de Portais e Colaborao, este artigo tem como prespectiva a sua demostrao como ferramenta de desenvolvimento para Solues empresariais. Neste artigo irei ainda dar ateno a um dos novos servios disponibilizados pelo SharePoint 201 0 que o Client Object Model para Silverlight, com a criao de um projecto e chamada de mtodos para demostrar a sua capacidade de acesso a conteudos existente nos sites em SharePoint. A plataforma SharePoint um conjunto integrado de recursos que pode ajudar a melhorar a eficcia organizacional fornecendo uma gesto de contedo abrangente e pesquisa empresarial, acelerando os processos comerciais compartilhados e facilitando a partilha de informaes para uma melhor viso dos negcios. Os servios disponibilizados vo desde Gesto de Contedos, Gesto Documental, Business Intelligence, Comunidades, Integrao de Plataforma externas a Microsoft atravs dos BCS(Business Connectivity Services), Workflows, Office Web app (Integrao das ferramentas Microsoft Office em formato Web), SharePoint Designer 201 0, Gesto de Projectos, Servios de Pesquisa de Portal e Contedos Externo, com diversos tipos de autenticao utilizao de federaes entre outros servios. Enfim uma plataforma bastante completa. Durante os ltimos anos a plataforma tem
57

crescido a nvel de servio e a nvel de importncia nas instituies empresariais, tornando uma aposta mais que decisiva da Microsoft, com a sua implementao e integrao de todos os seus produtos nesta plataforma, tornando-se o sistema operativo das empresas. Uma das suas vantagens a capacidade de integrao entre as diversas tecnologias Microsoft e a capacidade de integraes de plataformas externas, como SAP, Oracle entre outras, de forma a torna um ponto de partilha nica da Informao da empresa, sendo construido numa plataforma Web o que torna bastante acessvel o seu acesso. No prximo quadro encontram-se os servios que esto disponveis para o SharePoint 201 0.

Com o lanamento do SharePoint 201 0 foram disponibilizados mltiplos novos servios como LINQ, novas APIs para acesso a dados (utilizando o Client Object Model), utilizao de REST - ADO.NET Data Services e utilizao de Ajax em webParts com processos Asynchronous (sem utilizao de postback nas pginas) entre outros novos servios. O SharePoint 201 0 apresenta 3 novas Client

COMUNIDADE SHAREPOINTPT
C l i e n t O b j e c t M o d e l p a ra S i l ve rl i gh t

APIs para interagir com contedos dos sites de SharePoint: A partir de aplicaes .Net nunca inferiores a Framework 3.5; A partir de aplicaes Silverlight nunca inferiores a Silverlight 2.0 A partis de ECMAScript ou seja de Javascript, Jscript
Arquitectura do Client Object Model

no Visual Studio 201 0, com uma aplicao em Silverlight 4, utilizando a API do SharePoint e integrando do SharePoint 201 0. Para suporte da nossa soluo em SharePoint eu criei uma Lista chamada Geral com um conjunto de dados para teste. Criar um novo Projecto com o Visual Studio

201 0 no Template Silverlight e seleccionar a opo para associar a um novo Web site com a verso do Silverlight 4:

Estas novas API em Client Object Model fornecem um sistema orientado a objectos para interagir com os dados do SharePoint remotamente, sendo bastante fceis de utilizar porque a sua nomenclatura bastante parecida do Server Object Model do SharePoint. Para demostrar a forma de acesso aos Objectos da API na prxima tabela mostra a diferentes APIs para as diversas plataformas e a forma idntica da utilizao do Object Model. Neste exemplo, irei criar um pequeno Projecto

58

COMUNIDADE SHAREPOINTPT
C l i e n t O b j e c t M o d e l p a ra Si l ve rl i gh t

Para realizar as chamadas ao contedo do SharePoint, atravs da API em Silverlight, ser necessrio adicionar como referencias as DLLs que se encontram na pasta da instalao do SharePoint 201 0 (Microsoft.SharePoint.Client.Silverlight e Microsoft.SharePoint.Client.Silverlight.Runtime), tipicamente em C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\1 4\TEMPLATE\LAYOUTS\ClientBin.

Mtodo 1 :

Retorna o nome das Listas existentes no site de SharePoint utilizando o Client Object Mode. Foi utilizado uma expresso Lambda para retornar as listas e o Titulo associado.
private void LoadLists() { ClientContext clientContext = oWebsite = clientContext.Web; collList = oWebsite.Lists;

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

clientContext.Load(oWebsite,

website => website.Title);

//Lambda expression para retornar as Listas

Futuramente, a Microsoft ir disponibilizar um package com as DLLs em SharePoint .NET Client Object Model, onde se poder realizar o download e a sua distribuio ao cliente. Com a utilizao do Visual Studio 201 0 existe a possibilidade de integrar o Microsoft Expression Blend 4 com as nossas aplicaes desenvolvidas em Silverlight.

listInfo = clientContext.LoadQuery( collList.Include( list => list.Title,

list => list.Fields.Include( field => field.Title).Where( && field.Hidden != true))); field => field.Required == true

clientContext.ExecuteQueryAsync(onQuerySuccee ded, onQueryFailed); }

private void onQuerySucceeded(object sender, ClientRequestSucceededEventArgs args) { UpdateUIMethod updateUI = DisplayInfo; this.Dispatcher.BeginInvoke(updateUI);

Depois de termos realizado a nossa customizao podemos voltar nossa soluo em Visual Studio 201 0 e comear a criar os nosso mtodos para retornar contedo do Site. Para isso criei 2 mtodos, um para retornar a listas do nosso site em SharePoint e outro para retornar o contedo de uma Lista numa Datagrid.

private void onQueryFailed(object sender, {

ClientRequestFailedEventArgs args)

MessageBox.Show("Request failed. " + args.Message + "\n" + args.StackTrace);

59

COMUNIDADE SHAREPOINTPT
C l i e n t O b j e c t M o d e l p a ra S i l ve rl i gh t
} private void DisplayInfo() { collList = oWebsite.Lists; projects.GetItems(camlQuery); _projectItems =

context.Load(_projectItems);

listBox1.ItemsSource = listInfo; }

listBox1.DisplayMemberPath = "Title";

context.ExecuteQueryAsync(OnRequestSucceeded, null); }

private delegate void UpdateUIMethod();

#region Methods private void OnRequestSucceeded(Object

Exemplo: http://msdn.microsoft.com/enus/library/ee538971 .aspx

sender, ClientRequestSucceededEventArgs args) { Dispatcher.BeginInvoke(BindData);

Mtodo 2:

} {

Retorna dados da Lista Geral para uma DataGrid utilizando CAML para realizar os filtros dos contedos a retornar:
private void LoadGrid() { //Contexto do site em SharePoint a chamar var context =

private void BindData() //Utilizando o contedo numa lista de

Objecto 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(), Convert.ToBoolean(li["Activo"].ToString()) } Datagrid } }); Activo =

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

new

Geral

//retornar o objecto List com o nome List projects =

context.Web.Lists.GetByTitle("Geral"); context.Load(projects);

//adicionar

os

Dados

da

Lista

na

nossa Lista

//CAML Query para Filtar os valores da

dataGrid1.ItemsSource = list;

CamlQuery camlQuery = new CamlQuery(); camlQuery.ViewXml

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

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

"<Value

No seguinte exemplo foi criado um pequeno formulrio no Silverlight para a lista Anuncios. Esta lista tem um conjunto de artigos de referncia ao Site e este mtodo mostra como se consegue criar um formulrio de uma forma simples, sem ter a necessidade de realizar
60

COMUNIDADE SHAREPOINTPT
C l i e n t O b j e c t M o d e l p a ra Si l ve rl i gh t

customizao de pginas em aspx.


TxtTitle.Text; TxtBody.Text;

oListItem["Title"] = oListItem["Body"] = oListItem.Update(); clientContext.Load(oList, list => list.Title);

Foram adicionadas na Tab formulrio do Silverlight, 3 campos de preenchimento do nosso Artigo, como o Url do site onde se destina, Titulo e corpo.

clientContext.ExecuteQueryAsync(onQueryInsert Succeeded, onQueryInsertFailed); } { } else MessageBox.Show("Vazio!!");

Mtodo 3:

Este mtodo ira criar uma nova entrada na Lista de SharePoint de um novo anncio.
if (!TxtTitle.Text.Equals("")) { ClientContext clientContext = Web oWebsite =

new ClientContext(TxtUrl.Text); clientContext.Web; oWebsite.Lists;

Com a criao deste 2 pequenos exemplos podemos criar a nossa soluo AccessData.XAP.

ListCollection collList =

SharePoint Silverlight Web Part


SharePoint disponibiliza ferramentas para integrar o projecto desenvolvido em Silverlight e adicionar nos nossos sites em SharePoint de uma forma bastante simples. O primeiro passo ser adicionar o nosso projecto em Silverlight, neste caso AccessData.XAP e adicionar no nosso site em SharePoint, podendo ser uma Folder, uma Document Library ou at na
61

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

oList

oList.AddItem(new

ListItem oListItem =

ListItemCreationInformation());

COMUNIDADE SHAREPOINTPT
C l i e n t O b j e c t M o d e l p a ra S i l ve rl i gh t

directoria ou pasta Hive onde se encontra instalado o SharePoint no servidor. Neste caso criei uma Folder dentro do site em SharePoint. Estas pastas no so visveis aos utilizadores finais, garantido que o ficheiro no apagado acidentalmente.

Quando nos encontramos a trabalhar em ambiente Web a aplicao Fiddler uma ferramenta essencial para captura e validao do nosso trfego na Web. Estando ela em funcionamento podemos encontrar as transaces realizadas, atravs da Client OM, e encontramos uma chamada ao WCF Web Service client.svc e um Web Service XML para comunicao e transaco das operaes.

Depois de adicionado a nossa soluo em Silverlight, acedemos ao nosso site em SharePoint e adicionamos uma Web Part que se encontra por defeito no SharePoint Silverlight Web Part. Um dos parmetros que requisitado o caminho de onde se encontra a nossa soluo em Silverlight.

Existem outra forma de poder interagir com os dados em SharePoint, com o Silverlight atravs dos REST em WCF e com todas as suas potencialidades.

Assim que esteja tudo correctamente adicionado, ir ser disponibilizado na nossa pgina de internet a nossa soluo de Silverlight, dentro do SharePoint, numa WebPart podendo trabalhar e interagir com o contedo do Site onde se encontra.

Concluso
Este foi um pequeno exemplo de como o Client
62

COMUNIDADE SHAREPOINTPT
C l i e n t O b j e c t M o d e l p a ra Si l ve rl i gh t

Object Model e como o SharePoint 201 0 consegue fornecer informao e integrao com Silverlight. Teria muita mais que falar, isto um tema para diversos subtpicos e com mltiplas formas de tratar, apenas quero demostra as portas que podem ser abertas e como o SharePoint 201 0 uma ferramenta de integrao com todas as diversas Tecnologias Microsoft. Alguns links teis: Using the Silverlight Object Model http://msdn.microsoft.com/enus/library/ee538971 .aspx Using the SharePoint Foundation 201 0 Managed Client Object Model http://msdn.microsoft.com/enus/library/ee857094.aspx Using the SharePoint Foundation 201 0 Managed Client Object Model with the Open XML SDK 2.0 http://msdn.microsoft.com/enus/library/ee956524.aspx SharePoint 201 0 Reference: Software Development Kit http://www.microsoft.com/downloads/en/details.a spx?FamilyID=f0c9daf3-4c54-45ed-9bde7b4d83a8f26f&displaylang=en

Create a Silverlight 4 Web Part for SharePoint 201 0 http://msdn.microsoft.com/enus/magazine/ff956224.aspx Pgina Oficial do SharePoint 201 0 http://sharepoint.microsoft.com/ptpt/Pages/default.aspx Este e outros artigos relacionados com a Tecnologia Microsoft SharePoint esto disponibilizados pelo site da Comunidade Portuguesa de SharePoint. Podem tornar-se membros activos, criando artigos e a participando em eventos mensais da Comunidade sobre a tecnologia SharePoint. Comunidade Portuguesa de SharePoint http://www.sharepointpt.org/

AUTOR
Escrito por Andr Lage Microsoft SharePoint MVP, trabalhando na Suia em empresa Farmaceutica e Banca. Apoiando as diversas Comunidades em SharePoint pelo mundo com participaoes 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/

63

Você também pode gostar