Real-world polyglot programming on the JVM - Ben Summers (ONEIS)

65
Ben Summers | ONEIS Real-world polyglot programming on the JVM

Transcript of Real-world polyglot programming on the JVM - Ben Summers (ONEIS)

Ben Summers | ONEIS

Real-world polyglot programmingon the JVM

Real-world polyglot programming on the JVMBen SummersTechnical director, ONEIS

@bensummers

This is nothing new.

Actual language usage

• Primary programming language

• Con!guration + build system

• Presentation

• Miscellaneous scripting

Polyglot programming is a formalisation.

A polyglot application

Ruby 40%

Java 20%

JavaScript 20%

HTML, CSS, etc 18%

C++ 1%

Python 1%

Table of contents

• How I became a polyglot programmer

• The case for polyglot programming

• Languages, JVM and polyglot apps

• Impedance mismatch

• Glue code

• Language boundaries

• Getting started

ONEIS architecture

Inte

rnet

Worker JVM

Worker JVM

Worker JVM

Worker JVM

JVM

JavaSandboxed JavaScript

pluginsJava

Java

Scri

pt

Ruby

Jett

y

Languages are not equal

• Expressiveness• Performance• Readability• Style

• Static• Dynamic• Functional• WTF

The case for polyglot

• “Real artists ship”

• You’re doing it already

• Formalisation and extension

Ola Bini’s pyramid

http://olabini.com/blog/2008/06/fractal-programming/

Ola Bini’s pyramid

JVM

Java

Sand

boxe

d Ja

vaSc

ript

plug

ins

JavaJava

Script

Ruby

Why the JVM?

• Great runtime

• Portability

• Common underlying VM for lots of languages

• Interoperability

• Java library for everything

Side note:Don’t forget the CLR

• Good stu" from Microsoft

• Great runtime

• DLR

• APIs

• Di"erent culture

• Trap?

Side note:Don’t forget IPC

• Go old school

• Separate processes

• Common protocol over sockets and pipes

• Thrift, Google Protocol Bu"ers, Avro

• or text over HTTP: XML, JSON, etc

What’s the best language?

• No such thing as the “best” language

• Use the best language for solvingyour problems

• Polyglot is about avoiding compromises

Language choice

• Don’t use two closely related languages

• Don’t forget the standard library

• And some have special featureseg. concurrency libraries

Pick one from each column

Static Dynamic Scripting / DSLs

Java Ruby JavaScript

Scala Groovy Ruby

Clojure Groovy

Jython

Aims

• Work in harmony

• Choose most appropriate language for each task

• Choose carefully as choices are hard to undo

Memory usage

• Multiple runtimes

• Multiple standard libraries

• Cloud is memory constrained

Impedance mismatch

• Type systems

• Your languages won’t agree on the simplest things:

• Strings, Numbers, Dates, Arrays, null

Strings

• Java: UTF-16 (ish) strings• JavaScript: implementation dependent

• Browsers: UCS-16 usually• JVM: Whatever Java does + optimisations

• Ruby• bytes (1.8), or bytes+encoding (1.9)

• JVM originated languages: Java Strings

Numbers

• Java: primitives, java.lang.Number, etc

• JavaScript: doubles only.Plus odd Number object.

• Ruby:• ints (always Fixnum) with silent promotion to

Bignum• doubles, Rational

null

• Java: null

• Ruby: nil

• JVM languages: null

• JavaScript: null and undefined

Javascript’snull and undefined

var o = {item: null};

if(o.item === undefined) { console.log("0");}if(o.noSuchItem === undefined) { console.log("1");} OUTPUT

1

Javascript’snull and undefined

var o = {item: null};

if(o.item === undefined) { console.log("0");}if(o.noSuchItem === undefined) { console.log("1");}

var undefined = 42;if(o.noSuchItem === undefined) { console.log("2");}

OUTPUT

1

JavaScript Top Tip

Use JSHint in your tests

(but not JSLint)

Strings, numbers, dates...

• Impedance mismatch means you haveto think about the boundaries

• Use Groovy?

Glue code

• Work around impedance mismatch

• Java: The new assembly language

• Rule enforcement & security

• Cheat until your pro!ler says it’s slow

• Serialise/deserialise to common format,eg JSON

undefined is not nullJAVA

public class Host extends ScriptableObject {

public String jsFunction_f(String x) { System.out.println( "x = " + x ); }

}

undefined is not nullJAVA

public class Host extends ScriptableObject {

public String jsFunction_f(String x) { System.out.println( "x = " + x ); }

}

JAVASCRIPT

var h = new Host();

h.f("Hello");h.f(2);h.f(null);

h.f(undefined);

undefined is not nullJAVA

public class Host extends ScriptableObject {

public String jsFunction_f(String x) { System.out.println( "x = " + x ); }

}

JAVASCRIPT

var h = new Host();

h.f("Hello");h.f(2);h.f(null);

h.f(undefined);

VALUES OF X

"Hello""2"null

"undefined"

null and undefined are 0JAVA

public void jsFunction_each(Integer desc, boolean hasDesc,Integer qual, boolean hasQual)

JAVASCRIPT

Store.prototype.each = function(desc, qual) { return this.$store.each(

desc, (desc !== null && desc !== undefined),qual, (qual !== null && qual !== undefined)

); };

Conversions public static Date tryConvertJsDate(Object jsObject) { if(jsObject == null) { return null;} if(nativeDateClass == null) { try { nativeDateClass = Class.forName("org.mozilla.javascript.NativeDate"); } catch(ClassNotFoundException e) { /* ... */ } } if(nativeDateClass.isInstance(jsObject)) { Object d = Context.jsToJava(jsObject, Date.class); if(d != null && d instanceof Date) { return (Date)d; } } return null; }

Calling Java is easy

• Don’t let JavaScript put you o"

• Calling Java APIs from any other language is easy

Create a JPEG with Javaimport java.awt.image.BufferedImage;import java.awt.Graphics2D;import javax.imageio.ImageIO;import java.io.File;

public class MakeImage{ public BufferedImage makeImage(int w, int h) { BufferedImage image = new BufferedImage(w, h, TYPE_INT_RGB); Graphics2D graphics = image.createGraphics(); graphics.drawString("Hello world", w/2, h/2); graphics.dispose(); return image; } public static void main(String args[]) throws Exception { BufferedImage img = (new MakeImage()).makeImage(200, 400); ImageIO.write(img, "jpeg", new File("test.jpeg")); }}

Create a JPEG with JRubyrequire 'java'

class MakeImage java_import java.awt.image.BufferedImage; java_import java.awt.Graphics2D; def make_image(w, h) image = BufferedImage.new(w, h, BufferedImage::TYPE_INT_RGB) graphics = image.create_graphics graphics.draw_string("Hello world", w/2, h/2) graphics.dispose image endend

java_import javax.imageio.ImageIO;java_import java.io.File;

img = MakeImage.new.make_image(200, 400)ImageIO.write(img, "jpeg", File.new("test.jpeg"))

The artwork

Divided by acommon language

•JRuby: Transparent bridging

•JavaScript: Host objects + bridging

•Groovy: Java is subset of Groovy

•Scala: Write Java with Scala syntax

JSR-223

• Java Scripting API

• Common API for scripting languages on the JVM

• Scripting “engines” available for many languages, variable quality

• Su"ers from impedance mismatch itself

• Functions may return unexpected types

Ola Bini’s pyramid

http://olabini.com/blog/2008/06/fractal-programming/

Boundaries

• Which language for each module?

• Clear boundaries, not a free-for-all.

• Well de!ned (and documented) interfaces

Java to Ruby

public interface Framework{ void startApplication(); void startBackgroundTasks(); void stopApplication();

Response handleFromJava( HttpServletRequest request, Application app, byte[] body, boolean isRequestSSL);}

Ruby implementation

class Framework

def start_application # ... end

def handle_from_java( servlet_request, application, body, is_ssl) # magic goes here end

end

JavaScript to Ruby(via Java)public interface AppWorkUnit{ public int id();

public Integer actionableById(); public void setActionableById(Integer id); public String jsGetDataRaw(); public void jsSetDataRaw(String data);

public boolean save(); public void destroy();}

Security

• Trust models

• Sandboxing interpretersvs sandboxed interpreters

Hiring polyglots

Hiring polyglotsdevelopers

Hiring polyglots

• Find people who can write code,not people who can write Java.

• Test to see if programming is instinctive, not syntax and trivia.

• Look for people who continuously learn,not those who have learnt.

developers

Finding a polyglot job

• Smaller companies, or smaller teams within large companies

• Early stage projects, not maintenance or enhancements

• Talk to really good recruiters

• Networking!

The Enterprise

• It’s just Java the JVM

• Implement a servlet

• Use tools like Warbler

• TorqueBox

• New job outside the Enterprise

Starting points

• Use JRuby to try out an API

• Use Ruby testing libraries to test your Java

• Use Groovy to a make business rules DSL

• Write a layer of a small project in a dynamic language

Polyglot programming:

Not new,but very e!ective.

Questions?

Ben SummersTechnical director, ONEIS

@bensummers http://bens.me.uk

oneis.co.uk /jobs