quinta-feira, 25 de agosto de 2011

Kb´s Grandes


Um tema fundamental levantado pelo Enrique Almeida para o próximo Encontro Genexus é a gestão de Kbs grandes no Genexus, e creio esse ser sem dúvida um dos assuntos mais importantes relacionados ao desenvolvimento com Genexus, pelo menos pra mim.

Falo isso porque nosso projeto alcançou uma dimensão exageradamente grande, gerando situações difíceis de serem resolvidas, algumas das quais já adianto no Genexando, para que possamos gerar reflexões no encontro:

  1. Tempo de compilação, backup da Kb
    1. Apesar dos avanços alcançados na questão da otimização do processo de compilação e geração de código, temos ainda grandes dificuldades no que se refere ao tempo gasto em um Build All.
    1. O tempo para a exportação completa de nossa KB é de 15 minutos.
    1. Geração de objetos desnecessários também vem nos causando grandes transtornos, atualmente temos 70 objetos que insistem em serem gerados mesmo que não se tenha nenhuma nova implementação sobre eles.
    2.  Infelizmente o Genexus também se torna lento e ineficaz, e olha que usamos um belo Intel Centrino QuadCore.
  1. Processos fundamentais centralizados e protegidos
    1. Infelizmente Genexus não possui ainda uma linguagem Orientada a Objetos, desta forma conceitos fundamental como classes, objetos, métodos private  e public, interfaces, sobrecarga, e outros, fazem muita falta.
    1. Uma vez que não possui os conceitos de objetos e classes, as regras de negócio ficam implementadas de forma esparsa dentro nos objetos Genexus: Transações, Procedimentos, Web Panels, cada um tratando de parte da regra, e claro, gerando grandes dificuldades para mantê-las integras de acordo com a evolução do projeto.
    1. Por exemplo, ao se realizar a manutenção em determinada regra de negócio em um Procedimento isolado, por exemplo, pode ocorrer que esta mesma manutenção não venha a ser aplicada em outros objetos similares, tornando esses geradores de bugs na aplicação. Se tivéssemos a possibilidade de criar uma Classe (de negócio) poderíamos concentrar todas as operações em um lugar único, disponibilizando os métodos públicos disponíveis para serem consumidos pelos objetos Genexus, tais como Transações, WebPanels, Procedures, e outros.  Uma manutenção em uma única classe traria muitos benefícios para projetos grandes e complexos.
    1. Atualmente diversos objetos apontam nessa direção, o External Object, por exemplo, permite encapsular métodos de classes externas ao Gx. Quem sabe não teríamos uma espécie de Internal Object, similar ao External Object, que disponibilizaria um tipo para se acessar métodos de negócio públicos encapsulados e protegidos na Kb.  Claro que nem todos os desenvolvedores teriam privilégios para manipular tais objetos.

  1. Todos tem acesso a tudo
    1. Independentemente da atuação da pessoa no projeto, quer seja um aprendiz, um desenvolvedor, um analista senior, qualquer um, possui acesso full a todos os objetos da KB. Esse acesso indiscriminado gera situações complicadoras, desde a modificação e remoção indevida de objetos, até mesmo questões de segurança do projeto, visto que a pessoa pode, por exemplo, obter uma cópia integral do código fonte, para quem sabe fazer o que.  Melhor seria se fosse possível estabelecer privilégios sobre os objetos para os diversos perfis de desenvolvedor, bloqueando inclusive operações de modificação, exportação, abertura, entre outras.
    1. Todos podem modificar a estrutura das transações, podendo gerar inconsistências na base de dados, duplicação de atributos e conceitos, e por ai vai.  Melhor seria se tivéssemos perfis para liberar modelagens da estrutura do sistema

Tem muitas outras coisinhas interessantes a serem discutidas, mas vou parar por aqui para não assustar as criancinhas!

quarta-feira, 24 de agosto de 2011

A Java Runtime (JRE) is not enough to develop for Android

 

Esse foi o meu cartão de visitas no teste do gerador Android, uma mensagem que aparecia ao tentar se instalar o Android SDK, acusando que o computador não tinha Java instalado, e adivinha, havia acabado de instalar.  Tudo bem que tratava- se de um Windows 7 64 Bits, mas não acha que nossa vida poderia ser um pouco mais fácil? 

Uma googlada revelou alguns companheiros na web que passaram pela mesma situação, almas generosas que compartilharam uma solução meio estranha, mas que testei aqui e rodou legal.

Digo inusitada porque a solução consiste em alterar o registro do Windows para apontar para o diretório correto de instalação Java.  Não me pergunte por que não estava correto, melhor perguntar pra Oracle.

A solução consiste em abrir o REGEDIT, e em seguida exportar para um arquivo REG o conteúdo da chave, [HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft], gerando um arquivo com todas as definições de instalação do Java na máquina.



Em seguida de um replace em todos os valores deste arquivo .REG em que aparece a chave  HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft pela chave HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\JavaSoft.



Execute o arquivo REG resultante (dando um click duplo) e adivinhe, o bixo instala! Daí é só correr para o abraço com Genexus Ev2 e Android!
 



terça-feira, 9 de agosto de 2011

Pise no Break


São Paulo resolveu punir motoristas que não pisam no freio e desrespeitam os pedestres nas faixas, e nesse sentido, Montevidéu é um exemplo, por lá todo mundo respeita os pedestres, chega a ser irritante quando sem querer você pisa na faixa, daí tem que atravessar, até por constrangimento, pois os motoristas param pra valer.

Nesses devaneios me lembrei que de vez em quando devemos pisar no Break do Genexus também, mas não no sentido de reduzir a velocidade, ao contrário, devemos remover os breaks de nossos for eachs para acelerar a velocidade de nossos programas.

A regra é simples, se você programou o Break pra valer, então com certeza é um programador hábil e seu código reflete um belo agrupamento de registros, agora se o break apareceu meio sem querer, e insiste em permanecer, até tem que criar aquela estúpida subrotina para enganar o Genexus, então meu amigo, você precisa sentar-se novamente no banquinho porque fez uma bela ‘kakinha’, com o perdão da palavra.

O que é o Break

No mapa de navegação o Genexus indica quais tabelas são recorridas (tabelas bases) e quando se programamfor eachs aninhados, as relações entre as tabelas dos for eachs são apresentadas. No exemplo abaixo, temos um break aparecendo no segundo for each.

Figura 1. Mapa de Navegação

O break é um indicativo de que está ocorrendo recursão, ou seja, o segundo for each está apontando para a mesma tabela que o primeiro for each no aninhamento, observe que é a NotaFiscal, no exemplo. E por que isso ocorre se estou tentando pegar registros de outra tabela? A resposta é simples: tabela estendida.

Tabela Estendida

Com certeza esse é um dos mecanismos mais interessantes do Genexus, e significa que ocorre Join automático a todas as tabelas que se encontram em uma relação N-1 com a tabela base apontada pelo for each.  O que isso significa? Que você não precisa fazer nenhum esforço para obter os dados complementares que se encontram na relação N-1.

Figura 2. Diagrama

Desta forma para obter o nome de um cliente ou da cidade desse cliente, por exemplo, estando na tabela de notas fiscais não é necessário recorrer a um for each adicional. Eu diria até que seria um crime caso você faça isso, ou melhor, que está perdendo seu tempo programando uma recursão para uma tabela que já está na sua mão, e nesses casos é que surgem os breaks indesejados.

Por essa razão é que o Break surgiu na nossa figura 1, que foi produzida a partir do seguinte código.

for each
      &NotaFiscalData = NotaFiscalData
      for each
            &ClienteNome = ClienteNome
      endfor
endfor
  
Veja que eu nem coloquei no for each a cláusula where para ligar o primeiro ao segundo for each, que alias muitos insistem em fazer de forma totalmente desnecessária.

Qual é a Solução?

Para os Breaks indesejados a solução é mais simples do que parece, apenas remova os for eachs que foram programados a mais, e o break some milagrosamente.
 


Para os desenvolvedores mais experientes, mil desculpas, mas apesar da simplicidade do tema, tinha que registrar esse importante avanço no transito brasileiro, enfim uma multa que vale a pena ser aplicada.

sexta-feira, 5 de agosto de 2011

Start somente no Start


Tem conceitos que soam de forma estranha quando estamos na Web, um deles é que o evento Start não ocorre somente quando a página 'inicia', pois toda vez que ocorre uma comunicação com o servidor, que não seja AJAX, isso fará com que o evento Start seja executado novamente.
 

Desta forma todo o conteúdo programado no evento Start seria executado novamente a cada recarga da interface, incluindo-se acessos às tabelas, cálculos, definição de valores, entre outras.  Você entende isso, tudo seria calculado novamente, cada vez que a pagina retornasse ao servidor, muitas vezes representando algo inútil, dispensioso em termos de processamento, tempo,.... 

Para tentar melhorar um pouco isso poderíamos atentar para outra característica a ser compreendida nas interfaces web que é: se o valor definido na primeira carga da interface (no primeiro evento Start, por exemplo) fosse colocado em uma variável na tela, oculta ou não, então, em uma segunda carga da mesma interface esse valor já estaria disponível antes do evento Refresh, mesmo se Start não fosse re-executado. 

Juntando as duas coisas teríamos uma situação em que na segunda carga da interface, não seria necessário acessar o banco para obter as definições iniciais, visto que essas já estariam disponíveis na interface.

Soa confuso? Simplificando nosso objetivo seria:
  1. Ler o valor de alguma coisa, a partir do banco de dados, na primeira carga da interface no evento Start
  2. Em seguida coloque esse valor em uma variável na interface, tornando-a oculta se necessário
  3. Daí pra frente, ou seja, nas próximas recargas não precisaríamos ler novamente o valor no banco, pois esse já estaria na interface.
Então, o problema é que o Start, querendo ou não é executado. A menos que... O Luis Alexandre (*) te ajude te dando uma dica espetacular.

Controlando o Start com o HttpRequest
Existem dois métodos de chamada da interface Web no servidor, um GET e outro POST. O primeiro é realizado quando a interface é aberta na primeira vez, e o segundo quando pressionamos algum controle que gera um evento no servidor, tipo um botão Confirmar, por exemplo.  Para entender isso, recomendo ler: Interface Web na base do Fórceps (http://profdouglasoliveira.blogspot.com/2011/06/interfaces-web-na-base-do-forceps.html )

Nosso objetivo aqui é controlar a primeira chamada, ou seja, somente carregar o valor de alguma coisa no database, uma única vez, e quando a mesma for do tipo GET.  Para isso programariamos:

Event Start
     // carrega o Cliente
     if &HttpRequest.Method = 'GET'
&ClienteId = GetCliente.Udp()
     endif
EndEvent

Esse trecho de código é muito interessante, pois permite definir o que queremos carregar apenas uma vez na interface.  A variável &HttpRequest  do tipo HttpRequest possui uma propriedade Method que se GET nos informa que a interface está sendo carregada pela primeira vez.

Se a variável &ClienteId for colocada na interface, como um controle (Visible=true ou false) então no evento Refresh, teríamos o valor da mesma disponível para realizar qualquer outra ação.

Event Refresh

     // utiliza o ClienteId carregado (no Start ou na Tela)
     AlgumaCoisa.Call(&ClienteId)

EndEvent

Com essa programação teríamos o acesso ao banco somente na primeira vez.





Apesar de tantos conceitos, espero que esse post seja tão útil pra você quanto foi pra mim, rs... Veja só como foi importante conversar com o Luis Alexandre, né.

_____
(*) Luis Alexandre de Oliveira, é desenvolvedor do projeto SIGA no Centro Paula Souza.