sábado, 16 de novembro de 2013

Notebook Fritando Ovos!

O que fazer quando o notebook pode fritar um ovo no teclado ou pior, trava quando chega ao ápice da temperatura?
  1. Colocar bacon também para fritar com os ovos
  2. Comprar um novo e jogar essa tranqueira fora
  3. Criar coragem e limpa-lo corretamente
E muitas vezes o travamento ocorria nos horários mais inapropriados, que vergonha!

Eu já estava fechando a compra de um novo, mas seria algo como trocar um i5 por um novo i5, pois os desempenhos eram semelhantes, tudo bem que esta minha máquina já estava com uma boa idade, mas era 'novinha'. Inclusive já falei dela aqui no blog quando quebrou o HD na praia, ..., tem muitas histórias...

Criei coragem e desmontei o bixo, claro que fotografando cada passo para não esquecer depois de alguma coisa, (mesmo assim não deu certo sobraram dois parafusos, rs...), meu conselho pra você é que além de fotografar o certo é fazer um desenho em uma folha grande de papel, esquematizando onde fica cada peça pois isso facilitaria muito o trabalho.  Foi necessário: Uma chave Phillips boa, um pouco de pasta térmica (para colocar sobre o processador), um pincel para remover a sujeira, e um iPhone para fotografar as coisas.

Em menos de 40 minutos a maquina já havia sido desmontada, limpa e remontada. E olha que tinha bastante poeira e algum material esquisito semelhante ao que vemos no aspirador de pó.

O resultado não poderia ser melhor, o teclado voltou ao frescor dos primeiros dias... Chega de travamentos e agora é só alegria, quem sabe ela dura mais uns 4 anos.


segunda-feira, 21 de outubro de 2013

Recursos de Design

Essa definitivamente não é a minha praia, mas sabe como são as coisas, volta e meia temos que improvisar, e além de analisar, especificar, projetar, programar, também desenhar.

Por falar em especialidade em WebDesign sou especialista em Paint, e essa é a minha ferramenta preferida para desenhar coisas, mas convenhamos, para um graduado na escola do Ilustrator, Photoshop, ..., parece até um pecado falar isso.  E definitivamente não dá pra fazer muita coisa com o Paint neste sentido.

Então, como gosto de compartilhar coisas, estou publicando aqui uma lista dos sites que mais gosto de frequentar quando o assunto é Design Web ou SD, espero que te ajude.

Design Web

http://www.webmonkey.com/
http://www.creativebloq.com/

Paleta de Cores

Adobe Kuler
https://kuler.adobe.com/

Fontes

Pencil Scoop
http://www.pencilscoop.com/tag/typography-tag/

Ícones

Icon Finder
https://www.iconfinder.com/

(*) Windows 8 Set
http://icons8.com/download-huge-windows8-set/

(*) Ios7 Set
http://icons8.com/free-ios-7-icons-in-vector/

(*) Para uso gratuito deve-se incluir o link para o icons8 na pagina.

IOs

Templates
http://www.pencilscoop.com/2013/09/free-ios-7-resources-for-developers-and-designers/

Designing iOS7 style icons
(ensina como criar um icone)
http://www.campaignmonitor.com/blog/post/4080/designing-ios7-style-icons

The iOS Design Cheat Sheet
Dimensoes, resolucao
http://ivomynttinen.com/blog/the-ios-7-design-cheat-sheet/

Bars and Bar Buttons
https://developer.apple.com/library/ios/documentation/userexperience/conceptual/TransitionGuide/Bars.html

Palestras

Temos também algumas palestras bem interessantes nos últimos eventos Genexus, que trataram deste tema.

Resources to be used in UX of Smart Device applications
Sebastian del Rio - Artech
 
Design for developers
Lucía Guedes - Artech

WEB: HTML5 wins. And now what?
Daniel Méndez - Artech

The design is ready! What do I do next?
Fabian Bonilla - Artech


Design and Development: searching for integration 
Lucía Guedes, Alejandro Cimas - Artech

quarta-feira, 16 de outubro de 2013

Pop3

Pop é de fato uma boa abreviação para popular, como diria o bom dicionário Oxford, o difícil é defini-lo como um estilo musical, o mesmo dicionário faz uma confusão danada ao tentar descrevê-lo.  A primeira referencia ao Pop é de 1926!, mas os mais estudiosos o posicionam em 1950 na Inglaterra, quando o termo Pop Music foi criado. Mas o fato é que uma pesquisa no Google revela 1.250 milhões de páginas que tratam deste assunto. Portanto, todos gostam de um bom estilo popular.

Acho que quando foi criado o Pop3 a ideia era popularizá-lo assim como ocorreu com a musica que se tornou mundial e importante.  E por incrível que pareça, creio que o tal Pop3 hoje deve ser mais importante no seu dia-a-dia que a própria musica Pop. Porque? simples, é o protocolo Post Office Protocol, que traduzido para o português simples significa: protocolo utilizado para acesso a uma caixa postal de correio eletrônico (email).

Agora vamos a um cenário interessante, que tal se você construir o próximo sistema de caixa de correio, para substituir os já re-estilizados Google Mail, Outlook e assim por diante, quem sabe se seu projeto incluísse recursos de troca de imagens, grupos, contatos,..., viagem? Acho que sim, creio que ninguém vai gastar muita energia para produzir algo assim, mesmo que em Genexus a coisa seja muito fácil de fazer.  Ou seja, Genexus oferece a você recursos que possibilitam a construção de sistemas do tipo caixa de correio eletrônico. Vamos programar uma, digamos, só por curiosidade?

Tipo Pop3Session

Tudo começa com uma variável &Pop3Session, do mesmo tipo, que tem por incumbência conectar a um certo servidor de e-mails, e obter as mensagens que lá estão.

// conexao no POP3
&pop3session.Host       = '*** servidor POP ***'
&pop3session.Port       = 110
&pop3session.UserName   =
'*** email ***'
&pop3session.Password   = '*** senha ***'     
&pop3session.Login()


Em caso de sucesso na conexão ao servidor, uma mensagem OK poderá ser utilizada para prosseguir com a operação.

if &pop3session.ErrDescription = 'OK'

   ... continuar ...
endif

Esse comando If nos permite saber se a conexão ocorreu com sucesso, mas caso contrário, talvez seja interessante você conhecer as possíveis mensagens de erro retornadas na operação.

Lendo mensagens

A segunda parte do processo consiste em ler as mensagens que estão no servidor, sendo que para isso podemos realizar dois algoritmos simples:

1) Total de mensagens a ler

&total = &pop3session.Count
for &i=1 to &total
  &pop3session.Receive(&mailmessage)

  
   ... tratar a mensagem
 
endfor

2) Ler enquanto não ocorrer erro

do while &erro=0
   &erro = &pop3session.Receive(&mailmessage)
   if &Erro = 0
      ... tratar a mensagem
   endif
enddo

Em ambas as situações o que Receive nos devolve é a mensagem no formato MailMessage, ou seja, com todas as informações, To, Subject, ..., bem simples de ler e entender o conteúdo recebido.

Uma vez lida a mensagem do servidor, algumas ações poderão ser realizadas, como por exemplo:

&pop3session.delete()
Para apagar a mensagem previamente lida, removendo-a da caixa de entrada remota.

Tem uma outra propriedade MarkAsRead que insiste em apresentar um erro quando utilizo, mas creio que possa ser útil, não tenho certeza.

Fechando a conta

Antes de fechar não se esqueça de realizar um.

&pop3session.logout()

Assim como ocorreu com o Pop Music, em 1950, esse tipo existe desde a versão 7.5 do Genexus, não que o nosso Gx existia nesta época, é que o recurso que temos em mãos na verdade já é bem antigo, mas continua a provocar suspiros nas meninas.

Eu particularmente, gosto bastante.




segunda-feira, 7 de outubro de 2013

Vários destinatários!

Mais uma para envio de emails, desculpa se o tema está meio recorrente, mas vamos aos poucos encerrando este assunto.

Outra necessidade que temos para o envio de emails é a opção de enviar para mais de um destinatário, na opção TO, BC, ou BCC, o que é plenamente possível, visto que temos nestas operações uma função Add(), que possibilita criar uma coleção de itens.

Recebi recentemente no Genexando um trecho de código que achei bem interessante e simples para implementar esse mecanismo, espero que o Antonio não fique bravo por explorarmos um pouco essa ideia, mudei um poucoe implementei uma collection ao invés de vetor.

Na estrutura do envio de emails, incluímos apenas uma sub rotina auxiliar que inclui os emails destinatários, que chamamos de 'incluidestinatarios'

Event Start 
    &smtpsession.Host            = 'smtp.gmail.com'
    &smtpsession.Port            = 465
    &smtpsession.Secure          = 1
    &smtpsession.Authentication  = 1
    &smtpsession.UserName        = '* usuario (email) *'
    &smtpsession.Password        = '* senha *'     
    &smtpsession.Sender.Address  = '* email de envio *'
    &smtpsession.Sender.Name     = '* nome  *'
       
    &smtpsession.Login()
    if &smtpsession.ErrCode <> 0
        msg(&smtpsession.ErrDescription)
    else
        &mailmessage.Text     = 'texto da mensagem'
        &mailmessage.Subject   ='titulo'
        
        do 'incluidestinatarios'
                  &smtpsession.Send(&mailmessage)
        msg(&smtpsession.ErrDescription)
    endif
   
EndEvent

Nessa rotina o que temos é o acesso a uma certa tabela de Clientes, que filtramos em um determinado Pais, e a construção de uma coleção de emails. Esse modelo é bem interessante pois não precisamos dimensionar a coleção antes de começar a carregá-la.  É um bom substituto para um vetor.


Sub 'incluidestinatarios'
    // carga dos emails, segundo uma condição
    for each
    where PaisNome='Brasil'
        &emails.Add(
ClienteEmail)
    endfor
 
    &mailmessage.To.Clear()
    for &email in &emails
       &mailrecipient.Address      = &email
       &mailrecipient.Name         = &email
       &mailmessage.To.Add(&mailrecipient)
    enddo 

EndSub 


São dois os detalhes para manipulação desta coleção, a variável &email e a &emails que são declaradas com Char(200), e a última marcada como Collection. Em seguida um for...in para recuperar os dados desta coleção.

Utilize com cautela isso hein! não vá me mandar um monte de spams.


Tilo: O que chama mais atenção!

Próximo da liberação da versão Beta2 o novo Genexus chamado de Tilo já começa a mostrar robustez e recursos muito interessantes e impactantes no modelo Genexus. Confesso que certos recursos de fato me surpreenderam.

Neste artigo apresento minhas impressões iniciais:

1) O GAM pode se tornar um provedor de identificação assim como ocorre com Facebook, Twitter, Google, Hotmail,  permitindo que as aplicações GX sejam Single Sign On, uma vez autenticado todos os demais sistemas Genexus acessados na mesma sessão não precisam de login.

2) Objeto modulo não apenas permite organizar uma kb que contem diversos subsistemas, mas também aproxima a linguagem de programação Genexus da já clássica Orientação a Objetos, com direito a Interface, Dados públicos e privados, Métodos, Objetos privados e públicos, e por ai vai. Porem, de uma forma mais visual, simples de ser compreendida no melhor padrão Genexus.

3) Gerador web com um novo modelo de chamada eventos de sistema, com o objetivo de minimizar os impactos de recarga da interface.  Eventos de usuário não executam Start, Refresh e Load, mas somente os que participam da ação provocada pelo user.  Isso faz com que o tamanho da mensagem trocada entre o Cliente e Servidor seja drasticamente reduzida, e como consequência um aumento significativo de desempenho.

4) Filtros e recarga de dados em webcomponentes a partir de ações em outro webcomponentes, por meio de notificações. Isso atualmente pode ser realizado por meio de TrackContext, mas o novo modelo é ativo, com envio de mensagens de um programa a outro, muito mais interessante.

5) Full Html5 com muitos novos recursos como web sockets, broadcast, notifications e event onmessage, podendo fazer modelos de interface tipo chat (facebook).

6) for each line in grid, modifica o grid sem recarregar tudo, recorrendo os registros alterados

7) Nova linguagem de programação como novos elementos como as transações dinâmicas que se conectam a um Data Provider para realizar a carga da informação, com isso a transação não precisa estar associada a uma tabela mas pode ser  alimentada por outras tabelas, dados obtidos de outras fontes, enfim, uma flexibilização total.  Esse recurso ainda encontra-se em definição se será liberado na nova versão Tilo ou em outra.

8) Gerador para Windows 8.
9) Aplicações full offline e com direito a um SQLLite no dispositivo para armazenar informações que serão posteriormente sincronizadas com o servidor. Deixei essa por último porque já vem sendo amplamente divulgada por ai.

Tudo isso pode ser conferido através dos vídeos das palestras do XXIII Encontro Genexus que finalizou quarta passada.








domingo, 6 de outubro de 2013

Integração Continua

Enfim, depois de um longo período de expectativas e frustrações, consegui finalmente integrar o CruiseControl.Net ao GxServer, claro que não fiz isso sozinho, tive a ajuda de nada mais nada menos do que o mestre José Lamas da Artech.  Qual foi o resultado final disso? espetacular! Parece até um sonho, ver o CCNet ler o GxServer e em caso de alterações na Kb iniciar um processo MSBuild para criar uma aplicação de forma automatizada, ou seja, sem a necessidade de nenhuma pessoa.
No desenvolvimento de software de forma compartilhada, ou seja, com muitos desenvolvedores, o que temos  é um processo constante de entrega de objetos e a necessidade de uma validação imediata se o mesmo pode ou não ser integrado ao que chamamos repositório central.  Isso ocorre porque todos os desenvolvedores possuem projetos locais que podem sofrer pequenas variações em termos de configurações, versões de objetos, banco de dados diferentes em relação à produção, enfim muitos fatores que podem levar a um problema. Isso ocorre porque nem todos os desenvolvedores baixam as atualizações em seu projeto com o repositório central de forma constante, por razões que vão desde preguiça, falta de interesse, tempo, ou mesmo coisas mais complexas como erros de objetos publicados por outros, que produzem atrasos, enfim é um processo meio caótico.

Integrar continuamente significa que ao ser publicado alguma coisa no repositório central, algum mecanismo deve validar se essa operação não afetou a construção do sistema como um todo, e qual a melhor forma de fazer isso? Recriando o sistema novamente, gerando não apenas o objeto que subiu, mas suas referências, e é exatamente isso que o servidor de integração faz.

O cenário que conseguimos resolver em nosso modelo envolve o GeneXus + GxServer + CruiseControl (CCNet) + .NetFramework, 

De forma que ao entregar algum objeto ao GxServer, faz com que o CCNet entre em ação fazendo com que uma aplicação seja construída.

Ao desenvolvedor cabem duas ações posteriores à entrega:
  1. Ingressar no painel do CCNet para verificar se houve sucesso em sua ação
  2. Testar o sistema gerado para ver se a operação

Não dá pra encerrar sem citar o post do José Lamas a respeito do CruiseControl.Net, sobre o tema Integração Continua. Se você se interessa por esse assunto, vale a pena ver.

Gracias José!

Anexando...

Este tema também já é antigo, mas sempre causa duvidas nas pessoas, já tínhamos postado sobre o Genexus Mail! versão em código nativo, mas não explorado muito sobre arquivos anexados que é muito simples também.

Neste caso, caso necessite incluir algum arquivo ao email, existe uma opção no tipo MailMessage, &mailmessage. Attachments, que é uma coleção de links de arquivos que podem ser incluídos por meio de uma operação Add()

 Event Enter

 // Conexao no provedor de email
 &smtpsession.Host     = 'smtp.gmail.com'
 &smtpsession.Port     = 465
 &smtpsession.Secure    = 1
 &smtpsession.Authentication  = 1
 &smtpsession.UserName    =
'***email sender***'
 &smtpsession.Password    = '*****'

  // remetente
  &smtpsession.Sender.Address  =
'***email sender***'
  &smtpsession.Sender.Name   = '*** Seu nome ***'

 &smtpsession.Login()
 if &smtpsession.ErrCode <> 0
  // composicao da mensagem
 &mailmessage.Text     = 'texto da mensagem'
 &mailmessage.Subject   ='titulo'

 // enviar para
 &mailrecipient.Address    =
'***email a enviar***'
 &mailrecipient.Name    = '*** nome da pessoa a receber ***'
 &mailmessage.To.Add(&mailrecipient)

 // anexos
 &arquivo      = 'C:\imagem.png'
 &mailmessage.Attachments.Add(&arquivo)


  msg(&smtpsession.ErrDescription)
 else
  &smtpsession.Send(&mailmessage)
   msg(&smtpsession.ErrDescription)
 endif

Endevent


Observe que a referencia ao arquivo a ser anexado é por meio do endereço físico do mesmo no diretório, não importando  a raiz da Web. Uma observação apenas, lembre-se que é possível utilizar uma procedure para gerar um relatório PDF que pode ser anexado, ou mesmo um arquivo XLS.

Neste ultimo caso, caso o arquivo seja grande, você deverá esperar até que o mesmo seja gerado fisicamente antes de anexar e enviar a mensagem, em certos casos é necessário programar um Delay devido ao processamento do arquivo.

quinta-feira, 3 de outubro de 2013

Como comparar JSON ou XML?

Quando se trata de comparações somos especialistas, sabemos distinguir facilmente um Fusca de uma Ferrari, mesmo se ambos forem da mesma cor, chega a ser impressionante nosso senso de observação, rs.

Comparar expressões numéricas ou texto também é simples, mas como comparar coisas mais complexas, como por exemplo dois xml´s, ou json, se estão exatamente iguais? Por incrível que pareça também é simples bastando um Hash, mas com um pequeno trabalho adicional.

Temos aqui um uso de encriptação em uma situação pouco comum e que traz resultados interessantes. Vamos a um exemplo.

Comparando Dois Textos


Em um Webpanel programamos um conteúdo tipo Json gerado no formato do tipo Messages, um SDT incluído automaticamente na Kb do Genexus.  Em seguida geramos um Hash que será utilizado para se comparar com um segundo texto que informamos livremente, e que utiliza a mesma chave e mecanismo de encriptação utilizado no primeiro texto, gerando um segundo hash.  Se forem diferentes ou iguais a respectiva mensagem será apresentada.

No primeiro teste utilizamos dois textos distintos e os valores calculados produzem resultados diferentes, (Hash e Hash2), devido aos valores em Original e Comparar Com.


Ao se copiar o conteúdo de Original , colando-o em Comparar Com, produzir-se-há hashs iguais, e o resultado será uma comparação positiva.


A programação é bem simples.

Event Start
 &message.Id    = "1"
 &message.Description  = 'Mensagem1'
 &messages.Add(&message)

 &message = new()
 &message.Id    = "2"
 &message.Description  = 'Mensagem1'
 &messages.Add(&message)

 &key=getsitekey()
 &original = &messages.ToJson()
 &hash = encrypt64(&original, &key)
Endevent


Event 'Comparar'
 &hash2 = encrypt64(&compararcom, &key)
 if &hash=&hash2
  msg('são iguais')
 else
  msg('são diferentes')
 endif
Endevent


Mais informações:


Sobre hashs tem um site bem interessante que gera encriptações com diferentes algoritmos que pode ser visto aqui.

O Xpz com o exemplo, para que você possa testar está aqui.

Duas conclusões:

  • Esse mesmo mecanismo poderia ser utilizado para comparar o conteúdo de um arquivo completo, aliás é isso que normalmente os sites sérios de download nos oferecem.
  • Qualquer pequena diferença (um espaço em branco, por exemplo) seria suficiente para tornar as duas strings diferentes.
Outra coisa que sabemos comparar com grande facilidade é a diferença de preço entre o tal Fusca e a tal Ferrari, veja como nosso senso de observação é apurado para coisas tão semelhantes...

Ainda não estamos seguros

Continuando a discussão sobre o tema de segurança nas aplicações Genexus, recebi recentemente um post do blog do Marcos Crispino (Seguridad en Aplicaciones Genexus), que joga um pouco mais de pimenta sobre este tema já ardido que é a insegurança de nossas aplicações, e claro, uma visão consciente de que o tema está longe de chegar ao final.

O que gosto no artigo é que inclui além das vulnerabilidades, também algumas estratégias, para buscarmos programar Gx de forma segura.



sábado, 28 de setembro de 2013

Make a difference



Próxima segunda-feira teremos inicio do 23o Encontro Genexus em Montevidéo, que tal acompanhar as palestras pela internet? pois é para os não afortunados que irão teremos a opção de acompanhar as palestras pela própria Web em transmissões simultâneas. Vale a pena, pois teremos muitas novidades da versão Tilo sendo apresentadas.

Confira tudo em: http://www.genexus.com/encontro2013/23-encontro-genexus?pt

sexta-feira, 20 de setembro de 2013

Query

Genexus possui recursos surpreendentes que de fato facilitam muito a vida dos desenvolvedores. Talvez você já conheça, mas para aqueles que ainda não tiveram o prazer, vamos falar um pouquinho do objeto Query.  Se você está vivendo o dilema de ter que programar inúmeros relatórios para seus clientes, talvez esse objeto te ofereça uma ajuda.

Primeiro Um Pouquinho de Conceito

Este objeto permite que você construa pesquisas sobre as tabelas do banco de dados e a publicação dos resultados na forma de tabelas (simples ou Pivot) ou gráficos, sendo esta uma operação que consiste em definir os atributos a serem recuperados, que na definição formal Artech, são chamados de eixos.

Neste ponto é necessária certa precaução para a montagem desses eixos, pois há a necessidade de que o modelo proposto tenha solução, significando que os atributos devem estar em uma relação de extensão.  No exemplo a seguir temos uma definição incorreta desses eixos, pois a relação entre a tabela Cidade e Bairro não possibilita resultados satisfatórios quando envolvem Cliente.

 

O resultado desta operação é inclusive um erro de falta de relacionamento, devido a relação entre a tabela Cidade e Bairro (não ser de extensão)

SQL statement generation Failed
error: No relationship found among attributes.

O correto seria envolver o relacionamento direto entre Cliente e Bairro, porém isso levaria a necessidade de rever a tabela Cliente para a inclusão do BairroId.

 
 
Portanto, para utilizar o objeto Query é importante conhecer não apenas as tabelas no Banco de Dados, mas também o conceito de tabelas estendidas. Se a estrutura do banco permitir gerar relacionamentos estendidos, então Query é possivelmente um bom substituto dos tradicionais relatórios.
 

Finalmente o Objeto

Fica a pergunta então: Como construir e utilizar o objeto Query? a resposta agora ficou facil, bastando incluir os atributos em Attributes.  Cada atributo possui propriedades que podem ser ajustadas pressionando-se a tecla F4.
 
 
Nestas propriedades podemos definir se estaremos aplicando ao eixo uma função de agregação Count ou Sum, ou ainda títulos, e totalizações nas tabelas Pivot.
 

Mostrando em um WebPanel

Uma vez construído o objeto Query podemos incluí-lo em nosso projeto através de um WebPanel e o usercontrol QueryViewer, que deve ser adicionado na interface, e em seguida apontando a propriedade Object deste controle para nosso objeto Query recém criado.
 
Existem certas propriedades que provavelmente você estará ajustando, como Autoresize=true, Paging,  e principalmente os tipos de saída, entre outros.
 
(formato Table)
 
(formato Pivot Table)
 
Com isso nossos usuários poderão não apenas visualizar os dados armazenados mas também exportá-los no formato PDF, XML, entre outros.
 

Conjunto de QuerieViewers

A novidade da versão Evolution 2 foi a possibilidade de eventos de filtragem em um QueryViewer influenciar os dados apresentados em outro QueryViewer que se encontra no mesmo WebPanel, possibilitando a construção de Dashboards (BI).
 
Para isso definimos a propriedade Auto Refresh Group com um nome comum entre todos os QuerieViewers da interface, como por exemplo GRUPO.
 
 
É possível que ambos os QuerieViewers apontem para o mesmo objeto Query, neste caso não é necessário fazer mais nada para conectá-los. Ou ainda conectar objetos Query distintos, nesse caso precisamos utilizar uma variável que seja comum entre os dois grupos.
 
 
Caso da Mesma Querie
 
No primeiro caso, poderíamos definer dois QuerieViewers no mesmo Grupo, sendo que um poderia ser apresentado no formato PivotTable e o segundo como Chart
 
 
 
Ao se aplicar um filtro no primeiro QueryViewer, como por exemplo selecionar uma cidade, ambos os QuerieViewers serão filtrados, como apresentado na figura a seguir.
 
 
Caso das Queries Distintas
Para o segundo caso, com Queries distintas, teríamos que passar parâmetros para a segunda Query, e claro, ambas devem ter algo em comum. Na imagem a seguir temos a Query2 que alimenta o primeiro QueryViewer e a Query1 que alimenta o segundo e que apresenta um gráfico de barras.
 
 
O parâmetro passado para Query1 (CidadeNome), é recebido em uma variável utilizada na expressão de filtro: CidadeNome in [&CidadeNome], ou seja, a variável &CidadeNome deve ser definida como uma coleção.
 
Ao realizer um filtro sobre a tabela a esquerda, o gráfico sera também filtrado .
 
 

Conclusão

Acredito que esse objeto representa um dos bons recursos implementados no EV1 e EV2, pois com mínimo esforço se atinge excelentes resultados.
 
Sempre tive dificuldades para conectar mais de um QuerieViewer, mas acredito que esse esquema, passado para vocês, é simples o bastante para desmistificar esse mistério.
 
Resta-nos aguardar o próximo evento Genexus em Motevideo para conferirmos se teremos melhores surpresas relacionadas com esse tema. Você vai?
 
 
 
 



quarta-feira, 14 de agosto de 2013

Depurando melhor

Tem certas mensagens que somente por intervenção divina! como a que apareceu (abaixo), que apresentava apenas uma única pista: tinha a ver com Business Component.

Não é possível converter um objeto do tipo 'GeneXus.Programs.plano_bc' no tipo 'GeneXus.Utils.IGxSilentTrn'.

Pois a transação Plano havia sido marcada como BC. Mas acontece que a interface parou de repente de funcionar e começou a apresentar esse erro estranho, claro que estava mexendo no programa, para ser mais preciso estava depurando erros, mas não ficou nenhuma dica do que estava acontecendo.

Depurador de Erros

Fazia tempo que algo tão inusitado não acontecia. E quando isso ocorre, o que fazer a não ser perder um pouco de tempo com tentativas para solucionar a coisa:
  1. Comentei todo código (não adiantou nada)
  2. Apaguei a tela (não adiantou nada)
  3. Apaguei a variável que referenciava o BC (adiantou!)
Ou seja, o depurador tem suas manhas e melindres, isso já sabemos, mas esse erro ai, nunca tinha visto.   Então, o que ocorreu, por alguma razão a transação causava problema ao ser depurada.

Quando se abre o modo DEBUG no Genexus, o interessante é dar um BUILD (Não precisa de REBUILD), para construir o objeto que se deseja depurar neste modo. Tem até uma janela que mostra os objetos que estão sendo construídos neste modo, fica ao lado direito e se chama DebugGx. É possível inclusive incluir e remover objetos através desta janela.


O que ocorria com o tal Plano_BC que causava o erro era um pequeno detalhe que sempre passava despercebido, o navegador estava aberto com este objeto, então via de regra, ao iniciar o depurador a primeira coisa que se deve fazer, antes mesmo do BUILD é fechar o navegador, e tudo mais que pode estar bloqueando ou mesmo referenciando algum objeto.

Outro detalhe importante é ao término da depuração retornar o Genexus ao modo normal (RELEASE), caso contrário você incorre na possibilidade de enviar para o servidor de produção objetos com debug ligado e nesse caso o mesmo apresentará uma série de mensagens estranhas para os seus usuários.

quarta-feira, 24 de julho de 2013

Justin Bieber Programa Genexus!

Mais essa, Justin Bieber está presente na comunidade do Genexando, rs... vai entender essas maluquices dos blogs. Acho que alguém está querendo ligar o blog do cantor nos blogs por ai, quem sabe para atingir os membros da comunidade. Ou ainda, vai que o Justin Bieber tem uma identidade secreta e é um desenvolvedor Genexus, será que ele tem certificação?

Então para os que gostam da criança tai a surpresa.

quarta-feira, 3 de julho de 2013

Desempenho

Programar é fazer escolhas e fazer escolhas boas é acreditar que temos elementos suficientes para tomarmos uma decisão certeira, não é assim que funciona? nem sempre, e muitas vezes nossas escolhas são mais baseadas em experiências bem sucedidas do que efetivamente em análises precisas da situação. Não se culpe, somos todos assim mesmo.

Muitas vezes, talvez a maioria das vezes, as escolhas são realizadas às cegas, não porque queremos, mas porque não temos informações suficientes.  Quanto mais informações tivermos, melhor seria nossa escolha? também é relativo, veja sua esposa, por exemplo, você sabia que ela roncava antes de se casar com ela? se soubesse desse pequeno detalhe, isso influenciaria sua decisão? mas o fato de aprender 'depois' que ela roncava, e pelo fato de ainda estar casado com ela, não significa que você se tornou uma pessoa melhor? mais compreensiva? ou na melhor das hipóteses, que usa aqueles eficientes tampões de ouvido para dormir, rs...

Enfim, divagações a parte, quando falamos em desempenho da aplicação o que temos que fazer é o seguinte, conhecer muito bem o custo x benefício de cada estratégia, e claro, os recursos que temos à nossa disposição. Motivado por perguntas do tipo o que era melhor programar for each de forma tradicional ou com data selector, acabei fazendo um teste que me surpreendeu.

Peguei uma tabela com 1,5 milhão de registros e fiz uma simples operação de contagem, medindo o consumo em milissegundos no tempo da solicitação (refresh no navegador) e a resposta devolvida pelo servidor.  Claro que não utilizei nenhum cronômetro para fazer isso, mas sim o Fiddler, que tem um timeline muito interessante.

Foram três webpanel bastante simples, o primeiro executava a operação de varrer a tabela utilizando um for each tradicional.

(1)
for each
defined by HistoricoData
    &total +=1
endfor

No segundo exemplo substituímos apenas o defined by no for each por um objeto data selector.

(2)

for each
using DataSelector1()
     &total +=1
endfor

Sendo que no DataSelector1 o que 'programamos' foi apenas o defined by, rs..

E o terceiro exemplo, partimos para a ignorância e programamos uma stored procedure direto na base de dados.

(3)
create proc usp_contaregistros @total bigint output
as
select @total=COUNT(HistoricoData) from Historico
return


A intenção? medir a velocidade dos três modelos, e os resultados que obtivemos foi surpreendente, porque o Data Selector teve um desempenho 11% superior ao for each tradicional. Claro que a Stored Procedure teve um desempenho surpreendente sobre o Data Selector 31%, já esperava isso, mas nunca imaginei que o Data Selector tinha um desempenho melhor na programação tradicional Gx.

(1)
for
each
(2)
data
selector
(3)
stored
procedure
1)
265 214 162
2)
277 231 151
3)
226 220 149
4)
238 231 153
media
251,5 224 153,7
11% 31%

Isso nos leva a algumas conclusões:
  1. Se possível atualize seus programas utilizando esse recurso, ou pelo menos faça um teste na sua realidade para comprovar esses dados. Não sei se uma querie mais complexa influenciaria nos resultados
  2. Stored procedure sempre terá um desempenho melhor, e sob este único ponto de vista, claro que sempre ganhará dos demais modelos, mas não se esqueça do problema de manutenção do sistema, que sempre será mais complicado que a programação Genexus tradicional
  3. Existem outros elementos na interface que afetam o desempenho da aplicação, não incorra no erro de pensar que a culpa de tudo é do acesso ao banco de dados
  4. Se desempenho for de fato um problema relevante, pois veja, que a influencia de uma navegação em uma tabela tão gigante foi mínima, o uso desse recurso 'especial' poderia ser justificada, mas sinceramente acho que deve haver alguma solução diferente para o caso.
Enfim, mesmo com esses resultados fico com a programação for each + Data Selector, que tenho buscado incluir em todos os programas, agora com essa medição de desempenho fico ainda mais seguro pra dizer isso, pois a manutenção do sistema fica absurdamente mais rápido com esses recursos.

Agora como nem todos os casos podem ser solucionados desta forma, se tiver que recorrer a recursos mais 'manuais' para ter um Usain Bolt em seu programa, você pode utilizar os External Objects que são ótimos para realizar a conexão.




Se quiser conferir, os valores auferidos são apresentados a seguir.

(1.1)
Request Count: 10
Bytes Sent: 5.913 (headers:5.913; body:0)
Bytes Received: 82.505 (headers:2.321; body:80.184)
ACTUAL PERFORMANCE
------------
Requests started at: 13:28:22.067
Responses completed at: 13:28:23.954
Sequence (clock) duration: 00:00:01.8871080
Aggregate Session duration: 00:00:00.265


(1.2)
Request Count: 10
Bytes Sent: 5.913 (headers:5.913; body:0)
Bytes Received: 8.888 (headers:2.284; body:6.604)
ACTUAL PERFORMANCE
--------------
Requests started at: 13:31:02.161
Responses completed at: 13:31:02.456
Sequence (clock) duration: 00:00:00.2950169
Aggregate Session duration: 00:00:00.277
(1.3)

Request Count: 10
Bytes Sent: 5.913 (headers:5.913; body:0)
Bytes Received: 8.888 (headers:2.284; body:6.604)
ACTUAL PERFORMANCE
--------------
Requests started at: 13:33:04.380
Responses completed at: 13:33:04.651
Sequence (clock) duration: 00:00:00.2710155
Aggregate Session duration: 00:00:00.226
TCP/IP Connect duration: 1ms


(1.4)
Request Count: 10
Bytes Sent: 5.913 (headers:5.913; body:0)
Bytes Received: 8.888 (headers:2.284; body:6.604)
ACTUAL PERFORMANCE
--------------
Requests started at: 13:33:39.050
Responses completed at: 13:33:39.343
Sequence (clock) duration: 00:00:00.2930168
Aggregate Session duration: 00:00:00.238
DNS Lookup time: 1ms


(2.1)
Request Count: 10
Bytes Sent: 5.915 (headers:5.915; body:0)
Bytes Received: 8.893 (headers:2.286; body:6.607)
ACTUAL PERFORMANCE
--------------
Requests started at: 21:25:02.735
Responses completed at: 21:25:02.970
Sequence (clock) duration: 00:00:00.2350134
Aggregate Session duration: 00:00:00.214
 

(2.2)
Request Count: 10
Bytes Sent: 5.915 (headers:5.915; body:0)
Bytes Received: 8.893 (headers:2.286; body:6.607)
ACTUAL PERFORMANCE
--------------
Requests started at: 21:26:16.958
Responses completed at: 21:26:17.235
Sequence (clock) duration: 00:00:00.2770159
Aggregate Session duration: 00:00:00.231
 
(2.3)
Request Count: 10
Bytes Sent: 5.915 (headers:5.915; body:0)
Bytes Received: 8.893 (headers:2.286; body:6.607)
ACTUAL PERFORMANCE
--------------
Requests started at: 21:27:16.887
Responses completed at: 21:27:17.130
Sequence (clock) duration: 00:00:00.2430139
Aggregate Session duration: 00:00:00.220

(2.4)
Request Count: 10
Bytes Sent: 5.915 (headers:5.915; body:0)
Bytes Received: 8.893 (headers:2.286; body:6.607)
ACTUAL PERFORMANCE
--------------
Requests started at: 21:27:47.828
Responses completed at: 21:27:48.129
Sequence (clock) duration: 00:00:00.3010172
Aggregate Session duration: 00:00:00.231
DNS Lookup time: 1ms
 
(3.1) 
Request Count: 10
Bytes Sent: 5.912 (headers:5.912; body:0)
Bytes Received: 8.887 (headers:2.285; body:6.602)
ACTUAL PERFORMANCE
--------------
Requests started at: 22:01:56.474
Responses completed at: 22:01:56.700
Sequence (clock) duration: 00:00:00.2260129
Aggregate Session duration: 00:00:00.162
 
(3.2) 
Request Count: 10
Bytes Sent: 5.912 (headers:5.912; body:0)
Bytes Received: 8.887 (headers:2.285; body:6.602)
ACTUAL PERFORMANCE
--------------
Requests started at: 22:02:27.434
Responses completed at: 22:02:27.643
Sequence (clock) duration: 00:00:00.2090119
Aggregate Session duration: 00:00:00.151
 
(3.3)
Request Count: 10
Bytes Sent: 5.912 (headers:5.912; body:0)
Bytes Received: 8.887 (headers:2.285; body:6.602)
ACTUAL PERFORMANCE
--------------
Requests started at: 22:02:53.429
Responses completed at: 22:02:53.635
Sequence (clock) duration: 00:00:00.2060118
Aggregate Session duration: 00:00:00.149
 
(3.4)
Request Count: 10
Bytes Sent: 5.912 (headers:5.912; body:0)
Bytes Received: 8.887 (headers:2.285; body:6.602)
ACTUAL PERFORMANCE
--------------
Requests started at: 22:03:15.874
Responses completed at: 22:03:16.079
Sequence (clock) duration: 00:00:00.2050117
Aggregate Session duration: 00:00:00.153


quarta-feira, 19 de junho de 2013

Backup da Kb II

Bom, felizmente esse tema ainda não acabou, e quem me trouxe uma nova luz foi o Alex Melo, e olha que não foi uma luzinha qualquer, o que ele disse foi o seguinte, após certo upgrade da versão X EV1, não precisamos mais do arquivo gxw e do knowledgebase.connection, basta apenas o mdf.

Então tá mais simples do que imaginava, o banco de dados é suficiente, e como devemos fazer?

  1. Copiar o mdf que se deseja restaurar na pasta onde se deseja criar a nova kb
  2. Diferentemente do artigo anterior, não é necessário conectar o banco ao SQL Server (atachar), e se estiver conectado deve-se desconectar
  3. Abrir o Genexus e em seguida execute a opção File - Open Knowledge Base, mude o filtro de tipos de arquivo para mdf, e aponte para o banco de dados previamente copiado.
O Genexus abrirá uma janela dizendo Knowledge Base Directory change detected, mas não ligue muito para isso, basta pressionar confirmar e a kb será recriada.

O Alex ainda alertou dos problemas relacionados com bases do SQL2008R2 que não abrem no SQL2008, então, será necessário um pouco de atenção com a versão correta do Banco de Dados instalada no equipamento.

Dica igual a essa não temos todos os dias, portanto, resta-nos um forte agradecimento ao nosso amigo.
 


segunda-feira, 17 de junho de 2013

Backup da Kb

Todos conhecemos muito bem o significado de Genexus Knowledge Base, visto que todo projeto Genexus é uma, mas poucos a respeito dos elementos que temos a nossa disposição em uma Kb.  E uma informação significativa, que fica meio obscura diante da estrutura da ferramenta é a simplicidade com que podemos restaurar um certo projeto por meio do próprio Banco de Dados da Kb.

Banco de Dados

A partir da versão Genexus X os projetos passaram a ser criados obrigatoriamente num banco de dados, mais especificamente no SQL Server, sendo que o próprio instalador do Genexus já adicionava uma versão 'Express' para que a ferramenta trabalhasse, isso caso não houvesse um banco desses instalados no equipamento. 

O fato é que a partir dessa versão a Kb passou a ser armazenada em um banco, não mais em arquivos no diretório do projeto, situação que inicialmente desagradou muita gente que, por falta de costume, diga-se de passagem, não gostou muito dessa ideia de ter que instalar um SQL Server, mas convenhamos esse mecanismo trouxe uma nova visão e recursos sobre o projeto.

Recriando a Kb através do BD

Um dos pontos positivos que o Banco de Dados trouxe para o projeto foi a possibilidade de se recriar totalmente certo projeto a partir do arquivo MDF/LDF.  Situação importante, principalmente em casos da quebra do computador, e claro, a falta de um backup do projeto.

Uma vez que o projeto encontra-se armazenado no banco de dados, podemos recriá-lo mediante uma pequena lista de ingredientes:
  1. O arquivo MDF e LDF do banco
  2. Um arquivo nome_do_projeto.gxw, cujo conteúdo é nenhum (vazio)
  3. Um arquivo knowledgebase.connection, contendo algo como:
<ConnectionInformation>
 <DBName>GX_KB_Curso</DBName>
 <IntegratedSecurity>True</IntegratedSecurity>
 <ServerInstance>SERVIDOR_BD</ServerInstance>
 <CreateDbInKbFolder>True</CreateDbInKbFolder>
 <Directory>Z:\NovaPasta\</Directory>
 <DataFile>GX_KB_Curso.mdf</DataFile>
 <LogFile>GX_KB_Curso_log.LDF</LogFile>
 <HostName>SERVIDOR_BD</HostName>
<ConnectionInformation>



Em negrito o caminho para a pasta onde o projeto será recriado.

Em seguida executar as seguintes operações:
  1. Anexar o BD ao SQL Server (Database - Attach), numa operação chamada de Attach.
  2. Abrir o arquivo gxw através do Genexus na operação File - Open Knowledge Base
O resultado é a reconstrução do projeto, claro que você deverá recriar o environment por meio da execução do Gx.


Esse recurso permite a realização do backup dos projetos Genexus simplesmente pelo Banco de Dados. Em caso de utilização do GxServer, o mesmo recurso pode ser utilizado, trazendo segurança aos projetos administrados pelo servidor.

Cuidado porém com o detalhe da informação Directory que se encontra no arquivo knowledgebase.connection, pois se não apontar para o novo local de criação do projeto, causará um erro Knowledge Base Directory change detected.



Cujo efeito será a tentativa de se recriar a base de dados, portanto, se aparecer uma mensagem assim você estará percorrendo um caminho incorreto para realizar a restauração e provavelmente tem a ver com essa propriedade directory.


PS: ver http://www.genexando.com/2013/06/backup-da-kb-ii_19.html

quinta-feira, 13 de junho de 2013

Quer aprender Genexus? (revisado)

Pessoal antes de iniciar um pequeno aviso, os links deste artigo são em sua maioria externos, me desculpe antecipadamente caso algum deles não responder adequadamente, pode ser que a fonte mudou de lugar.

O artigo foi revisado, e buscamos incluir novas conclusoes principalmente devido a abordagens que recebemos das pessoas que ingressam no desenvolvimento e de alguma forma esbarram em uma parede, que pode ser a própria dificuldade em aprender ou mesmo resistência, tentei deixar a coisa um pouco mais 'clara'.


Atualmente existe muito material disponibilizado para se aprender Genexus, a Artech oferece o site http://training.genexus.com com muitos vídeos em português, espanhol e inglês, abordando praticamente tudo que é necessário para se produzir excelentes programas com a ferramenta.

Por outro lado, aprender Genexus requer não apenas compreender uma nova linguagem de progranação, mas um conjunto de objetos com diversas finalidades, funcionalidades e características, que para um iniciante poderia trazer um pouco de confusão.

Me permitam selecionar certos fundamentos que, sob a minha ótica, são essenciais para compreender a filosofia envolvida no desenvolvimento com Genexus, e em cada um desses eixos fundamentais, um conjunto específico de objetos, que apresentamos na tabela abaixo, de forma resumida.

Modelagem
Tabela Base e Estendida


Diagrama e Navigation Report
Programação
Transformações
Interface Usuário

Na Modelagem o objetivo é representar a realidade através do objeto Transação, sendo necessário compreender um pouquinho de Análise de Sistemas.  Existe um outro video que apresenta alguns exemplos nesse sentido.

Tabela Base e Estendida são conceitos revolucionários na ferramenta e representam um importante nível de abstração para o acesso de dados nas tabelas, uma falha na aprendizagem deste conceito e você estará programando muito e obtendo poucos resultados com a ferramenta, portanto é crucial que compreenda isso.
Voce não precisa muita coisa para aprender tabela base e estendida, um objeto Diagram, uma Procedure para escrever seus for...eachs, e o objeto Navigation Report.

O objetivo da Programação é otimizar a aplicação por meio de operações não interativas, e aqui temos um reflexo do mundo real, pois Genexus oferece uma interessante linguagem de programação com muitos recursos automatizados.  O que você deve sempre pensar quando programa é fazer com que o resultado seja sempre eficaz, pois muitas vezes erramos produzindo programas lentos e ineficientes.
Outro conceito envolvido na programação é a busca por criar código reutilizável e de fácil manutenção, dai entramos no nivel dos Data Selectors e Business Components.
O conceito de Transformações representa o modelo no qual buscamos transferir informações de certo sistema para outro, muitas vezes recuperando informações de tabelas e transformando-as em outro formato como o XML ou JSON, por exemplo.  Trata-se de um conceito mais complexo, diria mais avançado, mas não deixa de ser importante destacá-lo.
Finalmente a questão relacionada com a construção de Interfaces Gráficas, aqui abordo somente Web, com dois objetos WebPanel e Patterns, não precisa muito mais que isso (talvez também o Theme, Images)

Conclusão e Dicas
Com um pouco de paciência nesse momento, porque entendo que aprender (ou reaprender) uma nova ferramenta sempre é um desafio bastante grande, procure conquistar os conceitos aos poucos. A sequencia que indicamos acima é interessante.

A dica principal que lhe passo é não buscar reproduzir a programação que está acostumado a desenvolver, no Genexus lembre-se que sempre é  ferramenta que programa para você, portanto se estiver escrevendo muito código numa procedure por exemplo, pode ser sinal que você pode não estar utilizando toda a capacidade de automação que tem a sua disposição.  Desligue um pouco seu modelo de pensar programação e passe a pensar 'como' o Genexus, quero dizer com isso que normalmente brigamos com coisas que não nos é lógica, e principalmente para desenvolvedores queremos reproduzir o que aprendemos a fazer ao longo de muitos anos de esforço e dedicação. Pensar que não será mais preciso programar um Insert por exemplo pode ser um pesadelo para alguns.

Se você não é programador, sinta-se livre para criar, sabe que tem uma pequena vantagem no inicio (mas só no inicio), conhecer sobre o que esta fazendo faz com que produza coisas 'mais' avançadas. Então, mesmo aprendendo Genexus é bom manter-se atualizado quanto as inovações.

Esqueça a programação das queries SQL (a menos que for encarregado da manutenção do BD), Genexus gera as queries de manutenção e também de recuperação e manutenção dos dados, e o próprio Genexus se encarrega de buscar os dados nas tabelas corretas.  Não precisa se preocupar com a programação de inner join, por exemplo. Mas para dominar esse tema precisa aprender o significado de tabela base e estendida.


Não queira provar que o Genexus está errado naquilo que faz, isso é sinal de que você não confia na ferramenta ou quer voltar rapidamente ao modelo 'tradicional' de programação, agindo assim não vai aprender nunca. A postura deve ser a inversa disso, deve entender 'como' o Genexus faz, aprender como o Genexus 'pensa'.  Buscar antecipar o que a ferramenta vai produzir é o exercício que o leva a dominar o bixo rapidamente.

Genexus não é fácil, parece simples, mas entenda, assim como toda tecnologia é muito simples para quem a domina, e leva-se um tempinho para assimilar tudo. Sempre me perguntam quanto tempo, e a resposta é:

Se você passar a respirar Genexus vai domina-la em um mês.  Se por outro lado ficar brigando com a ferramenta pode ser que nem aprenda.

Me desculpem agora, não quero gerar nenhuma polêmica, mas não sei quais as razões que te levaram a buscar Genexus, se for porque quer construir sistemas robustos altamente tecnológicos e de forma muito rápida, creio que vai gostar muito do que tem em mãos. Por outro lado se foi 'obrigado' a aprender porque sua empresa 'teve' que adota-la, lembre-se que deve ter havido uma razão para isso, pense comigo, a busca de uma ferramenta que automatize um pouco a programação pode significar que equipe de desenvolvimento pode não estar respondendo como deveria, ou ainda, que muitas oportunidades vem sendo perdidas devido a baixa capacidade de programação.  Em ambas as circunstâncias o melhor é realmente aprender.

Tenho plena certeza que é um excelente desenvolvedor, que tem habilidades absurdas, domina todos os frameworks, todos os caminhos que levam a produzir um programa 'especial'.  Entenda que Genexus vai expandir sua capacidade de produzir estas mesmas coisas especiais, mas pode ser que não pelo caminho que você conheça.


Desta forma desejo-lhe realmente um 'Caminho Suave' e bons estudos!

Ah, e claro que não se aprende sem o Genexus, portanto, pegue ele aqui.

Caminho Suave: que saudade dos meus tempos de criança!