quarta-feira, 30 de dezembro de 2009

Manipulando Imagens

Essa é bem simples, mas ajuda, a questão do tratamento de imagens em Genexus X, que a partir desta versão passou a tratar também do gerenciamento das imagens do projeto.

Genexus guarda as imagens do projeto em Customization->Images, sendo que todas devem ser importadas pela ferramenta com a opção New Image. Duplo clique sobre uma imagem nesta pasta permitirá abri-la para edição, e um novo duplo clique sobre a imagem aberta permitirá trocá-la por outra.

As imagens são armazenadas por default na pasta web/Resources do projeto, e caso a KB tenha definida vários idiomas e na carga da imagem seja especificado este tratamento, então uma imagem para cada idioma do projeto será colocada nas pastas web/Resources/.

Para incluir a imagem em uma interface utilize o controle Image na paleta, até aqui muito simples.

Acesso Runtime

Aqui a coisa fica mais interessante, ou seja, como manipular ou acessar a imagem na referida pasta.

Usando um controle TextBlock é possível apresentar a imagem, desde que este seja definido como Format=HTML. Daí é só programar a tag HTML , no formato a seguir.



(clique na imagem para aumentar)

Observe que o nome da imagem (nomeimagem) e a chamada a Link() retornam o endereço relativo (a partir da pasta raiz do sistema ‘web’), permitindo que a mesma seja acessada pelo browser. Em outras palavras, a chamada devolve algo como Resources/nomeimagem.gif

Botão com Imagem


Usando este simples recuso é possível programar um botão diferente com texto e imagem.



Este pode ser construído a partir de uma variável (Varchar(300), Readonly=true e Format=HTML) ou mesmo em um TextBlock.






Em ambos os casos é possível interceptar o pressionamento com um simples

Event &BotaoPrint.Click
...
EndEvent

Bitmap

Outra maneira de manipular uma imagem é através de variável Bitmap, sendo que neste caso, é necessário carregar a imagem a partir da função loadbitmap(). O mesmo resultado obtido por Link() pode ser utilizado para carregar a imagem na variável bitmap.




Antes de Fechar a Conta
A imagem que se encontra na pasta Resources ou nas pastas de idiomas, podem ser manipuladas (desde que não se troque o nome das mesmas) normalmente. Ou seja, para a realização de uma eventual manutenção, não é necessário recarregá-la no Genexus, bastando a gravação da modificação no arquivo de imagem nas referidas pastas.
Conclusão
Pequenas coisas que auxiliam na construção de interfaces interessantes e muitas outras podem ser criadas com esses recursos simples, deixemos isto para outra ocasião.

sábado, 5 de dezembro de 2009

Genexus é lento?

Muitas pessoas, ao ouvirem a respeito de Genexus, argumentam que a ferramenta é lenta no acesso ao banco de dados, e portanto, não é interessante. Meu argumento sempre foi o de que por facilitar a manutenção, a ferramenta poderia até ser um pouco mais lenta no acesso à base, mas que a longo prazoo sistema teria menor custo.

Bom, me deparei com uma situação que de fato trazia grande desconforto na montagem de uma determinada interface, porque levava segundos até ser apresentada para o usuário, em um sistema Web, e o pior era que essa interface tinha que ser reconstruída a cada clique do usuário na tela.

Isso me levou a descer um pouco mais nas profundezas do gerador, e tentar entender o porque do acesso á base deixava a interface tão lenta. No final das contas o acesso que tinha que fazer era a uma tabela com alguns joins inner e outer, mas que no final retornava em torno de 150 registros. Ou seja, nada muito complexo a ponto de justificar segundos para a montagem da interface.

Primeiramente descobri que o gerador inclui as queries SQL no próprio código gerado em C#, portanto podem ser estudadas e até mesmo testadas externamente, basta um CTRL + C e CTRL + V, no SQL Server, substituindo evidentemente os parâmetros da query, isso pode ser interessante, porque no final das contas se fosse programado manualmente a query gerada não seria muito diferente da que o Genexus cria. Portanto, alguma coisa não estava muito evidente, porque se a query era a mesma gerada manualmente, porque a interface estava lenta.

Eis um exemplo da query do Genexus no código:

new GeneXus.Data.NTier.ADO.CursorDef("T00012", "SELECT [CustomerId], [CustomerName], [CustomerAddress], [CustomerGender] FROM [Customer] WITH (UPDLOCK) WHERE [CustomerId] = @CustomerId ",true, GxErrorMask.GX_NOMASK, false, this,prmT00012,1,0,true,false )

Em seguida reprogramei o acesso a base de dados, desta vez programando a query manualmente na própria ferramenta, ou seja, em código nativo C#. Esperava que com isso o resultado fosse melhorar significativamente, mesmo porque deu muito trabalho para programar na mão o que o Genexus fazia apenas colocando um Grid e os atributos, e o resultado infelizmente não ajudou muito, continuava lento.

Enfim, não era o acesso que estava complicando, no meu caso, e sim a montagem da interface gráfica. Observando atentamente o que havia feito cheguei a conclusão que a interface possuía:

1. Um grid Freestyle com muitas variáveis (nenhum atributo) porque a programação do acesso foi totalmente manual
2. Muito código na área de eventos, e muitos repetidos, porque era necessário muitos cálculos e navegação nos dados recuperados da base.
3. Armazenamento de informações na própria interface gráfica (na prática estava colocando uma SDT do tipo collection na interface para recuperação dos flags gerados pelo usuário)

Recomendação

Após muita programação e reprogramação da interface, cheguei a algumas conclusões interessantes, e que acho que podem te ajudar em problemas semelhantes.

Em primeiro lugar deixe a database para o Genexus mesmo, não vai melhorar muita coisa, talvez alguns milisegundos, mas o argumento da manutenção continua a ser o mais importante, porque uma coisa é resolver o problema para entregar o programa e outra é resolver problemas após a entrega, que no meu ponto de vista é pior.

Outra coisa, fique atento ao uso de variáveis na interface, pois são mais lentas que atributos, evitando colocar muitas no Grid. Cheguei à conclusão que é melhor uma única com todos os valores em uma string do que várias com os valores separadinhos na interface. Mesmo que isso signifique que se tenha que separa os valores (SPLIT) para as utilizar.

Não siga a lógica do armazenamento dos valores na interface para uso na carga POST da interface (aquela realizada por uma ação do usuário), mesmo porque o Genexus vai executar tudo novamente, o START, a carga do grid, a leitura da interface, portanto, é mais fácil armazenar na base o que o usuário realizou e em seguida recalcular tudo do que guardar na interface o que o usuário fez.

A Interface

Após falar tanto, acho que voce deve ter ficado um pouco curioso a respeito da tal interface gráfica complexa, então vou deixar uma imagem aqui para que voce durma esta noite.

Não cabe aqui discutir muito a respeito da operação (matricula de alunos), mas trata-se de uma interface baseada em clicks nas caixinhas, onde a cor azul = selecionado, amarelo = escolhido pelo usuário e vermelho = bloqueado devido à escolha. A cada confirmação o usuário escolhe o recurso e a interface deve ser reconstruída.
Esta interface roda na Web, atualmente, quase com o mesmo desempenho de uma interface Windows local.
Conclusão

Talvez esse artigo sirva para os programadores mais experientes, e que tenham grandes desafios em interfaces complexas, e não para os iniciantes, mas posso dizer com certeza que Genexus é uma ferramenta poderosa no acesso á base e não deixa nada a desejar à programação tradicional e manual. Se dominada, permitirá a você fazer grandes coisas com pouco esforço.