[Pesquisar este blog]

quinta-feira, 12 de janeiro de 2017

JavaScript na JVM

O uso do JavaScript tem crescido consistentemente nestes últimos anos, tanto que a linguagem não apenas figura, mas aparece bem posicionada nos mais conhecidos rankings de utilização de linguagens de programação (TIOBE Index, GitHub PYPL, RedMonk, IEEE Spectrum, etc).


Não é preciso justificar porque o JavaScript é importante. Introduzido em 1995 por Brendan Eich, sob o nome original Mocha, acabou sendo renomeado para JavaScript para aproveitar o sucesso inicial do Java, lançado no mesmo ano. Sua característica mais marcante é trazer interatividade a páginas HTML, sendo executada pelo browser, ou seja, operando do lado do cliente.

Com o passar do tempo e apesar das críticas de muitos programadores, o JavaScript evoluiu e hoje permite o controle sofisticado do conteúdo de páginas web, permitindo a troca de estilos, a ocultação/exibição de elementos, a realização de validações e outras operações mais complexas.

A partir de 2005, com o advento do AJAX (Asynchronous JavaScript and XML), ocorre seu renascimento do JavaScript, e surgem frameworks importantes como Prototype, JQuery, Dojo e Mootools, assim como esforço consistente para sua padronização (ECMAScript 3.1 a 5.1). Hoje o JavaSript é uma linguagem de programação amplamente utilizada.

Nashorn

O Nashorn é uma implementação de um mecanismo (ou motor) de execução para linguagem de programação JavaScript integrado a plataforma Java, disponível a partir da versão 8, compatível com a especificação ECMAScript 262 v5.1, que se beneficia da enorme quantidade de ferramentas e bibliotecas disponíveis para JavaScript, possibilitando sua integração com a plataforma Java e, portanto, conjugando as vantagens destes dois mundos.

Até a versão 7 do Java, o mecanismo de execução padrão do JavaScript disponível no Java era o Rhino, baseado num projeto de mesmo nome voltado para os navegadores Mozilla. Apenas como curiosidade, a palavra nashorn significa rinoceronte em alemão e também denominou um tanque de guerra conhecido como destruidor de tanques.

O mecanismo de execução Nashorn é acessível por meio da API javax.script e da ferramenta de linha de comando jjs, suportando a execução de scripts escritos em JavaScript embutidos em programas Java, incluindo aplicações JavaFX.

A sintaxe da linguagem JavaScript é bastante semelhante a do Java e o acesso a elementos Java a partir do JavaScript, como arrays e objetos, é praticamente idêntico, de modo que o Java tem acesso a valores e elementos do JavaScript e vice-versa.

Programa Java executa script JavaScript

O exemplo que segue (classe Nashorn01) mostra um programa de console Java que utiliza o Nashorn para executar um comando JavaScript.

import javax.script.*;

public class Nashorn01 {
    public static void main(String[] arg) {
        // Obtem acesso ao mecanismo de execucao JS Nashorn
        final ScriptEngine nashorn =
               new ScriptEngineManager().getEngineByName("nashorn");
        try {
            // Script JS pode ser hardcoded ou
            // obtido por outros meios (p.e., arquivo)
            String script = "print('Hello World!')";
            // Execucao do script JS
            nashorn.eval(script);
        } catch (final ScriptException se) {
            System.out.println(se);
        }
    }
}

Na classe Nashorn01, uma instância de ScriptEngineManager é criada para que, por meio de seu método getEngineByName(String) e o nome "nashorn", se possa obter uma instância do mecanismo de execução correspondente ao Nashorn. Com o objeto ScriptEngine obtido é possível executar-se diretivas JavaScript individuais ou scripts inteiros com uso do método eval(String). É necessário monitorar tal avaliação com um try/catch.

Retorno de valor do script JavaScript para Java

Neste outro exemplo (classe Nashhor02), o script é lido de um arquivo cujo nome é fornecido como argumento para o programa. O mecanismo de execução Nashorn é obtido da mesma maneira, mas sua utilização é um pouco diferente.

import java.io.*;
import javax.script.*;

public class Nashorn02 {
    public static void main(String[] arg) {
        // Script obtido do arquivo indicado como argumento
        StringBuffer script = new StringBuffer();       
        try (BufferedReader br =
                 new BufferedReader(new FileReader(arg[0]))) {
            String line = null;
            while ( (line=br.readLine()) != null) {
                script.append(line);
                script.append("\n");
            }
        } catch (Exception exc) {
            System.out.println("Erro: " + exc);
            System.exit(-1);
        }
        try {
            // Obtem acesso ao mec. execucao JS Nashorn
            final ScriptEngine nashorn =
             = new ScriptEngineManager().getEngineByName("nashorn");
            // Execucao do script JS
            Object returnValue = nashorn.eval(script.toString());
            System.out.println("Java: " + returnValue);
        } catch (final ScriptException se) {
            System.out.println(se);
        }
    }
}

O resultado do método eval(String) é atribuído a uma variável Java do tipo Object, de modo que é possível transferir um resultado do script Javascript para o programa Java. Basta para isso que a variável cujo valor deseja-se retornar seja indicada como uma diretiva ao final do script, como no script simples que segue, onde a variável f tem seu valor retornado para o programa Java.

// teste01.js
var c = 33;
print('JavaScript: ' + c);
var f = c*9.0/5.0 + 32.0;
print('JavaScript: ' + f);
f; // retorno de valor

O valor retornado pode ser convertido em outros tipos por meio de operações de coerção, no caso, como o resultado é do tipo double, poderia ser aplicado:
double resultValue = (Double) nashorn.eval(script.toString);

Passagem de valores entre programa Java e script JavaScript

Também é possível passar valores do programa Java para o script Javascript com o uso do método put(String, Object) disponível na classe ScriptEngine. que define uma variável com o valor indicado (ou global variable binding). O exemplo que segue transfere dois valores do programa Java para o script, que soma tais valores, retornando tal resultado para o programa, usando o método get(String).

import javax.script.*;

public class Nashorn03 {
    public static void main(String[] arg) {
        // Obtem acesso ao mecanismo de execucao JS Nashorn
        final ScriptEngine nashorn =
               new ScriptEngineManager().getEngineByName("nashorn");
        // Script JS hardcoded
        String script =
               "var c = a + 2*b;\nprint('JavaScript: ' + c);";
        try {
            // Transferência de valores: programa -> script
            nashorn.put("a", 123);
            nashorn.put("b", 0.456);
            // Execucao do script JS
            nashorn.eval(script);
            // Transferência dos resultados: script -> programa
            double result = (Double) nashorn.get("c");
            System.out.println("Java: " + result);
        } catch (final ScriptException se) {
            System.out.println(se);
        }
    }
}

Script JavaScript que utiliza classes Java

Outra possibilidade interessante decorrente da integração do mecanismo de execução Nashorn na JVM é o compartilhamento da API Java por parte dos script JavaScript. Um objeto Java pode ser instanciado de duas formas:
  • Instanciação direta:var lista = new java.util.ArrayList();
  • Instanciação indireta:var AL = java.util.ArrayList;
    var lista = new AL;



As duas formas produzem o mesmo efeito. O que muda é a quantidade de código digitado: a instanciação direta é mais verborrágica, portanto, mais longa, no entanto, clara e direta; a instanciação indireta permite instanciar objetos com menos código, embora possa ser menos clara conforme os apelidos usados para as classes efetivamente usadas.

O uso dos objetos é como no Java, tal como mostrado no exemplo que segue, onde um script JavaScript utilizar uma tabela de hashing, um array elástico e um buffer para String para manipular uma lista de linguagens de programação e seus inventores.

// teste02.js
var HM = java.util.HashMap; // instanciação indireta
var map = new HM();
var list = new java.util.ArrayList(); // instanciação diretas
var buffer = new java.lang.StringBuffer("|");

map.put("JavaScript","Brendan Eich");
map.put("Java","James Gosling");
map.put("C#","Anders Hejlsberg");
map.put("Pascal","Niklaus Wirth");

for (var key in map) { print('key: ' + key); list.add(key); }
for each (var value in map) {
    print('value: ' + value);
    buffer.append(value); buffer.append("|");
}
for each (var key in list)
    print('{ ' + key + ', ' + map.get(key) + ' }');

print(buffer.toString());
list // retorno de objeto


Este script, salvo sob o nome de teste02.js, é executado com uso da classe/exemplo Nashorn02, dada anteriormente.

Console JavaScript


Junto com o JDK 8 existe um console JavaScript (uma ferramenta de linha de comando) denominada jjs que provê acesso direto ao mecanismo de execução Nashorn, comportando-se como um REPL (Read-Evaluate-Print-Loop), ou seja, um console que lê comandos JavaScript, executando-os e imprimindo os resultados no próprio console, interativa e repetidamente, o que é muito conveniente para testar comandos, executar pequenas rotinas e testes, incluindo experimentar elementos Java e JavaScript sem a necessidade de escrever programas completos.

Para acioná-la basta digitar 'jjs' (considerando que a variável de ambiente path está corretamente configurada para incluir o diretório <java_install>/bin). Considere as várias sequências que seguem de comandos que podem ser digitados no jjs. A primeira define variáveis e exibe o resultado de uma expressão:

jjs> var a = 1.5;
jjs> var b = -3;
jjs> print (2*a - 0.5*b);
4.5

Agora a definição e a exibição de um array simples:

jjs> var array = [];
jjs> array[0] = 'Peter';
Peter
jjs> array[1] = 2017;
2017
jjs> array
Peter,2017
jjs> array.length  
2
jjs> for(var i=0; i<array.length; i++) print(array[i]);
Peter
2017
jjs> for each (var v in array) print(v);
Peter
2017

Para encerrar o jjs deve ser fornecido quit().
Objetos Java podem ser instanciados e utilizados, como segue:

jjs> var list = new java.util.ArrayList();
jjs> list.add('Peter');
true
jjs> list.add('Jandl');
true
jjs> list
[Peter, Jandl]
jjs> list.size();
2
jjs> var i = 10;
jjs> for each (var v in list) { print(i + ':' + v); i = i + 10; }
10:Peter
20:Jandl
30

Características avançadas do Java, como expressões lambda e streams também podem ser usadas (com alguns cuidados). Considerando o ArrayList list definido acima, poderia ser escrito:

jjs> list .stream() .filter(function(s) s.startsWith('J')) .forEach(function(s) print(s));
Jandl
null

Neste fragmento devem ser observados alguns aspectos:
  • onde é possível usar uma expressão lambdas no Java, emprega-se uma função JavaScript; de maneira que o lambda Java
    "s -> s.startsWith('J')"
    torna-se
    "function(s) s.startsWith('J')";
  • o valor 'Jandl' é o valor resultante da exibição dos elementos filtrados do stream obtido da coleção list;
  • como o método forEach(Consumer) é terminal, seu valor de retorno é void, assim sua avaliação pelo jjs retorna null.


O modo interativo do jjs é bastante útil para experiências e testes diversos. Mas não é conveniente quando desejamos executar (ou repetir) uma sequência conhecida (ou longa) de comandos. Um conjunto de comandos JavaScript, com ou sem uso de elementos do Java, pode ser salvo num arquivo de script, o qual pode ser executado pelo jjs em seu modo de interpretação (ou batch). Para executar o script teste02.js basta escrever:

> jjs –scripting teste02.js

Conclusões

Dada a importância atual do JavaScript, sua utilização integrada à plataforma Java é bastante interessante. Assim o Nashorn é bastante útil ao permitir que programas Java utilizem funcionalidades JavaScript; que programas JavaScript compartilhem elementos do Java; que o desenvolvedor disponha de um console JavaScript para testes diversos, execução de tarefas rápidas, prototipação, teste de características do Java e construção de scripts usando Java e JavaScript combinados.
Atualmente o Nashorn (Java 8) suporta completamente o padrão ECMAScript 5.1, além de algumas extensões. Pretende-se que com o Java 9 o Nashorn seja atualizado para suportar o ECMAScript 6. Tudo muito útil e conveniente.

Para Saber Mais


quinta-feira, 5 de janeiro de 2017

Além do Java na JVM

Já se foi o tempo em que a Java Virtual Machine - JVM – era dedicada exclusivamente ao Java. Como a especificação da máquina virtual é pública, muitos desenvolvedores criaram linguagens de programação compiladas em bytecode, o formato próprio da JVM, permitindo que seus programas sejam executados em uma JVM.


Essa estratégia:
  • permite que tais linguagens sejam tão portáteis quanto o Java, pois os programas construídos com estas linguagens podem ser executados em qualquer plataforma onde exista uma 
  • possibilita que estas linguagens tenham características que o próprio Java não possui, servindo como um ambiente de pesquisa; e
  • constitui uma alternativa para que linguagens existentes sejam portadas para a JVM, aumentando as possibilidades de sua utilização.
Em algumas versões a linguagem de programação Java recebeu melhorias substanciais, como, por exemplo, os genéricos na versão 5; ou as expressões lambda, as referências para métodos e a API Stream da versão 8. Mas além disso não ser uma constante cada versão, seria impossível satisfazer todos os grupos, opiniões e necessidades da comunidade. Daí que este uso alternativo da JVM é tanto atraente como conveniente.

Assim, surgiram nestes últimos anos várias linguagens de programação novas voltadas para a JVM, como as conhecidas Scala e Groovy, mas existem outras como Xtend, Ceylon, Kotlin, X10 e Fantom.

Da mesma maneira, linguagens consagradas como o Python e Lisp estrearam na JVM respectivamente com Jython e Closure. O JRuby é um outro exemplo de linguagem portada para a JVM.

Neste post falaremos um pouco sobre o Scala e o Groovy.

Scala

Desenvolvida por Martin Odersky, a partir de 2001, como evolução de seus projetos de linguagens de programação envolvendo os paradigmas da orientação a objetos e funcional. Scala é considerada um linguagem multiparadigma de propósito geral. Seu nome é uma abreviação de scalable language.
É similar ao Java, com sintaxe básica bastante semelhante, compartilhando sua API. Mas possui diversas características próprias, que fazem seu código bastante distinto tem relação ao Java. Seus programas podem ser executados na JVM e podem ser integrados a outras aplicações Java. Um exemplo do tradicional programa Hello World com Scala:

object HelloWorld {
    def main(args: Array[String]): Unit = {
        println("Hello, world!")
    }
}

Aqui object define um singleton (um objeto único) denominado HelloWorld, no qual def declara um método denominado main que recebe um array de tipo String como argumento e tem Unit como valor de retorno. O código do método apenas efetua a impressão de uma string.

Neste exemplo coexistem elementos quase idênticos ao Java, junto de outros bastante diferentes.

Do ponto de vista de programação Scala é puramente orientada a objetos, não possuindo tipos primitivos. Também é funcional, tanto que todos os seus operadores são funções implícitas.

Scala possui um design muito interessante, pois a combinação de seu sistema de tipos, o fato de seus métodos poderem ser usados como operadores e parâmetros, além da construção de closures permite ampliar sua sintaxe substancialmente.

A linguagem de programação Scala é utilizada por grande companhias, como Twitter, Linkedin, Netflix, FourSquare, Tumblr, AirBnB e outras.

Para saber mais sobre o Scala, veja os links no final deste post.


Groovy

Desenvolvida por Guillaume Laforge, a partir de 2003, como uma alternativa ao Java. É um linguagem de programação dinâmica, orientada a objetos e funcional, que combina características do Smalltalk, Python, Ruby, entre outras. Atualmente é mantida como um projeto da Apache Software Foundation, considerada um linguagem multiparadigma de propósito geral. Seu nome é uma abreviação de scalable language.
Possui sintaxe similar ao Java, com a qual compartilha a API e pode se integrar facilmente. Mas possui várias características inexistentes no Java, como tipagem estática e dinâmica; sintaxe nativa para arranjos, listas, arrays associativos e expressões regulares, além de closures e sobrecarga de operadores. Programas Groovy são compilados dinamicamente para bytecodes Java, podendo então ser executados na JVM e, com isto, integrados a outras aplicações Java. Um exemplo do tradicional programa Hello World com Groovy:

class HelloWorld {
    static void main(String[] args) {
        println "Hello, World"
    }
}

Aqui class define uma classe denominada HelloWorld, na qual existe a declaração de um método estático denominado main que recebe um array de tipo String como argumento e não tem valor de retorno (void). O código deste método usa println para efetuar a impressão de uma string.

Neste exemplo todos os elementos são idênticos ao Java. Mas o Groovy oferece muitas outras possibilidades.

Do ponto de vista de programação Groovy é uma linguagem opcionalmente (fracamente) tipada, dotada de orientada a objetos e programação funcional. Permite a compilação estática, metaprogramação em tempo de compilação e execução, inferência de tipos e capacidade de scripting.

Devido a proximidade sintática com Java, é de fácil aprendizado, mas suas capacidades diferenciadas a tornam muito flexível, customizável e escalável. Sua integração transparente com Java e a quantidade de bibliotecas, ferramentas e frameworks de seu ecossistema a tornam muito interessante.

A linguagem de programação Groovy é utilizada pelas equipes de desenvolvimento de grande companhias, como IBM, Cisco, Sony, Target, MTv, Nestle, Oracle, SAS e outras.

Para saber mais sobre o Groovy, veja os links no final deste post.

Para Saber Mais




quarta-feira, 28 de dezembro de 2016

Desenvolvedor Poliglota

Poliglota. Segundo o Grande Dicionário Houaiss, adjetivo e substantivo de dois gêneros, cujo principal significado é aquele que sabe ou fala muitas línguas. Este termo é geralmente aplicado para pessoas que falam mais de três línguas. Mas também pode ser aplicado aos desenvolvedores capazes de construir softwares usando várias linguagens de programação.



Neste post vamos discutir (e incentivar) o aprendizado de várias linguagens de programação partindo do argumento conhecido da necessidade de conhecer vários idiomas.

Bilíngue, Trilíngue, Poliglota, Hiperglota


O domínio de vários idiomas é considerando, pela maioria dos recrutadores, um diferencial, que potencializa as qualidades de qualquer candidato, como nesta matéria da revista Exame.

Mas o maior benefício de falar várias línguas é o maior desenvolvimento de empatia, da criatividade, sem contar que é benéfico para o cérebro em qualquer idade, como afirma a revista Deutsche Welle. Não é necessário ser um hiperglota.

Linguagens de Programação

As estimativas sobre o número de linguagens de programação existentes são bastantes imprecisas, mas são várias centenas. Um artigo na DZone lista 256 (duzentas e cinquenta e seis) linguagens de programação diferentes, começando por 4D (4th Dimension), ABAP, ABC, e terminando em yacc, Yorick e Z Shell.

E por que tantas linguagens? O grande número de linguagens de programação que surgiu é justificado por dois fatores principais: evolução e necessidade.

É bastante comum que, após o uso sistemático de uma linguagem de programação qualquer, que sejam observadas limitações em sua sintaxe e até mesmo defeitos em seu projeto. Isto estimula a criação de novas versões desta linguagem. Mas como existem questões comerciais, problemas com retrocompatibilidade e outras, novas versões podem não atender os anseios dos programadores, motivando a construção de novas linguagens derivadas. Isto é a evolução, vista como motor de criação de novidades.

Outra situação é que problemas específicos, difíceis de solucionar com as linguagens disponíveis (ou conhecidas), acabem sendo solucionados por linguagens de programação construídas para esta finalidade ou para este domínio. Aqui a necessidade é a mãe da invenção.

Assim, muitas linguagens de programação são semelhantes, compartilhando uma raiz comum que nada mais é que o modelo conceitual tomado para seus projetos. Partindo da linguagem C (que também foi uma evolução de outras linguagens), do paradigma imperativo, surgiram: C++, que acrescentou o paradigma da orientação a objetos; PHP, voltado para o desenvolvimento web; Java, com sua natureza multiplataforma; C#, uma releitura deste mesmo conjunto de linguagens para a plataforma Microsoft; entre outras.

O que é importante notar é que enquanto algumas linguagens de programação são semelhantes; outras são substancialmente diferentes. E tais diferenças enfatizam os propósitos de cada uma destas alternativas.

Porque ser um Desenvolvedor Poliglota


Exatamente pelo fato de cada linguagem ter sido criada com objetivos claros em mente, a solução de um problema específico pode ser bastante facilitada pela escolha da linguagem de programação mais adequada. Note que a palavra usada aqui é adequada, pois não existe opção correta ou incorreta, mas apenas uma escolha que pode conduzir a melhores resultados no processo de desenvolvimento.

Para que possamos escolher uma linguagem de adequada para a solução de um problema, dois fatores são determinantes: quais linguagens de programação são conhecidas; e quais são convenientes no cenário do problema.

Se não conhecemos linguagens diferentes, não poderemos escolher. E aquela que conhecemos pode não ser a melhor alternativa. Além disso, o cenário do problema é preponderante: se o cliente tem uma coleção de aplicações numa linguagem específica, como propor a construção de um novo software com outra plataforma, que só dificultara a reutilização de módulos e a integração?

Conhecer várias linguagens é, então, uma necessidade do desenvolvedor de software profissional, ou seja, é importante ser um programador poliglota!

Linguagens de Programação Populares


Existem vários rankings, mantidos cuidadosamente por revistas especializadas e outras organizações na internet, interessantes em medir a popularidade das linguagens de programação. Cada índice tem metodologia própria, diferente, mas que mostra uma visão distinta da questão central: qual a linguagem de programação com maior utilização?

Seguem as oito linguagens de programação mais populares segundo os dados colhidos de alguns dos rankings disponíveis para 2016: 
  • TIOBE:
    Java, C, C++, Python, VB.NET, C#, PHP, JavaScript
  • GitHub PYPL:
    Java, Python, PHP, C#, JavaScript, C++, C, Objective-C
  • RedMonk:
    JavaScript, Java, ,PHP, Python, C#, C++, Ruby, CSS
  • English4IT:
    Java, C, C++, PHP, VB.NET, Python, C#, JavaScript
  • IEEE Spectrum:
    C, Java, Python, C++, R, C#, PHP, JavaScript
  • NewRelic:
    Java, C#, C++, JavaScript, PHP, Python, Ruby, C

É fácil notar que algumas linguagens estão sempre nestes rankings, o que é ilustrado na figura que segue. A pontuação atribuída (8 para 1º, 7 para 2º, até 1 para 8º) permite agregar as listas diferentes numa última classificação (última coluna da figura). Lá vemos: Java, C++, Python, C, PHP, C#, JavaScript e VB.NET.

Rankings 2016 das Linguagens de Programação

Java não é surpresa no primeiro lugar. Mas as veteranas C++ e C continuam nas listas das populares. Python vem crescendo em termos de popularidade. PHP e JavaScript são linguagens para web (no criterioso ranking da StackOverflow, JavaScript figura como a linguagem de programação mais usada no mundo). Se outros rankings forem consultados, veremos outras diferenças, como na figura abaixo:



De fato, a colocação nestes rankings não importa quase nada. O que vale, mesmo, é que a linguagem aparece na listagem de popularidade. E aí, a pergunta que não quer calar: você é capaz de programar em várias destas linguagens?

Como é muito provável que seu próximo empregador deseje isto, que seus colegas trabalhem com isso, e que existam muitos projetos que fazem uso destas linguagens, que tal pensar em expandir seus conhecimentos desenvolvendo suas habilidade de programação numas quatro ou cinco destas linguagens?

Espero ter convencido você! Fica a dica!

Para saber mais