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

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

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

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

Se m i n ri o Po c ke tPT s o b re

Pro 2 0 1 0

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

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/

1 6 a R e u n i o Pre s e n c i a l d a

SAPO C o d e B i ts 2 0 1 0

C o m u n i d a d e N e tPo n to
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):

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

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.

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.

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.

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)

Tinha de haver uma soluo melhor, e por isso


que eu implementei os Operadores Take Last:

.Reverse();

TakeLast<TSource>(IEnumerable<TSource>)

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.

Retorna o nmero especificado de elementos


contnuos no fim da sequncia.
int[] grades = { 59, 82, 70, 56, 92, 98, 85
};

var topThreeGrades = grades

.OrderBy(grade => grade)


.TakeLast(3);

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.

Console.WriteLine("As
so:");

notas

mais

foreach (int grade in topThreeGrades)


{
}

Se estiveram a contar, chegaram concluso de


que se iterou sobre todos os itens da sequncia
4

Console.WriteLine(grade);

altas

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
/*

string[] fruits =

Este cdigo produz o seguinte resultado:

{ "ma", "maracuj","banana", "manga",

As notas mais altas so:

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

98

var query = fruits

92

.TakeLastWhile((fruit, index) =>

85

fruit.Length >= index);

*/

foreach (string fruit in query)


{

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

Retorna os elementos do fim da sequncia para


os quais a condio especificada verdadeira.

/*

Este cdigo produz o seguinte resultado:


morango

string[] fruits =

*/

{ "ma", "maracuj","banana", "manga",


};

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

.TakeLastWhile(fruit =>

Tendo introduzido os operadores TakeLast, faz


todo o sentido introduzido os seus duais: os
operadores SkipLast:

fruit, true) != 0);

SkipLast<TSource>(IEnumerable<TSource>)

var query = fruits

string.Compare("laranja",

foreach (string fruit in query)


{
}

Console.WriteLine(fruit);

Retorna todos os elementos da sequncia


excepo do nmero especificado de elementos
contnuos no fim da sequncia.

Console.WriteLine(fruit);

int[] grades =

{ 59, 82, 70, 56, 92, 98, 85 };

/*

var lowerGrades = grades

Este cdigo produz o seguinte resultado:

.OrderBy(g => g)

maracuj

.SkipLast(3);

uva

morango

Console.WriteLine("Todas as notas excepto as

*/

top 3:");

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

foreach (int grade in lowerGrades)

Retorna os elementos do fim da sequncia para


os quais a condio especificada verdadeira.

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

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

/*

Este cdigo produz o seguinte resultado:


As notas mais altas, excepto:

Retorna todos os elementos da sequncia


excepo dos elementos do fim da sequncia
para os quais a condio especificada
verdadeira.

56
59
70
82
*/

int[] amounts =
{

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.

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

index * 1000);

foreach (int amount in query)

{ 59, 82, 70, 56, 92, 98, 85 };

var lowerGrades = grades

.OrderBy(grade => grade)

grade >= 80);

/*

.SkipLastWhile(grade =>

Console.WriteLine(amount);

Este cdigo produz o seguinte resultado:

Console.WriteLine("Todas as notas menores que

5000

80:");

2500
*/

foreach (int grade in lowerGrades)

6500, 4000, 1500, 5500

var query = amounts

int[] grades =

5000, 2500, 9000, 8000,

Console.WriteLine(grade);

IMPLEMENTADO OS OPERADORES
TAKELAST

/*

I mplementando O Operador TakeLast

Este cdigo produz o seguinte resultado:


Todas as notas menores que 80:

O operador TakeLast retorna o nmero


especificado de elementos contnuos do fim de
uma sequncia e implementado como o
mtodo de extenso TakeLast.

56
59
70
*/

Para implementar este operador, primeiro


comeamos por memorizar, pelo menos, o
nmero requerido (count) de itens da sequncia
6

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:

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


count, numOfItems--)
{

var sourceEnumerator =

source.GetEnumerator();

var buffer = new TSource[count];


var numOfItems = 0;
int idx;

H duas optimizaes que ainda podemos fazer.

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

A primeira bvia, se o nmero de itens


requerido for 0 (zero), retornamos uma
sequncia vazia:

sourceEnumerator.MoveNext(); idx++,
numOfItems++)
{

buffer[idx] = sourceEnumerator.Current;

if (count <= 0)
{

Se o nmero de itens memorizados


(numOfItems) for inferior ao nmero requerido
(count), produzimos os itens memorizados:

if (numOfItems < count)


{

yield return buffer[idx];

yield break;

(idx

0;

int listCount = list.Count;

sourceEnumerator.MoveNext();

for (int idx = listCount - ((count <

idx = (idx + 1) % count)


{

sourceEnumerator.Current;

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

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):

Em seguida, iteramos pelos restantes itens e


vamos os armazenando, de forma circular, na
memria intermdia:
for

return

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.

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

yield return buffer[idx];

listCount) ? count : listCount); idx <


buffer[idx]

listCount; idx++)

yield return list[idx];

Implementando os Operadores
TakeLastWhile

E finalmente, iteramos sobre os itens


memorizados para produzir a sequncia final:

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:

else
{

foreach (var item in source)

if (predicate(item))
{
}

buffer.Add(item);

Implementando o Operador SkipLast


O operador SkipLast retorna o nmero
especificado de elementos contnuos do fim de
uma sequncia e implementado como o
mtodo de extenso SkipLast.

buffer.Clear();

Depois de percorrer toda a sequncia fonte


(source), produzimos todos os itens, se
existirem, da memria intermdia:

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:

foreach (var item in buffer)


{
}

var sourceEnumerator =

yield return item;

source.GetEnumerator();

var buffer = new TSource[count];


int idx;

A diferena para o mtodo que tem em conta o


ndice do item no predicado (predicate) de
seleco apenas na invocao deste:

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

sourceEnumerator.MoveNext(); idx++)

var buffer = new List<TSource>();

var idx = 0;

foreach (var item in source)


{

yield return item;

IMPLEMENTANDO OS OPERADORES
SKIPLAST

else
{

buffer.Clear();

foreach (var item in buffer)

var buffer = new List<TSource>();


{

buffer.Add(item);

buffer[idx] = sourceEnumerator.Current;

Em seguida, iteramos pelos restantes itens da


sequncia fonte (source) memorizando

if (predicate(item, idx++))
{

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:

var list = source as IList<TSource>;


if (list != null)
{

idx = 0;

while (sourceEnumerator.MoveNext())
{

var item = buffer[idx];

idx = (idx + 1) % count;

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++)
{

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):

yield return list[idx];

Implementando os Operadores
SkipLastWhile

if (count <= 0)

// ...

yield return item;

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.

return

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

buffer[idx] = sourceEnumerator.Current;

if (count >= list.Count)

O operador SkipLastWhile retorna os ltimos


elementos contguos que satisfazem o critrio
especificado e implementado como os
mtodos de extenso SkipLastWhile.

return source.Select(i => i);

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.

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.

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:

Se o nmero de itens a excluir for igual ou


superior ao nmero de itens da sequncia fonte
(source), retornamos uma sequncia vazia:
9

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>();

else

foreach (var item in source)


{

if (predicate(item))
{
}

if (buffer.Count > 0)
{

foreach (var bufferedItem in buffer)

buffer.Add(item);

else
{

}
if (buffer.Count > 0)

foreach (var bufferedItem in buffer)


{
}

yield return bufferedItem;

var idx = 0;

foreach (var item in source)

Recursos

O meu website: http://PauloMorgado.NET/


Livro LINQ Com C#
PauloMorgado.Linq
Classe Enumerable
Mtodos de extenso

if (predicate(item, idx++))

yield return item;

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;

var buffer = new List<TSource>();

buffer.Clear();

Concluso

buffer.Clear();

A diferena para o mtodo que tem em conta o


ndice do item no predicado (predicate) de
seleco apenas na invocao deste:

yield return bufferedItem;

buffer.Add(item);

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.

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:

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:

%union {
};

definies

%token<d> NUMBER
%token NL

%%

%left '+' '-'

gramtica

%left '*' '/'


%right '^'

%%

%nonassoc UMINUS

int main()
{
}

double d;

%%

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

int main()
{
}

11

yyparse();

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.

%%

expr_list

: expr NL

{ std::cout

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


|

expr_list

expr

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

NL

expr
-$2; }

: NUMBER

{ $$ = $1; }

| '-' expr %prec UMINUS


| expr '+' expr

{ $$ =

| expr '-' expr

{ $$ = $1-

$1+$3; }
$3; }

| expr '*' expr

{ $$ =

| expr '/' expr

{ $$ =

| expr '^' expr

{ $$ =

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

pow($1, $3); }
}

%{

{ $$ =

| '(' expr ')'

{ $$ = $2;

#include <iostream>
#include <cmath>

%%

%}

int main()
{

%union {
};

double d;

yyparse();

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.

%token<d> NUMBER
%token NL

%left '+' '-'


%left '*' '/'
%right '^'

%nonassoc UMINUS
%type<d> expr

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,

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

| IF expression stmt ELSE stmt


| block

stmt : WHILE expression 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.

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.

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,

%%
program : list
;

list

: statement

| list statement
;

statement : declaration
| function
;

stmt : WHILE expression stmt;

declaration : type identifier

stmt : IF expression stmt;

stmt : IF expression stmt ELSE stmt;

expression

stmt : block;
...

13

|
;

type

identifier

'='

A PROGRAMAR
BYAC C

s : x
| y

type : INT

| DOUBLE

x : A B C ;

| CHAR

y : A B C ;

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.

function : type identifier '(' arg_list ')'


block

block : '{' stmt_list '}'

s : x

| y
;

stmt_list : stmt

x : A B C ;

| stmt_list stmt

...

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

%nonassoc IFX

| y F

%token ELSE

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.

...
stmt : IF expression stmt

%prec IFX

| IF expression stmt ELSE stmt


;

...
%%

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:

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.

stmt : IF expression 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.

15

A PROGRAMAR
BYAC C

expr : expr '*' expr

| expr '^' expr

| NUMBER

| '(' expr ')'

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.

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.

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:

Entendendo associatividade e precedncias


podemos comear a compreender a gramtica
da nossa calculadora.
%token NUMBER
%left '+' '-'
%left '*' '/'
%right '^'

%nonassoc UMINUS
%%

%%

expr : NUMBER

%{

| '-' expr %prec UMINUS

#include <iostream>

| expr '+' expr

#include <cmath>

| 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
;

expr : NUMBER

| '-' expr %prec UMINUS


| expr '+' expr
| expr '-' expr
| expr '*' expr
| expr '/' expr
| expr '^' expr
| '(' expr ')'

%%

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

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

{ $$ = $1; }

{ $$ = -$2; }

{ $$ = $1+$3; }
{ $$ = $1-$3; }
{ $$ = $1*$3; }
{ $$ = $1/$3; }

{ $$ = pow($1, $3); }
{ $$ = $2; }

int main()
{
}

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().

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.

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

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.

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.

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.

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)

Existem vrias vantagens na utilizao de um


ORM (Object-relational mapping), que tornam a
sua adopo quase inevitvel, mas vejamos o
seguinte exemplo:

MODELO

RELACIONAL

Para criao de um modelo relacional iremos


usar a seguinte base de dados SQL:

SELECT * FROM utilizadores WHERE nome =


Jorge AND morada = Moita

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

Para o nome da ligao, e para este exemplo,


utilize vendasEntities.

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.

A ltima opo deste Wizard onde so


seleccionados os objectos a utilizar no modelo.
Neste exemplo so escolhidas as trs tabelas j
referidas.

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.

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.

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

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.

' Podemos verificar logo o nmero


'

(ID) do registo inserido

Debug.WriteLine("Nmero de registo: " &


cliente.id.ToString())

End Using

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.

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.

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.

Finalmente gravamos as alteraes na base de


dados.

Using context As New vendasEntities


' Procura o registo com o nmero de
' cliente (ID) igual a 1

Dim cliente = context.clientes.Where(


Function(c) c.id = 1).
FirstOrDefault()

Using context As New vendasEntities

If cliente IsNot Nothing Then

context.clientes.DeleteObject(cliente)

' Cria um novo cliente

context.SaveChanges()

Dim cliente As New clientes With


{

Else

.nome = "Rui Paulo",


.morada = "Lisboa",

End If

.datanascimento =
}

MessageBox.Show(

New DateTime(1980, 10, 31)

End Using

20

"Nmero de cliente invlido")

VISUAL (NOT) BASIC


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

Modificar Registos

Using context As New vendasEntities

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.

Dim listaClientes =

From c In context.clientes

Where c.morada.Contains("Lisboa") And


c.datanascimento <
Select c

For Each c As clientes In listaClientes

Using context As New vendasEntities

Next

Dim cliente =

(From c In context.clientes

Debug.WriteLine(c.nome)

End Using

Where c.id = 1

Select c).FirstOrDefault()

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.

If cliente IsNot Nothing Then


With cliente

.nome = "Rui Paulo"


.morada = "Setbal"
.datanascimento =

New DateTime(1979, 10, 31)

End With
Else

New DateTime(1985, 1, 1)

context.SaveChanges()
MessageBox.Show(

O seguinte exemplo mostra esta abordagem,


definindo depois o resultado como DataSource
num controlo DataGridView.

"Nmero de cliente invlido")

End If
End Using

NOTA: Se utilizar uma base de dados anexa ao


Using context As New vendasEntities

Listar Registos

Dim listaClientes =

From c In context.clientes

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.

Join m In context.movimentos

On m.clienteid Equals c.id

Join p In context.produtos

On m.produtoid Equals p.id

Select m.datavenda,

21

VISUAL (NOT) BASIC


I n tro d u o a o E n ti ty Fra m e wo rk
Select m.datavenda,

especiais), etc

c.nome,

p.produto,

Estas so apenas algumas, das muitas


vantagens, que nos devem fazer de uma vez por
todas, deixar de usar SqlCommands,
SqlConnections, DataSets, etc.

m.preco

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

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.

ADO.NET team blog


http://blogs.msdn.com/b/adonet/
Julie Lerman's Blog
http://thedatafarm.com/blog/

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 )
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.

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.

Umas das principais


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

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.

Algumas das funcionalidades elementares das


linguagens funcionais so as funes annimas
e as closures. O Perl tem ambas as features.

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.

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";

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

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

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


say "Hello world!";

23

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

utilizao nas "dispach tables":

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 %lingua = (

"pt" => sub { return "Ol mundo!" },

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

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

#definio da funo say

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

my ($string, $format) = @_;

);

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

my

print $str;
$format

sub

formatao da string

#funo

sub dispach {
annima

my $l = shift;

de

if(defined

$lingua{$l}) {

my $str = shift;

};

#dispach table

$lingua{$l}

&&

exists

my $str = $lingua{$l}->();

return $str."\n";

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

print $str."\n";

else {

Explicao do cdigo do exemplo anterior:

print "Erro: lingua desconhecida!\n";

dispach("fr");

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).

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.

Qual a utilidade das funes annimas?

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.

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

Mas isso traria imediatamente dois problemas:


aumentaria a quantidade de cdigo necessrio e
este artigo tem um limite de caracteres; no
24

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

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.

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.

No prximo, artigo vou falar da segunda das


principais capacidades do Perl para a
Programao Funcional de que falei antes, as
closures.

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

(...) 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.

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.

Suponhamos:

As propriedades a ter em conta so:

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.

CancellationPending

Permite obter se a tarefa foi cancelada.


WorkerReportsProgress

Permite obter e definir se o BackgroundWorker


vai reportar o seu progresso da tarefa.

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;

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.

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.

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.

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.

ReportProgress

Antes de passarmos implementao vou dar


uma breve apresentao terica:

Permite reportar o progresso da tarefa em dado


momento.
Para que o progresso seja reportado
necessrio que o WorkerReportsProgress tenha

Um BackgroundWorker uma classe contida no


26

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.

Vamos agora passar implementao


prtica, para isso vou usar um projecto do
tipo WPF Application.

Os eventos a ter em conta:


DoWork

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 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.

Toda a interface definida no ficheiro .xaml.


Em Code Behind iremos proceder
implementao de toda a funcionalidade para
resolver o problema em causa.

ProgressChanged

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;

1. Comecemos ento por definir uma varivel


global:
private BackgroundWorker _backgroundWorker;

RunWorkerCompleted

2. De seguida vamos criar um mtodo onde


vamos fazer a inicializao desta varivel e
definir as suas propriedades e subscrever os
eventos:

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

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();

private void RunBackground_Click(


object sender,
RoutedEventArgs e)
{
ClearProgress();

_backgroundWorker.DoWork +=
new DoWorkEventHandler(DoWork);

_backgroundWorker.ProgressChanged +=
new ProgressChangedEventHandler(
ProgressChanged);

_backgroundWorker.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(
RunWorkerCompleted);

_backgroundWorker.RunWorkerAsync(
(object)_world);
btnCancel.IsEnabled = true;
btnRunBackground.IsEnabled=false;

Caso no pretendssemos enviar parmetros


usvamos a assinatura do RunWorkerAsync
sem parmetros.

_backgroundWorker.WorkerReportsProgress =
true;

_backgroundWorker.WorkerSupportsCancellation
= true;
}

5. No handler do evento do Click do


btnCancel vamos mandar cancelar a tarefa,
chamando o mtodo CancelAsync.

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.

private void btnCancel_Click(


object sender, RoutedEventArgs e)
{
_backgroundWorker.CancelAsync();
btnCancel.IsEnabled = false;
btnRunBackground.IsEnabled = true;
}

3. Agora vamos definir os handler dos


eventos:

6. Neste momento estamos prontos para


definir a tarefa (handler):

private void DoWork


(object sender, DoWorkEventArgs e)
{}

private
void
DoWork(object
DoWorkEventArgs e){}

private void ProgressChanged


(object sender, ProgressChangedEventArgs
args)
{}

sender,

executado quando o mtodo RunWorkerAsync


chamado. Consideremos a seguinte poro de
cdigo:

private void RunWorkerCompleted


(object sender,
RunWorkerCompletedEventArgs e)
{}

private void DoWork(object sender,


DoWorkEventArgs e)
{

4. No handler do evento do Click do


btnRunBackground vamos mandar executar
a tarefa e como parmetro vamos enviar o
objecto _world.

Algorithm algorithm = new Algorithm();


World world = (World)e.Argument;
object stepValue = world;

28

foreach
(IAlgorithmStep step in algorithm.Steps)
{stepValue = step.DoWork(stepValue);}
e.Result = stepValue;

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.

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));

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;

stepValue =
step.DoWork(stepValue);

object stepValue = world;

foreach
(IAlgorithmStep step in algorithm.Steps)
{
if
(_backgroundWorker.CancellationPending)
{
e.Cancel = true;
return;
}
else
{
stepValue =
step.DoWork(stepValue);
}
}
e.Result = stepValue;
}

_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:

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.

private void ProgressChanged(object sender,


ProgressChangedEventArgs args){}

Que executado quando


ReportProgress chamado.

Por fim temos que reportar o progresso de cada


passo e para isso vamos recorrer ao mtodo
ReportProgress.

mtodo

private void ProgressChanged(


object sender,
ProgressChangedEventArgs args)

private void DoWork(


object sender, DoWorkEventArgs e)
{
Algorithm algorithm = new Algorithm();

World world = (World)e.Argument;

_backgroundWorker.ReportProgress(
5, "Is starting...");

29

progressBar.Value +=
args.ProgressPercentage;
lbxProgress.Items.Add(
args.UserState.ToString());

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.

tarefa. Caso tenha ocorrido um erro, este ser


apresentado ao utilizador.

8. Para terminar, vejamos o handler:

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.

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

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;
}
}

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.

btnRunBackground.IsEnabled = true;
btnCancel.IsEnabled = false;

Vou verificar se a tarefa foi cancelada ou no.

Visite-nos em http://netponto.org

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 ?
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.

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).

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.

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.

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>

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.

<script

type="text/javascript"

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

</head>

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

<a

<body>

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

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

</html>

32

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:

Existem mais 2 modos de assignar um handler


ao evento ready do nosso document:
$(document).bind(ready,
function() {})

window.onload = function() { alert("on doc


ready"); }

e o modo mais abreviado e mais utilizado:

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.

$(function() {
})

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.

Por este motivo, o jQuery tem um evento que


despoletado logo que o DOM est carregado,
no esperando pelos recursos externos:

<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
})

$(document).ready(function() {
//cdigo aqui
})

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

Actualmente existem
cerca de 4000 plugins
na pgina oficial !

img.3

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:

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)

Lua 5.1.4
>

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.

Copyright (C) 1994-2008 Rio

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:

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.

print(7.5 + 4.8)

A linguagem Lua uma linguagem que apesar


de sua independncia operacional pode ser
36

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.

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:

Veja a seguir uma srie de operaes com


clculos matemticos que podem ser
efectivadas junto ao ambiente interactivo.

=9.5e2

print(-2 + -3)
print(2 * 3)

print(10 / 4)

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.

print(10 % 4)
print(2 ^ 3)

print(2 + 5 * 3)

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

Outra possibilidade de operaes so os usos


de valores hexadecimais convertidos em valores
decimais. Por exemplo, observe os seguintes
comandos.

Os exemplos apresentados anteriormente


resultam respectivamente nos valores: -5, 6, 2.5,
2, 8, 1 7, 1 7 e 21 .

=0xa
=0xA

O ambiente interactivo retorna mensagens de


erro quando alguma coisa no escrita dentro
das regras sintcticas do ambiente. Por
exemplo, execute o cdigo.

=0Xa
=0XA

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.

print(2 + + 3)

Ocorrer a apresentao da mensagem de erro


stdin:1: unexpected symbol near '+' informando
que um dos smbolos + desconhecido.

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.

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

A = 2

=2+3

print(A + B)

=2/3

B = 3

=2-3

37

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

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.

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

print(#" ")

COr = 2

print(#"Linguagem Lua")

Cor = 3
cor = 4
Cor = 5

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.

cOr = 6
CoR = 7
coR = 8

print(COR)
print(COr)

Arquivos

print(Cor)
print(cor)

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).

print(Cor)
print(cOr)
print(CoR)
print(coR)

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)

-- inicio do programa ARQ01


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

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).

for N = 1, 200 do
R = N % 2

if (R == 0) then

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

Deteco de Tamanho de String

end

end

38

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

Este valor poder ser 1 (se o valor for mpar) ou


0 (se o valor for par).

ARQ:close()

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.

-- fim do programa ARQ01

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:

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.

nome (primeiro argumento);


modo (segundo argumento).

O programa seguinte efectua a leitura do arquivo


pares.txt e faz o somatrio do valores e mostra
seu resultado.

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:

-- inicio do programa ARQ02


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

for VALOR in ARQ:lines() do

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.

SOMA = SOMA + tonumber(VALOR)

end

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 linha de instruo R = N % 2 obtm o valor do


resto da diviso do valor da varivel N por 2.
39

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() .

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

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

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

end

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.

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.

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.

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.

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 programa seguinte efectua a leitura dos dados


do arquivo agenda.txt.
-- inicio do programa ARQ04
ARQ = io.open("agenda.txt","r")

O prximo programa tem por objectivo fazer a


entrada de dados com nome e telefone e
armazenar os dados em uma agenda.

for REGISTO in

io.lines("agenda.txt") do

-- inicio do programa ARQ03

io.write(REGISTO.."\n")

end

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

ARQ:close()

RESP = "S"

while (RESP == "S") do

-- fim do programa ARQ04

io.write("Nome .......: ")

NOME = string.upper(io.read())
io.write("Telefone ...: ")

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.

TELE = io.read();

REGISTO = NOME.." "..TELE

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.

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.

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.

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.

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.

Errata

-- inicio do programa ARQ04

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.

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

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?
conceitos...

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.

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?

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

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
42

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.

Sim, disse apenas


iPhone; foi com este
produto que tudo comeou

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?

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

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.

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.

a lentido de uma
aplicao com acessos
base de dados resulta de
SQL mal construdo ou de
estruturas
de
dados
desadequadas

O tempo de espera na
execuo de uma query
pode
arruinar
uma
aplicao e, em ltima
instncia, uma base de
dados inteira

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.

Estrutura ultra simplificada de uma


BD Oracle

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.

Para sabermos o que optimizar e como


optimizar, h que conhecer a estrutura interna de
uma base de dados Oracle.

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

Como este artigo no pretende ser exaustivo,


mostra-se apenas uma viso muito simplista do
44

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.

O cliente envia a instruo SQL para o


servidor.
2.

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.

O server process procura na buffer cache


os blocos de dados que necessita. Se no
encontrar, faz uma consulta aos data files.

Cliente a nossa aplicao que comunica com

4.

a base de dados.

Oracle Server Process processo que recebe

Os dados so enviados para o cliente.

as instrues do cliente e as executa.

Se repetirmos a mesma
processo ser o seguinte:

Datafiles ficheiros onde armazenada a

1.

SGA zona de memria utilizada para guardar

2.

query,

de seguida, o

O cliente envia a instruo SQL para o


servidor.

estrutura e os dados de uma BD.

O server process procura na shared pool


uma instruo igual solicitada. Encontra-a e j
sabe como encontrar os dados.

dados
partilhados
pelos
vrios
utilizadores/aplicaes da BD. Armazena dados
no Buffer Cache e instrues SQL na Shared
Pool.

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.

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.

4.

cliente.

Como o Oracle processa um comando

Os dados so enviados da SGA para o

Por onde comear?

Tomemos como exemplo o seguinte query:

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:

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:

select nome, morada, telefone from t_clientes

variable nif_n number;

where nif = 12345;

query ->

select nome, morada, telefone from t_clientes

select nome, morada,

telefone from t_clientes where nif =

where nif = 12346;

:nif_n;

select nome, morada, telefone from t_clientes

exec :nif_n := 12346;

query ->

where nif = 23245;

select nome, morada,

telefone from t_clientes where nif =

(...)

:nif_n;

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.

Agora, sim, a query sempre igual, aos olhos do


optimizador Oracle e, em vez de guardar
inmeras queries iguais em memria, guarda
apenas uma:

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.

select

hash_value,sql_text,

loads, executions

nome,

morada,

telefone

t_clientes where nif = :nif_n;

Poderamos, facilmente, encontrar estas queries


em memria, na SGA, executando a seguinte
consulta:
select

exec :nif_n := 12345;

from

Estas situaes tomam especial importncia em


bases de dados onde a mesma query repetida
milhares de vezes ficando a memria entupida
com instrues iguais.

parse_calls,

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.

from v$sqlarea

where sql_text like 'select nome, morada,


telefone from t_clientes where nif =%';

Como caso prtico da utilizao de bind


variables podemos referir um website de venda
de automveis usados.

Verificaramos inmeras queries similares, com


varincia no parmetro nif.
46

A PROGRAMAR
SQL e m O ra c l e

quando tem apenas uma


executions.

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.

Existem muitas maneiras de tornar o cdigo SQL


mais eficiente e esta apenas uma delas e de
fcil implementao.

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.

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.

A utilizao de bind
variables uma prtica
que deve ser adoptada
sempre que possvel

O detalhe vai interessar mais ao DBA que


tambm poder fazer maravilhas no tunning da
base de dados.

Para isso, podemos olhar para as colunas


parse_calls e executions.
query

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 .

Concluso

Uma

parse_calls

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

(normalmente implementada nos drivers) e a


placa grfica?

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.

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.

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 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).

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

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
48

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

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).

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.

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.

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.

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

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.

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.

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).

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.

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).

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.

Esta representao vai permitir o uso de


matrizes (que podem ser visualizadas como um
conjunto de vectores) para a manipulao dos
vrtices.

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.

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):

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.

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.

As diferentes APIs grficas usam diferentes


convenes para a representao de matrizes e
vectores em memria. Vamos ver as diferenas:

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.

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.

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

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.
51

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:

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).

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).

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

Rasterizer stage

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).

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.

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).

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.

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.

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.

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.

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.

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.

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.

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).

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

Para controlar e saber quais os objectos a


AUTOR
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.

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.

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.

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.

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.

Se a produtividade
pode ser medida, a
ineficincia tambm

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,

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
55

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

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.

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.

Aps efectuar esta


medio, a extrapolao
dos
valores
obtidos
mostrou 33 horas de
inactividade mensal

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...

Tudo pode ser medido, pelo que o desafio est


em encontrar uma forma inteligente de medir o
que est mal e apresentar esses resultados.

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.

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.

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.

Da prxima vez, no se queixem, identifiquem a


ineficincia, meam a ineficincia e apresentem
essa ineficincia vossa gesto.

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
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
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.

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.

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.

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.

No prximo quadro encontram-se os servios


que esto disponveis para o SharePoint 201 0.

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.

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

Durante os ltimos anos a plataforma tem


57

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

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

Arquitectura do Client Object Model

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

Mtodo 1 :

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.

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 =

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

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

clientContext.Load(oWebsite,

website => website.Title);

//Lambda expression para retornar as Listas


listInfo = clientContext.LoadQuery(

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.

collList.Include(

list => list.Title,

list => list.Fields.Include(


field => field.Title).Where(

field => field.Required == true

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.

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

clientContext.ExecuteQueryAsync(onQuerySuccee
ded, onQueryFailed);
}

private void onQuerySucceeded(object sender,


ClientRequestSucceededEventArgs args)
{

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.

UpdateUIMethod updateUI = DisplayInfo;


this.Dispatcher.BeginInvoke(updateUI);

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

_projectItems

private void DisplayInfo()


{

projects.GetItems(camlQuery);

context.Load(_projectItems);

collList = oWebsite.Lists;

listBox1.ItemsSource = listInfo;
}

context.ExecuteQueryAsync(OnRequestSucceeded,

listBox1.DisplayMemberPath = "Title";

null);
}

private delegate void UpdateUIMethod();

#region Methods
private

OnRequestSucceeded(Object

Dispatcher.BeginInvoke(BindData);

Mtodo 2:

private void BindData()

Retorna dados da Lista Geral para uma


DataGrid utilizando CAML para realizar os filtros
dos contedos a retornar:

var list = new List<Geral>();

foreach (var li in _projectItems)


{

//Contexto do site em SharePoint a chamar


var

//Utilizando o contedo numa lista de

Objecto do tipo Geral como a Lista

private void LoadGrid()

context

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

new

projects

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

}
Datagrid

//CAML Query para Filtar os valores da

nossa Lista

camlQuery.ViewXml

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

Activo

Lista

na

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

context.Load(projects);

CamlQuery camlQuery = new CamlQuery();

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

//retornar o objecto List com o nome


List

list.Add(new Geral
{

context.Load(context.Web);

Geral

void

sender, ClientRequestSucceededEventArgs args)

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

});

//adicionar

os

Dados

da

dataGrid1.ItemsSource = list;

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

"<Value

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

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(""))
{

Com a criao deste 2 pequenos exemplos


podemos
criar
a
nossa
soluo
AccessData.XAP.

ClientContext clientContext =

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

Web

oWebsite

ListCollection collList =

oList

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

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

oList.AddItem(new

ListItem oListItem =

ListItemCreationInformation());

61

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

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

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.

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.

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

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