SlideShare uma empresa Scribd logo
Revista programar 31
EDITORIAL
EQUIPA PROGRAMAR                          (Des)Informação


                     Coordenadores        Actualmente muito se têm falado sobre tudo. Falado e especulado. Com a saída de
                       António Silva      Steve Jobs da Apple especula-se qual serão as implicações para a marca da maçã.
                   Fernando Martins       Com o lançamento do Windows 8 especula-se sobre a capacidade deste conquistar
                                          o mercado dos tablets. Com a conferência da Apple “Let’s talk about IPhone”
                                          especulou-se sobre o possível anúncio da data de lançamento do IPhone 5. Com o
                               Editor     abandono da Nokia, especulou-se o que aconteceria ao sistema operativo Meego. E
                      António Santos
                                          muito mais se especula.
                                          Infelizmente a nossa sociedade vive presa às especulações, e creio que o melhor
                             Design       exemplo disso, nem está na área tecnológica, mas sim na área financeira com a
                       Sérgio Alves       crise em que vivemos ser altamente ampliada pelas especulações. Há uns anos
           Twitter: @scorpion_blood       atrás sempre que alguém queria dar um exemplo financeiramente forte sobre
                                          especulações falava sobre a famosa Quinta-feira negra, onde as acções de um dia
                                          tiveram efeitos nos anos seguintes e onde aconteceu a muitos acordar rico e
                          Redacção
                                          adormecer pobre. Todavia hoje não precisámos de dar um exemplo tão longínquo no
                       António Silva
                                          tempo e em que muitos não conhecem as verdadeiras consequências. Agora
                   Augusto Manzano
                       Bruno Lopes        podemos fala no presente.
                   Fernando Martins       Mas não precisámos de falar apenas na área financeira, podemos falar de qualquer
                           Rui Melo       área, inclusivamente a informática. Apesar de o IPhone 5 ainda não ter sido lançado,
                          Sara Silva      nem existirem provas de que alguma vez irá ver a luz do dia, a “publicidade” feita em
                      Sérgio Ribeiro
                                          torno dele, torna-o no alvo de curiosidade para o bem e para o mal. Chamar-lhe-ia
                        Vítor Tomaz
                                          publicidade gratuita. Se eu dissesse que era provável um canal de televisão
                                          deixasse de existir no dia x, estaria a especular. Provavelmente teria pouco reflexo
                                          na sociedade, uma vez que os próprios meios de comunicação social me dariam
                               Staff      pouco tempo de antena, ao invés destes assuntos sobre grandes empresas.
                     António Santos       Contudo estaria a distorcer o mercado, criando expectativa em volta de algo que eu
                      Fábio Canada        apenas defendia/acreditava, mas sem ter provas ou factos.
                    Fábio Domingos
                                          Numa área cujo nome deriva de Informação automática, a verdadeira informação
                      Jorge Paulino
                                          que é processada, comparativamente com o total de dados é cada vez menor. Cada
                      Pedro Martins
                                          vez mais recorremos a uma ferramenta que deveria armazenar e processar dados
                       Sara Santos
                                          gerando informação, contudo devido à falta de fidedignidade das fontes e
                          Contacto        contrariedade dos dados lá introduzidos é muitas vezes gerada desinformação. Se
      revistaprogramar@portugal-a-        eu disse-se que o mundo acabava hoje dentro de 5 minutos, mesmo que muita gente
                     programar.org        acredita-se em mim pouco podia fazer até verificar a veracidade dessa informação.
                                          Passados 5 minutos saberiam se era verdade ou não. Se eu disser que o mundo
                                          acaba em 21 de Dezembro de 2012 ainda se terá muito que esperar até se
                            Website       conseguir confirmar ou não a afirmação. Por isso não é informação, mas sim
   http://www.revista-programar.info      especulação. Especulação que faz vender, que mexe com os mercados, que coloca
                                          em muitos os nervos à flor da pele, que deixa outros com um sorriso de vitória, que
                                          impede o sono tranquilo de muitos, mas que não passa de uma simples afirmação,
                               ISSN       cuja veracidade não pode ser demonstrada na altura em que foi proferida.
                         1 647-071 0
                                          NR: Em notícia de última hora soube-se do falecimento de Steve Jobs. Para o bem
                                          e para o mal foi um nome incontornável no mundo da tecnologia, e que contribuiu
                                          para a sua evolução., por isso aqui ficam registadas as nossas condolências.



                                                                         António Silva <antonio.silva@revista-programar.info>


A revista PROGRAMAR é um projecto voluntário sem fins lucrativos. Todos os artigos são da responsabilidade dos autores, não
 podendo a revista ou a comunidade ser responsável por alguma imprecisão ou erro. Para qualquer dúvida ou esclarecimento
                                             poderá sempre contactar-nos.


                                                             2
ÍNDICE
TEMA DE CAPA
  7    Netponto - NHibernate - Técnicas para software melhor e mais rápido
       Saiba mais sobre estas técnicas para melhor software e mais rápido. Bruno Lopes


A PROGRAMAR
 17    Geração de Números Aleatórios
       O primeiro de 4 artigos do mesmo autor da excelente série “Programação em Lua”, desta vez sobre geração de núme-
       ros aleatórios. Augusto Manzano

 21    Programar para Windows Azure
       Conheça alguns detalhes bem como alguns cuidados que deveremos ter em conta quando desenvolvemos para esta
       plataforma. Vítor Tomaz

 25    Programação Orientada a Objectos em Java 6
       Saiba as melhores práticas e métodos de programação neste paradigma em Java 6. António Silva

 30    DataBinding em Silverlight 4
       Conheça o conceito de Databinding na plataforma Silverlight. Sara Silva




COLUNAS
 36    Visual (NOT) Basic - Primeiros Passos com GDI+
       Saiba mais sobre a API responsável por tudo o que nos “chega aos olhos” no mundo Windows. Sérgio Ribeiro

 43    Core Dump - Martelo <=> Inépcia
       Neste artigo de opinião, conheça segundo o autor, a origem das falhas nas bases de muitos profissionais de TI. Fer-
       nando Martins


COMUNIDADES
 45      SharePointPt—Padrão alternativo de Sharepoint
         Neste artigo da comunidade SharePointPT, saiba como desconstruir as abordagens mais tradicionais, através de uma
         solução pouco comum através de uma arquitectura que optimiza os módulos de maior interesse para o cenário apre-
         sentado. Rui Melo.




EVENTOS
  19 a 21 Out     Capsi 2011
  18 Out          Upload Lisboa
  28 Out          24ª Reunião Presencial NetPonto
  10 a 12 Nov     Sapo Codebits V
  02 Nov          SASIG 4


  Para mais informações/eventos: http://bit.ly/PAP_Eventos




                                                             3
NOTICIAS
O melhor amigo do Ipad é português                                   Apple pode continuar a limitar uso
e ecológico                                                          do Mac OS aos seus computadores
                                                                     A Apple tem o direito de restringir a utilização do sistema ope-
“Kork2 foi desenhado pela A Pro-
                                                                     rativo OS X aos computadores fabricados pela empresa. A
dukt e produzido em Paços de
                                                                     decisão do tribunal de recurso norte-americano foi conhecida
Brandão num material reciclado e
                                                                     esta semana, três anos depois de iniciada a batalha legal con-
reciclável.                                                          tra a Psystar, uma fabricante de "clones" dos produtos da
É o “canivete suíço” do Ipad e foi                                   maçã. A sentença anterior já havia dado razão à empresa de
                                                                     Steve Jobs, mas a Psystar - embora não tenha reclamado da
desenhado pela A Produkt,
                                                                     violação de direitos de autor de que foi acusada por copiar o
empresa sediada em Portugal
                                                                     hardware da Apple - interpôs recurso da decisão alegando
rendida aos encantos da cortiça.
                                                                     que as condições de licenciamento impostas para o Mac OS
O Kork2 – sucessor do Kork por direito – ajusta-se ao Ipad2,         constituíam uma tentativa ilegal para estender a proteção dos
protegendo-o e tornando a sua utilização ainda mais confortá-        direitos de autor a produtos que não podem beneficiar dela.
vel e dinâmica.

Simples, leve, ergonómico, recortado (pela 3DCork, de Paços          A Psystar alegou que ao limitar o uso do software da Apple
de Brandão) num material reciclado e reciclável. São estes           aos produtos fabricados pela marca, a empresa estava a
                                                                     recorrer indevidamente à proteção que a lei dispensa aos
alguns dos segredos que atraíram o Kork2 até às prateleiras
                                                                     direitos de autor para falsear a concorrência. Note-se que a
do MoMA de Nova Iorque e de Tóquio.
                                                                     fabricante de "sucedâneos" dos Mac tinha comprado cópias
Todos os pormenores são estudados ao milímetro por Michael           do Mac OS X para instalar nos computadores que vendia.
Andersen e Benedita Feijó, dupla que se lançou no mercado
Apple com o StickyStrap para o iPhone antes de colocarem o           A juíza considerou que a concorrente não tinha apresentado
iPad nas passarelas internacionais.                                  provas de que as condições de licenciamento do sistema ope-
                                                                     rativo fossem lesivas da concorrência ou criatividade.
“Fazemos um exercício de especulação porque os desenhos              Os termos das licenças do software da Apple "não restringem
da Apple estão normalmente fechados a sete chaves”, expli-           a possibilidade de os concorrentes desenvolverem o seu pró-
cou ao P3 Michael Andersen, ansioso pelos desenhos deta-             prio software, nem impede os clientes de usarem componen-
lhados do iPhone5 e do iPad3.                                        tes de outra marca em computadores Apple", entendeu a
                                                                     magistrada, citada pela Ars Technica.
“Vamos trabalhando com esses rumores até termos o objecto
nas mãos para avançarmos com os desenhos finais. Os mol-
                                                                     O que a Apple faz é restringir o uso de software da marca ao
des são feitos ao milímetro porque a cortiça é um material           seu próprio hardware e a Psystar, que produz os seus pró-
extremamente complicado de moldar”, prossegue um dos                 prios computadores, é livre de desenvolver software para
fundadores da A Produkt, responsável por “produtos originais”        eles, concluiu.
que, graças a “materiais portugueses”, fazem a “ponte entre a
tecnologia e a natureza”. A A Produkt não exclui uma futura          A decisão chega no culminar de um processo que teve início
aventura no mundo da cerâmica e da indústria têxtil.                 em Julho de 2008, quando a Apple pediu a condenação da
                                                                     Psystar por copiar os seus produtos. A sentença representa
Fonte: Público, texto de Luís Octávio Costa
                                                                     uma vitória importante para a fabricante do iPhone, que vê
                                                                     corroborada a "intocabilidade" do seu ecossistema e assegu-
                                                                     rado o direito a não disponibilizar o seu sistema operativo a
Windows 8 - Novo Explorador
                                                                     outras fabricantes.
Segundo o blog oficial da equipa de desenvolvimento do Win-
dows 8, o explorador do Windows à semelhança do Microsoft            Escrito ao abrigo do
Office, uma ribbon. Outra das novidades, é o facto deste pos-        novo Acordo
sibilitar a abertura de ficheiros iso e vhd sem necessidade de       Ortográfico
aplicações de terceiros.

                                                                     Fonte: Tek Sapo
Imagens do novo explorador neste site: http://bit.ly/rj8vjI
Blog oficial do Windows 8: http://blogs.msdn.com/b/b8/

Fonte: P@P




                                                                 4
NOTICIAS
Investigadores quebram criptografia                                     BerliOS será fechado em 31.12.2011
SSL
                                                                        O BerliOS foi fundado há 10 anos como um dos primeiros
Acesso a bancos portugueses e estrangeiros em risco                     depósitos na Europa. Foi desenvolvido e mantido por Frau-
A segurança perfeita é um mito…já dizia o ditado! Nos dias de           nhofer FOKUS. Como Europeu, o projecto não-proprietário
hoje, a segurança de muitos sites (especialmente de home-               BerliOS tinha como objective apoiar vários intervenientes e
banking, ou compras online) passa pelo uso do protocolo SSL             providenciar uma função de mediação neutra. Em 2011 cerca
(Secure Sockets Layer), que permite (permitia) a integridade e          de 4710 projectos foram alojados no BerliOS, com 50,000
confidencialidade dos dados que são passados entre o cliente            utilizadores registados e mais de 2.6 milhões de ficheiros des-
e o servidor. Segundo informações disponíveis no site The               carregados cada mês. Estamos orgulhosos de, com o Ber-
Register, os investigadores tailandeses Thai Duong e Juliano            liOS, termos trazido a ideia de um depósito OSS à Europa.
Rizzo conseguiram pela primeira vez, quebrar o, até agora               Entretanto, o conceito tem permanecido e existem muitas
inquebrável, protocolo SSL e assim decifrar a informação que            alternativas boas.
é passada ponto a ponto (entre o cliente e o servidor).
                                                                        Infelizmente, como instituto de pesquisa Fraunhofer FOKUS
A noticia é preocupante e alarmante mas a descoberta levada             tem apenas algumas oportunidades para operar um depósito
a cabo pelo grupo de investigadores apenas põe em causa a               como o BerliOS. Tal projecto apenas funcionará com um
segurança as versões 1.0 e anteriores do TLS (Transport                 financiamento de seguimento, ou com patrocinadores ou par-
Layer Security) – o sucessor do SSL. Até ao momento não há              ceiros que assumam o controlo do depósito. No campo de
qualquer informação sobre vulnerabilidades que afectem a                OSS é um empreendimento difícil. Num inquérito recente a
versão 1.1 ou 1.2 do TLS.                                               comunidade indicou algum apoio em fundos e mão-de-obra
                                                                        pelos quais gostaríamos de vos agradecer. Infelizmente, o
A demonstração de tal feito ocorrerá na conferência Eko-                resultado não é suficiente para colocar o projecto numa base
party , que se realizará em Buenos Aires no final desta sema-           financeira sustentável. Além disso, a procura de patrocinado-
na. Thai Duong e Juliano Rizzo irão apresentar o exploit que            res ou parceiros foi sem êxito.
usaram para conseguir derrubar o SSL e ao qual deram o
nome de BEAST. O exploit foi programado em JavaScript e                 O Open Source é entendido pela Fraunhofer FOKUS como
funciona como um snifer, tendo a capacidade de decifrar a               um paradigma para a futura utilização de inteligência orienta-
informação. Segundo os autores, o exploit funciona também               da da TI. Magoa-nos ainda mais o facto de sermos forçados a
em sites que usam HSTS (HTTP Strict Transport Security).                descontinuar o alojamento para BerliOS em 31/12/2011.
Duong referiu que a demo que irão apresentar na conferência             Como programador, deverá exportar o seu projecto BerliOS
Ekoparty, consistirá na decifragem de um cookie de autentica-           para outro depósito. Como alternativas ver:
ção, utilizado no serviço Paypal.                                       http://bit.ly/18Pp6N . No nosso site irão encontrar um guia em
                                                                        como retirar os dados dos vossos projectos do portal e migrá-
Mas o que é o SSL? SSL é um protocolo criptográfico basea-              los para uma plataforma diferente. Ver: http://bit.ly/qGJfAo .
do em cifras assimétricas que providencia segurança e integri-
dade dos dados transmitidos em redes como a Internet. Este              A Fraunhofer FOKUS tem um forte compromisso com o Open
protocolo ajuda a prevenir que entre as duas extremidades da            Source e interoperabilidade, e está envolvida em numerosos
comunicação não exista nenhum acesso indevido ou falsifi-               projectos OSS de sucesso. O instituto está focado no desen-
quem os dados transmitidos, ou seja, apenas o emissor e o               volvimento de padrões de qualidade para o software open
receptor podem ver a informação da mensagem transmitida.                source e em particular na inoperabilidade técnica, semântica e
Existem várias aplicações para este protocolo, como por                 organizacional entre componentes de software open source e
exemplo o comércio electrónico, servidores Web, servidores              software closed source. Exemplo das nossas actividade OSS
FTP, etc.Para identificar facilmente se estão a visualizar um           incluindo a nossa gestão do Centro de Competência Alemão
site seguro basta verificar no URL que em vez de estar o nor-           QualiPSo.
mal http:// se encontra https://. Para saber mais: http://bit.ly/
p1MV0Y                                                                  Agradecemos a todos terem utilizado o BerliOS ao longo dos
                                                                        anos.Fraunhofer FOKUS http://www.fokus.fraunhofer.de
Fonte: Sapo
                                                                        Fonte: www.berlios.de
                                                                        Tradução: Sara Santos




                                                                    5
TEMA DA CAPA
NHibernate - Técnicas para software melhor e mais rápido
TEMA DA CAPA
NHibernate - Técnicas para software melhor e mais rápido
No artigo da edição anterior abordamos os temas de configu-          foreach (var artigo in
ração de NHibernate, diferentes formas de mapear as entida-                session.QueryOver<Artigo>().List())
des e diferentes formas de obter os dados da base de dados           {
no contexto do seguinte domínio:                                       var autores = artigo.Autores.Select(a =>
                                                                                      a.Nome);

public class Edicao                                                      Console.Out.WriteLine(
{                                                                               "Artigo {0} com autores {1}",
  public virtual DateTime DataEdicao {get; set; }                               artigo.Titulo,
  public virtual Artigo TemaDeCapa { get; set; }                                string.Join(", ", autores.ToArray()));
  public virtual IList<Artigo> Artigos {get;set;}
}                                                                    }


public class Artigo
{
  public virtual int Id { get; set; }                                Neste caso, estamos a mostrar o título de um artigo em con-
  public virtual string Titulo { get; set; }
  public virtual ISet<Autor> Autores {get;set; }                     junto com os autores. Se olharmos para o SQL gerado
}                                                                    vemos que por cada artigo vamos à base de dados buscar
                                                                     os autores:
public class Autor
{
  public virtual int Id { get; set; }
  public virtual string Nome { get; set; }
  public virtual string Email { get; set; }
  public virtual ISet<Artigo> Artigos {get;set; }
}


Neste artigo vamos ver como podemos aproveitar algumas
                                                                     Este comportamento é resultante das capacidades de lazy-
das funcionalidades mais avançadas do NHibernate para                loading da biblioteca em conjunto com as configurações por
tornar as nossas aplicações mais eficientes, reduzindo o             omissão que carregam os objectos de cada relação apenas
número de pedidos à base de dados assim como a quantida-             quando esta é acedida.
de de dados que são transmitidos. Em certos momentos
iremos usar a ferramenta NHProf para observar a comunica-            Tal comportamento implica que vão ser efectuados no míni-
                                                                     mo tantos queries quanto artigos mostrarmos. Qualquer
ção entre a nossa aplicação e a base de dados.
                                                                     latência no acesso ao servidor de sql aumenta significativa-
                                                                     mente o tempo de resposta da nossa aplicação, quando na
Performance                                                          realidade seria possível minimizar as chamadas à base de
                                                                     dados e obter todos os dados de uma só vez.
Uma das falácias de computação distribuída é de que latên-
cia é zero. Na realidade, qualquer chamada a um sistema              Select N+1
remoto é ordens de magnitude mais lenta do que a mesma
chamada a um sistema local e dentro do mesmo processo.               A esta classe de problemas dá-se o nome de “Select N+1”,
Outra falácia é de que a largura de banda é infinita. Como tal       em virtude de ser efectuada uma chamada à base de dados
                                                                     para obter a lista de objectos raiz, e posteriormente N cha-
é boa prática reduzir o número de chamadas remotas ao
                                                                     madas para obter os objectos relacionados de cada raiz. É
servidor de dados e o tamanho dos dados a receber e enviar           uma fonte típica de problemas de performance, e em quase
se queremos ter aplicações com boa performance mesmo                 todos os casos pode ser resolvida com um carregamento
quando em carga.                                                     mais inteligente dos dados.

Como reduzir o número de chamadas                                    Eager-Loading
Um dos casos típicos onde fazemos mais chamadas à base               Embora a intuição seja de que o oposto de lazy-loading seja
de dados do que o necessário é quando mostramos uma                  eager-loading, na realidade existem várias formas de fazer
listagem de itens que necessita de dados de mais do que              eager-loading de dados, pelo que devem ser usadas em
uma tabela:                                                          circunstâncias diferentes.




                                                                 7
TEMA DA CAPA
NHibernate - Técnicas para software melhor e mais rápido
É possível configurar este comportamento a nível dos
                                                                      Para carregar os dados dos Artigos sempre que uma edição
mapeamentos globais ou durante um query à base de                     é carregada, usamos a seguinte configuração:
dados. Quando é configurado no mapeamento pode ser feito
a uma classe ou a uma relação. Quando é feito durante o               public class EdicaoOverride : IAutoMappingOverri-
query é sempre respectivo a uma relação.                              de<Edicao>
                                                                      {
Quando uma classe é indicada como não lazy-loaded, qual-                public void Override(AutoMapping<Edicao>mapping)
quer instância da mesma criada pelo NHibernate deixará de                  {
ser uma proxy.                                                                 mapping.HasMany(e => e.Artigos)
                                                                                   .Not.LazyLoad();
A implicação é de que qualquer relação que seja de um para                 }
um ou de muitos para um com uma classe que não possa                  }
ser lazy-loaded terá de ser logo concretizada.

Considerando que queremos que a classe Artigo não seja
                                                                      Neste caso estamos a indicar que quando uma Edicao é
lazy-loaded:
                                                                      carregada, os Artigos também o são. A forma de carregar
                                                                      os dados varia entre três opções: select (comportamento por
public class ArtigoOverride : IAutoMappingOverri-
                                                                      omissão), subselect e join.
de<Artigo>
{                                                                     Quando é usado o select, por cada entidade com a relação é
  public void Override(AutoMapping<Artigo>mapping)                    efectuado um select à base de dados. Este é o comporta-
     {
                                                                      mento que existe por omissão e quer dizer que continuamos
         mapping.Not.LazyLoad();
     }                                                                com um problema de Select N+1:
}                                                                     Quando é usado o subselect, por cada query ou entidade
Quando carregamos uma Edicao (que tem uma colecção de                 obtida da base de dados é efectuado outro query que obtém
artigos e um tema de capa):                                           os dados necessários para popular as relações. Este com-
                                                                      portamento é interessante nas relações de muitos para mui-
var edicao = session.Get<Edicao>(dataEdicao);                         tos, como a entre Artigos e Autores. Se nós tivermos o
                                                                      seguinte query:

O sql gerado inclui já o join necessário para carregar o tema
de capa:                                                              Foreach (
                                                                         var artigo in session.QueryOver<Artigo>()
SELECT                                                                     .Where(a => a.Id < idQuartoArtigo).List())
      edicao0_.DataEdicao    as DataEdicao3_1_,
      edicao0_.TemaDeCapa_id as TemaDeCapa2_3_1_,                     {
      artigo1_.Id            as Id0_0_,                                   var autores = artigo.Autores.Select(a =>
      artigo1_.Titulo        as Titulo0_0_                                              a.Nome);
FROM [Edicao] edicao0_
       left outer join [Artigo] artigo1_
         on edicao0_.TemaDeCapa_id = artigo1_.Id                          Console.Out.WriteLine(
WHERE                                                                           "Artigo {0} com autores {1}",
   edicao0_.DataEdicao = '2011-07-01T00:00:00.00'                               artigo.Titulo,
                                                                                string.Join(", ", autores.ToArray()));
                                                                      }
Há aqui dois comportamentos que são necessário distinguir:
o da relação de muitos para um (TemaDeCapa) e o da rela-
ção de um para muitos (Artigos).                                      Os queries gerados por omissão são 4:
Como é a classe Artigo que deixa de ser lazy-loaded, quan-
do o NHibernate faz um query a partir da Edicao repara que
não vai poder criar a proxy para o TemaDeCapa, e cria o sql
necessário para carregar os dados do Artigo corresponden-
te.

No caso dos Artigos não surge esse problema porque não
necessita de criar as instâncias imediatamente, apenas uma            Um para obter os artigos, e um por cada artigo.
lista que as vai guardar. Até iterarmos por esta lista não pre-
cisamos de construir as respectivas instâncias de Artigos.




                                                                  8
TEMA DA CAPA
                                           NHibernate - Técnicas para software melhor e mais rápido
No entanto, se configurarmos a relação com um fetch por               SELECT TOP ( 2 /* @p0 */ )
subselect passamos a ter apenas dois queries:                               this_.DataEdicao    as DataEdicao3_1_,
                                                                            this_.TemaDeCapa_id as TemaDeCapa2_3_1_,
                                                                            artigos2_.Edicao_id as Edicao3_3_,
                                                                            artigos2_.Id         as Id3_,
                                                                            artigos2_.Id        as Id0_0_,
                                                                            artigos2_.Titulo     as Titulo0_0_
                                                                      FROM [Edicao] this_
                                                                             left outer join [Artigo] artigos2_
Neste caso o select que popula os autores é filtrado pelo                     on this_.DataEdicao = artigos2_.Edicao_id
primeiro query através de um subselect:

SELECT autores0_.Artigo_id as Artigo4_1_,
       autores0_.Id        as Id1_,                               Neste caso como é feito o carregamento imediato dos artigos
       autores0_.Id        as Id1_0_,                             através de um join, vamos ter edições repetidas quando uma
       autores0_.Nome      as Nome1_0_,                           edição tem mais que um artigo. Como tal, esta opção não é
       autores0_.Email     as Email1_0_
FROM   [Autor] autores0_                                          aconselhada na maioria dos casos, sendo preferível configu-
WHERE autores0_.Artigo_id in                                      rar o carregamento de dados por query em vez de forma
        (SELECT this_.Id                                          geral.
         FROM [Artigo] this_
         WHERE this_.Id < 1922 /* @p0 */)
                                                                  Configurado por relação no mapeamento tem também a des-
                                                                  vantagem de carregar os dados mesmo que não sejam usa-
                                                                  dos. Como tal, estas soluções são pouco flexíveis, visto
Reduz o número de queries efectuadas á base de dados, no
                                                                  assumirem que se pretende sempre os mesmos dados rela-
entanto necessita que a base de dados suporte este meca-
                                                                  cionados com as entidades em todos os casos de uso.
nismo.
                                                                  Para maior flexibilidade a solução acaba por passar por indi-
Quando é usado o join, como o nome indica, os dados da
                                                                  car no query quais as colecções que se pretende carregar
colecção são obtidos ao mesmo tempo que as entidades
                                                                  imediatamente:
através de um join. Para o código mencionado anteriormente
passamos a ter apenas um query:                                   foreach (var artigo in session.QueryOver<Artigo>
                                                                  ().Fetch(a => a.Autores).Eager.List())
SELECT this_.Id            as Id0_1_,                             {
       this_.Titulo        as Titulo0_1_,                              Console.Out.WriteLine(
       autores2_.Artigo_id as Artigo4_3_,                                "Artigo {0} com autores {1}",
       autores2_.Id        as Id3_,                                      artigo.Titulo,
       autores2_.Id        as Id1_0_,
       autores2_.Nome      as Nome1_0_,                                  string.Join(", ",
       autores2_.Email     as Email1_0_                                            artigo.Autores.Select(
FROM   [Artigo] this_                                                              a => a.Nome).ToArray()));
       left outer join [Autor] autores2_                          }
         on this_.Id = autores2_.Artigo_id
WHERE this_.Id < 2225 /* @p0 */
                                                                  Aqui estamos a indicar que queremos carregar a colecção
                                                                  Autores do Artigo juntamente com o artigo. O sql gerado usa
É necessário ter em atenção a forma como se usa estas
                                                                  joins para obter os dados das entidades relacionadas:
funcionalidades gerais de eager-loading. Por exemplo, ao
configurar a colecção de Artigos de uma Edicao para ser
                                                                      SELECT this_.Id            as Id0_1_,
automaticamente obtida por join, o seguinte código pode ter                  this_.Titulo        as Titulo0_1_,
um resultado inesperado:                                                     autores2_.Artigo_id as Artigo4_3_,
                                                                             autores2_.Id        as Id3_,
foreach (var edicao in session.QueryOver<Edicao>                             autores2_.Id        as Id1_0_,
().Take(2).List())                                                           autores2_.Nome      as Nome1_0_,
{                                                                            autores2_.Email     as Email1_0_
                                                                      FROM   [Artigo] this_
        Console.Out.WriteLine("Edicao {0} ",                                 left outer join [Autor] autores2_
                          edicao.DataEdicao);                                  on this_.Id = autores2_.Artigo_id
}

À primeira vista deveríamos obter duas edições distintas. E
em muitos casos é isso que temos. No entanto ocasional-
                                                                  Se olharmos para os métodos Get e Load, não temos nenhu-
mente encontramos edições duplicadas, e ao olharmos para
                                                                  ma forma de configurar eager-loading nesses casos.
o sql gerado vemos qual o problema:




                                                              9
TEMA DA CAPA
NHibernate - Técnicas para software melhor e mais rápido
Como tal, a forma de o fazer é com uma query por id, confi-         BatchSize é o número de instâncias de uma relação que são
gurando ai que relações é que pretendemos carregar logo:            carregadas em simultâneo em vez de separadas. Configura-
                                                                    do desta forma, o seguinte código:
foreach (var artigo in session.QueryOver<Artigo>
()
    .Where(a => a.Id == idTerceiroArtigo)                           foreach (var artigo in session.QueryOver<Artigo>
    .Fetch(a => a.Autores).Eager.List())                            ().List())
{                                                                   {
                                                                       var autores = artigo.Autores.Select(
    var autores = artigo.Autores.Select(                                                               a => a.Nome);
                       a => a.Nome).ToArray();
    Console.Out.WriteLine(                                              Console.Out.WriteLine(
        "Artigo {0} com autores {1}",                                          "Artigo {0} com autores {1}",
        artigo.Titulo,                                                         artigo.Titulo,
        string.Join(", ", autores));                                           string.Join(", ", autores.ToArray()));
}                                                                   }
Neste caso também podemos vir a ter o problema de entida-
des duplicadas. No entanto como o carregamento é feito por          Passa de :
query, podemos fazer o tuning em cada caso de uso, de
acordo com as necessidades reais.

Mais à frente neste artigo vamos ver uma forma mais correc-
ta e menos dada a erros de resolver este problema, fazendo
o carregamento de dados de forma fácil e rápida.

Batch fetching
                                                                    Para:
Outra forma de reduzir o número de vezes que efectuamos
chamadas à base de dados é configurar relações com batch-
fetching. Esta é uma configuração que apenas pode ser feita
no mapeamento, por oposição a eager-loading que também
pode ser feita por query.

Nestes casos, quando NHibernate detecta um acesso à
colecção, ele procura mais entidades dentro da mesma ses-           Como podemos ver, em vez de uma chamada para obter o
são que tenham essa relação e carrega os dados em conjun-           artigo e uma para cada autor, apenas fazemos uma chama-
tos de N, reduzindo o número de chamadas à base de                  da para obter o artigo, e outra para carregar os autores em
dados. É uma forma simples de melhorar performance, em              batch.
particular se o tamanho dos conjuntos for similar ao tamanho
das páginas de dados que apresentamos ao utilizador caso
em que reduzimos significativamente o número de queries:
                                                                    Futures
uma para obter as entidades raiz, e uma por cada colecção
que acedemos.                                                       Existe também o caso em que se pretende obter vários
                                                                    dados que não estão relacionados entre si. Este caso acon-
Para tal, usando FluentNHibernate, apenas precisamos de
                                                                    tece frequentemente quando uma página ou ecrã mostra
declarar um override para a entidade e indicar que a relação
                                                                    dados provenientes de várias tabelas ou componentes do
tem um BatchSize do tamanho que pretendemos.
                                                                    software, como um ecrã de resumo, ou uma caixa de infor-
                                                                    mação geral da aplicação.
public class ArtigoOverride : IAutoMappingOverri-
de<Artigo>                                                          Se quisermos mostrar numa página um índice de edições
{
                                                                    com número de artigos em cada uma, um índice com os
public void Override(AutoMapping<Artigo> mapping)
    {                                                               artigos da edição actual e um artigo em destaque com auto-
       mapping.HasMany(a => a.Autores)                              res, a solução mais directa passa por fazer três queries
            .BatchSize(10);                                         separados, resultando em três round-trips á base de dados:
    }
}




                                                               10
TEMA DA CAPA
                                           NHibernate - Técnicas para software melhor e mais rápido
var edicoes = session.QueryOver<Edicao>()                          var edicoes = session.QueryOver<Edicao>()
    .List();                                                           .Future();
var edicaoComArtigos = session                                     var edicaoComArtigos = session
    .QueryOver<Edicao>()                                               .QueryOver<Edicao>()
    .Fetch(e => e.Artigos).Eager                                       .Fetch(e => e.Artigos).Eager
    .WithSubquery.WhereProperty(e =>                                   .WithSubquery.WhereProperty(e =>
            e.DataEdicao)                                                      e.DataEdicao)
    .In(QueryOver.Of<Edicao>()                                         .In(QueryOver.Of<Edicao>()
            .Select(e => e.DataEdicao)                                         .Select(e => e.DataEdicao)
            .OrderBy(e =>                                                      .OrderBy(e => e.DataEdicao)
                  e.DataEdicao).Desc.Take(1))                                        .Desc.Take(1))
    .SingleOrDefault();                                                .FutureValue();
var artigoComAutor = session.QueryOver<Artigo>()                   var artigoComAutor = session.QueryOver<Artigo>()
    .Where(a => a.Id == idTerceiroArtigo)                              .Where(a => a.Id == idTerceiroArtigo)
    .Fetch(a => a.Autores).Eager                                       .Fetch(a => a.Autores).Eager
    .SingleOrDefault();                                                .FutureValue<Artigo>();
foreach (var edicao in edicoes)                                    foreach (var edicao in edicoes)
{                                                                  {
    Console.Out.WriteLine(                                             Console.Out.WriteLine(
           "Edicao {0} ",                                                      "Edicao {0} ",
           edicao.DataEdicao);                                                 edicao.DataEdicao);
}                                                                  }
var artigos = edicaoComArtigos.Artigos.Select(a                    var artigos = edicaoComArtigos.Value
=> a.Titulo).ToArray();                                                             .Artigos.Select(a => a.Titulo)
                                                                                    .ToArray();
Console.Out.WriteLine(
     "Edicao {0} - Artigos {1}",                                   Console.Out.WriteLine(
      edicaoComArtigos.DataEdicao,                                             "Edicao {0} - Artigos {1}",
      string.Join(", ", artigos));                                             edicaoComArtigos.Value.DataEdicao,
                                                                               string.Join(", ", artigos));
var autores = artigoComAutor.Autores.Select(a =>
a.Nome).ToArray();                                                 var autores = artigoComAutor.Value.Autores.Select
                                                                   (a => a.Nome).ToArray();
Console.Out.WriteLine(
     "Artigo {0} com autores {1}",                                 Console.Out.WriteLine(
      artigoComAutor.Titulo,                                                   "Artigo {0} com autores {1}",
      string.Join(", ", autores));                                             artigoComAutor.Value.Titulo,
                                                                               string.Join(", ", autores));
Usando a ferramenta NHProf para ver os pedidos que são
feitos à base de dados, vemos que são feitos 3 pedidos dis-
tintos:

                                                                        Desta forma, pode-
                                                                        mos preparar todos
Na realidade podemos diferir a definição das operações de
acesso a dados da sua execução. Podemos ter assim uma                os queries e de uma só
fase de preparação, onde se criam os queries que se preten-
dem fazer, e uma segunda fase onde se mostram os resulta-            vez fazer todos os pedi-
dos.

Desta forma, podemos preparar todos os queries e de uma
                                                                     dos à base de dados.
só vez fazer todos os pedidos à base de dados.

É este comportamento que os Futures nos permitem. A alte-
ração ao código é mínima. Usamos Futures em vez de List,           Enquanto os queries anteriores retornavam logo uma lista, o
e FutureValue em vez de SingleOrDefault:                           resultado de um Future ou de um FutureValue é apenas a
                                                                   promessa de que no futuro quando precisarmos dos dados
                                                                   eles estarão lá.




                                                              11
TEMA DA CAPA
NHibernate - Técnicas para software melhor e mais rápido
O que o NHibernate faz é registar internamente todos os
                                                                        Fazemos o eager-loading de todas as relações, resul-
Futures pedidos. Assim que um é concretizado (quer por
                                                                        tando num query com um número elevado de joins:
iterar sobre um IEnumerable de um Future, quer por aceder
ao valor de um FutureValue), são enviados todos os queries
                                                                        Usamos Futures para carregar em queries diferentes
registados para a base de dados e obtidos os resultados de
                                                                        relações diferentes da mesma entidade.
uma só vez.
                                                                  A terceira opção acaba por ser a que obtém tipicamente
O sql gerado é exactamente o mesmo, mas foi todo enviado
                                                                  melhores resultados e é concretizada da seguinte forma:
na mesma chamada, minimizando assim os problemas de
latência no acesso aos dados.
                                                                   var edicao = session.QueryOver<Edicao>()
                                                                       .Where(e => e.DataEdicao == dataEdicao)
Vemos então que em vez de três chamadas distintas faze-                .Fetch(e => e.Artigos).Eager.FutureValue();
mos apenas uma chamada que retorna três conjuntos de
resultados diferentes:                                             session.QueryOver<Edicao>()
                                                                       .Where(e => e.DataEdicao == dataEdicao)
                                                                       .Fetch(e => e.Patrocinadores)
                                                                          .Eager.FutureValue();
                                                                   var artigos = edicao.Value
                                                                         .Artigos.Select(a => a.Titulo).ToArray();
De reparar que por omissão o Future assume que se retorna
uma lista de entidades sobre as quais estamos a fazer o            Console.Out.WriteLine(
QueryOver, e o FutureValue assume que se retorna uma                     "Edicao {0} - Artigos {1}",
                                                                         edicao.Value.DataEdicao,
entidade. Como vamos ver mais à frente com projecções,                   string.Join(", ", artigos));
também é possível obter instâncias que não as indicadas
inicialmente como argumento de tipo ao QueryOver.                  var patrocinadores = edicao.Value
                                                                         .Patrocinadores.Select(a => a.Nome)
                                                                         .ToArray();
Esta funcionalidade tem a grande vantagem de poder reduzir
grandemente o número de chamadas à base de dados com               Console.Out.WriteLine(
alterações mínimas ao código.                                            "Artigo {0} com autores {1}",
                                                                         edicao.Value.DataEdicao,
                                                                         string.Join(", ", patrocinadores));
Outro caso de uso prende-se com o carregamento de várias
relações da mesma entidade.

Assumindo que a classe Edicao passa a ser a seguinte:             Saliente-se que usamos apenas o valor do primeiro QueryO-
                                                                  ver. O segundo é apenas usado para carregar os dados da
public class Edicao                                               colecção de forma indirecta.
{
  public virtual DateTime DataEdicao {get;set;}
  public virtual Artigo TemaDeCapa {get;set; }                    Isto é possível uma vez que o NHibernate implementa um
  public virtual IList<Artigo> Artigos{get;set;}                  identity map dentro da sessão. Quando acedemos ao valor
  public virtual IList<Patrocinador>                              do primeiro Future despoletamos todos os Futures regista-
                    Patrocinadores { get; set; }
}                                                                 dos até ao momento na sessão. Ao concretizar os objectos
                                                                  resultantes do segundo query, o NHibernate encontra a enti-
                                                                  dade já na sessão e preenche a colecção que foi carregada
public class Patrocinador
{                                                                 com os dados desse query, que incluem a relação Patrocina-
    public virtual int Id { get; set; }                           dores.
    public virtual string Nome { get; set; }
}                                                                 Desta forma conseguimos popular as relações necessárias
                                                                  apenas com uma chamada à base de dados e um conjunto
                                                                  pequeno de queries com apenas um join cada um:

Se nós pretendemos mostrar uma edição com todos os arti-
gos e todos os patrocinadores, temos várias hipóteses:

      Aproveitamos o lazy-loading e fazemos vários pedi-
      dos à base de dados:




                                                             12
TEMA DA CAPA
                                           NHibernate - Técnicas para software melhor e mais rápido
Como reduzir o tamanho de cada chamada                            Neste caso estamos a seleccionar o identificador da edição
                                                                  mais recente, e obter o numero de artigos dessa edição.
Até agora trabalhamos com as entidades completas. No
entanto existem muitas operações ou casos de uso que              Viewmodels
necessitam apenas de parte das entidades ou de dados
agregados. Ir buscar todos os artigos de uma edição quando        O segundo caso de uso que exemplifico para projecções
apenas pretendemos uma contagem de artigos da edição é            prende-se com situações onde temos uma ou varias entida-
improdutivo quando podemos fazer esses cálculos directa-          des com um número grande de campos e onde necessita-
mente na base de dados e obter apenas os dados que preci-         mos apenas de parte dos campos, ou de dados agregados
samos. Para este efeito usamos projecções em conjunto             em conjunto com alguns campos.
com transformadores.
                                                                  Da mesma forma que projectamos um valor de um resultado
Count, Max, Aggregate                                             de um query podemos também projectar uma lista de valo-
                                                                  res:
Os casos mais simples são aqueles em que pretendemos
obter um valor resultante de uma query:                           IList<Artigo> artigos = null;
                                                                  var edicoes = session.QueryOver<Edicao>()
var edicaoMaisAntiga = session.QueryOver<Edicao>                        .JoinQueryOver(
().Select(Projections                                                         e => e.Artigos,
      .Min<Edicao>(e => e.DataEdicao))                                        () => artigos,
      .SingleOrDefault<DateTime>();                                           JoinType.LeftOuterJoin)
                                                                        .SelectList(
                                                                              q => q.SelectGroup(e =>e.DataEdicao)
                                                                        .SelectCount(e => e.Artigos)
                                                                      )
Neste caso estamos a procurar o valor mínimo de todas as              .List<object[]>();
datas de edição. Como este query devolve um valor do tipo
DateTime, precisamos de indicar isso através do argumento         foreach (var edicao in edicoes)
                                                                  {
de tipo do método SingleOrDefault.                                    Console.Out.WriteLine(
                                                                             "Edicao {0} com {1} artigos",
É claro que podemos usar um Future para os casos em que                      edicao[0],
                                                                             edicao[1]);
pretendemos obter vários valores sem ter a penalização de         }
várias chamadas à base de dados:

var edicaoMaisRecente = session.QueryOver<Edicao>
                                                                  Neste caso estamos a projectar a data de edição e o número
().Select(Projections
      .Max<Edicao>(e => e.DataEdicao))                            de artigos que aparecem para cada edição. O sql gerado
      .FutureValue<DateTime>();                                   não tem surpresas:

                                                                  SELECT   this_.DataEdicao        as y0_,
                                                                           count(this_.DataEdicao) as y1_
Outra situação onde projecções são úteis é em subqueries,         FROM     [Edicao] this_
onde podemos projectar um valor para usar numa condição:                   inner join [Artigo] artigos1_
                                                                             on this_.DataEdicao = arti-
                                                                  gos1_.Edicao_id
Artigo artigo = null;                                             GROUP BY this_.DataEdicao

var numeroArtigosEdicaoMaisRecente = session
     .QueryOver<Edicao>()
     .WithSubquery
     .WhereProperty(e => e.DataEdicao)                            No entanto o acesso aos dados projectados torna-se propí-
     .In(QueryOver.Of<Edicao>()                                   cio a erros, visto retornar uma lista de vectores de objectos.
        .Select(e => e.DataEdicao)
        .OrderBy(e => e.DataEdicao).Desc.Take(1))                 Seria muito mais fácil se pudéssemos usar uma classe inter-
    .JoinQueryOver(e => e.Artigos, () => artigo)                  média que armazenasse os campos obtidos. E tal é possível
    .SelectList(q =>                                              recorrendo a aliases e a um ResultTransformer.
            q.SelectCount(() => artigo.Id))
    .FutureValue<int>();




                                                             13
TEMA DA CAPA
NHibernate - Técnicas para software melhor e mais rápido
Com a seguinte classe:                                                Utilizamos expressões para indicar os nomes dos campos,
                                                                      sendo que na realidade o que o NHibernate faz é apenas
public class EdicaoComNumeroArtigos                                   associar nomes dos campos à projecção. Depois o transfor-
{
  public virtual DateTime DataEdicao {get;set;}                       mador AliasToBean é que tem o trabalho de para cada cam-
  public virtual int NumeroArtigos {get;set;}                         po retornado do query procurar uma propriedade com um
}                                                                     setter público e colocar o valor do campo nessa propriedade.
                                                                      Isto quer dizer que é possível indicar nomes inválidos ou ter
                                                                      outros problemas semelhantes nos queries, no entanto são
Podemos alterar o query anterior para associar um alias a             erros facilmente detectados com testes de integração que
cada um dos campos e transformar os resultados em instân-             correm o query, visto o NHibernate identificar logo as irregu-
cias da classe EdicaoComNumeroArtigos:                                laridades.


IList<Artigo> artigos = null;
EdicaoComNumeroArtigos viewModel = null;                              Conclusão
var edicoes = session.QueryOver<Edicao>()                             Neste artigo analisamos algumas opções e funcionalidades
    .JoinQueryOver(
            e => e.Artigos,                                           que nos permitem melhorar as características de performan-
            () => artigos,                                            ce das nossas aplicações, quer por um carregamento mais
            JoinType.LeftOuterJoin)                                   inteligente dos dados, como pela redução do tamanho de
    .SelectList(q => q.SelectGroup(
            e => e.DataEdicao)                                        dados que é transferido da base de dados para a aplicação.
            .WithAlias(() => viewModel.DataEdicao)
            .SelectCount(e => e.Artigos).WithAlias                    Existem ainda algumas funcionalidades que não foram men-
            (() => viewModel.NumeroArtigos)                           cionadas, como interceptores, filtros, cache de segundo nível
    )
    .TransformUsing                                                   e concorrência optimista.
(Transformers.AliasToBean<EdicaoComNumeroArtigos>
())
    .List<EdicaoComNumeroArtigos>();
                                                                      Ver artigo Revista PROGRAMAR - edição 30 de Agosto
foreach (var edicao in edicoes)                                       2011: NHibernate - do Import Package à primeira iteração
{
    Console.Out.WriteLine(
            "Edicao {0} com {1} artigos",
            edicao.DataEdicao,
            edicao.NumeroArtigos);
}




AUTOR
               Bruno Lopes fez o curso de Engenharia Informática no IST, e neste momento conta com mais de 5 anos de experiência pro-
               fissional em IT, em particular nas áreas de desenvolvimento de software web-based. Actualmente é co-fundador da weListen
               Business Solutions, trabalhando no produto InnovationCast, e participa activamente na comunidade NetPonto, apresentando
               temas como NHibernate, RavenDB ou IoC.

               Tem blog em http://blog.brunomlopes.com, twitter em @brunomlopes e linkedin em http://pt.linkedin.com/in/brunomlopes




                                                                 14
Elege o melhor artigo desta edição
       Revista PROGRAMAR
       http://tiny.cc/ProgramarED31_V
A PROGRAMAR
Geração de números aleatórios (Parte 1)
Diferenças ao Desenvolver em Windows Azure
Programação Orientada a Objectos em Java 6
DataBinding em Silverlight 4
A PROGRAMAR
GNA - GERAÇÃO DE NÚMEROS ALEATÓRIOS (Parte 1)
A partir deste artigo, serão apresentadas em quatro partes,       vários tipos de aplicação, destacando-se algumas, como as
informações sobre a geração de números aleatórios ou              apontadas por Doricio (1998) e Zenil (2011):
random number generator em computadores.
                                                                        simulação – aplicação de modelos científicos na
São muitos os métodos existentes para a geração de                      simulação de fenómenos naturais;
números aleatórios. Podendo-se destacar: o método do meio
do quadrado (tema deste artigo), o método produto do meio,              amostragem – aplicação de modelos científicos
o randu e o método linear congruente.                                   baseados numa parte menor de um todo maior, que
                                                                        será analisada;
INTRODUÇÃO
                                                                        análise numérica – aplicação de modelos
As discussões sobre geração de números aleatórios                       determinísticos numéricos para a economia de tempo
originam-se a partir das ideias dos filósofos gregos                    de computação;
Demókritos e Epikurus, indicado por Silveira (2001) ao
mostrar as propostas de:                                                programação de computadores – aplicação de
                                                                        valores aleatórios para testes de eficiência algorítmica
aleatoriedade objetiva, proposta por Epikurus, que afirma
                                                                        computacional;
    existir na Natureza o aleatório verdadeiro, o qual ocorre
    a partir do desconhecimento das causas;                             teoria de decisão – auxiliar a tomada de decisão com
                                                                        base na escolha aleatória de dados;
aleatoriedade subjetiva, proposta por Demókritos, que
    afirma ser a Natureza determinista, onde tudo ocorre                recreação – aplicação em jogos de azar.
    devido a uma causa.
                                                                  A geração de números pseudo-aleatórios depende da
Para Doricio (1998) “não existe o que se possa chamar de
                                                                  escolha adequada dos parâmetros usados para a geração
número aleatório”, o que corrobora com a afirmação indicada
                                                                  do número em si. Um desses parâmetros, que merece
por Schildt (1990), ao dizer que “o termo geração de
                                                                  atenção, é o chamado “semente” (DIAS, 2005), o qual é
números aleatórios é um absurdo”.
                                                                  caracterizado por ser o valor inicial a ser usado para a
                                                                  geração dos demais valores “aleatórios” subsequentes por
Apesar da concordância, ou não, sobre este tema, os
computadores eletrónicos de alguma forma produzem                 meio de algum algoritmo específico para esta finalidade.
                                                                  Segundo Dias (2005) a escolha da semente deve ser
sequências de valores numéricos, chamados “números
aleatórios”, a partir de duas abordagens:                         realizada com muito cuidado, pois “a utilização de uma
                                                                  mesma semente […] entre diferentes aplicações […] pode
       geração de números pseudo-aleatórios (PRNG –               ocasionar erros bastante comuns que levam a conclusões
                                                                  que podem representar de forma incorreta o comportamento
       Pseudo-Random Number Genarator);
                                                                  dessas aplicações”.
       geração de números verdadeiramente aleatórios
       (TRNG – True Ramdom Number Generator).                     Para a geração de números pseudo-aleatórios existe de um
                                                                  grande conjunto de algoritmos. Neste estudo, em particular é
O mecanismo PRNG é a forma mais comum encontrada nos              apresentado o método do meio do quadrado.
computadores eletrónicos. A palavra “pseudo” sugere, neste
contexto, o uso de valores numéricos que não são gerados          MÉTODO DO MEIO DO QUADRADO
de forma aleatória, uma vez que são obtidos por meios
                                                                  A geração de números pseudo-aleatórios a partir do método
artificiais a partir de algoritmos matemáticos elaborados para
                                                                  do meio do quadrado (middle square method) foi propostao
esta finalidade.
                                                                  em 1946 por John von Neumann, sendo este algoritmo
                                                                  considerado o primeiro método de geração de números
O mecanismo TRNG não é comum ou de fácil acesso (os
                                                                  “aleatórios”
equipamentos para esta finalidade são muito caros para
utilizadores menos científicos), uma vez que os valores           (GIORDANO, FOX, WEIR, 2009 – p.184; TÖRN, 2001).
chamados aleatórios são obtidos a partir de fenómenos
oriundos da natureza, como: ruídos ambientais, alterações         No método do meio do quadrado, foi proposto por Von
climáticas, entre outros fenómenos. A geração de números          Neumann, o uso de um valor semente que, elevado ao
aleatórios, sejam PRNG ou TRNG, é são necessárias em              quadrado, gera um resultado. Desse resultado é retirado do




                                                             17
A PROGRAMAR
GNA - GERAÇÃO DE NÚMEROS ALEATÓRIOS (Parte 1)
meio um número com o mesmo tamanho em dígitos, do valor            t = tamanho em dígitos do quadrado de N: t = tamanho(N2).
usado para a semente. A partir do novo valor repete-se a
                                                                   tqd = tamanho em dígitos do quadrado de N, sua obtenção
operação para a obtenção de um novo valor e assim por
                                                                   depende de algumas condições.
diante (TÖRN, 2001; WHELAN, 2011; STUBBE, 2011).
Apesar de engenhoso, o método apresenta algumas falhas.            SE ((d é par) .E. (t é impar))
Segundo Knuth (KNUTH, 1969 – p. 4), várias pessoas
                                                                          .OU.
fizeram uso do método do meio do quadrado no início da
década de 1950 tendo sido utilizadas sementes com                        ((d é impor) .E. (t é impar))
tamanho de quatro dígitos, sendo este o tamanho de                       Acrescentar 00 à esquerda de tqd
semente mínimo recomendado. Descobriu-se que alguns
                                                                     SENÃO
valores levam a sequências infinitas de geração de valores
pseudo-aleatórios, ao apresentarem valores como: 6100,                   SE (d é par) .E. (t é par) ENTÃO
2100, 4100 e 8100. A partir daí, o cálculo do meio do                      Manter tqd como está
quadrado efetua a repetição infinita da mesma sequência.
Descobriu-se também, que alguns valores usados levam à             tq = tamanho em dígitos do valor gerado para tqd.
obtenção de valor zero como resultado do meio do
quadrado, impossibilitando a continuidade do uso do                 SE (t é impar) ENTÃO
método, tais como os múltiplos de 1000 para as sementes de
                                                                         tq = d.2+1
quadro dígitos. Um bom gerador de números “aleatórios”
deve gerar sequencias infinitas, sem resultar em zero. Não          SENÃO
deve repetir valores em sequências. No entanto, para
aplicações que não requerem grande grau de precisão o
método do meio do quadrado pode ser útil.                          m = posição inicial para extração do quadrado do meio a
                                                                   partir da quantidade de dígitos tqd.


Tomando-se por como base o valor de semente 5678 (quatro
dígitos de tamanho) e elevando-se este valor ao quadrado,
obter-se-á como resultado o valor 32239684 (oito dígitos de
tamanho). Do quadrado obtido são retirados os quatro
                                                                   ns = valor da próxima semente (valor pseudo-randômico
dígitos do meio desse quadrado. Assim sendo, do ao valor
                                                                   gerado) após extração do quadrado do meio.
32239684 tira-se o valor 2396.



Na sequência, a partir do valor 2396 calcula-se o seu
quadrado, que resultará no valor 5740816 (sete dígitos de          Com base no algoritmo do método do meio do quadrado
tamanho). No entanto, este segundo quadrado possui sete            proposto por von Neumann e das etapas conjugadas , é
dígitos de tamanho e devido a isto necessita ser                   possível obter os valores indicados na Tabela 1 a partir do
equacionado para que possua oito dígitos. Assim, basta             fornecimento de uma semente que tenha entre 4 e 7 dígitos
acrescentar um valor zero à esquerda do quadrado, de forma         de tamanho.
que fique assim representado 05740816. Deste ajuste, pega
-se nos quatro dígitos do meio, que neste caso é o valor
7408 e prossegue-se com a aplicação da técnica de forma            O tamanho máximo em dígitos para a semente deve ser 5
sequencial até o ponto desejado ou quando o meio do                para valores de 32 bits ou 15 para valores de 64 bits.
quadrado for 0000.

                                                                             (t
                                                                    (d)                  (tqd)       (tq)    (m)       (ns)
                                                                              )
ALGORITMO DO MEIO DO QUADRADO                                                 7         09999999                         8
                                                                     4        8         99999999      8       3
A aplicação do método pode ser efetivada a partir do                                                                    3,4
                                                                              9       00999999999                        11
algoritmo seguinte:                                                  5       10       09999999999    11       4
                                                                                                                        4,5
N = entrada do número que representa a semente (> que 4 -                    11       099999999999                       12
                                                                     6       12       999999999999   12       4
máx: 5 p/ 32 bits | 15 p/ 64 bits).                                                                                     4,6
                                                                             13   009999999999999                        15
d = tamanho em dígitos do valor N: d = tamanho(N).                   7       14   099999999999999    15       5
                                                                                                                        5,7




                                                              18
A PROGRAMAR
                                                     GNA - GERAÇÃO DE NÚMEROS ALEATÓRIOS (Parte 1)
CONCLUSÃO                                                                SCHILDT, H. Turbo C Avançado: Guia do Usuário. Rio de
                                                                         Janeiro: McGraw-Hill, 1990. 475 p.
Neste artigo foi apresentado o método de geração de
números pseudo-aleatórios meio do quadrado, que é                        SILVEIRA, J. F. P. da. Tipos de Aleatori-edade. Rio Grande
considerado por vários especialistas da área da computação               do Sul: Universidade Federal do Rio Grande do Sul, Depar-
como sendo um método não eficiente. No entanto, é                        tamento de Matemática. 2001. Disponível em: <http://bit.ly/
preferível ter possuir em mãos um método não eficiente de                r2YYis> . Acesso em: 29 jun. 2011, 11:50:23.
geração de números aleatórios do que não possuir
                                                                         STUBBE, J. An Introduction to Random Number Generation
absolutamente nenhum método.
                                                                         and Simulation. École Polytechnique Fédérale de Lausanne.
É claro que para uma aplicação que exija maior precisão,
                                                                         Disponível em: http://bit.ly/nvkNaP. Acesso em: 1 jul. 2011,
será necessário considerar algum outro método.
                                                                         08:59:12.
No próximo artigo será discutido o método quadrado do
                                                                         TÖRN, A. Probabilistic Algorithms: Spring 2001 Course. Åbo
meio, que é uma variação do método apresentado nesta
                                                                         Akademi University: Department of Computer Science. 2001.
parte.
                                                                          Disponível em <http://bit.ly/qYxYkQ>. Acesso em: 1 jul.
                                                                         2011, 08:27:32.
BIBLIOGRAFIA
                                                                         WHELAN, S. F. Models - Stochastic Models. University Col-
DIAS, G. N. A Influência da Semente na Geração de                        lege Dublin, School of Ma-thematical Sciences. Disponível
Seqüências de Números Aleatórios através de Geradores de                 em: http://bit.ly/nIy2nT
Números (Pseudo) Aleatórios. Rio de Janeiro: Universidade                Acesso em: 1 jul. 2011, 08:39:54.
Federal do Rio de Janeiro. 2005. Disponível em: <http://bit.ly/
qznXtW>. Acesso em: 29 jun. 2011, 10:52:35.                              ZENIL, H. John von Neumann's First Pseudorandom Number
                                                                         Generator Pseu-dorandom Number Generator. Champaign:
DORICIO, J. L. Número Aleatórios e Apli-cações. São Paulo:               Wolfram Demonstrations. 2011. Disponível em < http://
Universidade Federal de São Carlos, Departamento de                      bit.ly/6C7Q5
Matemática. 1998.
                                                                         JohnVonNeumannsFirstPseudorandomNumberGenerator>.
GIORDANO, F. R.; FOX, W.F. & WEIR, M. D. A first course
                                                                         Acesso em: 15 ago. 2011, 08:23:56.
in mathematical modeling. 4. ed. California Books/Cole. P.
184, 2009.

KNUTH, D. E. The Art of Computer Pro-gramming: series in
computer science and information processing. 2d ed. Indi-
ana: Addison-Wesley. 1981.

REYS, A. E. L.; MACHADO, A. A.; FERREIRA, D. F.;
DEMÉTRI, C. B. & RIBEIRO, P. J. Sistema Galileu de
Educação Estatística. São Paulo: Universidade de São
Paulo, ESALQ. 2011. Disponível em: http://bit.ly/q5jbT8

. Acesso em: 1 jul. 2011, 08:17:25.




AUTOR
                 Augusto Manzano, natural da Cidade de São Paulo, tem experiência em ensino e desenvolvimento de programação de soft-
                 ware desde 1 986. É professor da rede federal de ensino no Brasil, no Instituto Federal de Educação, Ciência e Tecnologia. É
                 também autor, possuindo na sua carreira várias obras publicadas na área da computação.




                                                                    19
Revista programar 31
A PROGRAMAR
Programar para Windows Azure
O Windows Azure é uma plataforma de alta disponibilidade e            Capacidade VS Quantidade
alta escalabilidade que é fornecida como serviço e tem por
isso algumas características diferentes em relação às plata-          Em Windows Azure podemos escalar horizontalmente adicio-
formas alvo tradicionais.                                             nando mais máquinas virtuais ou escalar verticalmente usan-
                                                                      do máquinas virtuais de maior capacidade.
Neste artigo vamos tentar alertar o leitor para alguns deta-
lhes que encontramos em Windows Azure Compute, SQLA-                  Dependendo do tipo de aplicação e da carga de trabalho que
zure e Windows Azure Storage bem como alguns cuidados                 cada aplicação, deverá ser escolhida a quantidade e capaci-
que deveremos ter quando desenvolvemos para estes servi-              dade das instâncias de modo a optimizar os custos e desem-
ços.                                                                  penho. A decisão poderá ser tomada tendo por base algu-
                                                                      mas das seguintes características:
Windows Azure Compute
                                                                      Maior capacidade
I/O Performance
                                                                            Comunicação mais rápida e mais barata entre proces-
Existem cinco tipos de instâncias de Windows Azure Compu-                   sos (mesma máquina)
te que permitem a execução de várias cargas de trabalho e
aplicações com vários níveis de complexidade.                               Pode sair mais barato nos casos em que se usam
                                                                            muito    Queues      porque    podemos      fazer
                                                                            Queue.GetMessages(32) e processar em paralelo
  Tamanho          CPU      Memória      Local      Largura
     da                                 Storage       de
                                                                            Máquinas com maior capacidade têm uma maior e
                                                     Banda
                                                                            mais consistente performance de I/O
    Extra        1.0 GHz     768 MB      20 GB      5 Mbps
    Small                                                             Maior quantidade
    Small        1.6 GHz    1.75 GB     225 GB       100
                                                     Mbps                   Permite uma escalabilidade mais granular e conse-
   Medium         2 x 1.6    3.5 GB     490 GB       200                    quentemente mais barata

    Large         4 x 1.6     7 GB       1,000       400                    Maior tolerância a falhas. A falha de uma máquina
                   GHz                    GB         Mbps                   virtual têm menor impacto
  Extra large     8 x 1.6    14 GB       2,040       800
                   GHz                    GB         Mbps                   Temos que usar Azure Storage para comunicar entre
                                                                            processos

                                                                            Local Storage
Cada instância de Windows Azure Compute representa um
servidor virtual. Apesar de muitos dos recursos serem dedi-
cados a essa instância em particular, alguns recursos asso-           O Fabric Controller pode a qualquer momento destruir a
ciados à performance de I/O, tais como largura de banda e             máquina virtual e substituir por uma nova. Isso pode aconte-
disco rígido, são partilhados entre as instâncias presentes na        cer, por exemplo, sempre que seja detectado falhas na apli-
mesma máquina física. Durante os períodos em que os                   cação, falhas no hardware, ou simplesmente porque precisa
recursos partilhados estão a ser muito utilizados poderemos           de realizar actualizações ao sistema operativo.
ver a performance de I/O baixar para os níveis mínimos
anunciados mas, em contrapartida, sempre que os recursos              Por essa razão a informação armazenada em local storage é
partilhados tiverem um nível de utilização inferior veremos           considerada volátil. Esta situação deverá ser levada em con-
essa performance aumentar.                                            ta, principalmente nos casos em que existe migração de
                                                                      aplicações para o Windows Azure. Algumas aplicações
Quanto maior for o tamanho da instância maior será a perfor-          desenhadas para correr apenas num servidor usam local
mance mínima de I/O e consequentemente essa performan-                storage para guardar alguns ficheiros de forma persistente.
ce será também mais consistente ao longo do tempo.




                                                                 21
A PROGRAMAR
Programar para Windows Azure
Como já vimos, em Windows Azure essa informação é consi-
                                                                     No entanto existem algumas diferenças entre as quais se
derada volátil. Em contrapartida a migração de aplicações
desenhadas para executar em web farms normalmente não                destacam as seguintes:
apresentam este problema.                                            Não existe Backup e Restore

Outro alerta em relação ao uso de local storage tem a ver
com a visibilidade da informação. Tudo o que for escrito para        Uma das funcionalidades que ainda não existe em SQLAzu-
local storage só vai ser visto pela instância actual.                re é a capacidade de realizar backup ou restore de uma
                                                                     base de dados. Apesar do estarmos na presença de um ser-
Estamos a desenvolver para um ambiente altamente escalá-             viço de alta disponibilidade onde “não existe” a preocupação
vel e na maioria dos casos manter a informação privada não           com a perca de informação, continuamos a ter que lidar com
é a melhor opção. Existem casos em que é vantajoso fazer             possíveis corrupções nas bases de dados devido a erros nas
cache local de alguns dados mas na maioria dos cenários              aplicações.
deve ser usado um tipo de storage persistente e partilhado.
                                                                     Não existe cross-database querying

                                                                     Em SQL Azure nós temos a capacidade de alugar bases de
Roles                                                                dados e não servidores de bases de dados. Não existe
                                                                     garantia que todas as bases de dados que alugamos estão
As instâncias são pagas por hora de relógio                          no mesmo servidor. A ideia principal que deveremos reter
                                                                     neste caso é que não existe conectividade entre bases de
As instâncias são facturadas com base nas horas de relógio           dados. Se for necessário combinar resultados de mais do
em que estiveram implementadas. As horas parciais serão              que uma base de dados teremos que resolver essa questão
facturadas como horas completas. Após esta frase podermos            na aplicação. Deveremos realizar as consultas a todas as
ficar a pensar que se for usada uma instância durante 30             bases de dados e depois, na aplicação, agregar os resulta-
minutos será facturada 1 hora, mas este pensamento pode              dos.
não ser verdade.
                                                                     Analysis Services, Replication e Service Broker não
Se fizer deployment de uma instância às 16h50 e parar essa           estão disponíveis como serviço
instância às 17H10 irá pagar duas horas. Uma hora pela
utilização entre as 16h50 e as 17H00 e outra hora pela utili-        Apesar de estes serviços ainda não estarem disponíveis é
zação entre as 17h00 e as 17h10.
                                                                     possível usar SQL Azure como fonte de dados para a versão
Instâncias que estejam implementadas menos de 5 minutos              on-premisses de Analysis Services e Integration Services.
dentro de uma hora não serão contabilizadas.                         Não suporta Database Mirroring ou Failover Clustering

Cada novo deployment conta uma nova hora
                                                                     Devido às características de alta disponibilidade do serviço
Deveremos evitar implementar, apagar e voltar a implemen-            SQL Azure os serviços de suporte a alta disponibilidade da
tar instâncias sempre que possível. Cada nova implementa-            versão on-premisses tais como database mirroring e failover
ção adiciona uma hora por cada instância à conta.                    cluster não são necessários e não estão disponíveis.

Imagine que implementou uma instância às 15h10 e parou a             Clustered Indexes são obrigatórios
mesma às 15h20. Se fizer nova implementação o App Fabric
irá arrancar uma nova máquina e será cobrada uma nova                Todas as tabelas em SQL Azure necessitam de um ter um
hora completa.                                                       clustered index. Um clustered index é um tipo de índice
                                                                     especial que ordena a forma como os registos são gravados
Windows Azure Database                                               fisicamente. Esta é uma das primeiras preocupações na
                                                                     migração de bases de dados para SQLAzure.
Limitações
                                                                     Não existe integração com CLR
O SQLAzure foi desenhado tendo como base o SQLServer
sendo por isso natural que partilhe muitas das suas funciona-
                                                                     SQLAzure não suporta CLR. Qualquer base de dados cons-
lidades. O SQLAzure suporta múltiplas bases de dados bem
                                                                     truída usando CLR não será possível mover para o SQLAzu-
como a maioria dos objectos presentes na versão on-
                                                                     re sem que se proceda a modificações.
premisses tais como tabelas, vistas, procedimentos armaze-
nados, funções, restrições (constraints) e triggers.




                                                                22
A PROGRAMAR
                                                                                   Programar para Windows Azure
Não existe acesso às System Tables                                 Em relação a custos com Windows Azure Storage, estes são
                                                                   medidos usando as seguintes variáveis:
Devido a inexistência de acesso ao hardware que suporta a
base de dados em SQLAzure não existe acesso às system                     Tráfego: quantidade de dados transferidos de e para
tables do SQLServer. Também não existe acesso às vistas e                 a o serviço
procedimentos armazenados do sistema.
                                                                          Transacções: quantidade de pedidos feitos ao serviço
SQL Azure necessita de SQL Server Management Studio
2008 R2                                                                   Capacidade: Quantidade de informação armazenada

                                                                   Tráfego
Para poder aceder a bases de dados através do SQLServer
Management Studio tem que actualizar para a versão 2008            O tráfego consumido internamente não tem custo associado,
R2. Apesar de as versões anteriores estabelecerem ligação          ou seja, os dados transferidos entre serviços presentes no
com o servidor SQL Azure o Object Browser não irá funcio-          mesmo datacenter não contam tráfego. Tráfego que tenha
nar. Podemos usar a versão gratuita desta ferramenta (SQL          origem ou destino diferente do datacenter onde o storage
Server Management Studio Express 2008 R2).                         service foi criado conta tráfego, seja ele externo ou até mes-
                                                                   mo outro datacenter Azure.

Nem todos os dados são relacionais                                 Transacções

Esta afirmação não trás novidade nenhuma mas ganha                 Cada chamada a storage service conta uma transacção e
especial importância no conceito de Cloud Computing e Win-         cada transacção tem um custo. Apesar de o custo de cada
dows Azure. O Windows Azure dispõe de diferentes supor-            transacção individualmente ser muito baixo (0.01$/10.000
tes ao armazenamento de dados, cada um com as suas                 transacções) deveremos ter esta situação em atenção no
características e custos. Ao afirmar que nem todos os dados        desenho das aplicações porque rapidamente se consegue
são relacionais pretendemos alertar para o facto de que            chegar a cenários em que o número de transacções é muito
deverá ser escolhido o tipo de storage certo para o tipo de        elevado. Alerta-se ainda para o facto de que cada pedido ao
dados certo.                                                       storage service conta uma transacção independentemente
                                                                   da origem. Isto significa que os pedidos de serviços presen-
O serviço SQLAzure é, relativamente a Azure Storage, um            tes no mesmo datacenter também contam transacções.
serviço mais caro. SQLAzure custa cerca de 10$/GB (7.5€/
GB) e TableStorage custa cerca de 0.15$/GB (0,11€/GB).             A maioria dos pedidos ao storage service conta apenas uma
Neste sentido, poderemos como exemplo recomendar o                 transacção mas existem algumas chamadas a métodos das
armazenamento de imagens em Blob Storage ou a passa-               Storage Client Library que podem resultar em várias transac-
gem de dados históricos ou dados de auditoria (Logs) da            ções (vários pedidos):
aplicação para Table Storage.
                                                                   Upload para Blob Storage
Procedimentos Armazenados
                                                                   Sempre que existe um pedido de upload para Blob Storage
A execução de procedimentos armazenados não tem custos             de um ficheiro com um tamanho superior a 32Mb a Storage
adicionais. Podemos tirar partido desta situação e usar            Cliente Library divide automaticamente o pedido em múlti-
algum poder de computação do servidor de SQL com o intui-          plos blocos de 4Mb. A cada bloco de 4Mb irá corresponder
to de poupar no número de roles necessários para a execu-          um pedido PutBlock que contará uma transacção cada. Exis-
ção da aplicação. De notar que não deveremos abusar des-           te ainda um PutBlockList no final que contará também uma
tes recursos.                                                      transacção. O tamanho do bloco poderá ser modificado atra-
                                                                   vés da propriedade CloudBlobClient.WriteBlockSizeInBytes.
Windows Azure Storage
                                                                   Consultas a tabelas
Relativamente a Windows Azure Storage vamos tentar per-
                                                                   Sempre que usar a classe CloudTableQuery para realizar
ceber alguns dos custos associados a este serviço e tentar
                                                                   consultas a um Azure Table Service terá automaticamente a
perceber alguns dos cuidados que deverão ser tidos em
conta na hora de desenvolver sobre estes serviços.                 resolução de continuations tokens de modo a obter todos os
                                                                   resultados pretendidos.




                                                              23
A PROGRAMAR
Programar para Windows Azure
Isto significa que sempre que a query retornar um continua-           estar constantemente a fazer pooling na queue para detectar
tion token irá ser lançado automaticamente um pedido dos              a entrada de novas mensagens.
restantes resultados e como já vimos anteriormente, cada
pedido conta uma transacção.
                                                                      Imagine que existe um worker role com duas instâncias (de
Table.SaveChanges
                                                                      modo cumprir o SLA) a fazer pooling com um intervalo de 1
Sempre que for realizada uma operação de Add, Update ou               segundo numa queue. Ao final de um mês haverá um custo
Delete sobre um objecto de uma tabela, esse objecto será              de mais de 5$ só derivado ao pooling.
adicionado ao datacontext de modo a que, mais à frente,
esse pedido possa ser enviado ao Table Service. Os pedidos            Poderá ser implementado um esquema de espera exponen-
não são enviados imediatemente, são enviados quando for               cial para reduzir o número de chamadas de pooling à queue.
chamado o método SaveChangesWithRetries.                              O incremento de tempo a esperar por cada chamada a uma
                                                                      queue vazia e o número máximo de tempo que esse backoff
Quando esse método é chamado as alterações pendentes                  poderá atingir deverá ser adaptado tendo em consideração o
são chamadas uma a uma sobre o table service resultando
                                                                      cenário para qual a queue está a ser utilizada.
numa transacção cada.
                                                                      Conclusão
Existe no entanto uma excepção a esta situação. Sempre
que as alterações pendentes incidirem numa única Partition-           Através deste artigo esperamos ter conseguido desafiar o
Key de uma tabela poderemos solicitar que as alterações               leitor para a necessidade de conhecer em detalhe a arquitec-
sejam efectuadas utilizando apenas um pedido através da               tura dos serviços e os custos associados de modo a que
chamada SaveChangesWithRetries                                        possa desenhar e desenvolver aplicações para Windows
 (SaveChangesOptions.Batch).                                          Azure de forma eficiente e eficaz.

Além de apenas contar uma transacções, submeter as alte-              Como dica final, no site de billing podemos ver o estado
rações pendentes em batch demora menos tempo e garante                actual da subscrição até ao final do dia de ontem e desta
processamento transaccional (ou todas são aplicadas ou                forma ir verificando os custos das nossas aplicações de
nenhuma é aplicada).                                                  modo a não existirem surpresas no final do mês.

Queues

Cada elemento numa Azure Queue custa 3 transacções

Nos casos mais comuns usar uma queue para enviar uma
mensagem de um role para outro custa cerca de 3 transac-
ções porque são necessárias as operações de Put, Get e
Delete para processar uma mensagem.

Poderemos diminuir o custo cada elemento na queue utili-
zando a operação GetMessages da Queue Service API para
obter e processar até 32 mensagens de uma só vez e assim
diminuir o custo até 2,03 transacções por elemento na
queue.

Usar backoff exponencial para tempos de espera

Devido à ausência de notificações nas queues é necessário



AUTOR
                Vítor Tomaz é consultor independente na área das tecnologias de informação. Tem especial interesse por Cloud Computing,
                programação concorrente e segurança informática. É membro de algumas comunidades tais como Portugal-a-Programar,
                NetPonto, AzurePT, HTML5PT e GASP.




                                                                 24
A PROGRAMAR
Programação Orientada a Objectos em Java 6
O objectivo deste artigo não é ensinar os conceitos de POO,
                                                                     Este código não dá nenhum erro de sintaxe, no entanto qual-
nem a programar em Java. Assim a leitura do artigo pressu-
                                                                     quer programador que perceba o mínimo de Java verá que
põe que o leitor já saiba os conceitos de POO, e conheça
                                                                     ao executar a aplicação dará um erro no ciclo. Porque tenta-
pelo menos a linguagem Java, ou outra de sintaxe seme-
                                                                     rá somar uma sequência de caracteres com um número
lhante para perceber os exemplos. O objectivo deste artigo é
                                                                     inteiro. Contudo se aplicarmos um código semelhante no
referir as melhores práticas e métodos de programar POO
                                                                     Java 6, graças às parametrizações obteremos um erro de
em Java 6.
                                                                     sintaxe.
Parametrização das Colecções                                           public int exemplo(){
                                                                             ArrayList<Integer> v = new Array-
       Antes do Java 5, a maneira de implementação de                List<Integer>();
colecções, por exemplo a classe ArrayList poderia levar ini-
                                                                              int soma = 0;
cialmente um int e posteriormente uma String. Assim era fácil
que fosse gerado um erro em runtime, quando estivéssemos                      v.add(new Integer(2));
por exemplo, a percorrer a colecção e somar todos os ele-                     v.add("Nome X"); //Aqui dará erro de sin-
mentos. No entanto agora é possível parametrizar a colec-            taxe
ção e dizer para ela só aceitar uma determinada estrutura de
dados (ou estruturas descendentes que herdem naturalmen-
te as mesmas propriedades). Assim quando antes podería-
mos ter no código algo como:                                         O ArrayList é assim genericamente ArrayList<E>, sendo que
                                                                     o E pode ser substituído por qualquer classe, mas não por
public int exemplo()
                                                                     dados de tipos primitivos (como o int, o double…), mas isso
{                                                                    é resolvido de maneira simples, como é explicado mais à
       ArrayList v = new ArrayList();                                frente na secção AutoBoxing.

       int soma = 0;                                                 Podemos aperceber-nos que a grande vantagem das para-
                                                                     metrizações, é garantir mais segurança ao programador, de
       v.add(new Integer(2));
                                                                     modo a que ele saiba que tipos de coisas estão em vários
       v.add("Nome X");                                              locais. O tipo Object dá uma sensação de liberdade, porque
       //...                                                         podemos meter tudo lá dentro, algo como o (void *) do C.
                                                                     Contudo deixa uma responsabilidade acrescida ao progra-
       Iterator x = v.iterator();
                                                                     mador que terá que ter em atenção sempre o que está real-
       while(x.hasNext())                                            mente lá dentro para não realizar operações não permitidas.
       soma += Integer.parseInt(x.next().toString                    Pelo contrário com as parametrizações é possível saber
());                                                                 exactamente que operações são permitidas sobre a estrutura
                                                                     de dados, porque ao escrever o código sabemos o que lá
       return soma;
                                                                     estará.
}
                                                                     Outra grande vantagem é a inexistência de conversões. No
                                                                     primeiro exemplo, depois de obter o valor da lista era neces-
                                                                     sário converter para inteiro (e o valor obtido poderia ser
                                                                     inconvertível para inteiro) e só depois somar. No segundo
                                                                     exemplo, o valor devolvido já é do tipo que pretendemos
                                                                     (neste caso um inteiro, o que nós estávamos à espera).

                                                                     AutoBoxing

                                                                            Infelizmente os tipos parametrizados não permitem
                                                                     trabalhar com tipos primitivos, algo que é extremamente
                                                                     importante. Aliás muitos dos problemas requerem vectores
                                                                     de inteiros. Será que então a única solução é trabalhar com
                                                                     os Arrays originais? Não. Todos os tipos primitivos possuem
                                                                     a correspondente classe. Por exemplo a classe Integer, cor-
                                                                     responde ao tipo primitivo int.


                                                                25
A PROGRAMAR
Programação Orientada a Objectos em Java 6
Assim podemos facilmente fazer:

ArrayList<Integer> v = new ArrayList<Integer>();

A seguir para adicionar elementos teríamos que colocar algo
deste género:


v.add(new Integer(3));
v.add(new Integer(9));
int r = v.get(1).intValue();

O construtor é necessário, uma vez que os tipos não são
compatíveis. Aliás o seguinte exemplo, compilado antes do
Java 5 não funcionaria correctamente:


int i;
Integer j;
i = 1;
j = 2;
i = j;
j = i;



Isto porque int é um tipo primitivo e Integer um tipo comple-
xo. Logo não é possível fazer uma atribuição de um tipo pri-
mitivo para um tipo complexo. Tanto mais que o que está
                                                                             Figura 1: Exemplo do Diamon of Death
realmente armazenado em j é um “apontador” para uma ins-
tância da classe Integer. Felizmente devido ao AutoBoxing o           Na fig. 1 podemos ver um exemplo em que ambas as clas-
exemplo a partir de Java 6 funciona perfeitamente, o que nos          ses B e C herdam da classe D. Por sua vez, a classe A her-
permite fazer também no ArrayList anteriormente criado algo           da da B e C simultaneamente. Supondo que a classe D pos-
mais simples:
                                                                      sui o método xpto(), e tanto a classe B como a C na sua
v.add(3);                                                             implementação reescrevem o método. Supondo que ele é
                                                                      chamado no contexto da classe A, e assumindo que ele não
v.add(9);
                                                                      é reescrito na classe A, então qual seria o método a ser cha-
int r = v.get(1);                                                     mado? O da classe B ou C? Nesse caso temos o famoso
                                                                      Diamante da Morte… Como não é possível definir comporta-
                                                                      mentos nas interfaces, apesar de uma classe poder imple-
Pode parecer uma pequena diferença, mas numa linguagem                mentar várias interfaces, mesmo que ambas possuam méto-
como Java, onde é muitas vezes necessário escrever gran-              dos com a mesma assinatura, ele têm que ser definido na
des linhas de código, isto pode poupar bastante esforço num           classe e é esse que será usado. Apesar de prevalecer o
projecto.                                                             problema de métodos com a mesma assinatura, mas com
                                                                      funções distintas, o que impossibilitava a implementação de
Interfaces
                                                                      ambas as interfaces.

                                                                      Aqui está um exemplo da declaração de uma interface.
       Apesar de já existir antes de Java 5, as interfaces são
uma maneira simples de Java ultrapassar as limitações de
herança simples, ao invés da múltipla do C++, e ao mesmo              public interface Expiravel {
tempo evitando grande parte do problema do Diamante da
                                                                             public bool estaExpirado();
Morte (Diamond of Death em Inglês), onde a múltipla heran-
ça pode criar problemas ao compilador e ao programador                       public GregorianCalendar expiraEm();
sobre qual o método a ser executado.                                  }




                                                                 26
A PROGRAMAR
                                                                  Programação Orientada a Objectos em Java 6
Qualquer classe que implemente esta interface, terá que
                                                                          public abstract int maximoDiasEmprestimo();
obrigatoriamente possuir aqueles dois métodos especifica-
dos. Assim poder-se-á facilmente percorrer, por exemplo
uma lista de objectos de diferentes classes, mas com uma                  public abstract String nomeTipo();
interface em comum. Como é óbvio, os únicos métodos que
poderão ser chamados, sem serem necessárias conversões,
serão os definidos na interface.                                       public abstract boolean utilizadorPodeRequisi-
                                                                   tar(String usercodigo);
Classes Abstractas                                                 }
                                                                   public class Livro extends Publicacoes{
As classes abstractas são muito úteis para possibilitar a pou-
pança de código, e garantir o funcionamento correcto da                   public Livro(String codigo){
classe, que apesar de tudo estará incompleta.                                  //Código
       Imaginemos por exemplo o caso de uma Biblioteca.                   }
Poderia existir uma classe abstracta, para as publicações,
                                                                          @Override
que teria informações gerais, como o código de identificação,
se estava requisitado, se era possível de requisitar, quantida-           public int maximoDiasEmprestimo(){
de, estado, entre outros atributos. No entanto possuiria méto-                 //Aqui já terá código também
dos abstractos, que têm que ser codificados obrigatoriamen-
te na primeira descendente não abstracta. Por exemplo os                       return 7;
métodos maximoDiasEmprestimo, nomeTipo, utilizadorPode-                   }
Requisitar, entre outros seriam definidos como abstractos e
não possuiriam código. Assim seriam codificados pelas clas-
ses Livro, DVD, Revista, e todos aqueles concretos que her-               @Override
dassem da classe abstracta mas os métodos já codificados                  public String nomeTipo(){
na classe abstracta poderiam ser aproveitados, poupando
código e trabalho.                                                             //Aqui já terá código      também
                                                                               return "Livro";
public abstract class Publicacoes {                                       }
    //Variáveis que segundo as regras do encapsula-
mento deverão ser privadas
                                                                          @Override
    public Publicacoes(){
                                                                       public boolean utilizadorPodeRequisitar(String
         //Código                                                  usercodigo){
    }                                                                          //Aqui já terá código      também
    public Publicacoes(String codigo){                                         return true;
         //Código                                                         }
    }                                                              }
    public String getCodigo(){
                                                                       Este é um exemplo da aplicação de uma classe abstracta e
         //Código                                                      de uma descendente que implementa as funções abstractas
         return "x";                                                   e como tal é possível de criar uma instância do mesmo,
                                                                       onde, tal como na herança entre classes simples, podemos
    }
                                                                       chamar os métodos públicos definidos e herdados da classe
  public int getQuantidade(){                                          mãe.
         //Código
                                                                       Diferentes Tipos de Colecções
         return 0;
    }                                                                        A JFC (JAVA Collections Framework) oferece ao pro-
                                                                       gramador muito mais que simplesmente o ArrayList. Este é
    //... Mais métodos públicos e se necessário
                                                                       apenas uma pequena parte, embora seja talvez a mais utili-
alguns privados
                                                                       zada nem sempre adequadamente.




                                                                  27
A PROGRAMAR
Programação Orientada a Objectos em Java 6
Para um conjunto de problemas que necessitem de uma                    definição matemática de conjunto implica isso mesmo que
colecção de valores guardados em memória, muitos progra-               não haja repetições. É por isso importante estar a par das
madores por desconhecimento utilizam muitas vezes os                   possibilidades existentes e saber decidir qual a melhor
métodos menos adequados. A JFC está dividida em três                   opção.
grandes grupos as Listas (List<E>), os Conjuntos (Set<E>) e
as Correspondências(Map<K,V>).                                         Conclusão
Supondo, por exemplo uma lista de amigos, qual seria talvez
                                                                       Tal como disse no inicio este não pretendeu ser um artigo
o grupo mais interessante? Todos eles podem de maneira
                                                                       que ensinasse a programar Java, nem POO, mas sim um
mais ou menos expedita servir para guardar esta informação.
                                                                       artigo que mostrasse algumas novidades de Java 6 em rela-
Se a informação fosse guardada na lista teríamos que ter em
atenção que não poderíamos repetir amigos e seria necessá-             ção ao Java 2 (que por motivos de compatibilidade ainda
rio andar sempre a verificar a existência o valor a inserir            existem em Java 6, mas são desaconselhados) e a sua liga-
antes de o fazer. Como as listas não são ordenadas por defi-           ção à Programação Orientada a Objectos, já que é possível
nição, a pesquisa demoraria algum tempo para listas de ami-            programar em Java sem ter em conta os princípios de POO.
gos extensas.                                                          Apesar de tudo ficou ainda muito por dizer já que Java é
                                                                       uma linguagem muito extensa e foram focados apenas
Nas correspondências teríamos o mesmo problema de verifi-              alguns pormenores, no entanto são pormenores que podem
car a existência de amizade, mas teríamos a vantagem de                permitir um código mais limpo, talvez mais rápido e por ven-
esta estar optimizada para pesquisas. Contudo teríamos a               tura mais fácil de actualizar.
desvantagem de por cada amigo ser necessário guardar um
valor, o que pode acabar por não ser uma desvantagem, se
for necessário, por exemplo guardar algo associado a essa
amizade.                                                               Bibliografia
                                                                       http://wiki.portugal-a-programar.org/
Num conjunto não seria necessária a verificação de repeti-             dev_geral:java:tutorial:home
dos porque ele próprio faz essa verificação, uma vez que a
                                                                       http://download.oracle.com/javase/6/docs/api/




AUTOR
                António Silva, actualmente a frequentar o 3º ano da Licenciatura de Engenharia Informática da Universidade do Minho sente
                uma enorme paixão pela programação, nomeadamente em VB.Net e C. Apesar disso possui um conhecimento sobre várias
                outras linguagens de programação como Java, PHP, Javascript, C#, Haskell, entre outras.




                                                                  28
Elege o melhor artigo desta edição
       Revista PROGRAMAR
       http://tiny.cc/ProgramarED31_V
A PROGRAMAR
DataBinding em Silverlight 4
Neste artigo pretendo apresentar o conceito databinding em
                                                                          Binding Target – vai representar um objecto do tipo
Silverlight 4. Vou começar por uma breve apresentação
                                                                          DependencyObject ou do tipo FrameworkElement, ou
teórica e em seguida irei apresentar vários exemplos. De
                                                                          seja, na maioria dos casos o controlo da interface
salientar que não terei em conta Design Patterns.
                                                                          com o utilizador.

                                                                          Binding Source – vai representar um objecto fonte a
O conceito Databinding permite-nos de uma forma simples e                 visualizar/editar;
consistente apresentar e interagir a informação da nossa
aplicação, através da criação de um relacionamento entre                  Dependency Property – permite definir o valor da
dois objectos para que a alteração de uma propriedade de                  propriedade e reflectir/propagar a alteração do valor
um deles seja reproduzida numa propriedade de um outro.                   atribuído, assim como permite definir um valor de
Existindo uma separação entre a interface com o utilizador e              omissão.
a informação, é estabelecido qual o fluxo entre os dois, a
                                                                          Value converter – é um conversor que permitir
forma como a alteração é reflectida, a forma como os erros
                                                                          efectuar uma transformação
são detectados e a forma como a informação é mostrada na
interface com o utilizador.

                                                                    As propriedades a ter em conta:

      Databinding permite-
      nos de uma forma                                                    Converter permite converter a informação apresentar
                                                                          ao utilizador;
  simples e consistente                                                   ConverterCulture permite definir qual a cultura a

  (…) a criação de um                                                     utilizar no conversor;

                                                                          ConverterParameter permite definir o parâmetro do
  relacionamento entre                                                    conversor;

  dois objectos                                                           ElementName permite definir o nome do controlo ao
                                                                          qual se está usar no binding como objecto fonte;

                                                                          FallbackValue permite definir qual o valor atribuir em
A classe Binding representa a relação entre a                             caso de erro;
interface com o utilizador e a informação. Esta classe está
incluída no namespace System.Windows.Data e na                            Mode permite definir o modo do binding; Existem dois
                                                                          tipos: Default e Explicit.
assembly System. Windows (na System.Windows.dll)
                                                                          Path permite definir a propriedade a qual se atribui o
                                                                          binding;

                                                                          RelativeSource permite definir qual o objecto fonte
                                                                          associado, existindo uma hierarquia relativa ao
                                                                          objecto fonte actual;

                                                                          Source permite definir qual o objecto fonte;

                                                                          StringFormat permite especificar como formatar a
                                                                          informação a apresentar;

                                                                          TargetNullValue permite definir o valor a usar quando
                                                                          o objecto fonte é nulo;
     Fig.1 Esquema de relacionamento do Databinding
                                                                          UpdateSourceTrigger permite definir o tipo de
                                                                          actualização do binding.




                                                               30
A PROGRAMAR
                                                                                DataBinding em Silverlight 4
As propriedades ValidatesOnDataErrors; ValidatesOnEx-
ceptions; NotifyOnValidationError; ValidatesOnNotifyDataEr-           public Professional()
rors estão relacionadas com validação de dados e notifica-            {
ção de erros. Devem ser definidos a quando da implementa-                 _isProgrammer = true;
ção da interface IDataErrorInfo ou INotifyDataErrorInfo.              }


De seguida iremos apresentar alguns exemplos práticos!                #region ------ Properties ------
                                                                      public string Name
                                                                      {
Suponhamos a criação de uma classe chamada Professio-                     get { return _name; }
nal, que representa um profissional da comunidade NetPon-                 set { _name = value;
to. Esta classe implementa as interfaces IProfessional, que                   OnPropertyChanged("Name");
                                                                          }
define o que é um Professional e a interface INotifyProperty-         }
Changed, que permite propagar as alterações que ocorre-
rem.
                                                                      public DateTime DateOfBirth
                                                                      {
                                                                          get { return _dateOfBirth; }
                                                                          set
                                                                          {
                                                                              _dateOfBirth = value;
                                                                              OnPropertyChanged("DateOfBirth");
                                                                          }
                                                                      }


                                                                      public string Address
                                                                      {
                                                                          get { return _address; }
                                                                          set
                                                                          {
                                                                              _address = value;
                                                                              OnPropertyChanged("Adress");
                                                                          }
                                                                      }


                                                                      public string Locality
                                                                      {
                                                                          get { return _locality; }
                                                                          set
                                                                          {
                                                                              _locality = value;
                                                                              OnPropertyChanged("Locality");
                                                                          }
                                                                      }

public class Professional : INotifyPropertyChanged,
IProfessional                                                         public int PostalCode
   {                                                                  {
        #region ------ Private members ------                             get { return _postalCode; }
                                                                          set
         private   string _name;                                          {
         private   DateTime _dateOfBirth;                                     _postalCode = value;
         private   string _address;                                           OnPropertyChanged("PostalCode");
         private   string _locality;                                      }
         private   int _postalCode;                                   }
         private   string _mail;
         private   int _contact;
         private   bool _isProgrammer;
                                                                      public int Contact
        #endregion                                                    {
                                                                          get { return _contact; }




                                                                31
A PROGRAMAR
DataBinding em Silverlight 4
              set                                                  Caso prático 1
              {
                    _contact = value;                              Suponhamos que pretendemos interagir a propriedade
                    OnPropertyChanged("Contact");
              }                                                    Name com uma TextBox.
         }

                                                                   Em XAML:
         public string Mail
         {
                                                                   <TextBox Name="tbxName"
              get { return _mail; }                                         Text="{Binding Path=Name,
              set                                                           Mode=TwoWay,
              {
                  _mail = value;                                            UpdateSourceTrigger=Default}"/>
                  OnPropertyChanged("Mail");
              }
         }                                                         Ou em code-behind:

                                                                   var binding =new Binding("Name")
         public bool IsProgrammer
                                                                        {
         {
              get { return _isProgrammer; }                                 Mode = BindingMode.TwoWay, _
              set                                                             UpdateSourceTrigger _
              {                                                               =UpdateSourceTrigger.Default
                  _isProgrammer = value;
                  OnPropertyChanged("IsProgrammer");                        };
              }                                                    tbxName.SetBinding(TextBox.TextProperty, _
         }
        #endregion                                                 binding);


        #region ------ INotifyPropertyChanged ------
        /// <summary>                                              Caso prático 2
        /// Called when [property changed].
        /// </summary>                                             Suponhamos que pretendemos interagir a propriedade
        /// <param name="propertyName">Name of the
property.</param>                                                  IsProgrammer com uma CheckBox.
        public void OnPropertyChanged(
                             string propertyName)                  Em XAML:
        {
            if (PropertyChanged != null)                           <CheckBox Name="ckboxIsProgrammed"
                PropertyChanged(this,
                  new PropertyChangedEventArgs                     IsChecked="{Binding Path=IsProgrammer,
                             (propertyName));                      Mode=TwoWay,UpdateSourceTrigger=Default}"/>
        }


         public event PropertyChangedEventHandler                  Ou em code-behind:
                                    PropertyChanged;
         #endregion                                                var binding = new Binding("IsProgrammer")
   }                                                               {
                                                                   Mode = BindingMode.TwoWay,
                                                                   UpdateSourceTrigger = UpdateSourceTrigger.Default
                                                                       };


                                                                   ckboxIsProgrammed.SetBinding
                                                                   (CheckBox.IsCheckedProperty, binding);

Nota: Nos próximos casos práticos o source é atribuído no
DataContext da Page e o binding irá subir na hierarquia até
encontrar o source.




                                                              32
A PROGRAMAR
                                                                                        DataBinding em Silverlight 4
Caso prático 3                                                    Caso prático 4
Suponhamos que pretendemos apresentar o PostalCode                 Atribuir uma lista de profissionais a uma listbox, apresentan-
numa label, usando um conversor para formatar a informa-          do a propriedade Name.
ção.                                                              No XAML:

Como o PostalCode é um valor inteiro que guarda o código          <ListBox Name="lbxProfessional"
postal, o PostalCodeConverter é o conversor que separa os                  DisplayMemberPath="Name"/>
primeiros 4 dígitos dos 3 últimos dígitos usando um hífen.
                                                                  Em code behind:
A classe PostalCodeConverter implementa a interface IVa-
lueConverter e consiste na implementação de dois métodos          var professionals = new List<Professional>();
fundamentais, o Convert e o ConvertBack.
                                                                  ...
                                                                  lbxProfessional.ItemsSource = professionals;
public class PostalCodeConverter:IValueConverter
{
public object Convert(object value, System.Type
targetType, object parameter, System.Globalization                Caso prático 5
.CultureInfo culture)
                                                                  Atribuir uma lista de profissionais a uma datagrid.
{
                                                                  No XAML:
 return value.ToString().Substring(0, 4) + "-" +
value.ToString().Substring(4, 3);                                 É preciso definir o namespace

}
                                                                  xmlns:sdk="http://schemas.microsoft.com/
public object ConvertBack(object value,
                                                                  winfx/2006/xaml/presentation/sdk"
System.Type targetType, object parameter,
System.Globalization.CultureInfo culture)                         <sdk:DataGrid x:Name="datagrid"
{                                                                             AutoGenerateColumns="False">
  return int.Parse(value.ToString().Remove('-'));
                                                                  <sdk:DataGrid.Columns>
}                                                                  <sdk:DataGridTextColumn Header="Nome"
}                                                                       MinWidth="200"
                                                                        Binding="{Binding Name}" />
                                                                   <sdk:DataGridTextColumn
No XAML:
                                                                        Header="Código Postal"
É preciso definir o namespace                                           Width="100"
                                                                        MaxWidth="150"
                                                                        Binding="{Binding Path=PostalCode,
xmlns:sdk="http://schemas.microsoft.com/
                                                                              Converter={StaticResource
winfx/2006/xaml/presentation/sdk"
                                                                                    postalCodeConverter}}"/>
                                                                   <sdk:DataGridTextColumn
É preciso definir o conversor nos resources:
                                                                        Header="Endereço"
                                                                        Width="50"
<navigation:Page.Resources>
                                                                        Binding="{Binding Path=Address}"/>
   <Demo:PostalCodeConverter
                                                                   <sdk:DataGridTextColumn
                 x:Key="postalCodeConverter" />
                                                                        Header="Localidade"
</navigation:Page.Resources>
                                                                        Binding="{Binding Path=Locality}"/>

                                                                  </sdk:DataGrid.Columns>
Definição da label
                                                                  </sdk:DataGrid>
<sdk:Label Name="lblPostalCode"
      Content="{Binding Path=PostalCode,
                                                                  Em code-behind:
            Mode=TwoWay,
            UpdateSourceTrigger=Default,
            Converter={StaticResource                         datagrid.ItemsSource = professionals;
                  postalCodeConverter}}" />




                                                             33
A PROGRAMAR
DataBinding em Silverlight 4

Caso prático 6
                                                                      No XAML:
Definir um ItemTemplate para uma listbox.

No XAML:                                                              <TextBox Name="tbxDateOfBirth" Grid.Column="2"
                                                                      Grid.Row="2" Text="{Binding Path=DateOfBirth,
                                                                      StringFormat=MM-dd-yyyy}"/>
<ListBox Name="lbxProfessionalWidthDataTemplate">
  <ListBox.ItemTemplate>
                                                                      Ou
   <DataTemplate>
    <StackPanel Orientation="Vertical">                               <TextBox Name="tbxDateOfBirth" Grid.Column="2"
       <TextBlock Text="{Binding Path=Name}"/>                        Grid.Row="2" Text="{Binding Path=DateOfBirth,
       <TextBlock Text="{Binding _                                    StringFormat=MMM dd yyyy}"/>
             Path=PostalCode,
             Converter={StaticResource
                        postalCodeConverter}}"/>
       <TextBlock   Text="{Binding     Path=Address}"/>
       <TextBlock   Text="{Binding     Path=Locality}"/>
       <TextBlock   Text="{Binding     Path=Contact}"/>
       <TextBlock   Text="{Binding     Path=Mail}"/>                  Conclusão
    </StackPanel>
   </DataTemplate>
                                                                      Em conclusão, o conceito Databinding é uma forma simples
  </ListBox.ItemTemplate>                                             e eficiente de visualização e edição da informação nas apli-
 </ListBox>                                                           cações desenvolvidas em Silverlight.




Caso prático 7
Formatar o dia de aniversário usando o StringFormat.




AUTOR
                Sara Silva, é licenciada em Matemática – Especialidade em Computação, pela Universidade de Coimbra, actualmente é Software
                Developer no Porto.
                O entusiasmo pela área resultou na obtenção dos títulos de Microsoft Certified Profissional Developer – Windows 3.5, Microsoft
                Certified Tecnology Specialist – WPF 3.5, WPF 4 e Windows Forms.




                                                                 34
COLUNAS
VISUAL (NOT) BASIC — Primeiros passos com GDI+
CoreDump — Martelo <=> Inépcia
VISUAL (NOT) BASIC
Primeiros passos com GDI+
GDI?                                                                  A classe Graphics é a nossa porta da frente.
GDI ou Graphic Device Interface é a API responsável, directa          Podemos preparar uma superfície GDI+ com muita facilida-
ou indirectamente, total ou parcialmente, por tudo o que nos
                                                                      de.
chega aos olhos no mundo Windows.

Se não existe aceleração por hardware e estamos a ver cur-
                                                                      No decorrer do artigo, vou desenhar tudo num panel, apro-
vas, linhas, texto e gráficos desenhados, é porque a GDI              veitando o disparo do evento “Paint”, que ocorre sempre
assim o permite.                                                      que a área de desenho precise de ser actualizada, quer por
Através desta API conseguimos, de forma bastante penosa               indicação explícita invalidando o interface do objecto -
(para os produtos de desenvolvimento Microsoft de outrora),           PanelGDI.Invalidate() ,ou porque a área saiu do ecrã ou tem
desenhar geometria, gráficos e fontes para o ecrã ou para a           outra janela a tapar.
impressora.
                                                                      Normalmente podemos referenciar a superfície GDI do
                                                                      objecto por:
Com a evolução dos tempos, surgem novas necessidades e
por volta do Windows XP a Microsoft cria uma API para C/              Dim GDI As Graphics = PanelGDI.CreateGraphics()
C++ que chamou simplesmente de GDI+.

A API resistiu até hoje, onde já se tentam incutir tecnologias        Neste caso, como vamos utilizar o disparo do evento Paint,
baseadas em GDI mas que visam substituí-la, como                      um dos parâmetros que nos chegam do evento é precisa-
Direct2D.                                                             mente uma referência à superfície GDI:
A nova API reduziu significativamente a complexidade para o           Dim GDI As Graphics = e.Graphics
programador.


                                                                      Preparar para os primeiros rabiscos
GDI na .NET
                                                                      Com a superfície GDI preparada, poderíamos começar a
A API já se tinha tornado mais poderosa, mais fácil e repre-
                                                                      desenhar imediatamente.
sentando uma bela fatia no bolo da relevância de um siste-
ma operativo, só seria natural criar um acesso de alto nível,         Existem essencialmente      4   maneiras       diferentes   para
muito mais fácil e controlado na .NET framework. De facto a           “desenhar”:
Microsoft não poderia ter tornado o namespace mais sim-
                                                                      Bitmap, Pen, Brush e Font, servem respectivamente para
ples.
                                                                      desenhar imagens, desenhar linhas, pintar áreas e desenhar
                                                                      letras.
Para ganharmos acesso a todas as classes expostas basta-              Diferentes métodos utilizam diferentes formas de desenhar e
nos importar / fazer referência ao namespace Sys-                     todos em conjunto formam composições.
tem.Drawing.
                                                                      Estas formas de desenhar têm que ser preparadas antes de
É neste namespace que se encontram todas as classes e                 poderem ser utilizadas, mas antes…
sub-namespaces que nos permitem trabalhar imediatamente
com a API.
                                                                      Tamanho, posição e cor
Onde posso desenhar?
                                                                      Antes de poder começar a desenhar é importante entender
Como todos os componentes passam pela GDI, todos repre-
                                                                      algumas classes que nos ajudam a posicionar, dimensionar
sentam uma potencial folha em branco para os nossos dotes
                                                                      e colorir os nossos rabiscos:
artísticos.
Isto significa que todos os exemplos neste artigo, se aplica-
dos por exemplo num form, podem perfeitamente ser aplica-
dos desde o panel até a um item de listbox.



                                                                 36
VISUAL (NOT) BASIC
                                                                                          Primeiros passos com GDI+
Point / PointF                                                      As principais formas de desenhar
O Point é uma estrutura que representa essencialmente um            Bitmap / Image
conjunto de dois valores, X e Y, que representam uma coor-
                                                                    A classe Bitmap representa uma imagem completa, com
denada num referencial bidimensional.
                                                                    todas as suas propriedades e informação de cor pixel a pixel.
Podemos criar um ponto directamente no construtor:
                                                                    Nos métodos que impliquem desenhar imagens, é uma ins-
Dim Ponto As New Point(25, 35)                                      tância desta classe que vai ser usada.

Dim PontoF As New PointF(20.5F, 22.03F)                             Bitmap tem vários construtores, bastante específicos, mas
                                                                    vamos apenas considerar dois para este artigo.

                                                                    Dim Imagem As New Bitmap("C:imagem.png")
Size / SizeF
                                                                    Dim Imagem As New Bitmap(800, 600)
O Size é uma estrutura que representa um conjunto de dois
valores, Width e Height, que representam valores de largura         O primeiro construtor vai instanciar a classe com a informa-
e altura, respectivamente.                                          ção da imagem indicada.

Podemos criar uma dimensão directamente no construtor:              O segundo construtor vai criar uma imagem abstracta, com
                                                                    800x600 px
Dim Dimensao As New Size(800, 600)
                                                                    O primeiro construtor vai instanciar a classe com a informa-
Dim DimensaoF As New SizeF(100.05F, 100.07F)
                                                                    ção da imagem indicada.
Rectangle / RectangleF
                                                                    O segundo construtor vai criar uma imagem abstracta, com
O Rectangle é uma estrutura que representa um conjunto de
                                                                    800x600 px
4 valores, X, Y, Width e Height, que representam um combi-
nado de coordenadas XY e dimensão.                                  Pen
Podemos criar um Rectangle directamente no construtor:              A Pen é necessária para todos os métodos que impliquem o
                                                                    desenho de linhas, curvas e contornos.
Color
                                                                    Podemos criar uma Pen apenas por indicar a sua cor e
Dim Rectangulo As New Rectangle(0, 0, 100, 100)                     espessura:
Dim RectanguloF As _
                                                                    Mas existem mais propriedades na classe Pen que lhe
    New RectangleF(0.5F, 0.8F, 100.03F, 100.25F)                    Dim P As New Pen(Color.Black,2)

A Color é uma estrutura que representa um conjunto de 4
valores, A, R, G e B que representam os 4 canais que consti-        podem conferir mais características visíveis, tais como a
tuem uma cor aRGB: A para Alpha, ou o canal de opacidade,           forma terminal ou o estilo da linha, que não vou abordar.
RG e B para Red, Green e Blue, respectivamente.
                                                                    Brush
Cada canal comporta valores que variam dos 0 (ausência)
até 255 (presença total)                                            O Brush é necessário para todos os métodos que impliquem
                                                                    preenchimento de áreas.
A classe Color não tem construtores. Podemos obter uma
cor quer através da enumeração disponível, quer por utiliza-        Existem vários tipos de “pincel” que permitem a aplicação de
ção de alguns métodos disponíveis.                                  texturas, gradientes, padrões ou simplesmente uma cor.

                                                                    Vou focar essencialmente o SolidBrush, para cores únicas e
Dim Cor As Color = Color.FromArgb(255, 255, 0, 0)
                                                                    o LinearGradientBrush para gradientes de duas cores sim-
Dim Cor As Color = Color.Red                                        ples.
Dim Cor As Color = Color.FromName("Red")
                                                                    Podemos criar SolidBrush directamente no construtor:
Dim Cor As Color = _
                                                                    Dim B As New SolidBrush(Color.Red)
    Color.FromKnownColor(KnownColor.ActiveBorder)
                                                                    Também podemos criar LinearGradientBrush directamente
                                                                    no construtor:

                                                                    Dim B As New LinearGradientBrush(New         _
Com estas noções estamos aptos a colorir e posicionar os            Point(0, 0), New     _
nossos rabiscos.                                                    Point(100, 100), Color.Red, Color.Green)


                                                               37
VISUAL (NOT) BASIC
Primeiros passos com GDI+
É necessário um ponto onde o gradiente vai iniciar e um
ponto onde vai terminar, bem como as cores nesses mes-
mos pontos.
A mistura de cor no intervalo intermédio é automaticamente
calculada.

Existem classes que desempenham um papel importante na
mistura de cores do gradiente, mas não as vamos abordar.
                                                                   DrawBezier (Pen, Ponto1,Ponto2,Ponto3,Ponto4)
Observemos diferentes colocações dos pontos do gradiente
                                                                   O método DrawBezier desenha uma curva de Bézier com 4
abaixo:
                                                                   pontos de controlo.

                                                                   Existem mais overloads, mas são redundantes.

                                                                   Dim pt1 As New Point(0, 0)
                                                                   Dim pt2 As New Point(80, 20)
Font
                                                                   Dim pt3 As New Point(20, 80)
A Font é necessária para todos os métodos que impliquem o
uso das fontes do sistema.                                         Dim pt4 As New Point(100, 100)
                                                                   Dim g As Graphics = e.Graphics
Será tipicamente utilizada sempre que for necessário escre-
ver alguma coisa na superfície GDI.                                g.DrawBezier(New Pen(Brushes.Black, 2), _

Podemos criar uma Font directamente no construtor:                 pt1, pt2, pt3, pt4)

Dim F As New Font("Arial", 14)
Dim F As New Font("Arial", 14, FontStyle.Bold Or _
    FontStyle.Italic)
Dim F As New Font("Arial", 14, FontStyle.Bold Or _
    FontStyle.Italic, GraphicsUnit.Pixel)
Os métodos, finalmente.
                                                                   DrawCurve / DrawColsedCurve (Pen,Pontos(),Tensão)
Descrita toda a preparação, está na altura de explorar os
métodos da classe Graphics.                                        O método DrawCurve desenha uma curva linear, passando
                                                                   por os pontos no array Pontos(), aplicando a tensão defenida
O namespace “Drawing” é vasto e bastante completo.                 (valor de 0.0 a 1.0)
Vou apontar apenas o que considero mais importante.                DrawClosedCurve é em tudo semelhante, mas liga o último
                                                                   ponto em Pontos() ao primeiro, fechando a curva.

DrawArc(Pen,X,Y,Width,Height,AnguloInicial,Varrimento)             Existem mais overloads.

O método DrawArc desenha um arco com as propriedades               Dim pt1 As New Point(0, 0)
da Pen, com centro em XY, incluído no rectângulo de largura
                                                                   Dim pt2 As New Point(80, 20)
Width e altura Height, centrado.
                                                                   Dim pt3 As New Point(20, 80)
A curva começa no AnguloInicial e é desenhada até ao
ângulo AnguloInicial + Varrimento.                                 Dim pt4 As New Point(100, 100)
                                                                   Dim pts As Point() = New Point() {pt1, pt2, pt3,
Os ângulos são dados em graus.
                                                                   pt4}
Existem mais overloads, mas são redundantes.                       Dim g As Graphics = e.Graphics
Dim g As Graphics = e.Graphics                                     g.DrawCurve(New Pen(Brushes.Black, 2), pts, 0F)
g.DrawArc(New Pen(Brushes.Black, 2), 0, 0, 100,                    g.DrawCurve(New Pen(Brushes.Black, 2), pts, 0.5F)
100, 0, 90)
                                                                   g.DrawCurve(New Pen(Brushes.Black, 2), pts, 1F)
g.DrawArc(New Pen(Brushes.Black, 2), 0, 0, 100,
100, 180, 90)




                                                              38
VISUAL (NOT) BASIC
                                                                                        Primeiros passos com GDI+




DrawEllipse (Pen, Rectangulo)                                     DrawLine (Pen,Ponto1,Ponto2)
O método DrawEllipse desenha uma elipse inscrita no rec-          O método DrawLine desenha uma linha com origem em Pon-
tângulo especificado.                                             to1 e destino em Ponto2.

A elipse é desenhada no centro do rectângulo o que faz com        Existem mais overloads, mas são redundantes.
que se possa afirmar que, por exemplo, num quadrado
                                                              Dim pt1 As New Point(25, 25)
100x100, o método DrawEllipse vai desenhar uma circunfe-
rência centrada em x=50 e y=50 com raio de 50px               Dim pt2 As New Point(75, 75)

Dim rect1 As New Rectangle(0, 0, 100, 100)                    Dim g As Graphics = e.Graphics

Dim rect2 As New Rectangle(0, 0, 100, 50)                     g.DrawLine(New Pen(Brushes.Black, 2), pt1, pt2)

Dim g As Graphics = e.Graphics
g.DrawEllipse(New Pen(Brushes.Black, 2), rect1)
g.DrawEllipse(New Pen(Brushes.Black, 2), rect2)




                                                                  DrawPie (Pen,X,Y,Width,Height,AnguloInicial,Varrimento)
                                                                  O método DrawPie desenha uma secção de um círculo, lem-
                                                                  brando uma fatia de pizza ou tarte (Pie).

                                                                  A circunferência é inscrita no rectângulo formado por XY,
                                                                  Width e Height e é desenhada a secção da circunferência
                                                                  que começa no AnguloInicial e termina em AnguloIni-
                                                                  cial+Varrimento.
DrawImage (Bitmap,Ponto / Rectangulo)
                                                                  Os ângulos são dados em graus.
O método DrawImage desenha a informação de uma classe
Bitmap com origem no ponto especificado ou com origem e           Existem mais overloads, mas são redundantes.
dimensões ditadas pelo rectângulo.
                                                                  Dim g As Graphics = e.Graphics
Existem outros métodos semelhantes e muitos overloads, a          g.DrawPie(New Pen(Brushes.Black, 2), _
maioria redundantes.
                                                                       0, 0, 100, 100, 0, 90)
O canal Alpha é perfeitamente respeitado e obtêm-se boni-
                                                                  g.DrawPie(New Pen(Brushes.Black, 2), _
tos resultados com PNG.
                                                                       0, 0, 100, 100, 180, 90)

Dim B As New Bitmap("c:pap.png")
Dim Ponto As New Point(0, 0)
Dim g As Graphics = e.Graphics
g.DrawImage(B, Ponto)
Dim Rectangulo As New Rectangle(0, 50, 50, 50)
g.DrawImage(B, Rectangulo)




                                                             39
VISUAL (NOT) BASIC
Primeiros passos com GDI+
DrawPolygon (Pen,Pontos())
O método DrawPolygon desenha um polígono, ao ligar
sequencialmente todos os pontos especificados, voltando ao
primeiro depois do último.

Existe apenas mais um overload para utilizar valores com
casas decimais.

Dim pt1 As New Point(50, 0)
Dim pt2 As New Point(60, 40)                                      DrawString

Dim pt3 As New Point(100, 40)                                     (Texto,Fonte,Brush,Rectangulo,StringFormat)

Dim pt4 As New Point(65, 60)                                      O método DrawString desenha texto a partir de uma string,
                                                                  com uma determinada fonte e conjunto de características de
Dim pt5 As New Point(80, 100)
                                                                  formato.
Dim pt6 As New Point(50, 70)
                                                                  Existem overloads, alguns redundantes.
Dim pt7 As New Point(20, 100)
Dim pt8 As New Point(35, 60)
                                                                  Dim F As New Font("Arial", 7, FontStyle.Italic)
Dim pt9 As New Point(0, 40)
                                                                  Dim SF As New StringFormat
Dim pt10 As New Point(40, 40)
                                                                  SF.Alignment = StringAlignment.Center
Dim pts As Point() = New Point() _
                                                                  Dim R As New Rectangle(0, 50, 100, 40)
    {pt1, pt2, pt3, pt4, pt5, pt6, pt7, pt8, pt9,
pt10}                                                             Dim g As Graphics = e.Graphics

Dim g As Graphics = e.Graphics                                    g.DrawString("Portugal-a-Programar", F, _

g.DrawPolygon(New Pen(Brushes.Black, 2), pts)                         Brushes.Black, R, SF)
                                                                  SF.FormatFlags = StringFormat-
                                                                  Flags.DirectionVertical _
                                                                      Or StringFormatFlags.LineLimit
                                                                  F = New Font("Arial", 10, FontStyle.Italic _
                                                                      Or FontStyle.Bold)
                                                                  g.DrawString("GDI+", F, Brushes.Black, 0, 20, SF)




DrawRectangle (Pen,X,Y,Width.Height)
O método DrawRectangle desenha um rectângulo com ori-
                                                                  A maioria dos                         métodos de prefixo
gem no XY especificado e com as dimensões especificadas.
                                                                  “Draw” existe numa segunda versão “Fill”.
Existem mais overloads, mas são redundantes.
                                                                  A operação é semelhante, mas as áreas geradas são preen-
                                                                  chidas de acordo com um brush fornecido, quer seja ele sóli-
Dim g As Graphics = e.Graphics                                    do, gradiente, textura, hatch ou de qualquer outro tipo.
g.DrawRectangle(New _                                             Performance versus Qualidade
    Pen(Brushes.Black, 2), 10, 10, 80, 40)                        A classe Graphics possui algumas propriedades que defi-
                                                                  nem a forma como a GDI vai render os gráficos.




                                                             40
VISUAL (NOT) BASIC
                                                                                            Primeiros passos com GDI+
Como em tudo, se pretendemos qualidade temos de sacrifi-
car performance e vice-versa.
                                                                     MeasureString
Eis algumas das propriedades mais comuns e seus efeitos:
                                                                     Nos casos em que desenhamos texto indicando apenas uma
                                                                     posição de origem XY, este é desenhado de forma linear,
                                                                     sem qualquer limite.
                                                                     O método MeasureString permite-nos medir o tamanho que
                                                                     essa string vai ocupar, para que possamos fazer correcta-
                                                                     mente os nossos cálculos.
                                                                     Também é possível medir as dimensões de uma string dese-
                                                                     nhada dentro de uma área, que faz com que possamos ter
                                                                     noção do quanto “cresceu” nos casos onde ocorre
                                                                     “wordwrap”.
                                                                     O método MeasureString é muito semelhante ao método
                                                                     DrawString, pois precisa de saber exactamente como é que
                                                                     o texto foi (ou vai ser) desenhado, para que possa interna-
                                                                     mente fazer a simulação.
                                                                     O método devolve-nos as dimensões do texto, em largura e
                                                                     altura, num tipo de dados SizeF.


                                                                     Pen Cap / Dash Style
                                                                     Ao desenhar linhas, sobretudo com alguma espessura visí-
                                                                     vel, podemos notar que os terminais da linha são abrupta-
                                                                     mente cortados, como é normal.
                                                                     O pen cap determina precisamente como esses terminais
                                                                     são desenhados.
                                                                     Existem alguns caps disponíveis, para além da possibilidade
                                                                     de desenhar os nossos próprios caps (custom).
                                                                     Para além dos caps e de outras propiedades, é possível
Algumas dicas                                                        determinar como vai ser o traçado da linha, o Dash Style.
                                                                     Para este exemplo foi necessário utilizar a classe Graphics-
                                                                     Path, a qual não está prevista para este artigo.
Double Buffer
Se a intenção é usar a GDI+ para criar algum tipo de movi-
mento, tal como um pequeno jogo, algo que necessite de
constante e rápido refrescamento, rapidamente se nota que            Dim g1 As Graphics = PanelGDI.CreateGraphics
se torna impossível de continuar pois cada ciclo de refresca-        Dim g2 As Graphics = Panel1.CreateGraphics
mento é reflectido de forma negativa na superfície GDI.
                                                                     Dim g3 As Graphics = Panel2.CreateGraphics
Isto traduz-se num “piscar” insuportável que é causado pela
                                                                     Dim g4 As Graphics = Panel3.CreateGraphics
constante soma de execução do refrescamento e dos gráfi-
cos propriamente ditos.                                              Dim g5 As Graphics = Panel4.CreateGraphics

Nestes casos podemos, sacrificando um pouco de perfor-               g1.Clear(Color.White)
mance, utilizar um “Double buffer” que fará com que as               g2.Clear(Color.White)
actualizações sejam feitas em paralelo com a apresentação,
                                                                     g3.Clear(Color.White)
o que se traduz numa actualização “suave” da superfície
GDI, mas um pouco mais demorada.                                     g4.Clear(Color.White)

Num objecto como a Form, basta alimentar a propriedade               g5.Clear(Color.White)
DoubleBuffered para True.




                                                                41
VISUAL (NOT) BASIC
Primeiros passos com GDI+
                                                                       Dim cpts As Point() = New Point() _
Dim pt1 As New Point(20, 20)
Impressão                                                                  {cpt1, cpt2, cpt3, cpt4, cpt5, cpt6, cpt7,
Dim pt2 As New Point(80, 20)
                                                                       cpt8, cpt9, cpt10}
Dentro do namespace Drawing, pertencente ao namespace
Dim pt3 As New Point(20, 80)
Printing, encontramos algumas classes como PrintDocu-                  GP.AddPolygon(cpts)
Dim pt4 As New já conhecem80) fazer impressão de
ment, que muitos Point(80, para                                        Dim MyC As New CustomLineCap(Nothing, GP)
dados.
Dim MyP As New Pen(Brushes.Black, 6)
                                                                       MyP.EndCap = LineCap.Custom
Não é uma falha o namespace Printing estar incluído no
g1.DrawBezier(MyP, pt1, pt2, pt3, pt4) 'IMG1
namespace Drawing.                                                     MyP.StartCap = LineCap.Custom
                                                                       MyP.CustomStartCap = MyC
Na verdade, é possível desenhar documentos para a impres-
MyP = New Pen(Brushes.Black, 6)
sora exactamente da mesma forma que os desenharíamos                   MyP.CustomEndCap = MyC
MyP.StartCap = LineCap.DiamondAnchor
no form.                                                               g5.DrawBezier(MyP, pt1, pt2, pt3, pt4) 'IMG5
MyP.EndCap = LineCap.ArrowAnchor
g2.DrawBezier(MyP, pt1, pt2, pt3, pt4) 'IMG2
Em suma...
MyP = New Pen(Brushes.Black, 6)
O namespace Drawing e a GDI+ no geral, oferecem-nos um
MyP.DashStyle = DashStyle.Custompartir do qual pode-
grande potencial para a imaginação, a
MyP.DashPattern = visualmente ricas.
mos criar aplicações New Single() {0.5F, 1.0F, 0.5F,
                                                                       I
1.0F} como se programa com a API, em nível mais eleva-
A forma
Dim Setanamespace Drawing concede uma simplicidade de
do com o As New AdjustableArrowCap(1, 2)                               mpressão
tal forma que é possível desenhar uma linha com duas linhas            Dentro do namespace Drawing, pertencente ao namespace
Seta.Filled = False
de código.
                                                                       Printing, encontramos algumas classes como
MyP.CustomEndCap = Seta
Se queremos enriquecer visualmente uma aplicação Win-                  PrintDocument, que muitos já conhecem para fazer
g3.DrawBezier(MyP, pt1, pt2, pt3, pt4) 'IMG3 e
Forms, nem vale a pena procurar mais. A GDI+ é ideal                   impressão de dados.
está incluída na .NET.
MyP = New Pen(Brushes.Black, 6)                                        Não é uma falha o namespace Printing estar incluído no
MyP.DashCap = DashCap.Round                                            namespace Drawing.
MyP.EndCap = LineCap.RoundAnchor                                       Na verdade, é possível desenhar documentos para a
g4.DrawBezier(MyP, pt1, pt2, pt3, pt4) 'IMG4                           impressora exactamente da mesma forma que os
                                                                       desenharíamos no form.
MyP = New Pen(Brushes.Black, 1.5F)
Dim GP As New GraphicsPath()
                                                                       Em suma...
Dim cpt1 As New Point(5, 0)
Dim cpt2 As New Point(6, 4)                                            O namespace Drawing e a GDI+ no geral, oferecem-nos um
                                                                       grande potencial para a imaginação, a partir do qual
Dim cpt3 As New Point(10, 4)                                           podemos criar aplicações visualmente ricas.
Dim cpt4 As New Point(6, 6)
                                                                       A forma como se programa com a API, em nível mais
Dim cpt5 As New Point(8, 10)                                           elevado com o namespace Drawing concede uma
Dim cpt6 As New Point(5, 7)                                            simplicidade de tal forma que é possível desenhar uma linha
                                                                       com duas linhas de código.
Dim cpt7 As New Point(2, 10)
                                                                       Se queremos enriquecer visualmente uma aplicação
Dim cpt8 As New Point(3, 6)
                                                                       WinForms, nem vale a pena procurar mais. A GDI+ é ideal e
Dim cpt9 As New Point(0, 4)                                            está incluída na .NET.



AUTOR
                Sérgio Ribeiro, curioso e auto-didacta com uma enorme paixão por tecnologias de informação e uma saudável relação com
                a .NET framework.
                Moderador do quadro de Visual Basic.NET na comunidade Portugal@Programar desde Setembro de 2009.
                Alguns frutos do seu trabalho podem ser encontrados em http://www.sergioribeiro.com




                                                                  42
CoreDump
Martelo <=> Inépcia
Esta semana conversava com um colega e amigo sobre o                   primeira abordagem deve ser sempre a
facto da maioria dos profissionais de TI que chegam actual-            observação do plano de execução e a
mente ao mercado de trabalho não compreenderem as                      reescrita da query de forma mais eficien-
bases sobre as quais assentam as tecnologias que utilizam.             te.
Pode parecer conversa de “velho do restelo”, de quem tinha
                                                                       E quando chegamos aos paradigmas,
de saber configurar um disco rígido como master ou slave
                                                                       enfim... Constato que muitos não sabem
através de jumpers no hardware ou de quem tinha de saber
                                                                       sequer o que é a herança no paradigma
configurar o DOS correctamente para poder fazer uso total
                                                                       OO, fazendo classes que diferem ape-
dos 4 MB de RAM que estavam disponíveis e libertar ao
                                                                       nas num pequeno conjunto de atributos distinto. Pior, igno-
máximo os míticos 640Kb. Acreditem que nenhuma destas
                                                                       ram mecanismos como cálculo lambda e paradigmas como
experiências é saudosista e que o tema da conversa não
                                                                       os da programação funcional.
originou daí...
                                                                       Tenho outro amigo que costuma dizer, em relação a este tipo
A verdade é que actualmente detecto falhas nas bases de
                                                                       de comportamento padrão, que “quando a única ferramen-
muitos profissionais de TI que, ou por não terem sido bem
                                                                       ta que se conhece é o martelo, todos os problemas pare-
orientados, ou pela actual facilidade tecnológica, ou por sim-
                                                                       cem um prego”. E a verdade é que esta frase resume um
ples preguiça pessoal, não compreendem na totalidade as
                                                                       pouco o que se passa. Em vez de se compreender o que se
tecnologias com que trabalham diariamente.
                                                                       passa para procurar a melhor solução a aplicar, martela-se a
São exemplos típicos a utilização de frameworks, que facili-           única solução que se conhece... Por vezes a aplicação da
tam o desenvolvimento através da elevação de conceitos e               solução escala com o problema e quanto maior o problema,
abstracção, a utilização de bases de dados e a utilização do           maior a martelada... Fico a pensar se será ironia ou pura
paradigma Object Oriented.                                             casualidade o facto de tantas aplicações terem um martelo
                                                                       como ícone em algumas das suas opções de menu.
Uma framework simplifica e agiliza o desenvolvimento, mas
também esconde e abstrai o trabalho que está por detrás,               É óbvio que compreender as bases da tecnologia é impres-
fazendo querer a muitos dos seus utilizadores que é magia.             cindível para saber o que andamos a fazer. Se não com-
Como resultado, temos muitas vezes profissionais de TI                 preendermos as bases da tecnologia, dificilmente saberemos
incapazes de compreender a sua ferramenta de trabalho,                 o que estamos a fazer e se não sabemos o que estamos a
ficando à sua mercê. Este desconhecimento torna-se rele-               fazer, então o resultado do nosso trabalho nunca será gran-
vante quando se deparam com determinados bugs relacio-                 de coisa... Ninguém nasce ensinado, mas nunca na história
nados com a framework ou quando necessitam de imple-                   da Humanidade foi tão simples, rápido e barato aceder ao
mentar uma solução que sai fora do âmbito da aplicação da              conhecimento. Na área de TI não faltam livros, blogs, fóruns
framework.                                                             e afins onde tudo se encontra documentado e descrito para
                                                                       nossa compreensão. Infelizmente, também aqui, vejo que
É preocupante observar que todos os problemas de lentidão
                                                                       muitos usam a internet de forma errada, fazendo copy-
de uma aplicação se resolvem com mais RAM ou mais CPU
                                                                       paste programming em vez de compreenderem a solu-
sem sequer se identificar a causa do problema recorrendo à
                                                                       ção e, quando o código copiado de um qualquer site não
utilização de um profiler.
                                                                       funciona à primeira, o resultado é um post com um pedido de
Uma base de dados é imprescindível para qualquer sistema               ajuda. Infelizmente, a nossa comunidade também tem exem-
informático, e desconhecer a 3ª Forma Normal é meio cami-              plos de sobra deste tipo… A culpa da formação inadequada
nho andado para um sistema deficiente. Este problema é                 só é responsável até certo ponto, uma vez que todos estes
visível na nossa própria comunidade, onde recorrentemente              problemas se resolvem com a adopção de uma postura e
se vêm estagiários e estudantes – futuros profissionais de TI          atitude de querer saber e compreender por parte de cada
– a desenvolverem projectos em que criam tabelas sem                   um. Por isso peço a todos os que pretendem trabalhar em TI
saber o que representam e não terem qualquer noção das                 que façam um favor a vocês próprios: larguem o martelo,
suas relações. É gritante observar que a única solução para            continuem a aprender e não cedam à inépcia.
uma query lenta passa pela criação de um índice, quando a


AUTOR
                Fernando Martins, faz parte da geração que se iniciou nos ZX Spectrum 48K. Tem um Mestrado em Informática e mais de
                uma década de experiência profissional nas áreas de Tecnologias e Sistemas de Informação. Criou a sua
                própria consultora sendo a sua especialidade a migração de dados.




                                                                  43
COMUNIDADES
SharePointPT - Padrão alternativo de Sharepoint
COMUNIDADE SHAREPOINTPT                                                                        http://www.sharepointpt.org




Padrão alternativo de Sharepoint: a pesquisa como
fonte de dados – parte I – Arquitectura
A plataforma Sharepoint tem sido nos últimos anos, um                       Robustez: os tempos de indisponibilidade são críticos
importante suporte para o desenvolvimento de soluções                       para a organização; dada a especialidade do negócio
empresariais de intra/extra/internet. Com maior ou menor                    a suportar pela plataforma, a aplicação não deverá
dificuldade as equipas entram no padrão de desenvolvimen-                   apresentar picos diários de utilização, prevendo-se
to modular (p.e. webparts) ou via extensão da própria plata-                um volume de utilizadores estável no período 06:00
forma, suportado por pacotes de instalação (wsps) e funcio-                 até às 02:00, altura em que a utilização decai para um
nalidades empacotadas (features), tendo asseguradas de                      valor residual;
base algumas funcionalidades interessantes, como p.e.:
                                                                            Não perder 1 única encomenda: a plataforma deverá
       Controlo de acessos                                                  permitir recuperar todas as encomendas que possam
                                                                            falhar, para posterior processamento por operadores;
       Motor de workflows
                                                                            Ter um portal para gerir a informação genérica dos
       Plataforma de edição de conteúdos                                    produtos.
       Serviços transversais (pesquisa, excel, business intel-        A XPTO tem um volume de aproximadamente 20.000 utiliza-
       ligence, etc)                                                  dores registados, com um acesso diário previsto de 10%.

       Instalação de pacotes em toda a farm de forma auto-
       mática
                                                                      Arquitectura
Neste artigo pretende-se desconstruir as abordagens mais              Como componentes da arquitectura, é proposta uma aborda-
tradicionais, apresentando uma solução pouco comum atra-              gem distribuída em vários componentes/plataformas, tirando
vés de uma arquitectura, mas que optimiza os módulos de               proveito das principais características de cada uma:
maior interesse para o cenário apresentado, centrando-se
principalmente na componente de indexação e pesquisa do                     Apresentação: IIS (Internet Information Services), .Net
Sharepoint. Este cenário corresponde a parte de uma imple-                  4 e MVC
mentação real.
                                                                            Como principais vantagens destas tecnologias temos
Neste 1º artigo, é abordada a componente de arquitectura da                 a escalabilidade, robustez e flexibilidade
solução e componentes de alto nível, para permitir a visuali-
                                                                            Gestão de conteúdos e indexação: Sharepoint
zação da solução.
                                                                            A gestão de conteúdos e indexação são alguns dos
No 2º artigo da série, será descrita a componente mais técni-               principais pontos fortes da plataforma Sharepoint
ca, incluindo a configuração das regras de pesquisa, das
propriedades (crawlled e managed), models de consumo dos                    Gestão de catálogo: Commerce Server
dados e o respectivo empacotamento da solução de indexa-
                                                                            A plataforma de comércio electrónico centra-se
ção.

Cenário
                                                                      Esta arquitectura conta ainda com as plataformas Biztalk na
A empresa XPTO necessita de um portal público que dispo-              componente de integração e com o CRM na componente de
nibilize uma loja de comércio electrónico, tendo como princi-         gestão de clientes, ficando no entanto de fora do tema pro-
pais requisitos:                                                      posto neste artigo.

                                                                      A camada de apresentação é integralmente suportada por
       Performance: carregamento de páginas até 3 segun-
                                                                      uma implementação MVC, cujos models vão beber dados
       dos, independentemente do volume de acessos;
                                                                      principalmente às plataformas Commerce e Sharepoint
       Escalabilidade: a plataforma deve permitir um proces-          (search services).
       so evolutivo simples e sólido;
                                                                      A gestão de conteúdos é suportada por um portal Share-
                                                                      point, onde as características de produtos, ficheiros


                                                                 45
COMUNIDADE SHAREPOINTPT
http://www.sharepointpt.org

Padrão alternativo de Sharepoint: a pesquisa como fonte de dados
multimédia e documentos são geridos e mantidos por circui-
tos de aprovação standard.

Toda a informação de catálogo e stock é mantida na platafor-
ma Commerce, que tembém suporta toda a parte de carrinho
de compras.

Uma vez que a informação se encontra distribuída nas plata-
formas Commerce, Sharepoint e ainda em alguns sistemas
externos, opta-se pela utilização da componente de indexa-
ção para unir esta informação dispersa, através da constru-
ção de uma plataforma de indexação costumizada, composta
por uma componente de listagem e um segundo nível com o
detalhe dos produtos.




                                                                                                                       Este padrão apresenta como principais vantagens:

                                                                                                                             Melhor organização da aplicação pela divisão das
                                                                                                                             várias lógicas em zonas separadas;

                                                                                                                             Não usa view state ou forms, o que dá um maior con-
                                                                                                                             trolo sobre a aplicação e sobre a informação trocada
Stock, preço, carrinho e perfil                                         Dados de produtos
                                        IIS,MVC

                                                                                                                             com o utilizador;
                                              Dados de Catálogo
                                                                                                                             Melhor suporte para um padrão de desenvolvimento
                          Commerce                                Sharepoint
                                                                                                                             TDD (Test Driven Development é um padrão que pro-
                                                                                            Edição de conteúdos
                                                                                                                             move o desenvolvimento baseado na existência de
                                                                                                                             testes unitários);

                                                                                                                             Dada a granularidade fina dos componentes, é uma
                                                                                                                             boa aposta para equipas de maior dimensão.


                                     SQL Server

                                                                                                                       Indexação e pesquisa
                                                                                                                       Tendo a pesquisa como fonte de dados da camada de apre-
Padrão MVC (Model-View-Controller)                                                                                     sentação, vários pontos surgem como requisitos deste com-
                                                                                                                       ponente:
Tema para um artigo só por si, o MVC é um padrão de imple-
mentação que merece uma breve referência para enquadra-                                                                      Fornecer informação de carácter genérico, contida
mento (e para despertar o interesse pelos padrões, para                                                                      num portal de Sharepoint;
quem ainda não os conhece).
                                                                                                                             Fornecer informação de catálogo, contida no Com-
                                                                                                                             merce Server;
O padrão arquitectural MVC separa as camadas aplicacio-
nais em 3 componentes:                                                                                                       Fornecer informação de cariz técnico, contida em
                                                                                                                             outros sistemas externos;
                   Model: responsável pela representação e manuten-
                   ção dos estados dos dados;                                                                          Com base nestas necessidades optou-se pela seguinte abor-
                                                                                                                       dagem:
                   View: camada de apresentação, responsável por
                                                                                                                             Criação de um conjunto de páginas de índice em cas-
                   mostrar os dados e interagir com o utilizador;
                                                                                                                             cata, que começam por listar sites com link para o
                   Controller: camada de lógica que toma as decisões                                                         nível seguinte onde passa o site seleccionado no link;
                   baseada nos dados inseridos pelos utilizadores na                                                         no nível seguinte lista os sub-sites do site selecciona-
                   View, passando a informação necessária ao Model                                                           do e por último, lista os produtos com link para a pági-
                   correspondente para manuseamento dos dados.                                                               na de detalhe do produto.



                                                                                                                  46
COMUNIDADE SHAREPOINTPT                                                                      http://www.sharepointpt.org


                               Padrão alternativo de Sharepoint: a pesquisa como fonte de dados
                                                                         multithreaded permite paralelizar as várias recolhas e
                                                                         diminuir significativamente o tempo de carregamento
              List sites                                                 da página. Uma vez que esta página será chamada
                                                                         tantas vezes, quantos os produtos existentes, tem um
                                                                         impacto significativo na duração total do processo de
                    List subsites                                        indexação e consequentemente na desactualização
                                                                         da informação para o utilizador final (p.e. se uma
                                                                         indexação demorar 1 hora, há a probabilidade dos
                        List products                                    dados dos produtos apresentados estejam desactuali-
                                                                         zados até 1 hora atrás).
                             Produt detail                               O modelo do processo de recolha de informação e
                                                                         geração da página de indexação é apresentado no
                                                                         diagrama seguinte.
     Página de detalhe do produto que recebe por parâ-
     metro o sub-site, bem como o código do produto e
     gera uma página de detalhe contendo os dados
     necessários para a camada de apresentação. Estes
     dados, ao serem indexados na mesma “página” ficam
     relacionados entre si. Ao incluirmos uma chave (ex. id
     do produto), vamos poder aceder-lhe como uma enti-
     dade.




                                                                   O código gerado pela página de detalhe do produto é algo
                                                                   do tipo:

                                                                   <html>
                                                                     <head>
                                                                       <title>Detalhe de produto</title>

                                                                             <meta name="ProductName"
                                                                                   content="Single Track King" />

                                                                             <meta name="ProductCategory"
                                                                                   content="Bicicletas Todo Terreno" />
Os principais desafios da componente de indexação,                           <meta name="ProductDescription"
revelam-se nesta altura e vale a pena salientar:                                   content="A melhor btt de sempre." />

     Uma vez que para um comportamento correcto desta                        <meta name="ProductImage"
     página, os dados têm de ser indexados em metatags                         content="/images/products/1234567.jpg" />
     e consequentemente são indexados como texto pelo                     <meta name="ProductId"
     Sharepoint;                                                                content="1234567" />
                                                                             …
     Ao indexar via metatags, perde-se a caracterização              </head>
     dos dados (ver “O que perdemos com a indexação via              <body></body>
     metatags”);
                                                                   </html>
     Esta página tem de aceder a vários sistemas, desde
     listas de Sharepoint a web services e WCFs de outras          Ao ser indexada esta página fará com que sejam criadas
     plataformas, o que a torna pesada; uma abordagem              propriedades (crawlled properties de Sharepoint), com os
                                                                   nomes ProductName, ProductCategory, ProductDescription,
                                                                   etc. que por sua vez poderão ser promovidas por configura-


                                                              47
COMUNIDADE SHAREPOINTPT
http://www.sharepointpt.org

Padrão alternativo de Sharepoint: a pesquisa como fonte de dados
A abordagem do processo de indexação é propositadamente                         melhor performance, mas potencialmente mais onero-
simplista, para permitir tirarmos proveito do modelo multith-                   sa tendo em conta o licenciamento;
readed da pesquisa, levando-nos a construir as páginas tão
                                                                                Via serviços (Query Via serviços (Query Web Servi-
simples e pequenas quanto possível, evitando desta forma
                                                                                ce); solução mais flexível mas com alguma desvanta-
esgotar os recursos das máquinas.
                                                                                gem em termos de performance.
O que perdemos com a indexação via metatags

O processo de indexação baseado em metatags tem uma
desvantagem imediata que é a descaracterização do tipo de                 Conclusão
dados, uma vez que estaremos a indexar páginas HTML, em
                                                                          Plataformas com a complexidade do Sharepoint são candi-
cujos campos de meta são sempre indexados como texto.
                                                                          datas a implementações inovadoras, uma vez que disponibi-
No nosso cenário, esta desvantagem é minimizada, uma vez
                                                                          lizam um conjunto grande de funcionalidades, para os quais
que os dados indexados são utilizados apenas para geração
                                                                          nem todos os cenários foram equacionados pelas equipas
da apresentação, baseando-se os dados e processo de com-
                                                                          de produto e/ou arquitectura. Neste artigo é apresentada
pra na plataforma Commerce.
                                                                          uma solução diferente das habitualmente recomendas, mas
É sempre possível efectuar transformações de tipo (cast ou                com provas dadas de escalabilidade e fiabilidade para um
parse) que devidamente efectuadas não trazem desvanta-                    ambiente empresarial bastante exigente. Espero com este
gens em termo de estabilidade, mas são operações pesadas                  exemplo conseguir despertar em si, o pensamento fora da
em termos de ciclos de processamento trazendo uma degra-                  caixa.
dação significativa da performance quando invocadas fre-
                                                                          No próximo artigo desta série, será abordada a componente
quentemente.
                                                                          de implementação da solução, com exemplos de código de
string myText = "123456";                                                 cada um dos componentes.
   int myVal;

                                                                          Referências
   if (!int.TryParse(myText, out myVal))
                                                                           Nota: apesar de estarmos numa publicação em língua portu-
   {
                                                                          guesa, as referências apresentadas são na maioria dos
       // Ocorreu um erro no processo de parse                            casos para as versões inglesas. Isto deve-se somente a, por
       // tratar o erro neste ponto                                       experiência própria, o conteúdo em inglês ser mais rico e
   }                                                                      actualizado que nas restantes línguas.



                                                                          IIS – http://www.iis.net
Consumo da informação                                                     Microsoft Commerce Server - http://bit.ly/s5Uu2
                                                                          Microsoft Sharepoint Server - http://bit.ly/qmpwu3
Estando a informação devidamente indexada pelo Share-
point, é altura de ser consumida e renderizada nas máquinas               MVC - http://www.asp.net/mvc
responsáveis pela apresentação dos dados. O consumo da                    SharePoint Search Service Tool - http://bit.ly/ZY9H3
informação, efectuado pelos models MVC, poderá ser feito                  Test Driven Development - http://bit.ly/qAIxha
de duas formas:                                                           The Search Developer Story in SharePoint 2010 - Query In-
        Via API (Query Object Model), necessitando de ter o               terfaces - http://bit.ly/bnaA4G
        Sharepoint instalado nestas máquinas; solução de



AUTOR
                   Rui Melo - rui.melo@microsoft.com

                   Desde há 12 anos, no mundo das IT, iniciou a carreira na área de I&D de comércio electrónico. Passou por empresas como
                   SMD, Pararede, Newvalue e Link, integrou os quadros da Microsoft como consultor há cerca de 5 anos, mais focado na plata-
                   forma Sharepoint. Envolvido desde cedo na comunidade SharepointPT, tem na partilha de conhecimento uma forte motiva-
                   ção. Blog: http://mystepstones.wordpress.com.




                                                                     48
Veja também as edições anteriores da




                                                                                                www.revista-programar.info
        Revista PROGRAMAR




                                       28ª Edição - Abril 2011    25ª Edição - Setembro 2010




                                                                                                   e muito mais em …
                                       29ª Edição - Junho 2011    26ª Edição - Dezembro 2010
                                       30ª Edição - Agosto 2011   27ª Edição - Fevereiro 2011
Revista programar 31

Mais conteúdo relacionado

PDF
Revista programar 29
PDF
CONVERGÊNCIA DIGITAL - COMUNICANDO O EVANGELHO COM OS RECURSOS DA ATUALIDADE ...
PDF
Livigno cosmesi-naturale
PDF
Revista programar 11
PDF
RESEÑA DE LA I.E. 3014 - LEONCIO PRADO
PPTX
UN MODELO PARA INTEGRAR LAS TIC AL CURRÍCULO ESCOLAR INFRAESTRUCTURA TIC
PPTX
Web 2.0, Brenda Y Sofia.
PPTX
Revista programar 29
CONVERGÊNCIA DIGITAL - COMUNICANDO O EVANGELHO COM OS RECURSOS DA ATUALIDADE ...
Livigno cosmesi-naturale
Revista programar 11
RESEÑA DE LA I.E. 3014 - LEONCIO PRADO
UN MODELO PARA INTEGRAR LAS TIC AL CURRÍCULO ESCOLAR INFRAESTRUCTURA TIC
Web 2.0, Brenda Y Sofia.

Semelhante a Revista programar 31 (20)

PDF
Revista programar 32
PDF
Revista programar 36
PDF
Revista programar 30
PDF
Revista programar 33
PDF
Revista programar 34
PDF
Steve Jobs no Página 1
PPTX
Bruno 7ºb
PPTX
Bruno7b
PDF
Revista programar 39
PDF
Revista programar 27
PDF
Revista programar 28
PDF
Revista programar 38
PDF
Era Digital, Cabeça Industrial
PDF
Revista programar 25
PDF
Revista programar 23
PDF
Revista programar 26
PDF
Porque é que o iPad não é indicado para as Forças de Vendas (Pharma)
PDF
Software livre e Empresas
PDF
Software Livre E As Empresas
PDF
Revista programar 17
Revista programar 32
Revista programar 36
Revista programar 30
Revista programar 33
Revista programar 34
Steve Jobs no Página 1
Bruno 7ºb
Bruno7b
Revista programar 39
Revista programar 27
Revista programar 28
Revista programar 38
Era Digital, Cabeça Industrial
Revista programar 25
Revista programar 23
Revista programar 26
Porque é que o iPad não é indicado para as Forças de Vendas (Pharma)
Software livre e Empresas
Software Livre E As Empresas
Revista programar 17
Anúncio

Mais de Filipe Bezerra Sousa (18)

PDF
Revista programar 23
PDF
Revista Programar 43
PDF
Revista Programar 42
PDF
Revista Programar 41
PDF
Revista Programar 40
PDF
Revista programar 37
DOCX
Como criar metas por fred graef
DOCX
Estudo de produtividade com eclipse
PDF
Revista espirito livre_035_fevereiro2012
PDF
Revista espirito livre_0019_outubro2010
PDF
Revista espirito livre_016_julho2010
PDF
Revista espirito livre_015_junho2010
PDF
Revista espirito livre_014_maio2010
PDF
Revista espirito livre_013_abril2010
PDF
Revista espirito livre_012_marco2010
PDF
Revista espirito livre_011_fevereiro10
PDF
Revista espirito livre_010_janeiro10
PDF
Revista espirito livre_009_dezembro09
Revista programar 23
Revista Programar 43
Revista Programar 42
Revista Programar 41
Revista Programar 40
Revista programar 37
Como criar metas por fred graef
Estudo de produtividade com eclipse
Revista espirito livre_035_fevereiro2012
Revista espirito livre_0019_outubro2010
Revista espirito livre_016_julho2010
Revista espirito livre_015_junho2010
Revista espirito livre_014_maio2010
Revista espirito livre_013_abril2010
Revista espirito livre_012_marco2010
Revista espirito livre_011_fevereiro10
Revista espirito livre_010_janeiro10
Revista espirito livre_009_dezembro09
Anúncio

Último (20)

PPTX
ANALISE E GERENCIAMENTO DE RISCO_mba.pptx
PPSX
10ano-Q-1-2-1-espetros-continuos-e-descontinuos.ppsx
PPT
TREINAMENTO COMBATE A INCÊNDIO para empresas
PPTX
analise-swot- turma ADM - E SUAS CONCEPÇÕES
PDF
Brincar é coisa séria_ como jogos desenvolvem competências socioemocionais...
PDF
EQUIPE CARLOS.pdffffffffffffffffffffffffffffffffff
PDF
Apresentação sobre a sustentabilidade, ambiental, social e governança da Unil...
PDF
Processos_Gerenciais_Modelos_de_Gestão.pdf
PPTX
Inteligência Artificial no Cotidiano 333
PDF
599625643-MARKETING-PESSOAL.pdfffffffffffffffffffff
PPTX
Capacitacao_online_Monitoramento_Ciclo_PDCA.pptx Lamentamos, mas o ficheiro C...
PPTX
Aula de administração estrategica_mba.pptx
PPTX
Aula_Processo_Administrativo_Gestão_e_Organização
PDF
EMANUEL.pdffffffffffffffffffffffffffffffffffffffffff
PPTX
estratégia em rh sjdfjdjfhd cojkjdgkdf bdjfgkdfg
DOCX
projeto ceara cientifico.docx PARA ALEM DA EDUCAÇÃO INCLUSIVA
PDF
Riscos da IA: O Guia Definitivo para Gestores sobre Governança, PL 2338 e a A...
PPT
CIPA CURSO MOTIVAÇÃO AO CIPEIRO.ppt kjsb
PDF
ilide.info-aula01-origem-e-evoluo-da-gesto-de-projetos-pr_c710e42c1fc6e323463...
PDF
APRESENTACAO COLETIVA ABRAS RETROSPECTIVA 2020.pdf
ANALISE E GERENCIAMENTO DE RISCO_mba.pptx
10ano-Q-1-2-1-espetros-continuos-e-descontinuos.ppsx
TREINAMENTO COMBATE A INCÊNDIO para empresas
analise-swot- turma ADM - E SUAS CONCEPÇÕES
Brincar é coisa séria_ como jogos desenvolvem competências socioemocionais...
EQUIPE CARLOS.pdffffffffffffffffffffffffffffffffff
Apresentação sobre a sustentabilidade, ambiental, social e governança da Unil...
Processos_Gerenciais_Modelos_de_Gestão.pdf
Inteligência Artificial no Cotidiano 333
599625643-MARKETING-PESSOAL.pdfffffffffffffffffffff
Capacitacao_online_Monitoramento_Ciclo_PDCA.pptx Lamentamos, mas o ficheiro C...
Aula de administração estrategica_mba.pptx
Aula_Processo_Administrativo_Gestão_e_Organização
EMANUEL.pdffffffffffffffffffffffffffffffffffffffffff
estratégia em rh sjdfjdjfhd cojkjdgkdf bdjfgkdfg
projeto ceara cientifico.docx PARA ALEM DA EDUCAÇÃO INCLUSIVA
Riscos da IA: O Guia Definitivo para Gestores sobre Governança, PL 2338 e a A...
CIPA CURSO MOTIVAÇÃO AO CIPEIRO.ppt kjsb
ilide.info-aula01-origem-e-evoluo-da-gesto-de-projetos-pr_c710e42c1fc6e323463...
APRESENTACAO COLETIVA ABRAS RETROSPECTIVA 2020.pdf

Revista programar 31

  • 2. EDITORIAL EQUIPA PROGRAMAR (Des)Informação Coordenadores Actualmente muito se têm falado sobre tudo. Falado e especulado. Com a saída de António Silva Steve Jobs da Apple especula-se qual serão as implicações para a marca da maçã. Fernando Martins Com o lançamento do Windows 8 especula-se sobre a capacidade deste conquistar o mercado dos tablets. Com a conferência da Apple “Let’s talk about IPhone” especulou-se sobre o possível anúncio da data de lançamento do IPhone 5. Com o Editor abandono da Nokia, especulou-se o que aconteceria ao sistema operativo Meego. E António Santos muito mais se especula. Infelizmente a nossa sociedade vive presa às especulações, e creio que o melhor Design exemplo disso, nem está na área tecnológica, mas sim na área financeira com a Sérgio Alves crise em que vivemos ser altamente ampliada pelas especulações. Há uns anos Twitter: @scorpion_blood atrás sempre que alguém queria dar um exemplo financeiramente forte sobre especulações falava sobre a famosa Quinta-feira negra, onde as acções de um dia tiveram efeitos nos anos seguintes e onde aconteceu a muitos acordar rico e Redacção adormecer pobre. Todavia hoje não precisámos de dar um exemplo tão longínquo no António Silva tempo e em que muitos não conhecem as verdadeiras consequências. Agora Augusto Manzano Bruno Lopes podemos fala no presente. Fernando Martins Mas não precisámos de falar apenas na área financeira, podemos falar de qualquer Rui Melo área, inclusivamente a informática. Apesar de o IPhone 5 ainda não ter sido lançado, Sara Silva nem existirem provas de que alguma vez irá ver a luz do dia, a “publicidade” feita em Sérgio Ribeiro torno dele, torna-o no alvo de curiosidade para o bem e para o mal. Chamar-lhe-ia Vítor Tomaz publicidade gratuita. Se eu dissesse que era provável um canal de televisão deixasse de existir no dia x, estaria a especular. Provavelmente teria pouco reflexo na sociedade, uma vez que os próprios meios de comunicação social me dariam Staff pouco tempo de antena, ao invés destes assuntos sobre grandes empresas. António Santos Contudo estaria a distorcer o mercado, criando expectativa em volta de algo que eu Fábio Canada apenas defendia/acreditava, mas sem ter provas ou factos. Fábio Domingos Numa área cujo nome deriva de Informação automática, a verdadeira informação Jorge Paulino que é processada, comparativamente com o total de dados é cada vez menor. Cada Pedro Martins vez mais recorremos a uma ferramenta que deveria armazenar e processar dados Sara Santos gerando informação, contudo devido à falta de fidedignidade das fontes e Contacto contrariedade dos dados lá introduzidos é muitas vezes gerada desinformação. Se revistaprogramar@portugal-a- eu disse-se que o mundo acabava hoje dentro de 5 minutos, mesmo que muita gente programar.org acredita-se em mim pouco podia fazer até verificar a veracidade dessa informação. Passados 5 minutos saberiam se era verdade ou não. Se eu disser que o mundo acaba em 21 de Dezembro de 2012 ainda se terá muito que esperar até se Website conseguir confirmar ou não a afirmação. Por isso não é informação, mas sim http://www.revista-programar.info especulação. Especulação que faz vender, que mexe com os mercados, que coloca em muitos os nervos à flor da pele, que deixa outros com um sorriso de vitória, que impede o sono tranquilo de muitos, mas que não passa de uma simples afirmação, ISSN cuja veracidade não pode ser demonstrada na altura em que foi proferida. 1 647-071 0 NR: Em notícia de última hora soube-se do falecimento de Steve Jobs. Para o bem e para o mal foi um nome incontornável no mundo da tecnologia, e que contribuiu para a sua evolução., por isso aqui ficam registadas as nossas condolências. António Silva <antonio.silva@revista-programar.info> A revista PROGRAMAR é um projecto voluntário sem fins lucrativos. Todos os artigos são da responsabilidade dos autores, não podendo a revista ou a comunidade ser responsável por alguma imprecisão ou erro. Para qualquer dúvida ou esclarecimento poderá sempre contactar-nos. 2
  • 3. ÍNDICE TEMA DE CAPA 7 Netponto - NHibernate - Técnicas para software melhor e mais rápido Saiba mais sobre estas técnicas para melhor software e mais rápido. Bruno Lopes A PROGRAMAR 17 Geração de Números Aleatórios O primeiro de 4 artigos do mesmo autor da excelente série “Programação em Lua”, desta vez sobre geração de núme- ros aleatórios. Augusto Manzano 21 Programar para Windows Azure Conheça alguns detalhes bem como alguns cuidados que deveremos ter em conta quando desenvolvemos para esta plataforma. Vítor Tomaz 25 Programação Orientada a Objectos em Java 6 Saiba as melhores práticas e métodos de programação neste paradigma em Java 6. António Silva 30 DataBinding em Silverlight 4 Conheça o conceito de Databinding na plataforma Silverlight. Sara Silva COLUNAS 36 Visual (NOT) Basic - Primeiros Passos com GDI+ Saiba mais sobre a API responsável por tudo o que nos “chega aos olhos” no mundo Windows. Sérgio Ribeiro 43 Core Dump - Martelo <=> Inépcia Neste artigo de opinião, conheça segundo o autor, a origem das falhas nas bases de muitos profissionais de TI. Fer- nando Martins COMUNIDADES 45 SharePointPt—Padrão alternativo de Sharepoint Neste artigo da comunidade SharePointPT, saiba como desconstruir as abordagens mais tradicionais, através de uma solução pouco comum através de uma arquitectura que optimiza os módulos de maior interesse para o cenário apre- sentado. Rui Melo. EVENTOS 19 a 21 Out Capsi 2011 18 Out Upload Lisboa 28 Out 24ª Reunião Presencial NetPonto 10 a 12 Nov Sapo Codebits V 02 Nov SASIG 4 Para mais informações/eventos: http://bit.ly/PAP_Eventos 3
  • 4. NOTICIAS O melhor amigo do Ipad é português Apple pode continuar a limitar uso e ecológico do Mac OS aos seus computadores A Apple tem o direito de restringir a utilização do sistema ope- “Kork2 foi desenhado pela A Pro- rativo OS X aos computadores fabricados pela empresa. A dukt e produzido em Paços de decisão do tribunal de recurso norte-americano foi conhecida Brandão num material reciclado e esta semana, três anos depois de iniciada a batalha legal con- reciclável. tra a Psystar, uma fabricante de "clones" dos produtos da É o “canivete suíço” do Ipad e foi maçã. A sentença anterior já havia dado razão à empresa de Steve Jobs, mas a Psystar - embora não tenha reclamado da desenhado pela A Produkt, violação de direitos de autor de que foi acusada por copiar o empresa sediada em Portugal hardware da Apple - interpôs recurso da decisão alegando rendida aos encantos da cortiça. que as condições de licenciamento impostas para o Mac OS O Kork2 – sucessor do Kork por direito – ajusta-se ao Ipad2, constituíam uma tentativa ilegal para estender a proteção dos protegendo-o e tornando a sua utilização ainda mais confortá- direitos de autor a produtos que não podem beneficiar dela. vel e dinâmica. Simples, leve, ergonómico, recortado (pela 3DCork, de Paços A Psystar alegou que ao limitar o uso do software da Apple de Brandão) num material reciclado e reciclável. São estes aos produtos fabricados pela marca, a empresa estava a recorrer indevidamente à proteção que a lei dispensa aos alguns dos segredos que atraíram o Kork2 até às prateleiras direitos de autor para falsear a concorrência. Note-se que a do MoMA de Nova Iorque e de Tóquio. fabricante de "sucedâneos" dos Mac tinha comprado cópias Todos os pormenores são estudados ao milímetro por Michael do Mac OS X para instalar nos computadores que vendia. Andersen e Benedita Feijó, dupla que se lançou no mercado Apple com o StickyStrap para o iPhone antes de colocarem o A juíza considerou que a concorrente não tinha apresentado iPad nas passarelas internacionais. provas de que as condições de licenciamento do sistema ope- rativo fossem lesivas da concorrência ou criatividade. “Fazemos um exercício de especulação porque os desenhos Os termos das licenças do software da Apple "não restringem da Apple estão normalmente fechados a sete chaves”, expli- a possibilidade de os concorrentes desenvolverem o seu pró- cou ao P3 Michael Andersen, ansioso pelos desenhos deta- prio software, nem impede os clientes de usarem componen- lhados do iPhone5 e do iPad3. tes de outra marca em computadores Apple", entendeu a magistrada, citada pela Ars Technica. “Vamos trabalhando com esses rumores até termos o objecto nas mãos para avançarmos com os desenhos finais. Os mol- O que a Apple faz é restringir o uso de software da marca ao des são feitos ao milímetro porque a cortiça é um material seu próprio hardware e a Psystar, que produz os seus pró- extremamente complicado de moldar”, prossegue um dos prios computadores, é livre de desenvolver software para fundadores da A Produkt, responsável por “produtos originais” eles, concluiu. que, graças a “materiais portugueses”, fazem a “ponte entre a tecnologia e a natureza”. A A Produkt não exclui uma futura A decisão chega no culminar de um processo que teve início aventura no mundo da cerâmica e da indústria têxtil. em Julho de 2008, quando a Apple pediu a condenação da Psystar por copiar os seus produtos. A sentença representa Fonte: Público, texto de Luís Octávio Costa uma vitória importante para a fabricante do iPhone, que vê corroborada a "intocabilidade" do seu ecossistema e assegu- rado o direito a não disponibilizar o seu sistema operativo a Windows 8 - Novo Explorador outras fabricantes. Segundo o blog oficial da equipa de desenvolvimento do Win- dows 8, o explorador do Windows à semelhança do Microsoft Escrito ao abrigo do Office, uma ribbon. Outra das novidades, é o facto deste pos- novo Acordo sibilitar a abertura de ficheiros iso e vhd sem necessidade de Ortográfico aplicações de terceiros. Fonte: Tek Sapo Imagens do novo explorador neste site: http://bit.ly/rj8vjI Blog oficial do Windows 8: http://blogs.msdn.com/b/b8/ Fonte: P@P 4
  • 5. NOTICIAS Investigadores quebram criptografia BerliOS será fechado em 31.12.2011 SSL O BerliOS foi fundado há 10 anos como um dos primeiros Acesso a bancos portugueses e estrangeiros em risco depósitos na Europa. Foi desenvolvido e mantido por Frau- A segurança perfeita é um mito…já dizia o ditado! Nos dias de nhofer FOKUS. Como Europeu, o projecto não-proprietário hoje, a segurança de muitos sites (especialmente de home- BerliOS tinha como objective apoiar vários intervenientes e banking, ou compras online) passa pelo uso do protocolo SSL providenciar uma função de mediação neutra. Em 2011 cerca (Secure Sockets Layer), que permite (permitia) a integridade e de 4710 projectos foram alojados no BerliOS, com 50,000 confidencialidade dos dados que são passados entre o cliente utilizadores registados e mais de 2.6 milhões de ficheiros des- e o servidor. Segundo informações disponíveis no site The carregados cada mês. Estamos orgulhosos de, com o Ber- Register, os investigadores tailandeses Thai Duong e Juliano liOS, termos trazido a ideia de um depósito OSS à Europa. Rizzo conseguiram pela primeira vez, quebrar o, até agora Entretanto, o conceito tem permanecido e existem muitas inquebrável, protocolo SSL e assim decifrar a informação que alternativas boas. é passada ponto a ponto (entre o cliente e o servidor). Infelizmente, como instituto de pesquisa Fraunhofer FOKUS A noticia é preocupante e alarmante mas a descoberta levada tem apenas algumas oportunidades para operar um depósito a cabo pelo grupo de investigadores apenas põe em causa a como o BerliOS. Tal projecto apenas funcionará com um segurança as versões 1.0 e anteriores do TLS (Transport financiamento de seguimento, ou com patrocinadores ou par- Layer Security) – o sucessor do SSL. Até ao momento não há ceiros que assumam o controlo do depósito. No campo de qualquer informação sobre vulnerabilidades que afectem a OSS é um empreendimento difícil. Num inquérito recente a versão 1.1 ou 1.2 do TLS. comunidade indicou algum apoio em fundos e mão-de-obra pelos quais gostaríamos de vos agradecer. Infelizmente, o A demonstração de tal feito ocorrerá na conferência Eko- resultado não é suficiente para colocar o projecto numa base party , que se realizará em Buenos Aires no final desta sema- financeira sustentável. Além disso, a procura de patrocinado- na. Thai Duong e Juliano Rizzo irão apresentar o exploit que res ou parceiros foi sem êxito. usaram para conseguir derrubar o SSL e ao qual deram o nome de BEAST. O exploit foi programado em JavaScript e O Open Source é entendido pela Fraunhofer FOKUS como funciona como um snifer, tendo a capacidade de decifrar a um paradigma para a futura utilização de inteligência orienta- informação. Segundo os autores, o exploit funciona também da da TI. Magoa-nos ainda mais o facto de sermos forçados a em sites que usam HSTS (HTTP Strict Transport Security). descontinuar o alojamento para BerliOS em 31/12/2011. Duong referiu que a demo que irão apresentar na conferência Como programador, deverá exportar o seu projecto BerliOS Ekoparty, consistirá na decifragem de um cookie de autentica- para outro depósito. Como alternativas ver: ção, utilizado no serviço Paypal. http://bit.ly/18Pp6N . No nosso site irão encontrar um guia em como retirar os dados dos vossos projectos do portal e migrá- Mas o que é o SSL? SSL é um protocolo criptográfico basea- los para uma plataforma diferente. Ver: http://bit.ly/qGJfAo . do em cifras assimétricas que providencia segurança e integri- dade dos dados transmitidos em redes como a Internet. Este A Fraunhofer FOKUS tem um forte compromisso com o Open protocolo ajuda a prevenir que entre as duas extremidades da Source e interoperabilidade, e está envolvida em numerosos comunicação não exista nenhum acesso indevido ou falsifi- projectos OSS de sucesso. O instituto está focado no desen- quem os dados transmitidos, ou seja, apenas o emissor e o volvimento de padrões de qualidade para o software open receptor podem ver a informação da mensagem transmitida. source e em particular na inoperabilidade técnica, semântica e Existem várias aplicações para este protocolo, como por organizacional entre componentes de software open source e exemplo o comércio electrónico, servidores Web, servidores software closed source. Exemplo das nossas actividade OSS FTP, etc.Para identificar facilmente se estão a visualizar um incluindo a nossa gestão do Centro de Competência Alemão site seguro basta verificar no URL que em vez de estar o nor- QualiPSo. mal http:// se encontra https://. Para saber mais: http://bit.ly/ p1MV0Y Agradecemos a todos terem utilizado o BerliOS ao longo dos anos.Fraunhofer FOKUS http://www.fokus.fraunhofer.de Fonte: Sapo Fonte: www.berlios.de Tradução: Sara Santos 5
  • 6. TEMA DA CAPA NHibernate - Técnicas para software melhor e mais rápido
  • 7. TEMA DA CAPA NHibernate - Técnicas para software melhor e mais rápido No artigo da edição anterior abordamos os temas de configu- foreach (var artigo in ração de NHibernate, diferentes formas de mapear as entida- session.QueryOver<Artigo>().List()) des e diferentes formas de obter os dados da base de dados { no contexto do seguinte domínio: var autores = artigo.Autores.Select(a => a.Nome); public class Edicao Console.Out.WriteLine( { "Artigo {0} com autores {1}", public virtual DateTime DataEdicao {get; set; } artigo.Titulo, public virtual Artigo TemaDeCapa { get; set; } string.Join(", ", autores.ToArray())); public virtual IList<Artigo> Artigos {get;set;} } } public class Artigo { public virtual int Id { get; set; } Neste caso, estamos a mostrar o título de um artigo em con- public virtual string Titulo { get; set; } public virtual ISet<Autor> Autores {get;set; } junto com os autores. Se olharmos para o SQL gerado } vemos que por cada artigo vamos à base de dados buscar os autores: public class Autor { public virtual int Id { get; set; } public virtual string Nome { get; set; } public virtual string Email { get; set; } public virtual ISet<Artigo> Artigos {get;set; } } Neste artigo vamos ver como podemos aproveitar algumas Este comportamento é resultante das capacidades de lazy- das funcionalidades mais avançadas do NHibernate para loading da biblioteca em conjunto com as configurações por tornar as nossas aplicações mais eficientes, reduzindo o omissão que carregam os objectos de cada relação apenas número de pedidos à base de dados assim como a quantida- quando esta é acedida. de de dados que são transmitidos. Em certos momentos iremos usar a ferramenta NHProf para observar a comunica- Tal comportamento implica que vão ser efectuados no míni- mo tantos queries quanto artigos mostrarmos. Qualquer ção entre a nossa aplicação e a base de dados. latência no acesso ao servidor de sql aumenta significativa- mente o tempo de resposta da nossa aplicação, quando na Performance realidade seria possível minimizar as chamadas à base de dados e obter todos os dados de uma só vez. Uma das falácias de computação distribuída é de que latên- cia é zero. Na realidade, qualquer chamada a um sistema Select N+1 remoto é ordens de magnitude mais lenta do que a mesma chamada a um sistema local e dentro do mesmo processo. A esta classe de problemas dá-se o nome de “Select N+1”, Outra falácia é de que a largura de banda é infinita. Como tal em virtude de ser efectuada uma chamada à base de dados para obter a lista de objectos raiz, e posteriormente N cha- é boa prática reduzir o número de chamadas remotas ao madas para obter os objectos relacionados de cada raiz. É servidor de dados e o tamanho dos dados a receber e enviar uma fonte típica de problemas de performance, e em quase se queremos ter aplicações com boa performance mesmo todos os casos pode ser resolvida com um carregamento quando em carga. mais inteligente dos dados. Como reduzir o número de chamadas Eager-Loading Um dos casos típicos onde fazemos mais chamadas à base Embora a intuição seja de que o oposto de lazy-loading seja de dados do que o necessário é quando mostramos uma eager-loading, na realidade existem várias formas de fazer listagem de itens que necessita de dados de mais do que eager-loading de dados, pelo que devem ser usadas em uma tabela: circunstâncias diferentes. 7
  • 8. TEMA DA CAPA NHibernate - Técnicas para software melhor e mais rápido É possível configurar este comportamento a nível dos Para carregar os dados dos Artigos sempre que uma edição mapeamentos globais ou durante um query à base de é carregada, usamos a seguinte configuração: dados. Quando é configurado no mapeamento pode ser feito a uma classe ou a uma relação. Quando é feito durante o public class EdicaoOverride : IAutoMappingOverri- query é sempre respectivo a uma relação. de<Edicao> { Quando uma classe é indicada como não lazy-loaded, qual- public void Override(AutoMapping<Edicao>mapping) quer instância da mesma criada pelo NHibernate deixará de { ser uma proxy. mapping.HasMany(e => e.Artigos) .Not.LazyLoad(); A implicação é de que qualquer relação que seja de um para } um ou de muitos para um com uma classe que não possa } ser lazy-loaded terá de ser logo concretizada. Considerando que queremos que a classe Artigo não seja Neste caso estamos a indicar que quando uma Edicao é lazy-loaded: carregada, os Artigos também o são. A forma de carregar os dados varia entre três opções: select (comportamento por public class ArtigoOverride : IAutoMappingOverri- omissão), subselect e join. de<Artigo> { Quando é usado o select, por cada entidade com a relação é public void Override(AutoMapping<Artigo>mapping) efectuado um select à base de dados. Este é o comporta- { mento que existe por omissão e quer dizer que continuamos mapping.Not.LazyLoad(); } com um problema de Select N+1: } Quando é usado o subselect, por cada query ou entidade Quando carregamos uma Edicao (que tem uma colecção de obtida da base de dados é efectuado outro query que obtém artigos e um tema de capa): os dados necessários para popular as relações. Este com- portamento é interessante nas relações de muitos para mui- var edicao = session.Get<Edicao>(dataEdicao); tos, como a entre Artigos e Autores. Se nós tivermos o seguinte query: O sql gerado inclui já o join necessário para carregar o tema de capa: Foreach ( var artigo in session.QueryOver<Artigo>() SELECT .Where(a => a.Id < idQuartoArtigo).List()) edicao0_.DataEdicao as DataEdicao3_1_, edicao0_.TemaDeCapa_id as TemaDeCapa2_3_1_, { artigo1_.Id as Id0_0_, var autores = artigo.Autores.Select(a => artigo1_.Titulo as Titulo0_0_ a.Nome); FROM [Edicao] edicao0_ left outer join [Artigo] artigo1_ on edicao0_.TemaDeCapa_id = artigo1_.Id Console.Out.WriteLine( WHERE "Artigo {0} com autores {1}", edicao0_.DataEdicao = '2011-07-01T00:00:00.00' artigo.Titulo, string.Join(", ", autores.ToArray())); } Há aqui dois comportamentos que são necessário distinguir: o da relação de muitos para um (TemaDeCapa) e o da rela- ção de um para muitos (Artigos). Os queries gerados por omissão são 4: Como é a classe Artigo que deixa de ser lazy-loaded, quan- do o NHibernate faz um query a partir da Edicao repara que não vai poder criar a proxy para o TemaDeCapa, e cria o sql necessário para carregar os dados do Artigo corresponden- te. No caso dos Artigos não surge esse problema porque não necessita de criar as instâncias imediatamente, apenas uma Um para obter os artigos, e um por cada artigo. lista que as vai guardar. Até iterarmos por esta lista não pre- cisamos de construir as respectivas instâncias de Artigos. 8
  • 9. TEMA DA CAPA NHibernate - Técnicas para software melhor e mais rápido No entanto, se configurarmos a relação com um fetch por SELECT TOP ( 2 /* @p0 */ ) subselect passamos a ter apenas dois queries: this_.DataEdicao as DataEdicao3_1_, this_.TemaDeCapa_id as TemaDeCapa2_3_1_, artigos2_.Edicao_id as Edicao3_3_, artigos2_.Id as Id3_, artigos2_.Id as Id0_0_, artigos2_.Titulo as Titulo0_0_ FROM [Edicao] this_ left outer join [Artigo] artigos2_ Neste caso o select que popula os autores é filtrado pelo on this_.DataEdicao = artigos2_.Edicao_id primeiro query através de um subselect: SELECT autores0_.Artigo_id as Artigo4_1_, autores0_.Id as Id1_, Neste caso como é feito o carregamento imediato dos artigos autores0_.Id as Id1_0_, através de um join, vamos ter edições repetidas quando uma autores0_.Nome as Nome1_0_, edição tem mais que um artigo. Como tal, esta opção não é autores0_.Email as Email1_0_ FROM [Autor] autores0_ aconselhada na maioria dos casos, sendo preferível configu- WHERE autores0_.Artigo_id in rar o carregamento de dados por query em vez de forma (SELECT this_.Id geral. FROM [Artigo] this_ WHERE this_.Id < 1922 /* @p0 */) Configurado por relação no mapeamento tem também a des- vantagem de carregar os dados mesmo que não sejam usa- dos. Como tal, estas soluções são pouco flexíveis, visto Reduz o número de queries efectuadas á base de dados, no assumirem que se pretende sempre os mesmos dados rela- entanto necessita que a base de dados suporte este meca- cionados com as entidades em todos os casos de uso. nismo. Para maior flexibilidade a solução acaba por passar por indi- Quando é usado o join, como o nome indica, os dados da car no query quais as colecções que se pretende carregar colecção são obtidos ao mesmo tempo que as entidades imediatamente: através de um join. Para o código mencionado anteriormente passamos a ter apenas um query: foreach (var artigo in session.QueryOver<Artigo> ().Fetch(a => a.Autores).Eager.List()) SELECT this_.Id as Id0_1_, { this_.Titulo as Titulo0_1_, Console.Out.WriteLine( autores2_.Artigo_id as Artigo4_3_, "Artigo {0} com autores {1}", autores2_.Id as Id3_, artigo.Titulo, autores2_.Id as Id1_0_, autores2_.Nome as Nome1_0_, string.Join(", ", autores2_.Email as Email1_0_ artigo.Autores.Select( FROM [Artigo] this_ a => a.Nome).ToArray())); left outer join [Autor] autores2_ } on this_.Id = autores2_.Artigo_id WHERE this_.Id < 2225 /* @p0 */ Aqui estamos a indicar que queremos carregar a colecção Autores do Artigo juntamente com o artigo. O sql gerado usa É necessário ter em atenção a forma como se usa estas joins para obter os dados das entidades relacionadas: funcionalidades gerais de eager-loading. Por exemplo, ao configurar a colecção de Artigos de uma Edicao para ser SELECT this_.Id as Id0_1_, automaticamente obtida por join, o seguinte código pode ter this_.Titulo as Titulo0_1_, um resultado inesperado: autores2_.Artigo_id as Artigo4_3_, autores2_.Id as Id3_, foreach (var edicao in session.QueryOver<Edicao> autores2_.Id as Id1_0_, ().Take(2).List()) autores2_.Nome as Nome1_0_, { autores2_.Email as Email1_0_ FROM [Artigo] this_ Console.Out.WriteLine("Edicao {0} ", left outer join [Autor] autores2_ edicao.DataEdicao); on this_.Id = autores2_.Artigo_id } À primeira vista deveríamos obter duas edições distintas. E em muitos casos é isso que temos. No entanto ocasional- Se olharmos para os métodos Get e Load, não temos nenhu- mente encontramos edições duplicadas, e ao olharmos para ma forma de configurar eager-loading nesses casos. o sql gerado vemos qual o problema: 9
  • 10. TEMA DA CAPA NHibernate - Técnicas para software melhor e mais rápido Como tal, a forma de o fazer é com uma query por id, confi- BatchSize é o número de instâncias de uma relação que são gurando ai que relações é que pretendemos carregar logo: carregadas em simultâneo em vez de separadas. Configura- do desta forma, o seguinte código: foreach (var artigo in session.QueryOver<Artigo> () .Where(a => a.Id == idTerceiroArtigo) foreach (var artigo in session.QueryOver<Artigo> .Fetch(a => a.Autores).Eager.List()) ().List()) { { var autores = artigo.Autores.Select( var autores = artigo.Autores.Select( a => a.Nome); a => a.Nome).ToArray(); Console.Out.WriteLine( Console.Out.WriteLine( "Artigo {0} com autores {1}", "Artigo {0} com autores {1}", artigo.Titulo, artigo.Titulo, string.Join(", ", autores)); string.Join(", ", autores.ToArray())); } } Neste caso também podemos vir a ter o problema de entida- des duplicadas. No entanto como o carregamento é feito por Passa de : query, podemos fazer o tuning em cada caso de uso, de acordo com as necessidades reais. Mais à frente neste artigo vamos ver uma forma mais correc- ta e menos dada a erros de resolver este problema, fazendo o carregamento de dados de forma fácil e rápida. Batch fetching Para: Outra forma de reduzir o número de vezes que efectuamos chamadas à base de dados é configurar relações com batch- fetching. Esta é uma configuração que apenas pode ser feita no mapeamento, por oposição a eager-loading que também pode ser feita por query. Nestes casos, quando NHibernate detecta um acesso à colecção, ele procura mais entidades dentro da mesma ses- Como podemos ver, em vez de uma chamada para obter o são que tenham essa relação e carrega os dados em conjun- artigo e uma para cada autor, apenas fazemos uma chama- tos de N, reduzindo o número de chamadas à base de da para obter o artigo, e outra para carregar os autores em dados. É uma forma simples de melhorar performance, em batch. particular se o tamanho dos conjuntos for similar ao tamanho das páginas de dados que apresentamos ao utilizador caso em que reduzimos significativamente o número de queries: Futures uma para obter as entidades raiz, e uma por cada colecção que acedemos. Existe também o caso em que se pretende obter vários dados que não estão relacionados entre si. Este caso acon- Para tal, usando FluentNHibernate, apenas precisamos de tece frequentemente quando uma página ou ecrã mostra declarar um override para a entidade e indicar que a relação dados provenientes de várias tabelas ou componentes do tem um BatchSize do tamanho que pretendemos. software, como um ecrã de resumo, ou uma caixa de infor- mação geral da aplicação. public class ArtigoOverride : IAutoMappingOverri- de<Artigo> Se quisermos mostrar numa página um índice de edições { com número de artigos em cada uma, um índice com os public void Override(AutoMapping<Artigo> mapping) { artigos da edição actual e um artigo em destaque com auto- mapping.HasMany(a => a.Autores) res, a solução mais directa passa por fazer três queries .BatchSize(10); separados, resultando em três round-trips á base de dados: } } 10
  • 11. TEMA DA CAPA NHibernate - Técnicas para software melhor e mais rápido var edicoes = session.QueryOver<Edicao>() var edicoes = session.QueryOver<Edicao>() .List(); .Future(); var edicaoComArtigos = session var edicaoComArtigos = session .QueryOver<Edicao>() .QueryOver<Edicao>() .Fetch(e => e.Artigos).Eager .Fetch(e => e.Artigos).Eager .WithSubquery.WhereProperty(e => .WithSubquery.WhereProperty(e => e.DataEdicao) e.DataEdicao) .In(QueryOver.Of<Edicao>() .In(QueryOver.Of<Edicao>() .Select(e => e.DataEdicao) .Select(e => e.DataEdicao) .OrderBy(e => .OrderBy(e => e.DataEdicao) e.DataEdicao).Desc.Take(1)) .Desc.Take(1)) .SingleOrDefault(); .FutureValue(); var artigoComAutor = session.QueryOver<Artigo>() var artigoComAutor = session.QueryOver<Artigo>() .Where(a => a.Id == idTerceiroArtigo) .Where(a => a.Id == idTerceiroArtigo) .Fetch(a => a.Autores).Eager .Fetch(a => a.Autores).Eager .SingleOrDefault(); .FutureValue<Artigo>(); foreach (var edicao in edicoes) foreach (var edicao in edicoes) { { Console.Out.WriteLine( Console.Out.WriteLine( "Edicao {0} ", "Edicao {0} ", edicao.DataEdicao); edicao.DataEdicao); } } var artigos = edicaoComArtigos.Artigos.Select(a var artigos = edicaoComArtigos.Value => a.Titulo).ToArray(); .Artigos.Select(a => a.Titulo) .ToArray(); Console.Out.WriteLine( "Edicao {0} - Artigos {1}", Console.Out.WriteLine( edicaoComArtigos.DataEdicao, "Edicao {0} - Artigos {1}", string.Join(", ", artigos)); edicaoComArtigos.Value.DataEdicao, string.Join(", ", artigos)); var autores = artigoComAutor.Autores.Select(a => a.Nome).ToArray(); var autores = artigoComAutor.Value.Autores.Select (a => a.Nome).ToArray(); Console.Out.WriteLine( "Artigo {0} com autores {1}", Console.Out.WriteLine( artigoComAutor.Titulo, "Artigo {0} com autores {1}", string.Join(", ", autores)); artigoComAutor.Value.Titulo, string.Join(", ", autores)); Usando a ferramenta NHProf para ver os pedidos que são feitos à base de dados, vemos que são feitos 3 pedidos dis- tintos: Desta forma, pode- mos preparar todos Na realidade podemos diferir a definição das operações de acesso a dados da sua execução. Podemos ter assim uma os queries e de uma só fase de preparação, onde se criam os queries que se preten- dem fazer, e uma segunda fase onde se mostram os resulta- vez fazer todos os pedi- dos. Desta forma, podemos preparar todos os queries e de uma dos à base de dados. só vez fazer todos os pedidos à base de dados. É este comportamento que os Futures nos permitem. A alte- ração ao código é mínima. Usamos Futures em vez de List, Enquanto os queries anteriores retornavam logo uma lista, o e FutureValue em vez de SingleOrDefault: resultado de um Future ou de um FutureValue é apenas a promessa de que no futuro quando precisarmos dos dados eles estarão lá. 11
  • 12. TEMA DA CAPA NHibernate - Técnicas para software melhor e mais rápido O que o NHibernate faz é registar internamente todos os Fazemos o eager-loading de todas as relações, resul- Futures pedidos. Assim que um é concretizado (quer por tando num query com um número elevado de joins: iterar sobre um IEnumerable de um Future, quer por aceder ao valor de um FutureValue), são enviados todos os queries Usamos Futures para carregar em queries diferentes registados para a base de dados e obtidos os resultados de relações diferentes da mesma entidade. uma só vez. A terceira opção acaba por ser a que obtém tipicamente O sql gerado é exactamente o mesmo, mas foi todo enviado melhores resultados e é concretizada da seguinte forma: na mesma chamada, minimizando assim os problemas de latência no acesso aos dados. var edicao = session.QueryOver<Edicao>() .Where(e => e.DataEdicao == dataEdicao) Vemos então que em vez de três chamadas distintas faze- .Fetch(e => e.Artigos).Eager.FutureValue(); mos apenas uma chamada que retorna três conjuntos de resultados diferentes: session.QueryOver<Edicao>() .Where(e => e.DataEdicao == dataEdicao) .Fetch(e => e.Patrocinadores) .Eager.FutureValue(); var artigos = edicao.Value .Artigos.Select(a => a.Titulo).ToArray(); De reparar que por omissão o Future assume que se retorna uma lista de entidades sobre as quais estamos a fazer o Console.Out.WriteLine( QueryOver, e o FutureValue assume que se retorna uma "Edicao {0} - Artigos {1}", edicao.Value.DataEdicao, entidade. Como vamos ver mais à frente com projecções, string.Join(", ", artigos)); também é possível obter instâncias que não as indicadas inicialmente como argumento de tipo ao QueryOver. var patrocinadores = edicao.Value .Patrocinadores.Select(a => a.Nome) .ToArray(); Esta funcionalidade tem a grande vantagem de poder reduzir grandemente o número de chamadas à base de dados com Console.Out.WriteLine( alterações mínimas ao código. "Artigo {0} com autores {1}", edicao.Value.DataEdicao, string.Join(", ", patrocinadores)); Outro caso de uso prende-se com o carregamento de várias relações da mesma entidade. Assumindo que a classe Edicao passa a ser a seguinte: Saliente-se que usamos apenas o valor do primeiro QueryO- ver. O segundo é apenas usado para carregar os dados da public class Edicao colecção de forma indirecta. { public virtual DateTime DataEdicao {get;set;} public virtual Artigo TemaDeCapa {get;set; } Isto é possível uma vez que o NHibernate implementa um public virtual IList<Artigo> Artigos{get;set;} identity map dentro da sessão. Quando acedemos ao valor public virtual IList<Patrocinador> do primeiro Future despoletamos todos os Futures regista- Patrocinadores { get; set; } } dos até ao momento na sessão. Ao concretizar os objectos resultantes do segundo query, o NHibernate encontra a enti- dade já na sessão e preenche a colecção que foi carregada public class Patrocinador { com os dados desse query, que incluem a relação Patrocina- public virtual int Id { get; set; } dores. public virtual string Nome { get; set; } } Desta forma conseguimos popular as relações necessárias apenas com uma chamada à base de dados e um conjunto pequeno de queries com apenas um join cada um: Se nós pretendemos mostrar uma edição com todos os arti- gos e todos os patrocinadores, temos várias hipóteses: Aproveitamos o lazy-loading e fazemos vários pedi- dos à base de dados: 12
  • 13. TEMA DA CAPA NHibernate - Técnicas para software melhor e mais rápido Como reduzir o tamanho de cada chamada Neste caso estamos a seleccionar o identificador da edição mais recente, e obter o numero de artigos dessa edição. Até agora trabalhamos com as entidades completas. No entanto existem muitas operações ou casos de uso que Viewmodels necessitam apenas de parte das entidades ou de dados agregados. Ir buscar todos os artigos de uma edição quando O segundo caso de uso que exemplifico para projecções apenas pretendemos uma contagem de artigos da edição é prende-se com situações onde temos uma ou varias entida- improdutivo quando podemos fazer esses cálculos directa- des com um número grande de campos e onde necessita- mente na base de dados e obter apenas os dados que preci- mos apenas de parte dos campos, ou de dados agregados samos. Para este efeito usamos projecções em conjunto em conjunto com alguns campos. com transformadores. Da mesma forma que projectamos um valor de um resultado Count, Max, Aggregate de um query podemos também projectar uma lista de valo- res: Os casos mais simples são aqueles em que pretendemos obter um valor resultante de uma query: IList<Artigo> artigos = null; var edicoes = session.QueryOver<Edicao>() var edicaoMaisAntiga = session.QueryOver<Edicao> .JoinQueryOver( ().Select(Projections e => e.Artigos, .Min<Edicao>(e => e.DataEdicao)) () => artigos, .SingleOrDefault<DateTime>(); JoinType.LeftOuterJoin) .SelectList( q => q.SelectGroup(e =>e.DataEdicao) .SelectCount(e => e.Artigos) ) Neste caso estamos a procurar o valor mínimo de todas as .List<object[]>(); datas de edição. Como este query devolve um valor do tipo DateTime, precisamos de indicar isso através do argumento foreach (var edicao in edicoes) { de tipo do método SingleOrDefault. Console.Out.WriteLine( "Edicao {0} com {1} artigos", É claro que podemos usar um Future para os casos em que edicao[0], edicao[1]); pretendemos obter vários valores sem ter a penalização de } várias chamadas à base de dados: var edicaoMaisRecente = session.QueryOver<Edicao> Neste caso estamos a projectar a data de edição e o número ().Select(Projections .Max<Edicao>(e => e.DataEdicao)) de artigos que aparecem para cada edição. O sql gerado .FutureValue<DateTime>(); não tem surpresas: SELECT this_.DataEdicao as y0_, count(this_.DataEdicao) as y1_ Outra situação onde projecções são úteis é em subqueries, FROM [Edicao] this_ onde podemos projectar um valor para usar numa condição: inner join [Artigo] artigos1_ on this_.DataEdicao = arti- gos1_.Edicao_id Artigo artigo = null; GROUP BY this_.DataEdicao var numeroArtigosEdicaoMaisRecente = session .QueryOver<Edicao>() .WithSubquery .WhereProperty(e => e.DataEdicao) No entanto o acesso aos dados projectados torna-se propí- .In(QueryOver.Of<Edicao>() cio a erros, visto retornar uma lista de vectores de objectos. .Select(e => e.DataEdicao) .OrderBy(e => e.DataEdicao).Desc.Take(1)) Seria muito mais fácil se pudéssemos usar uma classe inter- .JoinQueryOver(e => e.Artigos, () => artigo) média que armazenasse os campos obtidos. E tal é possível .SelectList(q => recorrendo a aliases e a um ResultTransformer. q.SelectCount(() => artigo.Id)) .FutureValue<int>(); 13
  • 14. TEMA DA CAPA NHibernate - Técnicas para software melhor e mais rápido Com a seguinte classe: Utilizamos expressões para indicar os nomes dos campos, sendo que na realidade o que o NHibernate faz é apenas public class EdicaoComNumeroArtigos associar nomes dos campos à projecção. Depois o transfor- { public virtual DateTime DataEdicao {get;set;} mador AliasToBean é que tem o trabalho de para cada cam- public virtual int NumeroArtigos {get;set;} po retornado do query procurar uma propriedade com um } setter público e colocar o valor do campo nessa propriedade. Isto quer dizer que é possível indicar nomes inválidos ou ter outros problemas semelhantes nos queries, no entanto são Podemos alterar o query anterior para associar um alias a erros facilmente detectados com testes de integração que cada um dos campos e transformar os resultados em instân- correm o query, visto o NHibernate identificar logo as irregu- cias da classe EdicaoComNumeroArtigos: laridades. IList<Artigo> artigos = null; EdicaoComNumeroArtigos viewModel = null; Conclusão var edicoes = session.QueryOver<Edicao>() Neste artigo analisamos algumas opções e funcionalidades .JoinQueryOver( e => e.Artigos, que nos permitem melhorar as características de performan- () => artigos, ce das nossas aplicações, quer por um carregamento mais JoinType.LeftOuterJoin) inteligente dos dados, como pela redução do tamanho de .SelectList(q => q.SelectGroup( e => e.DataEdicao) dados que é transferido da base de dados para a aplicação. .WithAlias(() => viewModel.DataEdicao) .SelectCount(e => e.Artigos).WithAlias Existem ainda algumas funcionalidades que não foram men- (() => viewModel.NumeroArtigos) cionadas, como interceptores, filtros, cache de segundo nível ) .TransformUsing e concorrência optimista. (Transformers.AliasToBean<EdicaoComNumeroArtigos> ()) .List<EdicaoComNumeroArtigos>(); Ver artigo Revista PROGRAMAR - edição 30 de Agosto foreach (var edicao in edicoes) 2011: NHibernate - do Import Package à primeira iteração { Console.Out.WriteLine( "Edicao {0} com {1} artigos", edicao.DataEdicao, edicao.NumeroArtigos); } AUTOR Bruno Lopes fez o curso de Engenharia Informática no IST, e neste momento conta com mais de 5 anos de experiência pro- fissional em IT, em particular nas áreas de desenvolvimento de software web-based. Actualmente é co-fundador da weListen Business Solutions, trabalhando no produto InnovationCast, e participa activamente na comunidade NetPonto, apresentando temas como NHibernate, RavenDB ou IoC. Tem blog em http://blog.brunomlopes.com, twitter em @brunomlopes e linkedin em http://pt.linkedin.com/in/brunomlopes 14
  • 15. Elege o melhor artigo desta edição Revista PROGRAMAR http://tiny.cc/ProgramarED31_V
  • 16. A PROGRAMAR Geração de números aleatórios (Parte 1) Diferenças ao Desenvolver em Windows Azure Programação Orientada a Objectos em Java 6 DataBinding em Silverlight 4
  • 17. A PROGRAMAR GNA - GERAÇÃO DE NÚMEROS ALEATÓRIOS (Parte 1) A partir deste artigo, serão apresentadas em quatro partes, vários tipos de aplicação, destacando-se algumas, como as informações sobre a geração de números aleatórios ou apontadas por Doricio (1998) e Zenil (2011): random number generator em computadores. simulação – aplicação de modelos científicos na São muitos os métodos existentes para a geração de simulação de fenómenos naturais; números aleatórios. Podendo-se destacar: o método do meio do quadrado (tema deste artigo), o método produto do meio, amostragem – aplicação de modelos científicos o randu e o método linear congruente. baseados numa parte menor de um todo maior, que será analisada; INTRODUÇÃO análise numérica – aplicação de modelos As discussões sobre geração de números aleatórios determinísticos numéricos para a economia de tempo originam-se a partir das ideias dos filósofos gregos de computação; Demókritos e Epikurus, indicado por Silveira (2001) ao mostrar as propostas de: programação de computadores – aplicação de valores aleatórios para testes de eficiência algorítmica aleatoriedade objetiva, proposta por Epikurus, que afirma computacional; existir na Natureza o aleatório verdadeiro, o qual ocorre a partir do desconhecimento das causas; teoria de decisão – auxiliar a tomada de decisão com base na escolha aleatória de dados; aleatoriedade subjetiva, proposta por Demókritos, que afirma ser a Natureza determinista, onde tudo ocorre recreação – aplicação em jogos de azar. devido a uma causa. A geração de números pseudo-aleatórios depende da Para Doricio (1998) “não existe o que se possa chamar de escolha adequada dos parâmetros usados para a geração número aleatório”, o que corrobora com a afirmação indicada do número em si. Um desses parâmetros, que merece por Schildt (1990), ao dizer que “o termo geração de atenção, é o chamado “semente” (DIAS, 2005), o qual é números aleatórios é um absurdo”. caracterizado por ser o valor inicial a ser usado para a geração dos demais valores “aleatórios” subsequentes por Apesar da concordância, ou não, sobre este tema, os computadores eletrónicos de alguma forma produzem meio de algum algoritmo específico para esta finalidade. Segundo Dias (2005) a escolha da semente deve ser sequências de valores numéricos, chamados “números aleatórios”, a partir de duas abordagens: realizada com muito cuidado, pois “a utilização de uma mesma semente […] entre diferentes aplicações […] pode geração de números pseudo-aleatórios (PRNG – ocasionar erros bastante comuns que levam a conclusões que podem representar de forma incorreta o comportamento Pseudo-Random Number Genarator); dessas aplicações”. geração de números verdadeiramente aleatórios (TRNG – True Ramdom Number Generator). Para a geração de números pseudo-aleatórios existe de um grande conjunto de algoritmos. Neste estudo, em particular é O mecanismo PRNG é a forma mais comum encontrada nos apresentado o método do meio do quadrado. computadores eletrónicos. A palavra “pseudo” sugere, neste contexto, o uso de valores numéricos que não são gerados MÉTODO DO MEIO DO QUADRADO de forma aleatória, uma vez que são obtidos por meios A geração de números pseudo-aleatórios a partir do método artificiais a partir de algoritmos matemáticos elaborados para do meio do quadrado (middle square method) foi propostao esta finalidade. em 1946 por John von Neumann, sendo este algoritmo considerado o primeiro método de geração de números O mecanismo TRNG não é comum ou de fácil acesso (os “aleatórios” equipamentos para esta finalidade são muito caros para utilizadores menos científicos), uma vez que os valores (GIORDANO, FOX, WEIR, 2009 – p.184; TÖRN, 2001). chamados aleatórios são obtidos a partir de fenómenos oriundos da natureza, como: ruídos ambientais, alterações No método do meio do quadrado, foi proposto por Von climáticas, entre outros fenómenos. A geração de números Neumann, o uso de um valor semente que, elevado ao aleatórios, sejam PRNG ou TRNG, é são necessárias em quadrado, gera um resultado. Desse resultado é retirado do 17
  • 18. A PROGRAMAR GNA - GERAÇÃO DE NÚMEROS ALEATÓRIOS (Parte 1) meio um número com o mesmo tamanho em dígitos, do valor t = tamanho em dígitos do quadrado de N: t = tamanho(N2). usado para a semente. A partir do novo valor repete-se a tqd = tamanho em dígitos do quadrado de N, sua obtenção operação para a obtenção de um novo valor e assim por depende de algumas condições. diante (TÖRN, 2001; WHELAN, 2011; STUBBE, 2011). Apesar de engenhoso, o método apresenta algumas falhas. SE ((d é par) .E. (t é impar)) Segundo Knuth (KNUTH, 1969 – p. 4), várias pessoas .OU. fizeram uso do método do meio do quadrado no início da década de 1950 tendo sido utilizadas sementes com ((d é impor) .E. (t é impar)) tamanho de quatro dígitos, sendo este o tamanho de Acrescentar 00 à esquerda de tqd semente mínimo recomendado. Descobriu-se que alguns SENÃO valores levam a sequências infinitas de geração de valores pseudo-aleatórios, ao apresentarem valores como: 6100, SE (d é par) .E. (t é par) ENTÃO 2100, 4100 e 8100. A partir daí, o cálculo do meio do Manter tqd como está quadrado efetua a repetição infinita da mesma sequência. Descobriu-se também, que alguns valores usados levam à tq = tamanho em dígitos do valor gerado para tqd. obtenção de valor zero como resultado do meio do quadrado, impossibilitando a continuidade do uso do SE (t é impar) ENTÃO método, tais como os múltiplos de 1000 para as sementes de tq = d.2+1 quadro dígitos. Um bom gerador de números “aleatórios” deve gerar sequencias infinitas, sem resultar em zero. Não SENÃO deve repetir valores em sequências. No entanto, para aplicações que não requerem grande grau de precisão o método do meio do quadrado pode ser útil. m = posição inicial para extração do quadrado do meio a partir da quantidade de dígitos tqd. Tomando-se por como base o valor de semente 5678 (quatro dígitos de tamanho) e elevando-se este valor ao quadrado, obter-se-á como resultado o valor 32239684 (oito dígitos de tamanho). Do quadrado obtido são retirados os quatro ns = valor da próxima semente (valor pseudo-randômico dígitos do meio desse quadrado. Assim sendo, do ao valor gerado) após extração do quadrado do meio. 32239684 tira-se o valor 2396. Na sequência, a partir do valor 2396 calcula-se o seu quadrado, que resultará no valor 5740816 (sete dígitos de Com base no algoritmo do método do meio do quadrado tamanho). No entanto, este segundo quadrado possui sete proposto por von Neumann e das etapas conjugadas , é dígitos de tamanho e devido a isto necessita ser possível obter os valores indicados na Tabela 1 a partir do equacionado para que possua oito dígitos. Assim, basta fornecimento de uma semente que tenha entre 4 e 7 dígitos acrescentar um valor zero à esquerda do quadrado, de forma de tamanho. que fique assim representado 05740816. Deste ajuste, pega -se nos quatro dígitos do meio, que neste caso é o valor 7408 e prossegue-se com a aplicação da técnica de forma O tamanho máximo em dígitos para a semente deve ser 5 sequencial até o ponto desejado ou quando o meio do para valores de 32 bits ou 15 para valores de 64 bits. quadrado for 0000. (t (d) (tqd) (tq) (m) (ns) ) ALGORITMO DO MEIO DO QUADRADO 7 09999999 8 4 8 99999999 8 3 A aplicação do método pode ser efetivada a partir do 3,4 9 00999999999 11 algoritmo seguinte: 5 10 09999999999 11 4 4,5 N = entrada do número que representa a semente (> que 4 - 11 099999999999 12 6 12 999999999999 12 4 máx: 5 p/ 32 bits | 15 p/ 64 bits). 4,6 13 009999999999999 15 d = tamanho em dígitos do valor N: d = tamanho(N). 7 14 099999999999999 15 5 5,7 18
  • 19. A PROGRAMAR GNA - GERAÇÃO DE NÚMEROS ALEATÓRIOS (Parte 1) CONCLUSÃO SCHILDT, H. Turbo C Avançado: Guia do Usuário. Rio de Janeiro: McGraw-Hill, 1990. 475 p. Neste artigo foi apresentado o método de geração de números pseudo-aleatórios meio do quadrado, que é SILVEIRA, J. F. P. da. Tipos de Aleatori-edade. Rio Grande considerado por vários especialistas da área da computação do Sul: Universidade Federal do Rio Grande do Sul, Depar- como sendo um método não eficiente. No entanto, é tamento de Matemática. 2001. Disponível em: <http://bit.ly/ preferível ter possuir em mãos um método não eficiente de r2YYis> . Acesso em: 29 jun. 2011, 11:50:23. geração de números aleatórios do que não possuir STUBBE, J. An Introduction to Random Number Generation absolutamente nenhum método. and Simulation. École Polytechnique Fédérale de Lausanne. É claro que para uma aplicação que exija maior precisão, Disponível em: http://bit.ly/nvkNaP. Acesso em: 1 jul. 2011, será necessário considerar algum outro método. 08:59:12. No próximo artigo será discutido o método quadrado do TÖRN, A. Probabilistic Algorithms: Spring 2001 Course. Åbo meio, que é uma variação do método apresentado nesta Akademi University: Department of Computer Science. 2001. parte. Disponível em <http://bit.ly/qYxYkQ>. Acesso em: 1 jul. 2011, 08:27:32. BIBLIOGRAFIA WHELAN, S. F. Models - Stochastic Models. University Col- DIAS, G. N. A Influência da Semente na Geração de lege Dublin, School of Ma-thematical Sciences. Disponível Seqüências de Números Aleatórios através de Geradores de em: http://bit.ly/nIy2nT Números (Pseudo) Aleatórios. Rio de Janeiro: Universidade Acesso em: 1 jul. 2011, 08:39:54. Federal do Rio de Janeiro. 2005. Disponível em: <http://bit.ly/ qznXtW>. Acesso em: 29 jun. 2011, 10:52:35. ZENIL, H. John von Neumann's First Pseudorandom Number Generator Pseu-dorandom Number Generator. Champaign: DORICIO, J. L. Número Aleatórios e Apli-cações. São Paulo: Wolfram Demonstrations. 2011. Disponível em < http:// Universidade Federal de São Carlos, Departamento de bit.ly/6C7Q5 Matemática. 1998. JohnVonNeumannsFirstPseudorandomNumberGenerator>. GIORDANO, F. R.; FOX, W.F. & WEIR, M. D. A first course Acesso em: 15 ago. 2011, 08:23:56. in mathematical modeling. 4. ed. California Books/Cole. P. 184, 2009. KNUTH, D. E. The Art of Computer Pro-gramming: series in computer science and information processing. 2d ed. Indi- ana: Addison-Wesley. 1981. REYS, A. E. L.; MACHADO, A. A.; FERREIRA, D. F.; DEMÉTRI, C. B. & RIBEIRO, P. J. Sistema Galileu de Educação Estatística. São Paulo: Universidade de São Paulo, ESALQ. 2011. Disponível em: http://bit.ly/q5jbT8 . Acesso em: 1 jul. 2011, 08:17:25. AUTOR Augusto Manzano, natural da Cidade de São Paulo, tem experiência em ensino e desenvolvimento de programação de soft- ware desde 1 986. É professor da rede federal de ensino no Brasil, no Instituto Federal de Educação, Ciência e Tecnologia. É também autor, possuindo na sua carreira várias obras publicadas na área da computação. 19
  • 21. A PROGRAMAR Programar para Windows Azure O Windows Azure é uma plataforma de alta disponibilidade e Capacidade VS Quantidade alta escalabilidade que é fornecida como serviço e tem por isso algumas características diferentes em relação às plata- Em Windows Azure podemos escalar horizontalmente adicio- formas alvo tradicionais. nando mais máquinas virtuais ou escalar verticalmente usan- do máquinas virtuais de maior capacidade. Neste artigo vamos tentar alertar o leitor para alguns deta- lhes que encontramos em Windows Azure Compute, SQLA- Dependendo do tipo de aplicação e da carga de trabalho que zure e Windows Azure Storage bem como alguns cuidados cada aplicação, deverá ser escolhida a quantidade e capaci- que deveremos ter quando desenvolvemos para estes servi- dade das instâncias de modo a optimizar os custos e desem- ços. penho. A decisão poderá ser tomada tendo por base algu- mas das seguintes características: Windows Azure Compute Maior capacidade I/O Performance Comunicação mais rápida e mais barata entre proces- Existem cinco tipos de instâncias de Windows Azure Compu- sos (mesma máquina) te que permitem a execução de várias cargas de trabalho e aplicações com vários níveis de complexidade. Pode sair mais barato nos casos em que se usam muito Queues porque podemos fazer Queue.GetMessages(32) e processar em paralelo Tamanho CPU Memória Local Largura da Storage de Máquinas com maior capacidade têm uma maior e Banda mais consistente performance de I/O Extra 1.0 GHz 768 MB 20 GB 5 Mbps Small Maior quantidade Small 1.6 GHz 1.75 GB 225 GB 100 Mbps Permite uma escalabilidade mais granular e conse- Medium 2 x 1.6 3.5 GB 490 GB 200 quentemente mais barata Large 4 x 1.6 7 GB 1,000 400 Maior tolerância a falhas. A falha de uma máquina GHz GB Mbps virtual têm menor impacto Extra large 8 x 1.6 14 GB 2,040 800 GHz GB Mbps Temos que usar Azure Storage para comunicar entre processos Local Storage Cada instância de Windows Azure Compute representa um servidor virtual. Apesar de muitos dos recursos serem dedi- cados a essa instância em particular, alguns recursos asso- O Fabric Controller pode a qualquer momento destruir a ciados à performance de I/O, tais como largura de banda e máquina virtual e substituir por uma nova. Isso pode aconte- disco rígido, são partilhados entre as instâncias presentes na cer, por exemplo, sempre que seja detectado falhas na apli- mesma máquina física. Durante os períodos em que os cação, falhas no hardware, ou simplesmente porque precisa recursos partilhados estão a ser muito utilizados poderemos de realizar actualizações ao sistema operativo. ver a performance de I/O baixar para os níveis mínimos anunciados mas, em contrapartida, sempre que os recursos Por essa razão a informação armazenada em local storage é partilhados tiverem um nível de utilização inferior veremos considerada volátil. Esta situação deverá ser levada em con- essa performance aumentar. ta, principalmente nos casos em que existe migração de aplicações para o Windows Azure. Algumas aplicações Quanto maior for o tamanho da instância maior será a perfor- desenhadas para correr apenas num servidor usam local mance mínima de I/O e consequentemente essa performan- storage para guardar alguns ficheiros de forma persistente. ce será também mais consistente ao longo do tempo. 21
  • 22. A PROGRAMAR Programar para Windows Azure Como já vimos, em Windows Azure essa informação é consi- No entanto existem algumas diferenças entre as quais se derada volátil. Em contrapartida a migração de aplicações desenhadas para executar em web farms normalmente não destacam as seguintes: apresentam este problema. Não existe Backup e Restore Outro alerta em relação ao uso de local storage tem a ver com a visibilidade da informação. Tudo o que for escrito para Uma das funcionalidades que ainda não existe em SQLAzu- local storage só vai ser visto pela instância actual. re é a capacidade de realizar backup ou restore de uma base de dados. Apesar do estarmos na presença de um ser- Estamos a desenvolver para um ambiente altamente escalá- viço de alta disponibilidade onde “não existe” a preocupação vel e na maioria dos casos manter a informação privada não com a perca de informação, continuamos a ter que lidar com é a melhor opção. Existem casos em que é vantajoso fazer possíveis corrupções nas bases de dados devido a erros nas cache local de alguns dados mas na maioria dos cenários aplicações. deve ser usado um tipo de storage persistente e partilhado. Não existe cross-database querying Em SQL Azure nós temos a capacidade de alugar bases de Roles dados e não servidores de bases de dados. Não existe garantia que todas as bases de dados que alugamos estão As instâncias são pagas por hora de relógio no mesmo servidor. A ideia principal que deveremos reter neste caso é que não existe conectividade entre bases de As instâncias são facturadas com base nas horas de relógio dados. Se for necessário combinar resultados de mais do em que estiveram implementadas. As horas parciais serão que uma base de dados teremos que resolver essa questão facturadas como horas completas. Após esta frase podermos na aplicação. Deveremos realizar as consultas a todas as ficar a pensar que se for usada uma instância durante 30 bases de dados e depois, na aplicação, agregar os resulta- minutos será facturada 1 hora, mas este pensamento pode dos. não ser verdade. Analysis Services, Replication e Service Broker não Se fizer deployment de uma instância às 16h50 e parar essa estão disponíveis como serviço instância às 17H10 irá pagar duas horas. Uma hora pela utilização entre as 16h50 e as 17H00 e outra hora pela utili- Apesar de estes serviços ainda não estarem disponíveis é zação entre as 17h00 e as 17h10. possível usar SQL Azure como fonte de dados para a versão Instâncias que estejam implementadas menos de 5 minutos on-premisses de Analysis Services e Integration Services. dentro de uma hora não serão contabilizadas. Não suporta Database Mirroring ou Failover Clustering Cada novo deployment conta uma nova hora Devido às características de alta disponibilidade do serviço Deveremos evitar implementar, apagar e voltar a implemen- SQL Azure os serviços de suporte a alta disponibilidade da tar instâncias sempre que possível. Cada nova implementa- versão on-premisses tais como database mirroring e failover ção adiciona uma hora por cada instância à conta. cluster não são necessários e não estão disponíveis. Imagine que implementou uma instância às 15h10 e parou a Clustered Indexes são obrigatórios mesma às 15h20. Se fizer nova implementação o App Fabric irá arrancar uma nova máquina e será cobrada uma nova Todas as tabelas em SQL Azure necessitam de um ter um hora completa. clustered index. Um clustered index é um tipo de índice especial que ordena a forma como os registos são gravados Windows Azure Database fisicamente. Esta é uma das primeiras preocupações na migração de bases de dados para SQLAzure. Limitações Não existe integração com CLR O SQLAzure foi desenhado tendo como base o SQLServer sendo por isso natural que partilhe muitas das suas funciona- SQLAzure não suporta CLR. Qualquer base de dados cons- lidades. O SQLAzure suporta múltiplas bases de dados bem truída usando CLR não será possível mover para o SQLAzu- como a maioria dos objectos presentes na versão on- re sem que se proceda a modificações. premisses tais como tabelas, vistas, procedimentos armaze- nados, funções, restrições (constraints) e triggers. 22
  • 23. A PROGRAMAR Programar para Windows Azure Não existe acesso às System Tables Em relação a custos com Windows Azure Storage, estes são medidos usando as seguintes variáveis: Devido a inexistência de acesso ao hardware que suporta a base de dados em SQLAzure não existe acesso às system Tráfego: quantidade de dados transferidos de e para tables do SQLServer. Também não existe acesso às vistas e a o serviço procedimentos armazenados do sistema. Transacções: quantidade de pedidos feitos ao serviço SQL Azure necessita de SQL Server Management Studio 2008 R2 Capacidade: Quantidade de informação armazenada Tráfego Para poder aceder a bases de dados através do SQLServer Management Studio tem que actualizar para a versão 2008 O tráfego consumido internamente não tem custo associado, R2. Apesar de as versões anteriores estabelecerem ligação ou seja, os dados transferidos entre serviços presentes no com o servidor SQL Azure o Object Browser não irá funcio- mesmo datacenter não contam tráfego. Tráfego que tenha nar. Podemos usar a versão gratuita desta ferramenta (SQL origem ou destino diferente do datacenter onde o storage Server Management Studio Express 2008 R2). service foi criado conta tráfego, seja ele externo ou até mes- mo outro datacenter Azure. Nem todos os dados são relacionais Transacções Esta afirmação não trás novidade nenhuma mas ganha Cada chamada a storage service conta uma transacção e especial importância no conceito de Cloud Computing e Win- cada transacção tem um custo. Apesar de o custo de cada dows Azure. O Windows Azure dispõe de diferentes supor- transacção individualmente ser muito baixo (0.01$/10.000 tes ao armazenamento de dados, cada um com as suas transacções) deveremos ter esta situação em atenção no características e custos. Ao afirmar que nem todos os dados desenho das aplicações porque rapidamente se consegue são relacionais pretendemos alertar para o facto de que chegar a cenários em que o número de transacções é muito deverá ser escolhido o tipo de storage certo para o tipo de elevado. Alerta-se ainda para o facto de que cada pedido ao dados certo. storage service conta uma transacção independentemente da origem. Isto significa que os pedidos de serviços presen- O serviço SQLAzure é, relativamente a Azure Storage, um tes no mesmo datacenter também contam transacções. serviço mais caro. SQLAzure custa cerca de 10$/GB (7.5€/ GB) e TableStorage custa cerca de 0.15$/GB (0,11€/GB). A maioria dos pedidos ao storage service conta apenas uma Neste sentido, poderemos como exemplo recomendar o transacção mas existem algumas chamadas a métodos das armazenamento de imagens em Blob Storage ou a passa- Storage Client Library que podem resultar em várias transac- gem de dados históricos ou dados de auditoria (Logs) da ções (vários pedidos): aplicação para Table Storage. Upload para Blob Storage Procedimentos Armazenados Sempre que existe um pedido de upload para Blob Storage A execução de procedimentos armazenados não tem custos de um ficheiro com um tamanho superior a 32Mb a Storage adicionais. Podemos tirar partido desta situação e usar Cliente Library divide automaticamente o pedido em múlti- algum poder de computação do servidor de SQL com o intui- plos blocos de 4Mb. A cada bloco de 4Mb irá corresponder to de poupar no número de roles necessários para a execu- um pedido PutBlock que contará uma transacção cada. Exis- ção da aplicação. De notar que não deveremos abusar des- te ainda um PutBlockList no final que contará também uma tes recursos. transacção. O tamanho do bloco poderá ser modificado atra- vés da propriedade CloudBlobClient.WriteBlockSizeInBytes. Windows Azure Storage Consultas a tabelas Relativamente a Windows Azure Storage vamos tentar per- Sempre que usar a classe CloudTableQuery para realizar ceber alguns dos custos associados a este serviço e tentar consultas a um Azure Table Service terá automaticamente a perceber alguns dos cuidados que deverão ser tidos em conta na hora de desenvolver sobre estes serviços. resolução de continuations tokens de modo a obter todos os resultados pretendidos. 23
  • 24. A PROGRAMAR Programar para Windows Azure Isto significa que sempre que a query retornar um continua- estar constantemente a fazer pooling na queue para detectar tion token irá ser lançado automaticamente um pedido dos a entrada de novas mensagens. restantes resultados e como já vimos anteriormente, cada pedido conta uma transacção. Imagine que existe um worker role com duas instâncias (de Table.SaveChanges modo cumprir o SLA) a fazer pooling com um intervalo de 1 Sempre que for realizada uma operação de Add, Update ou segundo numa queue. Ao final de um mês haverá um custo Delete sobre um objecto de uma tabela, esse objecto será de mais de 5$ só derivado ao pooling. adicionado ao datacontext de modo a que, mais à frente, esse pedido possa ser enviado ao Table Service. Os pedidos Poderá ser implementado um esquema de espera exponen- não são enviados imediatemente, são enviados quando for cial para reduzir o número de chamadas de pooling à queue. chamado o método SaveChangesWithRetries. O incremento de tempo a esperar por cada chamada a uma queue vazia e o número máximo de tempo que esse backoff Quando esse método é chamado as alterações pendentes poderá atingir deverá ser adaptado tendo em consideração o são chamadas uma a uma sobre o table service resultando cenário para qual a queue está a ser utilizada. numa transacção cada. Conclusão Existe no entanto uma excepção a esta situação. Sempre que as alterações pendentes incidirem numa única Partition- Através deste artigo esperamos ter conseguido desafiar o Key de uma tabela poderemos solicitar que as alterações leitor para a necessidade de conhecer em detalhe a arquitec- sejam efectuadas utilizando apenas um pedido através da tura dos serviços e os custos associados de modo a que chamada SaveChangesWithRetries possa desenhar e desenvolver aplicações para Windows (SaveChangesOptions.Batch). Azure de forma eficiente e eficaz. Além de apenas contar uma transacções, submeter as alte- Como dica final, no site de billing podemos ver o estado rações pendentes em batch demora menos tempo e garante actual da subscrição até ao final do dia de ontem e desta processamento transaccional (ou todas são aplicadas ou forma ir verificando os custos das nossas aplicações de nenhuma é aplicada). modo a não existirem surpresas no final do mês. Queues Cada elemento numa Azure Queue custa 3 transacções Nos casos mais comuns usar uma queue para enviar uma mensagem de um role para outro custa cerca de 3 transac- ções porque são necessárias as operações de Put, Get e Delete para processar uma mensagem. Poderemos diminuir o custo cada elemento na queue utili- zando a operação GetMessages da Queue Service API para obter e processar até 32 mensagens de uma só vez e assim diminuir o custo até 2,03 transacções por elemento na queue. Usar backoff exponencial para tempos de espera Devido à ausência de notificações nas queues é necessário AUTOR Vítor Tomaz é consultor independente na área das tecnologias de informação. Tem especial interesse por Cloud Computing, programação concorrente e segurança informática. É membro de algumas comunidades tais como Portugal-a-Programar, NetPonto, AzurePT, HTML5PT e GASP. 24
  • 25. A PROGRAMAR Programação Orientada a Objectos em Java 6 O objectivo deste artigo não é ensinar os conceitos de POO, Este código não dá nenhum erro de sintaxe, no entanto qual- nem a programar em Java. Assim a leitura do artigo pressu- quer programador que perceba o mínimo de Java verá que põe que o leitor já saiba os conceitos de POO, e conheça ao executar a aplicação dará um erro no ciclo. Porque tenta- pelo menos a linguagem Java, ou outra de sintaxe seme- rá somar uma sequência de caracteres com um número lhante para perceber os exemplos. O objectivo deste artigo é inteiro. Contudo se aplicarmos um código semelhante no referir as melhores práticas e métodos de programar POO Java 6, graças às parametrizações obteremos um erro de em Java 6. sintaxe. Parametrização das Colecções public int exemplo(){ ArrayList<Integer> v = new Array- Antes do Java 5, a maneira de implementação de List<Integer>(); colecções, por exemplo a classe ArrayList poderia levar ini- int soma = 0; cialmente um int e posteriormente uma String. Assim era fácil que fosse gerado um erro em runtime, quando estivéssemos v.add(new Integer(2)); por exemplo, a percorrer a colecção e somar todos os ele- v.add("Nome X"); //Aqui dará erro de sin- mentos. No entanto agora é possível parametrizar a colec- taxe ção e dizer para ela só aceitar uma determinada estrutura de dados (ou estruturas descendentes que herdem naturalmen- te as mesmas propriedades). Assim quando antes podería- mos ter no código algo como: O ArrayList é assim genericamente ArrayList<E>, sendo que o E pode ser substituído por qualquer classe, mas não por public int exemplo() dados de tipos primitivos (como o int, o double…), mas isso { é resolvido de maneira simples, como é explicado mais à ArrayList v = new ArrayList(); frente na secção AutoBoxing. int soma = 0; Podemos aperceber-nos que a grande vantagem das para- metrizações, é garantir mais segurança ao programador, de v.add(new Integer(2)); modo a que ele saiba que tipos de coisas estão em vários v.add("Nome X"); locais. O tipo Object dá uma sensação de liberdade, porque //... podemos meter tudo lá dentro, algo como o (void *) do C. Contudo deixa uma responsabilidade acrescida ao progra- Iterator x = v.iterator(); mador que terá que ter em atenção sempre o que está real- while(x.hasNext()) mente lá dentro para não realizar operações não permitidas. soma += Integer.parseInt(x.next().toString Pelo contrário com as parametrizações é possível saber ()); exactamente que operações são permitidas sobre a estrutura de dados, porque ao escrever o código sabemos o que lá return soma; estará. } Outra grande vantagem é a inexistência de conversões. No primeiro exemplo, depois de obter o valor da lista era neces- sário converter para inteiro (e o valor obtido poderia ser inconvertível para inteiro) e só depois somar. No segundo exemplo, o valor devolvido já é do tipo que pretendemos (neste caso um inteiro, o que nós estávamos à espera). AutoBoxing Infelizmente os tipos parametrizados não permitem trabalhar com tipos primitivos, algo que é extremamente importante. Aliás muitos dos problemas requerem vectores de inteiros. Será que então a única solução é trabalhar com os Arrays originais? Não. Todos os tipos primitivos possuem a correspondente classe. Por exemplo a classe Integer, cor- responde ao tipo primitivo int. 25
  • 26. A PROGRAMAR Programação Orientada a Objectos em Java 6 Assim podemos facilmente fazer: ArrayList<Integer> v = new ArrayList<Integer>(); A seguir para adicionar elementos teríamos que colocar algo deste género: v.add(new Integer(3)); v.add(new Integer(9)); int r = v.get(1).intValue(); O construtor é necessário, uma vez que os tipos não são compatíveis. Aliás o seguinte exemplo, compilado antes do Java 5 não funcionaria correctamente: int i; Integer j; i = 1; j = 2; i = j; j = i; Isto porque int é um tipo primitivo e Integer um tipo comple- xo. Logo não é possível fazer uma atribuição de um tipo pri- mitivo para um tipo complexo. Tanto mais que o que está Figura 1: Exemplo do Diamon of Death realmente armazenado em j é um “apontador” para uma ins- tância da classe Integer. Felizmente devido ao AutoBoxing o Na fig. 1 podemos ver um exemplo em que ambas as clas- exemplo a partir de Java 6 funciona perfeitamente, o que nos ses B e C herdam da classe D. Por sua vez, a classe A her- permite fazer também no ArrayList anteriormente criado algo da da B e C simultaneamente. Supondo que a classe D pos- mais simples: sui o método xpto(), e tanto a classe B como a C na sua v.add(3); implementação reescrevem o método. Supondo que ele é chamado no contexto da classe A, e assumindo que ele não v.add(9); é reescrito na classe A, então qual seria o método a ser cha- int r = v.get(1); mado? O da classe B ou C? Nesse caso temos o famoso Diamante da Morte… Como não é possível definir comporta- mentos nas interfaces, apesar de uma classe poder imple- Pode parecer uma pequena diferença, mas numa linguagem mentar várias interfaces, mesmo que ambas possuam méto- como Java, onde é muitas vezes necessário escrever gran- dos com a mesma assinatura, ele têm que ser definido na des linhas de código, isto pode poupar bastante esforço num classe e é esse que será usado. Apesar de prevalecer o projecto. problema de métodos com a mesma assinatura, mas com funções distintas, o que impossibilitava a implementação de Interfaces ambas as interfaces. Aqui está um exemplo da declaração de uma interface. Apesar de já existir antes de Java 5, as interfaces são uma maneira simples de Java ultrapassar as limitações de herança simples, ao invés da múltipla do C++, e ao mesmo public interface Expiravel { tempo evitando grande parte do problema do Diamante da public bool estaExpirado(); Morte (Diamond of Death em Inglês), onde a múltipla heran- ça pode criar problemas ao compilador e ao programador public GregorianCalendar expiraEm(); sobre qual o método a ser executado. } 26
  • 27. A PROGRAMAR Programação Orientada a Objectos em Java 6 Qualquer classe que implemente esta interface, terá que public abstract int maximoDiasEmprestimo(); obrigatoriamente possuir aqueles dois métodos especifica- dos. Assim poder-se-á facilmente percorrer, por exemplo uma lista de objectos de diferentes classes, mas com uma public abstract String nomeTipo(); interface em comum. Como é óbvio, os únicos métodos que poderão ser chamados, sem serem necessárias conversões, serão os definidos na interface. public abstract boolean utilizadorPodeRequisi- tar(String usercodigo); Classes Abstractas } public class Livro extends Publicacoes{ As classes abstractas são muito úteis para possibilitar a pou- pança de código, e garantir o funcionamento correcto da public Livro(String codigo){ classe, que apesar de tudo estará incompleta. //Código Imaginemos por exemplo o caso de uma Biblioteca. } Poderia existir uma classe abstracta, para as publicações, @Override que teria informações gerais, como o código de identificação, se estava requisitado, se era possível de requisitar, quantida- public int maximoDiasEmprestimo(){ de, estado, entre outros atributos. No entanto possuiria méto- //Aqui já terá código também dos abstractos, que têm que ser codificados obrigatoriamen- te na primeira descendente não abstracta. Por exemplo os return 7; métodos maximoDiasEmprestimo, nomeTipo, utilizadorPode- } Requisitar, entre outros seriam definidos como abstractos e não possuiriam código. Assim seriam codificados pelas clas- ses Livro, DVD, Revista, e todos aqueles concretos que her- @Override dassem da classe abstracta mas os métodos já codificados public String nomeTipo(){ na classe abstracta poderiam ser aproveitados, poupando código e trabalho. //Aqui já terá código também return "Livro"; public abstract class Publicacoes { } //Variáveis que segundo as regras do encapsula- mento deverão ser privadas @Override public Publicacoes(){ public boolean utilizadorPodeRequisitar(String //Código usercodigo){ } //Aqui já terá código também public Publicacoes(String codigo){ return true; //Código } } } public String getCodigo(){ Este é um exemplo da aplicação de uma classe abstracta e //Código de uma descendente que implementa as funções abstractas return "x"; e como tal é possível de criar uma instância do mesmo, onde, tal como na herança entre classes simples, podemos } chamar os métodos públicos definidos e herdados da classe public int getQuantidade(){ mãe. //Código Diferentes Tipos de Colecções return 0; } A JFC (JAVA Collections Framework) oferece ao pro- gramador muito mais que simplesmente o ArrayList. Este é //... Mais métodos públicos e se necessário apenas uma pequena parte, embora seja talvez a mais utili- alguns privados zada nem sempre adequadamente. 27
  • 28. A PROGRAMAR Programação Orientada a Objectos em Java 6 Para um conjunto de problemas que necessitem de uma definição matemática de conjunto implica isso mesmo que colecção de valores guardados em memória, muitos progra- não haja repetições. É por isso importante estar a par das madores por desconhecimento utilizam muitas vezes os possibilidades existentes e saber decidir qual a melhor métodos menos adequados. A JFC está dividida em três opção. grandes grupos as Listas (List<E>), os Conjuntos (Set<E>) e as Correspondências(Map<K,V>). Conclusão Supondo, por exemplo uma lista de amigos, qual seria talvez Tal como disse no inicio este não pretendeu ser um artigo o grupo mais interessante? Todos eles podem de maneira que ensinasse a programar Java, nem POO, mas sim um mais ou menos expedita servir para guardar esta informação. artigo que mostrasse algumas novidades de Java 6 em rela- Se a informação fosse guardada na lista teríamos que ter em atenção que não poderíamos repetir amigos e seria necessá- ção ao Java 2 (que por motivos de compatibilidade ainda rio andar sempre a verificar a existência o valor a inserir existem em Java 6, mas são desaconselhados) e a sua liga- antes de o fazer. Como as listas não são ordenadas por defi- ção à Programação Orientada a Objectos, já que é possível nição, a pesquisa demoraria algum tempo para listas de ami- programar em Java sem ter em conta os princípios de POO. gos extensas. Apesar de tudo ficou ainda muito por dizer já que Java é uma linguagem muito extensa e foram focados apenas Nas correspondências teríamos o mesmo problema de verifi- alguns pormenores, no entanto são pormenores que podem car a existência de amizade, mas teríamos a vantagem de permitir um código mais limpo, talvez mais rápido e por ven- esta estar optimizada para pesquisas. Contudo teríamos a tura mais fácil de actualizar. desvantagem de por cada amigo ser necessário guardar um valor, o que pode acabar por não ser uma desvantagem, se for necessário, por exemplo guardar algo associado a essa amizade. Bibliografia http://wiki.portugal-a-programar.org/ Num conjunto não seria necessária a verificação de repeti- dev_geral:java:tutorial:home dos porque ele próprio faz essa verificação, uma vez que a http://download.oracle.com/javase/6/docs/api/ AUTOR António Silva, actualmente a frequentar o 3º ano da Licenciatura de Engenharia Informática da Universidade do Minho sente uma enorme paixão pela programação, nomeadamente em VB.Net e C. Apesar disso possui um conhecimento sobre várias outras linguagens de programação como Java, PHP, Javascript, C#, Haskell, entre outras. 28
  • 29. Elege o melhor artigo desta edição Revista PROGRAMAR http://tiny.cc/ProgramarED31_V
  • 30. A PROGRAMAR DataBinding em Silverlight 4 Neste artigo pretendo apresentar o conceito databinding em Binding Target – vai representar um objecto do tipo Silverlight 4. Vou começar por uma breve apresentação DependencyObject ou do tipo FrameworkElement, ou teórica e em seguida irei apresentar vários exemplos. De seja, na maioria dos casos o controlo da interface salientar que não terei em conta Design Patterns. com o utilizador. Binding Source – vai representar um objecto fonte a O conceito Databinding permite-nos de uma forma simples e visualizar/editar; consistente apresentar e interagir a informação da nossa aplicação, através da criação de um relacionamento entre Dependency Property – permite definir o valor da dois objectos para que a alteração de uma propriedade de propriedade e reflectir/propagar a alteração do valor um deles seja reproduzida numa propriedade de um outro. atribuído, assim como permite definir um valor de Existindo uma separação entre a interface com o utilizador e omissão. a informação, é estabelecido qual o fluxo entre os dois, a Value converter – é um conversor que permitir forma como a alteração é reflectida, a forma como os erros efectuar uma transformação são detectados e a forma como a informação é mostrada na interface com o utilizador. As propriedades a ter em conta: Databinding permite- nos de uma forma Converter permite converter a informação apresentar ao utilizador; simples e consistente ConverterCulture permite definir qual a cultura a (…) a criação de um utilizar no conversor; ConverterParameter permite definir o parâmetro do relacionamento entre conversor; dois objectos ElementName permite definir o nome do controlo ao qual se está usar no binding como objecto fonte; FallbackValue permite definir qual o valor atribuir em A classe Binding representa a relação entre a caso de erro; interface com o utilizador e a informação. Esta classe está incluída no namespace System.Windows.Data e na Mode permite definir o modo do binding; Existem dois tipos: Default e Explicit. assembly System. Windows (na System.Windows.dll) Path permite definir a propriedade a qual se atribui o binding; RelativeSource permite definir qual o objecto fonte associado, existindo uma hierarquia relativa ao objecto fonte actual; Source permite definir qual o objecto fonte; StringFormat permite especificar como formatar a informação a apresentar; TargetNullValue permite definir o valor a usar quando o objecto fonte é nulo; Fig.1 Esquema de relacionamento do Databinding UpdateSourceTrigger permite definir o tipo de actualização do binding. 30
  • 31. A PROGRAMAR DataBinding em Silverlight 4 As propriedades ValidatesOnDataErrors; ValidatesOnEx- ceptions; NotifyOnValidationError; ValidatesOnNotifyDataEr- public Professional() rors estão relacionadas com validação de dados e notifica- { ção de erros. Devem ser definidos a quando da implementa- _isProgrammer = true; ção da interface IDataErrorInfo ou INotifyDataErrorInfo. } De seguida iremos apresentar alguns exemplos práticos! #region ------ Properties ------ public string Name { Suponhamos a criação de uma classe chamada Professio- get { return _name; } nal, que representa um profissional da comunidade NetPon- set { _name = value; to. Esta classe implementa as interfaces IProfessional, que OnPropertyChanged("Name"); } define o que é um Professional e a interface INotifyProperty- } Changed, que permite propagar as alterações que ocorre- rem. public DateTime DateOfBirth { get { return _dateOfBirth; } set { _dateOfBirth = value; OnPropertyChanged("DateOfBirth"); } } public string Address { get { return _address; } set { _address = value; OnPropertyChanged("Adress"); } } public string Locality { get { return _locality; } set { _locality = value; OnPropertyChanged("Locality"); } } public class Professional : INotifyPropertyChanged, IProfessional public int PostalCode { { #region ------ Private members ------ get { return _postalCode; } set private string _name; { private DateTime _dateOfBirth; _postalCode = value; private string _address; OnPropertyChanged("PostalCode"); private string _locality; } private int _postalCode; } private string _mail; private int _contact; private bool _isProgrammer; public int Contact #endregion { get { return _contact; } 31
  • 32. A PROGRAMAR DataBinding em Silverlight 4 set Caso prático 1 { _contact = value; Suponhamos que pretendemos interagir a propriedade OnPropertyChanged("Contact"); } Name com uma TextBox. } Em XAML: public string Mail { <TextBox Name="tbxName" get { return _mail; } Text="{Binding Path=Name, set Mode=TwoWay, { _mail = value; UpdateSourceTrigger=Default}"/> OnPropertyChanged("Mail"); } } Ou em code-behind: var binding =new Binding("Name") public bool IsProgrammer { { get { return _isProgrammer; } Mode = BindingMode.TwoWay, _ set UpdateSourceTrigger _ { =UpdateSourceTrigger.Default _isProgrammer = value; OnPropertyChanged("IsProgrammer"); }; } tbxName.SetBinding(TextBox.TextProperty, _ } #endregion binding); #region ------ INotifyPropertyChanged ------ /// <summary> Caso prático 2 /// Called when [property changed]. /// </summary> Suponhamos que pretendemos interagir a propriedade /// <param name="propertyName">Name of the property.</param> IsProgrammer com uma CheckBox. public void OnPropertyChanged( string propertyName) Em XAML: { if (PropertyChanged != null) <CheckBox Name="ckboxIsProgrammed" PropertyChanged(this, new PropertyChangedEventArgs IsChecked="{Binding Path=IsProgrammer, (propertyName)); Mode=TwoWay,UpdateSourceTrigger=Default}"/> } public event PropertyChangedEventHandler Ou em code-behind: PropertyChanged; #endregion var binding = new Binding("IsProgrammer") } { Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.Default }; ckboxIsProgrammed.SetBinding (CheckBox.IsCheckedProperty, binding); Nota: Nos próximos casos práticos o source é atribuído no DataContext da Page e o binding irá subir na hierarquia até encontrar o source. 32
  • 33. A PROGRAMAR DataBinding em Silverlight 4 Caso prático 3 Caso prático 4 Suponhamos que pretendemos apresentar o PostalCode Atribuir uma lista de profissionais a uma listbox, apresentan- numa label, usando um conversor para formatar a informa- do a propriedade Name. ção. No XAML: Como o PostalCode é um valor inteiro que guarda o código <ListBox Name="lbxProfessional" postal, o PostalCodeConverter é o conversor que separa os DisplayMemberPath="Name"/> primeiros 4 dígitos dos 3 últimos dígitos usando um hífen. Em code behind: A classe PostalCodeConverter implementa a interface IVa- lueConverter e consiste na implementação de dois métodos var professionals = new List<Professional>(); fundamentais, o Convert e o ConvertBack. ... lbxProfessional.ItemsSource = professionals; public class PostalCodeConverter:IValueConverter { public object Convert(object value, System.Type targetType, object parameter, System.Globalization Caso prático 5 .CultureInfo culture) Atribuir uma lista de profissionais a uma datagrid. { No XAML: return value.ToString().Substring(0, 4) + "-" + value.ToString().Substring(4, 3); É preciso definir o namespace } xmlns:sdk="http://schemas.microsoft.com/ public object ConvertBack(object value, winfx/2006/xaml/presentation/sdk" System.Type targetType, object parameter, System.Globalization.CultureInfo culture) <sdk:DataGrid x:Name="datagrid" { AutoGenerateColumns="False"> return int.Parse(value.ToString().Remove('-')); <sdk:DataGrid.Columns> } <sdk:DataGridTextColumn Header="Nome" } MinWidth="200" Binding="{Binding Name}" /> <sdk:DataGridTextColumn No XAML: Header="Código Postal" É preciso definir o namespace Width="100" MaxWidth="150" Binding="{Binding Path=PostalCode, xmlns:sdk="http://schemas.microsoft.com/ Converter={StaticResource winfx/2006/xaml/presentation/sdk" postalCodeConverter}}"/> <sdk:DataGridTextColumn É preciso definir o conversor nos resources: Header="Endereço" Width="50" <navigation:Page.Resources> Binding="{Binding Path=Address}"/> <Demo:PostalCodeConverter <sdk:DataGridTextColumn x:Key="postalCodeConverter" /> Header="Localidade" </navigation:Page.Resources> Binding="{Binding Path=Locality}"/> </sdk:DataGrid.Columns> Definição da label </sdk:DataGrid> <sdk:Label Name="lblPostalCode" Content="{Binding Path=PostalCode, Em code-behind: Mode=TwoWay, UpdateSourceTrigger=Default, Converter={StaticResource datagrid.ItemsSource = professionals; postalCodeConverter}}" /> 33
  • 34. A PROGRAMAR DataBinding em Silverlight 4 Caso prático 6 No XAML: Definir um ItemTemplate para uma listbox. No XAML: <TextBox Name="tbxDateOfBirth" Grid.Column="2" Grid.Row="2" Text="{Binding Path=DateOfBirth, StringFormat=MM-dd-yyyy}"/> <ListBox Name="lbxProfessionalWidthDataTemplate"> <ListBox.ItemTemplate> Ou <DataTemplate> <StackPanel Orientation="Vertical"> <TextBox Name="tbxDateOfBirth" Grid.Column="2" <TextBlock Text="{Binding Path=Name}"/> Grid.Row="2" Text="{Binding Path=DateOfBirth, <TextBlock Text="{Binding _ StringFormat=MMM dd yyyy}"/> Path=PostalCode, Converter={StaticResource postalCodeConverter}}"/> <TextBlock Text="{Binding Path=Address}"/> <TextBlock Text="{Binding Path=Locality}"/> <TextBlock Text="{Binding Path=Contact}"/> <TextBlock Text="{Binding Path=Mail}"/> Conclusão </StackPanel> </DataTemplate> Em conclusão, o conceito Databinding é uma forma simples </ListBox.ItemTemplate> e eficiente de visualização e edição da informação nas apli- </ListBox> cações desenvolvidas em Silverlight. Caso prático 7 Formatar o dia de aniversário usando o StringFormat. AUTOR Sara Silva, é licenciada em Matemática – Especialidade em Computação, pela Universidade de Coimbra, actualmente é Software Developer no Porto. O entusiasmo pela área resultou na obtenção dos títulos de Microsoft Certified Profissional Developer – Windows 3.5, Microsoft Certified Tecnology Specialist – WPF 3.5, WPF 4 e Windows Forms. 34
  • 35. COLUNAS VISUAL (NOT) BASIC — Primeiros passos com GDI+ CoreDump — Martelo <=> Inépcia
  • 36. VISUAL (NOT) BASIC Primeiros passos com GDI+ GDI? A classe Graphics é a nossa porta da frente. GDI ou Graphic Device Interface é a API responsável, directa Podemos preparar uma superfície GDI+ com muita facilida- ou indirectamente, total ou parcialmente, por tudo o que nos de. chega aos olhos no mundo Windows. Se não existe aceleração por hardware e estamos a ver cur- No decorrer do artigo, vou desenhar tudo num panel, apro- vas, linhas, texto e gráficos desenhados, é porque a GDI veitando o disparo do evento “Paint”, que ocorre sempre assim o permite. que a área de desenho precise de ser actualizada, quer por Através desta API conseguimos, de forma bastante penosa indicação explícita invalidando o interface do objecto - (para os produtos de desenvolvimento Microsoft de outrora), PanelGDI.Invalidate() ,ou porque a área saiu do ecrã ou tem desenhar geometria, gráficos e fontes para o ecrã ou para a outra janela a tapar. impressora. Normalmente podemos referenciar a superfície GDI do objecto por: Com a evolução dos tempos, surgem novas necessidades e por volta do Windows XP a Microsoft cria uma API para C/ Dim GDI As Graphics = PanelGDI.CreateGraphics() C++ que chamou simplesmente de GDI+. A API resistiu até hoje, onde já se tentam incutir tecnologias Neste caso, como vamos utilizar o disparo do evento Paint, baseadas em GDI mas que visam substituí-la, como um dos parâmetros que nos chegam do evento é precisa- Direct2D. mente uma referência à superfície GDI: A nova API reduziu significativamente a complexidade para o Dim GDI As Graphics = e.Graphics programador. Preparar para os primeiros rabiscos GDI na .NET Com a superfície GDI preparada, poderíamos começar a A API já se tinha tornado mais poderosa, mais fácil e repre- desenhar imediatamente. sentando uma bela fatia no bolo da relevância de um siste- ma operativo, só seria natural criar um acesso de alto nível, Existem essencialmente 4 maneiras diferentes para muito mais fácil e controlado na .NET framework. De facto a “desenhar”: Microsoft não poderia ter tornado o namespace mais sim- Bitmap, Pen, Brush e Font, servem respectivamente para ples. desenhar imagens, desenhar linhas, pintar áreas e desenhar letras. Para ganharmos acesso a todas as classes expostas basta- Diferentes métodos utilizam diferentes formas de desenhar e nos importar / fazer referência ao namespace Sys- todos em conjunto formam composições. tem.Drawing. Estas formas de desenhar têm que ser preparadas antes de É neste namespace que se encontram todas as classes e poderem ser utilizadas, mas antes… sub-namespaces que nos permitem trabalhar imediatamente com a API. Tamanho, posição e cor Onde posso desenhar? Antes de poder começar a desenhar é importante entender Como todos os componentes passam pela GDI, todos repre- algumas classes que nos ajudam a posicionar, dimensionar sentam uma potencial folha em branco para os nossos dotes e colorir os nossos rabiscos: artísticos. Isto significa que todos os exemplos neste artigo, se aplica- dos por exemplo num form, podem perfeitamente ser aplica- dos desde o panel até a um item de listbox. 36
  • 37. VISUAL (NOT) BASIC Primeiros passos com GDI+ Point / PointF As principais formas de desenhar O Point é uma estrutura que representa essencialmente um Bitmap / Image conjunto de dois valores, X e Y, que representam uma coor- A classe Bitmap representa uma imagem completa, com denada num referencial bidimensional. todas as suas propriedades e informação de cor pixel a pixel. Podemos criar um ponto directamente no construtor: Nos métodos que impliquem desenhar imagens, é uma ins- Dim Ponto As New Point(25, 35) tância desta classe que vai ser usada. Dim PontoF As New PointF(20.5F, 22.03F) Bitmap tem vários construtores, bastante específicos, mas vamos apenas considerar dois para este artigo. Dim Imagem As New Bitmap("C:imagem.png") Size / SizeF Dim Imagem As New Bitmap(800, 600) O Size é uma estrutura que representa um conjunto de dois valores, Width e Height, que representam valores de largura O primeiro construtor vai instanciar a classe com a informa- e altura, respectivamente. ção da imagem indicada. Podemos criar uma dimensão directamente no construtor: O segundo construtor vai criar uma imagem abstracta, com 800x600 px Dim Dimensao As New Size(800, 600) O primeiro construtor vai instanciar a classe com a informa- Dim DimensaoF As New SizeF(100.05F, 100.07F) ção da imagem indicada. Rectangle / RectangleF O segundo construtor vai criar uma imagem abstracta, com O Rectangle é uma estrutura que representa um conjunto de 800x600 px 4 valores, X, Y, Width e Height, que representam um combi- nado de coordenadas XY e dimensão. Pen Podemos criar um Rectangle directamente no construtor: A Pen é necessária para todos os métodos que impliquem o desenho de linhas, curvas e contornos. Color Podemos criar uma Pen apenas por indicar a sua cor e Dim Rectangulo As New Rectangle(0, 0, 100, 100) espessura: Dim RectanguloF As _ Mas existem mais propriedades na classe Pen que lhe New RectangleF(0.5F, 0.8F, 100.03F, 100.25F) Dim P As New Pen(Color.Black,2) A Color é uma estrutura que representa um conjunto de 4 valores, A, R, G e B que representam os 4 canais que consti- podem conferir mais características visíveis, tais como a tuem uma cor aRGB: A para Alpha, ou o canal de opacidade, forma terminal ou o estilo da linha, que não vou abordar. RG e B para Red, Green e Blue, respectivamente. Brush Cada canal comporta valores que variam dos 0 (ausência) até 255 (presença total) O Brush é necessário para todos os métodos que impliquem preenchimento de áreas. A classe Color não tem construtores. Podemos obter uma cor quer através da enumeração disponível, quer por utiliza- Existem vários tipos de “pincel” que permitem a aplicação de ção de alguns métodos disponíveis. texturas, gradientes, padrões ou simplesmente uma cor. Vou focar essencialmente o SolidBrush, para cores únicas e Dim Cor As Color = Color.FromArgb(255, 255, 0, 0) o LinearGradientBrush para gradientes de duas cores sim- Dim Cor As Color = Color.Red ples. Dim Cor As Color = Color.FromName("Red") Podemos criar SolidBrush directamente no construtor: Dim Cor As Color = _ Dim B As New SolidBrush(Color.Red) Color.FromKnownColor(KnownColor.ActiveBorder) Também podemos criar LinearGradientBrush directamente no construtor: Dim B As New LinearGradientBrush(New _ Com estas noções estamos aptos a colorir e posicionar os Point(0, 0), New _ nossos rabiscos. Point(100, 100), Color.Red, Color.Green) 37
  • 38. VISUAL (NOT) BASIC Primeiros passos com GDI+ É necessário um ponto onde o gradiente vai iniciar e um ponto onde vai terminar, bem como as cores nesses mes- mos pontos. A mistura de cor no intervalo intermédio é automaticamente calculada. Existem classes que desempenham um papel importante na mistura de cores do gradiente, mas não as vamos abordar. DrawBezier (Pen, Ponto1,Ponto2,Ponto3,Ponto4) Observemos diferentes colocações dos pontos do gradiente O método DrawBezier desenha uma curva de Bézier com 4 abaixo: pontos de controlo. Existem mais overloads, mas são redundantes. Dim pt1 As New Point(0, 0) Dim pt2 As New Point(80, 20) Font Dim pt3 As New Point(20, 80) A Font é necessária para todos os métodos que impliquem o uso das fontes do sistema. Dim pt4 As New Point(100, 100) Dim g As Graphics = e.Graphics Será tipicamente utilizada sempre que for necessário escre- ver alguma coisa na superfície GDI. g.DrawBezier(New Pen(Brushes.Black, 2), _ Podemos criar uma Font directamente no construtor: pt1, pt2, pt3, pt4) Dim F As New Font("Arial", 14) Dim F As New Font("Arial", 14, FontStyle.Bold Or _ FontStyle.Italic) Dim F As New Font("Arial", 14, FontStyle.Bold Or _ FontStyle.Italic, GraphicsUnit.Pixel) Os métodos, finalmente. DrawCurve / DrawColsedCurve (Pen,Pontos(),Tensão) Descrita toda a preparação, está na altura de explorar os métodos da classe Graphics. O método DrawCurve desenha uma curva linear, passando por os pontos no array Pontos(), aplicando a tensão defenida O namespace “Drawing” é vasto e bastante completo. (valor de 0.0 a 1.0) Vou apontar apenas o que considero mais importante. DrawClosedCurve é em tudo semelhante, mas liga o último ponto em Pontos() ao primeiro, fechando a curva. DrawArc(Pen,X,Y,Width,Height,AnguloInicial,Varrimento) Existem mais overloads. O método DrawArc desenha um arco com as propriedades Dim pt1 As New Point(0, 0) da Pen, com centro em XY, incluído no rectângulo de largura Dim pt2 As New Point(80, 20) Width e altura Height, centrado. Dim pt3 As New Point(20, 80) A curva começa no AnguloInicial e é desenhada até ao ângulo AnguloInicial + Varrimento. Dim pt4 As New Point(100, 100) Dim pts As Point() = New Point() {pt1, pt2, pt3, Os ângulos são dados em graus. pt4} Existem mais overloads, mas são redundantes. Dim g As Graphics = e.Graphics Dim g As Graphics = e.Graphics g.DrawCurve(New Pen(Brushes.Black, 2), pts, 0F) g.DrawArc(New Pen(Brushes.Black, 2), 0, 0, 100, g.DrawCurve(New Pen(Brushes.Black, 2), pts, 0.5F) 100, 0, 90) g.DrawCurve(New Pen(Brushes.Black, 2), pts, 1F) g.DrawArc(New Pen(Brushes.Black, 2), 0, 0, 100, 100, 180, 90) 38
  • 39. VISUAL (NOT) BASIC Primeiros passos com GDI+ DrawEllipse (Pen, Rectangulo) DrawLine (Pen,Ponto1,Ponto2) O método DrawEllipse desenha uma elipse inscrita no rec- O método DrawLine desenha uma linha com origem em Pon- tângulo especificado. to1 e destino em Ponto2. A elipse é desenhada no centro do rectângulo o que faz com Existem mais overloads, mas são redundantes. que se possa afirmar que, por exemplo, num quadrado Dim pt1 As New Point(25, 25) 100x100, o método DrawEllipse vai desenhar uma circunfe- rência centrada em x=50 e y=50 com raio de 50px Dim pt2 As New Point(75, 75) Dim rect1 As New Rectangle(0, 0, 100, 100) Dim g As Graphics = e.Graphics Dim rect2 As New Rectangle(0, 0, 100, 50) g.DrawLine(New Pen(Brushes.Black, 2), pt1, pt2) Dim g As Graphics = e.Graphics g.DrawEllipse(New Pen(Brushes.Black, 2), rect1) g.DrawEllipse(New Pen(Brushes.Black, 2), rect2) DrawPie (Pen,X,Y,Width,Height,AnguloInicial,Varrimento) O método DrawPie desenha uma secção de um círculo, lem- brando uma fatia de pizza ou tarte (Pie). A circunferência é inscrita no rectângulo formado por XY, Width e Height e é desenhada a secção da circunferência que começa no AnguloInicial e termina em AnguloIni- cial+Varrimento. DrawImage (Bitmap,Ponto / Rectangulo) Os ângulos são dados em graus. O método DrawImage desenha a informação de uma classe Bitmap com origem no ponto especificado ou com origem e Existem mais overloads, mas são redundantes. dimensões ditadas pelo rectângulo. Dim g As Graphics = e.Graphics Existem outros métodos semelhantes e muitos overloads, a g.DrawPie(New Pen(Brushes.Black, 2), _ maioria redundantes. 0, 0, 100, 100, 0, 90) O canal Alpha é perfeitamente respeitado e obtêm-se boni- g.DrawPie(New Pen(Brushes.Black, 2), _ tos resultados com PNG. 0, 0, 100, 100, 180, 90) Dim B As New Bitmap("c:pap.png") Dim Ponto As New Point(0, 0) Dim g As Graphics = e.Graphics g.DrawImage(B, Ponto) Dim Rectangulo As New Rectangle(0, 50, 50, 50) g.DrawImage(B, Rectangulo) 39
  • 40. VISUAL (NOT) BASIC Primeiros passos com GDI+ DrawPolygon (Pen,Pontos()) O método DrawPolygon desenha um polígono, ao ligar sequencialmente todos os pontos especificados, voltando ao primeiro depois do último. Existe apenas mais um overload para utilizar valores com casas decimais. Dim pt1 As New Point(50, 0) Dim pt2 As New Point(60, 40) DrawString Dim pt3 As New Point(100, 40) (Texto,Fonte,Brush,Rectangulo,StringFormat) Dim pt4 As New Point(65, 60) O método DrawString desenha texto a partir de uma string, com uma determinada fonte e conjunto de características de Dim pt5 As New Point(80, 100) formato. Dim pt6 As New Point(50, 70) Existem overloads, alguns redundantes. Dim pt7 As New Point(20, 100) Dim pt8 As New Point(35, 60) Dim F As New Font("Arial", 7, FontStyle.Italic) Dim pt9 As New Point(0, 40) Dim SF As New StringFormat Dim pt10 As New Point(40, 40) SF.Alignment = StringAlignment.Center Dim pts As Point() = New Point() _ Dim R As New Rectangle(0, 50, 100, 40) {pt1, pt2, pt3, pt4, pt5, pt6, pt7, pt8, pt9, pt10} Dim g As Graphics = e.Graphics Dim g As Graphics = e.Graphics g.DrawString("Portugal-a-Programar", F, _ g.DrawPolygon(New Pen(Brushes.Black, 2), pts) Brushes.Black, R, SF) SF.FormatFlags = StringFormat- Flags.DirectionVertical _ Or StringFormatFlags.LineLimit F = New Font("Arial", 10, FontStyle.Italic _ Or FontStyle.Bold) g.DrawString("GDI+", F, Brushes.Black, 0, 20, SF) DrawRectangle (Pen,X,Y,Width.Height) O método DrawRectangle desenha um rectângulo com ori- A maioria dos métodos de prefixo gem no XY especificado e com as dimensões especificadas. “Draw” existe numa segunda versão “Fill”. Existem mais overloads, mas são redundantes. A operação é semelhante, mas as áreas geradas são preen- chidas de acordo com um brush fornecido, quer seja ele sóli- Dim g As Graphics = e.Graphics do, gradiente, textura, hatch ou de qualquer outro tipo. g.DrawRectangle(New _ Performance versus Qualidade Pen(Brushes.Black, 2), 10, 10, 80, 40) A classe Graphics possui algumas propriedades que defi- nem a forma como a GDI vai render os gráficos. 40
  • 41. VISUAL (NOT) BASIC Primeiros passos com GDI+ Como em tudo, se pretendemos qualidade temos de sacrifi- car performance e vice-versa. MeasureString Eis algumas das propriedades mais comuns e seus efeitos: Nos casos em que desenhamos texto indicando apenas uma posição de origem XY, este é desenhado de forma linear, sem qualquer limite. O método MeasureString permite-nos medir o tamanho que essa string vai ocupar, para que possamos fazer correcta- mente os nossos cálculos. Também é possível medir as dimensões de uma string dese- nhada dentro de uma área, que faz com que possamos ter noção do quanto “cresceu” nos casos onde ocorre “wordwrap”. O método MeasureString é muito semelhante ao método DrawString, pois precisa de saber exactamente como é que o texto foi (ou vai ser) desenhado, para que possa interna- mente fazer a simulação. O método devolve-nos as dimensões do texto, em largura e altura, num tipo de dados SizeF. Pen Cap / Dash Style Ao desenhar linhas, sobretudo com alguma espessura visí- vel, podemos notar que os terminais da linha são abrupta- mente cortados, como é normal. O pen cap determina precisamente como esses terminais são desenhados. Existem alguns caps disponíveis, para além da possibilidade de desenhar os nossos próprios caps (custom). Para além dos caps e de outras propiedades, é possível Algumas dicas determinar como vai ser o traçado da linha, o Dash Style. Para este exemplo foi necessário utilizar a classe Graphics- Path, a qual não está prevista para este artigo. Double Buffer Se a intenção é usar a GDI+ para criar algum tipo de movi- mento, tal como um pequeno jogo, algo que necessite de constante e rápido refrescamento, rapidamente se nota que Dim g1 As Graphics = PanelGDI.CreateGraphics se torna impossível de continuar pois cada ciclo de refresca- Dim g2 As Graphics = Panel1.CreateGraphics mento é reflectido de forma negativa na superfície GDI. Dim g3 As Graphics = Panel2.CreateGraphics Isto traduz-se num “piscar” insuportável que é causado pela Dim g4 As Graphics = Panel3.CreateGraphics constante soma de execução do refrescamento e dos gráfi- cos propriamente ditos. Dim g5 As Graphics = Panel4.CreateGraphics Nestes casos podemos, sacrificando um pouco de perfor- g1.Clear(Color.White) mance, utilizar um “Double buffer” que fará com que as g2.Clear(Color.White) actualizações sejam feitas em paralelo com a apresentação, g3.Clear(Color.White) o que se traduz numa actualização “suave” da superfície GDI, mas um pouco mais demorada. g4.Clear(Color.White) Num objecto como a Form, basta alimentar a propriedade g5.Clear(Color.White) DoubleBuffered para True. 41
  • 42. VISUAL (NOT) BASIC Primeiros passos com GDI+ Dim cpts As Point() = New Point() _ Dim pt1 As New Point(20, 20) Impressão {cpt1, cpt2, cpt3, cpt4, cpt5, cpt6, cpt7, Dim pt2 As New Point(80, 20) cpt8, cpt9, cpt10} Dentro do namespace Drawing, pertencente ao namespace Dim pt3 As New Point(20, 80) Printing, encontramos algumas classes como PrintDocu- GP.AddPolygon(cpts) Dim pt4 As New já conhecem80) fazer impressão de ment, que muitos Point(80, para Dim MyC As New CustomLineCap(Nothing, GP) dados. Dim MyP As New Pen(Brushes.Black, 6) MyP.EndCap = LineCap.Custom Não é uma falha o namespace Printing estar incluído no g1.DrawBezier(MyP, pt1, pt2, pt3, pt4) 'IMG1 namespace Drawing. MyP.StartCap = LineCap.Custom MyP.CustomStartCap = MyC Na verdade, é possível desenhar documentos para a impres- MyP = New Pen(Brushes.Black, 6) sora exactamente da mesma forma que os desenharíamos MyP.CustomEndCap = MyC MyP.StartCap = LineCap.DiamondAnchor no form. g5.DrawBezier(MyP, pt1, pt2, pt3, pt4) 'IMG5 MyP.EndCap = LineCap.ArrowAnchor g2.DrawBezier(MyP, pt1, pt2, pt3, pt4) 'IMG2 Em suma... MyP = New Pen(Brushes.Black, 6) O namespace Drawing e a GDI+ no geral, oferecem-nos um MyP.DashStyle = DashStyle.Custompartir do qual pode- grande potencial para a imaginação, a MyP.DashPattern = visualmente ricas. mos criar aplicações New Single() {0.5F, 1.0F, 0.5F, I 1.0F} como se programa com a API, em nível mais eleva- A forma Dim Setanamespace Drawing concede uma simplicidade de do com o As New AdjustableArrowCap(1, 2) mpressão tal forma que é possível desenhar uma linha com duas linhas Dentro do namespace Drawing, pertencente ao namespace Seta.Filled = False de código. Printing, encontramos algumas classes como MyP.CustomEndCap = Seta Se queremos enriquecer visualmente uma aplicação Win- PrintDocument, que muitos já conhecem para fazer g3.DrawBezier(MyP, pt1, pt2, pt3, pt4) 'IMG3 e Forms, nem vale a pena procurar mais. A GDI+ é ideal impressão de dados. está incluída na .NET. MyP = New Pen(Brushes.Black, 6) Não é uma falha o namespace Printing estar incluído no MyP.DashCap = DashCap.Round namespace Drawing. MyP.EndCap = LineCap.RoundAnchor Na verdade, é possível desenhar documentos para a g4.DrawBezier(MyP, pt1, pt2, pt3, pt4) 'IMG4 impressora exactamente da mesma forma que os desenharíamos no form. MyP = New Pen(Brushes.Black, 1.5F) Dim GP As New GraphicsPath() Em suma... Dim cpt1 As New Point(5, 0) Dim cpt2 As New Point(6, 4) O namespace Drawing e a GDI+ no geral, oferecem-nos um grande potencial para a imaginação, a partir do qual Dim cpt3 As New Point(10, 4) podemos criar aplicações visualmente ricas. Dim cpt4 As New Point(6, 6) A forma como se programa com a API, em nível mais Dim cpt5 As New Point(8, 10) elevado com o namespace Drawing concede uma Dim cpt6 As New Point(5, 7) simplicidade de tal forma que é possível desenhar uma linha com duas linhas de código. Dim cpt7 As New Point(2, 10) Se queremos enriquecer visualmente uma aplicação Dim cpt8 As New Point(3, 6) WinForms, nem vale a pena procurar mais. A GDI+ é ideal e Dim cpt9 As New Point(0, 4) está incluída na .NET. AUTOR Sérgio Ribeiro, curioso e auto-didacta com uma enorme paixão por tecnologias de informação e uma saudável relação com a .NET framework. Moderador do quadro de Visual Basic.NET na comunidade Portugal@Programar desde Setembro de 2009. Alguns frutos do seu trabalho podem ser encontrados em http://www.sergioribeiro.com 42
  • 43. CoreDump Martelo <=> Inépcia Esta semana conversava com um colega e amigo sobre o primeira abordagem deve ser sempre a facto da maioria dos profissionais de TI que chegam actual- observação do plano de execução e a mente ao mercado de trabalho não compreenderem as reescrita da query de forma mais eficien- bases sobre as quais assentam as tecnologias que utilizam. te. Pode parecer conversa de “velho do restelo”, de quem tinha E quando chegamos aos paradigmas, de saber configurar um disco rígido como master ou slave enfim... Constato que muitos não sabem através de jumpers no hardware ou de quem tinha de saber sequer o que é a herança no paradigma configurar o DOS correctamente para poder fazer uso total OO, fazendo classes que diferem ape- dos 4 MB de RAM que estavam disponíveis e libertar ao nas num pequeno conjunto de atributos distinto. Pior, igno- máximo os míticos 640Kb. Acreditem que nenhuma destas ram mecanismos como cálculo lambda e paradigmas como experiências é saudosista e que o tema da conversa não os da programação funcional. originou daí... Tenho outro amigo que costuma dizer, em relação a este tipo A verdade é que actualmente detecto falhas nas bases de de comportamento padrão, que “quando a única ferramen- muitos profissionais de TI que, ou por não terem sido bem ta que se conhece é o martelo, todos os problemas pare- orientados, ou pela actual facilidade tecnológica, ou por sim- cem um prego”. E a verdade é que esta frase resume um ples preguiça pessoal, não compreendem na totalidade as pouco o que se passa. Em vez de se compreender o que se tecnologias com que trabalham diariamente. passa para procurar a melhor solução a aplicar, martela-se a São exemplos típicos a utilização de frameworks, que facili- única solução que se conhece... Por vezes a aplicação da tam o desenvolvimento através da elevação de conceitos e solução escala com o problema e quanto maior o problema, abstracção, a utilização de bases de dados e a utilização do maior a martelada... Fico a pensar se será ironia ou pura paradigma Object Oriented. casualidade o facto de tantas aplicações terem um martelo como ícone em algumas das suas opções de menu. Uma framework simplifica e agiliza o desenvolvimento, mas também esconde e abstrai o trabalho que está por detrás, É óbvio que compreender as bases da tecnologia é impres- fazendo querer a muitos dos seus utilizadores que é magia. cindível para saber o que andamos a fazer. Se não com- Como resultado, temos muitas vezes profissionais de TI preendermos as bases da tecnologia, dificilmente saberemos incapazes de compreender a sua ferramenta de trabalho, o que estamos a fazer e se não sabemos o que estamos a ficando à sua mercê. Este desconhecimento torna-se rele- fazer, então o resultado do nosso trabalho nunca será gran- vante quando se deparam com determinados bugs relacio- de coisa... Ninguém nasce ensinado, mas nunca na história nados com a framework ou quando necessitam de imple- da Humanidade foi tão simples, rápido e barato aceder ao mentar uma solução que sai fora do âmbito da aplicação da conhecimento. Na área de TI não faltam livros, blogs, fóruns framework. e afins onde tudo se encontra documentado e descrito para nossa compreensão. Infelizmente, também aqui, vejo que É preocupante observar que todos os problemas de lentidão muitos usam a internet de forma errada, fazendo copy- de uma aplicação se resolvem com mais RAM ou mais CPU paste programming em vez de compreenderem a solu- sem sequer se identificar a causa do problema recorrendo à ção e, quando o código copiado de um qualquer site não utilização de um profiler. funciona à primeira, o resultado é um post com um pedido de Uma base de dados é imprescindível para qualquer sistema ajuda. Infelizmente, a nossa comunidade também tem exem- informático, e desconhecer a 3ª Forma Normal é meio cami- plos de sobra deste tipo… A culpa da formação inadequada nho andado para um sistema deficiente. Este problema é só é responsável até certo ponto, uma vez que todos estes visível na nossa própria comunidade, onde recorrentemente problemas se resolvem com a adopção de uma postura e se vêm estagiários e estudantes – futuros profissionais de TI atitude de querer saber e compreender por parte de cada – a desenvolverem projectos em que criam tabelas sem um. Por isso peço a todos os que pretendem trabalhar em TI saber o que representam e não terem qualquer noção das que façam um favor a vocês próprios: larguem o martelo, suas relações. É gritante observar que a única solução para continuem a aprender e não cedam à inépcia. uma query lenta passa pela criação de um índice, quando a AUTOR Fernando Martins, faz parte da geração que se iniciou nos ZX Spectrum 48K. Tem um Mestrado em Informática e mais de uma década de experiência profissional nas áreas de Tecnologias e Sistemas de Informação. Criou a sua própria consultora sendo a sua especialidade a migração de dados. 43
  • 44. COMUNIDADES SharePointPT - Padrão alternativo de Sharepoint
  • 45. COMUNIDADE SHAREPOINTPT http://www.sharepointpt.org Padrão alternativo de Sharepoint: a pesquisa como fonte de dados – parte I – Arquitectura A plataforma Sharepoint tem sido nos últimos anos, um Robustez: os tempos de indisponibilidade são críticos importante suporte para o desenvolvimento de soluções para a organização; dada a especialidade do negócio empresariais de intra/extra/internet. Com maior ou menor a suportar pela plataforma, a aplicação não deverá dificuldade as equipas entram no padrão de desenvolvimen- apresentar picos diários de utilização, prevendo-se to modular (p.e. webparts) ou via extensão da própria plata- um volume de utilizadores estável no período 06:00 forma, suportado por pacotes de instalação (wsps) e funcio- até às 02:00, altura em que a utilização decai para um nalidades empacotadas (features), tendo asseguradas de valor residual; base algumas funcionalidades interessantes, como p.e.: Não perder 1 única encomenda: a plataforma deverá Controlo de acessos permitir recuperar todas as encomendas que possam falhar, para posterior processamento por operadores; Motor de workflows Ter um portal para gerir a informação genérica dos Plataforma de edição de conteúdos produtos. Serviços transversais (pesquisa, excel, business intel- A XPTO tem um volume de aproximadamente 20.000 utiliza- ligence, etc) dores registados, com um acesso diário previsto de 10%. Instalação de pacotes em toda a farm de forma auto- mática Arquitectura Neste artigo pretende-se desconstruir as abordagens mais Como componentes da arquitectura, é proposta uma aborda- tradicionais, apresentando uma solução pouco comum atra- gem distribuída em vários componentes/plataformas, tirando vés de uma arquitectura, mas que optimiza os módulos de proveito das principais características de cada uma: maior interesse para o cenário apresentado, centrando-se principalmente na componente de indexação e pesquisa do Apresentação: IIS (Internet Information Services), .Net Sharepoint. Este cenário corresponde a parte de uma imple- 4 e MVC mentação real. Como principais vantagens destas tecnologias temos Neste 1º artigo, é abordada a componente de arquitectura da a escalabilidade, robustez e flexibilidade solução e componentes de alto nível, para permitir a visuali- Gestão de conteúdos e indexação: Sharepoint zação da solução. A gestão de conteúdos e indexação são alguns dos No 2º artigo da série, será descrita a componente mais técni- principais pontos fortes da plataforma Sharepoint ca, incluindo a configuração das regras de pesquisa, das propriedades (crawlled e managed), models de consumo dos Gestão de catálogo: Commerce Server dados e o respectivo empacotamento da solução de indexa- A plataforma de comércio electrónico centra-se ção. Cenário Esta arquitectura conta ainda com as plataformas Biztalk na A empresa XPTO necessita de um portal público que dispo- componente de integração e com o CRM na componente de nibilize uma loja de comércio electrónico, tendo como princi- gestão de clientes, ficando no entanto de fora do tema pro- pais requisitos: posto neste artigo. A camada de apresentação é integralmente suportada por Performance: carregamento de páginas até 3 segun- uma implementação MVC, cujos models vão beber dados dos, independentemente do volume de acessos; principalmente às plataformas Commerce e Sharepoint Escalabilidade: a plataforma deve permitir um proces- (search services). so evolutivo simples e sólido; A gestão de conteúdos é suportada por um portal Share- point, onde as características de produtos, ficheiros 45
  • 46. COMUNIDADE SHAREPOINTPT http://www.sharepointpt.org Padrão alternativo de Sharepoint: a pesquisa como fonte de dados multimédia e documentos são geridos e mantidos por circui- tos de aprovação standard. Toda a informação de catálogo e stock é mantida na platafor- ma Commerce, que tembém suporta toda a parte de carrinho de compras. Uma vez que a informação se encontra distribuída nas plata- formas Commerce, Sharepoint e ainda em alguns sistemas externos, opta-se pela utilização da componente de indexa- ção para unir esta informação dispersa, através da constru- ção de uma plataforma de indexação costumizada, composta por uma componente de listagem e um segundo nível com o detalhe dos produtos. Este padrão apresenta como principais vantagens: Melhor organização da aplicação pela divisão das várias lógicas em zonas separadas; Não usa view state ou forms, o que dá um maior con- trolo sobre a aplicação e sobre a informação trocada Stock, preço, carrinho e perfil Dados de produtos IIS,MVC com o utilizador; Dados de Catálogo Melhor suporte para um padrão de desenvolvimento Commerce Sharepoint TDD (Test Driven Development é um padrão que pro- Edição de conteúdos move o desenvolvimento baseado na existência de testes unitários); Dada a granularidade fina dos componentes, é uma boa aposta para equipas de maior dimensão. SQL Server Indexação e pesquisa Tendo a pesquisa como fonte de dados da camada de apre- Padrão MVC (Model-View-Controller) sentação, vários pontos surgem como requisitos deste com- ponente: Tema para um artigo só por si, o MVC é um padrão de imple- mentação que merece uma breve referência para enquadra- Fornecer informação de carácter genérico, contida mento (e para despertar o interesse pelos padrões, para num portal de Sharepoint; quem ainda não os conhece). Fornecer informação de catálogo, contida no Com- merce Server; O padrão arquitectural MVC separa as camadas aplicacio- nais em 3 componentes: Fornecer informação de cariz técnico, contida em outros sistemas externos; Model: responsável pela representação e manuten- ção dos estados dos dados; Com base nestas necessidades optou-se pela seguinte abor- dagem: View: camada de apresentação, responsável por Criação de um conjunto de páginas de índice em cas- mostrar os dados e interagir com o utilizador; cata, que começam por listar sites com link para o Controller: camada de lógica que toma as decisões nível seguinte onde passa o site seleccionado no link; baseada nos dados inseridos pelos utilizadores na no nível seguinte lista os sub-sites do site selecciona- View, passando a informação necessária ao Model do e por último, lista os produtos com link para a pági- correspondente para manuseamento dos dados. na de detalhe do produto. 46
  • 47. COMUNIDADE SHAREPOINTPT http://www.sharepointpt.org Padrão alternativo de Sharepoint: a pesquisa como fonte de dados multithreaded permite paralelizar as várias recolhas e diminuir significativamente o tempo de carregamento List sites da página. Uma vez que esta página será chamada tantas vezes, quantos os produtos existentes, tem um impacto significativo na duração total do processo de List subsites indexação e consequentemente na desactualização da informação para o utilizador final (p.e. se uma indexação demorar 1 hora, há a probabilidade dos List products dados dos produtos apresentados estejam desactuali- zados até 1 hora atrás). Produt detail O modelo do processo de recolha de informação e geração da página de indexação é apresentado no diagrama seguinte. Página de detalhe do produto que recebe por parâ- metro o sub-site, bem como o código do produto e gera uma página de detalhe contendo os dados necessários para a camada de apresentação. Estes dados, ao serem indexados na mesma “página” ficam relacionados entre si. Ao incluirmos uma chave (ex. id do produto), vamos poder aceder-lhe como uma enti- dade. O código gerado pela página de detalhe do produto é algo do tipo: <html> <head> <title>Detalhe de produto</title> <meta name="ProductName" content="Single Track King" /> <meta name="ProductCategory" content="Bicicletas Todo Terreno" /> Os principais desafios da componente de indexação, <meta name="ProductDescription" revelam-se nesta altura e vale a pena salientar: content="A melhor btt de sempre." /> Uma vez que para um comportamento correcto desta <meta name="ProductImage" página, os dados têm de ser indexados em metatags content="/images/products/1234567.jpg" /> e consequentemente são indexados como texto pelo <meta name="ProductId" Sharepoint; content="1234567" /> … Ao indexar via metatags, perde-se a caracterização </head> dos dados (ver “O que perdemos com a indexação via <body></body> metatags”); </html> Esta página tem de aceder a vários sistemas, desde listas de Sharepoint a web services e WCFs de outras Ao ser indexada esta página fará com que sejam criadas plataformas, o que a torna pesada; uma abordagem propriedades (crawlled properties de Sharepoint), com os nomes ProductName, ProductCategory, ProductDescription, etc. que por sua vez poderão ser promovidas por configura- 47
  • 48. COMUNIDADE SHAREPOINTPT http://www.sharepointpt.org Padrão alternativo de Sharepoint: a pesquisa como fonte de dados A abordagem do processo de indexação é propositadamente melhor performance, mas potencialmente mais onero- simplista, para permitir tirarmos proveito do modelo multith- sa tendo em conta o licenciamento; readed da pesquisa, levando-nos a construir as páginas tão Via serviços (Query Via serviços (Query Web Servi- simples e pequenas quanto possível, evitando desta forma ce); solução mais flexível mas com alguma desvanta- esgotar os recursos das máquinas. gem em termos de performance. O que perdemos com a indexação via metatags O processo de indexação baseado em metatags tem uma desvantagem imediata que é a descaracterização do tipo de Conclusão dados, uma vez que estaremos a indexar páginas HTML, em Plataformas com a complexidade do Sharepoint são candi- cujos campos de meta são sempre indexados como texto. datas a implementações inovadoras, uma vez que disponibi- No nosso cenário, esta desvantagem é minimizada, uma vez lizam um conjunto grande de funcionalidades, para os quais que os dados indexados são utilizados apenas para geração nem todos os cenários foram equacionados pelas equipas da apresentação, baseando-se os dados e processo de com- de produto e/ou arquitectura. Neste artigo é apresentada pra na plataforma Commerce. uma solução diferente das habitualmente recomendas, mas É sempre possível efectuar transformações de tipo (cast ou com provas dadas de escalabilidade e fiabilidade para um parse) que devidamente efectuadas não trazem desvanta- ambiente empresarial bastante exigente. Espero com este gens em termo de estabilidade, mas são operações pesadas exemplo conseguir despertar em si, o pensamento fora da em termos de ciclos de processamento trazendo uma degra- caixa. dação significativa da performance quando invocadas fre- No próximo artigo desta série, será abordada a componente quentemente. de implementação da solução, com exemplos de código de string myText = "123456"; cada um dos componentes. int myVal; Referências if (!int.TryParse(myText, out myVal)) Nota: apesar de estarmos numa publicação em língua portu- { guesa, as referências apresentadas são na maioria dos // Ocorreu um erro no processo de parse casos para as versões inglesas. Isto deve-se somente a, por // tratar o erro neste ponto experiência própria, o conteúdo em inglês ser mais rico e } actualizado que nas restantes línguas. IIS – http://www.iis.net Consumo da informação Microsoft Commerce Server - http://bit.ly/s5Uu2 Microsoft Sharepoint Server - http://bit.ly/qmpwu3 Estando a informação devidamente indexada pelo Share- point, é altura de ser consumida e renderizada nas máquinas MVC - http://www.asp.net/mvc responsáveis pela apresentação dos dados. O consumo da SharePoint Search Service Tool - http://bit.ly/ZY9H3 informação, efectuado pelos models MVC, poderá ser feito Test Driven Development - http://bit.ly/qAIxha de duas formas: The Search Developer Story in SharePoint 2010 - Query In- Via API (Query Object Model), necessitando de ter o terfaces - http://bit.ly/bnaA4G Sharepoint instalado nestas máquinas; solução de AUTOR Rui Melo - rui.melo@microsoft.com Desde há 12 anos, no mundo das IT, iniciou a carreira na área de I&D de comércio electrónico. Passou por empresas como SMD, Pararede, Newvalue e Link, integrou os quadros da Microsoft como consultor há cerca de 5 anos, mais focado na plata- forma Sharepoint. Envolvido desde cedo na comunidade SharepointPT, tem na partilha de conhecimento uma forte motiva- ção. Blog: http://mystepstones.wordpress.com. 48
  • 49. Veja também as edições anteriores da www.revista-programar.info Revista PROGRAMAR 28ª Edição - Abril 2011 25ª Edição - Setembro 2010 e muito mais em … 29ª Edição - Junho 2011 26ª Edição - Dezembro 2010 30ª Edição - Agosto 2011 27ª Edição - Fevereiro 2011