terça-feira, 29 de novembro de 2011

Consulta CEP

Ainda bem que o mundo vem evoluindo não apenas na questão tecnológica, mas também humana, social e ambiental, e hoje a palavra chave é respeito ao próximo em primeiro lugar e também ao meio ambiente. Claro que poderíamos assistir essa onda vinda de forma mais rápida, ou na mesma velocidade em que ocorrem as degradações, mas fazer o que? Ainda estamos em construção e temos muito o que aprender. Se você não está surfando nessa onda 'verde', melhor repensar na maneira que vem descartando as coisas, pois antigamente a frase mais falada era: o que deixaríamos para nossos herdeiros se continuássemos destruindo o mundo, agora ouvimos que será da nossa própria geração.

E o que isso tem a ver com Consulta CEP? Podemos dizer que 'reciclar' informação também é uma coisa boa e quase imprescindível nos nossos sistemas, é quase ecológico.  CEP ou Código de Endereçamento Postal é um numero que representa endereços quase completos, tecnicamente só falta o número da residência, pois o restante (rua, bairro, cidade), já possuímos. A questão é como programamos um mecanismo que nos retorne os dados de um endereço a partir deste código. A resposta: WebService.




Onde Encontrar?
A fonte original é o serviço de Correios e Telégrafos que disponibiliza a base de dados de CEP do Brasil, mas esse material é pago. Porém, a mesma base é disponibilizada no ‘mercado negro’, mas cá entre nós, vamos levar a sério essa onda verde, pirataria não. Restam então os serviços benevolentes, que claro possuem limites, mas para nosso teste com caráter didático funciona.

Um desses serviços encontra-se no site www.buscarcep.com.br, que permite certo numero de consultas por minuto.  É necessário registrar-se no site para obter uma chave de acesso ao sistema, e desta forma usufruir dos benefícios.

Como Programar
Já existem exemplos sobre esse serviço, e o que vamos fazer é programar uma SDT simplificar a interpretação do XML de retorno. Desta forma, tiramos um pouco a poeira de nosso cérebro programando tipos estruturados, que é bem legal, diga-se de passagem, e também ao invés de um External Object estaremos consumindo o WebService com HttpClient, de forma a explorar um pouco mais esse recurso.

Esse SDT, apresentado na Figura 1, irá receber as informações do WebService, e seus tipos e nomes devem ser respeitados no momento da construção.
 

Para a implementação utilizamos o exemplo do HttpClient (http://www.genexando.com/2011/11/geolocalizacao-pelo-ip-com-httpclient.html), que possibilita apontar e executar uma ação remota na web, obtendo a resposta que desejamos, e para obtermos essa resposta o que você precisa é passar os parâmetros adequados, algo semelhante ao que aparece abaixo.


cep=13211111&formato=xml&chave=1VUSS3sdDo0Wu0NAo/0dPO5nDkHuTX


Portanto, uma variável &HttpClient, de mesmo tipo, pode receber a seguinte programação.



&HttpClient.Host =  'www.buscarcep.com.br'

&HttpClient.Port = 80

     

&urlString = '?cep='

&urlString += &CEP

&urlString += '&formato=xml&chave=1VUSS3sdDo0Wu0NAo/0dPO5nDkHuTX.'



Não se esqueça de criar sua própria chave e substituir o valor 1VUSS3sdDo0Wu0NAo/0dPO5nDkHuTX. O parâmetro &CEP representa o valor do CEP que desejamos consultar.

Para realizar a consulta executamos o método Execute que acionará o WebService para obter os dados.

&HttpClient.Execute('GET', &urlString)



Finalmente utilizamos uma variável &sdt do mesmo tipo do SDT declarado anteriormente (figura 1), para obter de forma organizada as informações.

&sdt.FromXml(&HttpClient.ToString())     


Simples, o resto é leitura do valor da variável &sdt.

&Endereco   = &sdt.retorno.logradouro

&Bairro     = &sdt.retorno.bairro

&CidadeId   = &sdt.retorno.ibge_municipio

Observe que no &sdt existem muitas informações interessantes a serem exploradas, no mesmo processo apresentado anteriormente.

Conclusão

Em termos de programação acho que não poderia ser mais simples e interessante, e reforça um pouco mais os conceitos de HttpClient, WebService, SDT's e por ai vai.

Agora quanto à onda verde, infelizmente ainda temos situações que apontam ao contrário, para citar um exemplo vamos ao 'Congresso Nacional' onde nessa semana nossos lideres discutem e comemoram a 'articulação feliz' de um novo Código Florestal que entre outros absurdos, anistia as multas, até certa data, 'daqueles cidadãos ilustres' que degradaram indiscriminadamente, irresponsavelmente, mais do que devia. O pior não é isso, ainda temos que ouvir as declarações do relator do projeto que 'articulamos o melhor para o Brasil'.


Não me tome por ecológico radical, mas creio que de fato, essa onda ainda deve virar um tsunami para que se dê a atenção e importância necessária, ou melhor, que de fato o interesse coletivo de toda uma população venha a ser de fato articulado.

sexta-feira, 11 de novembro de 2011

Expression

O próprio nome já diz que é coisa boa, parece até nome de carro chique. Alias, me desculpem os proprietários só estou falando do nome, mas tem carro com nome bem estranho por ai, movimento iniciado pela Besta, veja bem, Tiida é nome pra carro? Cerato? Enfim, como diria, gosto é gosto e não devemos discutir.

Voltemos a Expression, que, aliás, é o que nos interessa, considerando ser um dos recursos que nos remetem a flexibilização e parametrização de sistemas, assunto importante e que merece destaque em qualquer projeto. Quem não tem um daqueles usuários bem chatos que vivem pedindo para se alterar a formulas de calcular de certo imposto, não é mesmo?

Tipo Expression

Esse tipo Genexus é algo que merece respeito, visto que permite avaliar expressões aritméticas e lógicas registradas em formato texto. Entre outras palavras, se temos uma expressão: a + b / 2, então podemos fazer com que o valor obtido pela sua execução seja calculado por Expression , claro, desde que se forneçam os valores para a e b.

Algo do tipo, se a=1, b=10, então o valor resultante de a + b / 2 será 6. Não entendeu, o valor é diferente daquele que você chegaria? Isso acontece porque Expression também trata a hierarquia de operadores, primeiro realiza-se a divisão e depois a soma.

Como Funciona?

Simples, cria-se uma variável do tipo Expression e em seguida, realizam-se três operações fundamentais:

  1. Define-se a expressão a ser calculada
  2. Substitui-se os valores das variáveis na expressão
  3. Executa-se o calculo da mesma
Como exemplo, recorramos ao mesmo a + b / 2.

Event Start
   &expressao = 'a + b / 2'
EndEvent

Para permitir registrar expressões livres programamos uma variável &expressao que será manipulável na interface.


Portanto, criamos duas variáveis &a e &b para terem seus valores alteraveis. Para a execução da expressão, um botão ENTER.

Event Enter
   &expression.Expression = &expressao

   &expression.Variables.Set('a', &a)
   &expression.Variables.Set('b', &b)

   &resultado = &expression.Evaluate().ToString()
EndEvent

Simples, hein, define-se a expressão, substitui-se os valores com o método Variables, e finalmente Evaluate() para gerar o resultado.

Recursos
E quanto aos recursos, bem vem com Air-bag, freios ABS, ar-condicionado Digital, ...,  ou melhor, quanto aos operadores, é possível não apenas os operadores tradicionais ( + - * / ), mas também operadores lógicos e relacionais ( < <= > >= <> and or), mesmo porque é possível definir uma operação tipo if, ou melhor iif.

   iif( condicao , valor, valor)

Tudo isso, além das funções predefinidas, tais como tan() cos() pow() sqrt(), entre outras, que eu recomendo consultar o manual do proprietário para maiores informações.

Ah, e antes que eu me esqueça, também é possível o uso de parenteses na expressão, para resolver situações de hierarquia.

Vamos a um exemplo com iif.

Event Start
   &expressao = 'iif(a + b / 2 > 0, a + b / 2 , 0)'
EndEvent

Muito bem, se quiser fazer um test-drive recomendo abrir o Gx e começar, pois verá que o desempenho é ótimo, os recursos ilimitados, e claro, a solução final digna dos Rolls Royce, ou do Galaxy para os brasileiros mais antigos.

Ah, o endereço da concenssionária é http://wiki.gxtechnical.com/commwiki/servlet/hwiki?Expression+Data+Type,






Input parameter cannot be assigned

Uma das caracteristicas mais importantes em um programador é a sua capacidade de organização lógica, apesar de que raciocionio rápido, eficiência, velocidade também são fundamentais.  Por natureza todo programador é organizado, gosta de manter seu código limpo, comentado e claro, de forma que outros da equipe possam entender rapidamente o que foi feito, e por alguma necessidade, interferir realizando uma manutenção.  Estou enganado?

Pois é aqui buscamos duas coisas, uma é incentivar os desenvolvedores a documentarem e organizarem seu código, e a segunda é resolver a questão do erro Input parameter cannot be assigned.

'Melhores Práticas'

É uma pretensão gigante de minha parte criar aqui uma lista de melhores práticas de desenvolvimento, mesmo porque cada pessoa tem um perfil, cada empresa um padrão, ou seja, vamos direto ao ponto, que é como documentar os parametros utilizados para transferir informações de um lugar para outro.

Aprendi que existem dois tipos de pessoas no mundo, aquelas que fazem de tudo para esconder o que sabem e o que fizeram, e aquelas que sente prazer em falar o que sabe pra todo mundo.  Infelizmente o segundo tipo acaba se dando mal em algumas situações, experiência própria.  O primeiro tipo pensa o seguinte, vou programar de forma que somente eu possa entender o programa, assim, fico garantido porque ninguem mexe comigo, rs...., pode ser também uma questão de extrema desorganização, falta de tempo, ou seja, uma série de desculpas para não deixar a "coisa clara". Vamos ao exemplo, citando um amigo ficticio que chamaremos de Mario, cujo perfil é, mais ou menos, do primeiro tipo de pessoa.

Certo dia, o Mario chegou pra trabalhar em sua empresa e tinha que programar uma rotina complexa em uma procedure, algo relacionado a faturamento, impostos, ..., e como tinha que passar um montão de parametros, escreveu algo semelhante a:

parm(&invc, &xkpt, &sbtrr, &isn, &kkrg, &aaiins, &inss, &ir, &sbtstr, &opt1, &opt2, &opt3);

Nada muito complexo, sob a ótica do Mario, mesmo porque a procedure tratava todos esses parâmetros, com um extenso código de1200 linhas, mas que ele tinha tudo na cabeça, e claro, conhecia linha por linha desse procedimento e sabia exatamente o que tinha que passar de informação e o que tinha de receber da procedure. Já viu algo assim? pois é um dia eu vi e reforçou o que eu já fazia antes, que era programar de forma clara, mesmo porque levei dois dias para interpretar o que o Mario queria dizer com cada uma das variáveis malucas criadas.

Nem vou dizer a respeito de comentários de código, sub-rotinas documentadas e coisas do gênero, vamos apenas buscar melhorar a lista de parametros. Desta forma, acredito, na minha humilde e singela opinião, que uma prática melhor seria programar algo assim:

parm(

   &invc,    // indice de variacao

   &xkpt,    // pre-calculo final

   &sbtrr,   // valor da substituicao trib.

   &isn,     // valor do imposto recebido

   &kkrg,    // valor interno de calculo

   &aaiis,   // previa do iss 

   &iss,     // imposto iss calculado

   &ir,      // imposto ir calculado

   &sbtstr// valor final da subst. trib

   &opt1,    // opcao de calculo com ir

   &opt2,    // opcao de calculo com iss

   &opt3     // opcao de calculo com subst.

   );


'Input parameter cannot be assigned'

Vamos ao erro que motivou o post, Input parameter cannot be assigned, que quer dizer o seguinte, todo parametro recebido no parm não pode ser atribuido um valor diferente.  É causado toda vez que um parâmetro é envolvido em uma operação que altera seu valor, como no exemplo a seguir.

parm(&a, &b, &c);



&a = &a+1

&b = &b*&a

&c = &s+&b

Desta forma, se não se informa o contrário, todo parâmetro é de entrada, e não aceita alterações em seus valores.  E nessa lógica, se existe o conceito de parametro de entrada, temos também o conceito de parametros de saída e de entrada e saída.  E é exatamente para isso que servem os flags in:, out:, inout: providos pelo Gx.

O mais interessante é que parametros do tipo inout: tanto podem receber informações quanto devolver valores calculados, ou seja, a declaração do parametro desse tipo é suficiente para remover a mensagem Input parameter cannot be assigned.


Ja pensou então se definissemos no parm do Mario quais os parametros que seriam fornecidos a procedure, e quais a procedure nos devolveriam? Teriamos um código melhor mesmo, porque não precisariamos ligar toda hora pro Mario para perguntar o que é tal coisa.


parm(

      in: &invc,   // indice de variacao

     out: &xkpt,   // pre-calculo final

     out: &sbtrr// valor da substituicao trib.

      in: &isn,    // valor do imposto recebido

      in: &kkrg,   // valor interno de calculo

   inout: &aaiis// previa do iss 

     out: &iss,    // imposto iss calculado

     out: &ir,     // imposto ir calculado

     out: &sbtstr, // valor final da subst. trib

      in: &opt1,   // opcao de calculo com ir

      in: &opt2,   // opcao de calculo com iss

      in: &opt3    // opcao de calculo com subst.

   );

Enfim, parametros de saída são aqueles que em uma chamada com Call podem receber valores.


Tenho usado, na maioria das vezes, esse tipo de programação, e salvo a própria complexidade das rotinas programadas, acredito que a clareza e a documentação do código sejam práticas fundamentais para o sucesso nos projetos.

Agora muito cuidado com a história do Mario e do armário hein...



sábado, 5 de novembro de 2011

Geolocalização pelo IP com HttpClient

Existe um recurso muito interesante, com certa idade, meio timido pois fica alheio aos principais flashes na ferramenta, mas que até os dias atuais mostra-se de grande utilidade, é o HttpClient.  Porque? simplesmente pelo fato de que podemos usar o protocolo HTTP em modo de programação, ou seja, que se programe uma requisição, se envie para uma URL e se obtenha os resultados dessa chamada. Isso quer dizer, que se execute uma chamada HTTP em forma de programação, sem que a mesma seja apresentada no browser.

Aplicações para isso? Muitas, inclusive encontrar a geolocalização de um certo IP na web. Esse é o exemplo que será apresentado a seguir, e tem como objetivo obter informações de um determinado serviço na web.


Obtendo a geolocalização

Existem uma série de serviços na Web que realizam essa operação, selecionamos uma que devolve um XML, JSON ou CSV, a partir de um determinado IP fornecido, e que pode ser encontrado em (http://freegeoip.appspot.com/), que necessita apenas de dois 'parametros' para funcionar: o tipo de retorno e o IP.  O formato para a chamada pode ser algo semelhante ao seguinte exemplo: http://freegeoip.appspot.com/xml/72.14.247.141

O texto XML representa o formato do retorno do serviço, que nesse caso devolve algo como:



Outros formatos são disponiveis, em especial o JSON e CSV.

Programando


Não é necessária muita programação para obter essas informações, a não ser uma interface simples para obter um IP qualquer, e em seguida, acessar o WebService na web, algo semelhante a.


Para obter as informações, teriamos então a programação do HttpClient, apontando para o serviço na web, ou seja, o Host, Port e forma de Secure.

     &httpClient.Host = "freegeoip.appspot.com"
     &httpClient.Port = 80
     &httpClient.Secure = False

Os parâmetros são passados por meio de uma variável texto, incluindo-se o formato desejado e o IP que se deseja investigar. Em nosso caso optamos por um texto separado por vírgulas.

     &string  = "/csv/"
     &string += &ip

Em seguida a chamada ao WebService, por meio do método Execute.

     &httpClient.Execute("GET",&string )

Se não ocorrer nenhum erro nessa chamada, teremos um texto resultante da chamada, que pode ser obtida por.
          &texto = &httpClient.ToString()

O programa completo é apresentado a seguir, inclusive com o tratamento de erros.



Uma tabela foi programada para se mostrar o resultado, como aprsentado na figura 1, acima.

Voce pode encontrar maiores informações na documentação da Artech, agora, se não conseguiu visualizar uma boa aplicação para esse recurso, vou dar mais uma dica, consulte as páginas amarelas dos webservices em http://www.webservicelist.com/