JRuby for the Win - GOTO...
Transcript of JRuby for the Win - GOTO...
Ola Binicomputational metalinguist
[email protected]://olabini.com/blog
JRuby for the Win
tisdag 6 december 11
Logistics and Demographics
tisdag 6 december 11
From Sweden
Language geek at ThoughtWorks, in Chicago
JRuby core developer
Creator of some languages (Ioke, Seph)
Author of Practical JRuby on Rails, coauthor of Using JRuby
Member of the JSR 292 EG
Your host
tisdag 6 december 11
Implementation of the Ruby language
Java 1.5+
1.8.7 compatible (1.9.3 about 95%)
Open Source
Created 2001
Embraces testing (~50,000 tests)
Current version: 1.6.5
EngineYard
ThoughtWorks
JRuby
tisdag 6 december 11
Threading
Unicode
Performance
Memory
Explicit extension API and OO internals
Libraries and legacy systems
Politics
Why JRuby?
tisdag 6 december 11
What is Ruby?Dynamic, strongly typed, pure object oriented language
Interpreted
Open Source
Default implementation in C (called MRI)
Current versions: 1.8.7 and 1.9.3
Created in 1993 by Yukihiro ‘Matz’ Matsumoto
“More powerful than Perl and more object oriented than Python”
“The principle of least surprise”
tisdag 6 december 11
Object orientationEverything is an object:
All objects are instances of classes:
Circle.new(4) # => instance of Circle"abc".length # => 32.to_s # => "2"
1.class # => Fixnum(9**99).class # => Bignum"abc".class # => String/a/.class # => Regexptrue.class # => TrueClassnil.class # => NilClassString.class # => ClassClass.class # => Class
tisdag 6 december 11
Ruby - BlocksAttach code to any invocation:
# two syntaxes - curly brackets and do-end[1, 2, 3].each { |n| puts "Number #{n}" }
[1, 2, 3].each do |n| puts "Number #{n}"end
def foo(num) yield numendfoo(1) { |e| puts "I got number #{e}" }
tisdag 6 december 11
Ruby - BlocksRemoves dangerous repetition:
No need for external iterator:
The Ruby version shifts the responsibility:
Iterator<String> iter = list.iterator();while(iter.hasNext()) { System.out.println(iter.next());}
list.each do |element| puts elementend
tisdag 6 december 11
Ruby - BlocksInternalizes transactions:
open(filename) do |file| # ... do something with the fileend
transaction do # some inserts # some selects # some updatesend
tisdag 6 december 11
Ruby - ModulesAs namespaces
module Foo class Bar; end def self.hello # a module method puts "Hello" endend
Foo::Bar.new # :: is used for nested levelsFoo::hello # invoking the hello methodFoo.hello # the same thing
tisdag 6 december 11
Ruby - ModulesAs mixins:
module ShapeStuff def diameter 2 * @radius endend
class Circle include ShapeStuffend
Circle.new(4).diameter #=> 8
tisdag 6 december 11
Ruby - EnumerableImplement each
Include Enumerable
You get:
all?, any?, collect, detect, each_with_index,
entries, find, find_all, grep, include?,
inject, map, max, member?, min, partition,
reject, select, sort, sort_by, to_a, zip
tisdag 6 december 11
Ruby - ComparableImplement <=>
Include Comparable
You get:<
<=
==
>
>=
between?
tisdag 6 december 11
Ruby - Conclusions
Language succinctness
Malleability of language
Agile way of working
Quick turnaround
Support for writing domain specific languages
Sources of innovation
Rails
Testing
Language power
tisdag 6 december 11
Most compatible alternative implementation
Native threads vs Green threads
No C extensions (well, some)
No continuations
No fork
ObjectSpace disabled by default
JRuby Differences
tisdag 6 december 11
Simple JRuby
tisdag 6 december 11
Java types == Ruby types
Call methods, construct instances
Static generation of classes
camelCase or snake_case
.getFoo(), setFoo(v) becomes .foo and .foo = v
Interfaces can be implemented
Classes can be inherited from
Implicit closure conversion
Extra added features to Rubyfy Java
Java integration
tisdag 6 december 11
Ant+Rake
tisdag 6 december 11
Maven+Gems
tisdag 6 december 11
Clojure STM
tisdag 6 december 11
Web
tisdag 6 december 11
Rails
tisdag 6 december 11
Sinatra
tisdag 6 december 11
Trinidad
tisdag 6 december 11
SwingSwing API == large and complex
Ruby magic simplifies most of the tricky bits
Java is a very verbose language
Ruby makes Swing fun (more fun at least)
No consistent cross-platform GUI library for Ruby
Swing works everywhere Java does
tisdag 6 december 11
Swing - the direct approachjava_import javax.swing.JFramejava_import javax.swing.JButton
frame = JFrame.new("Swing is easy now!")frame.set_size 300, 300frame.always_on_top = true
button = JButton.new("Press me!")button.add_action_listener do |evt| evt.source.text = "Don't press me again!" evt.source.enabled = falseend
frame.add(button)frame.show
tisdag 6 december 11
Swing - Cheri (builder)include Cheri::Swing
frame = swing.frame("Swing builders!") { |form| size 300, 300 box_layout form, :Y_AXIS content_pane { background :WHITE }
button("Event binding is nice") { |btn| on_click { btn.text = "You clicked me!" } }}
frame.visible = true
tisdag 6 december 11
Swing - Profligacyclass ProfligacyDemo java_import javax.swing.* include Profligacy
def initialize layout = "[<translate][*input][>result]" @ui = Swing::LEL.new(JFrame, layout) {|cmps, ints| cmps.translate = JButton.new("Translate") cmps.input = JTextField.new cmps.result = JLabel.new
translator = proc {|id, evt| original = @ui.input.text translation = MyTranslator.translate(original) @ui.result.text = translation }
ints.translate = {:action => translator} } endend
tisdag 6 december 11
Swing - MonkeyBars (tools)GUI editor friendly (e.g. NetBeans “Matisse”)
Simple Ruby MVC based API
Combines best of both worlds
tisdag 6 december 11
TestingRuby frameworks
Cucumber
JtestR
tisdag 6 december 11
The problem with mockingIt works fine while staying in Ruby-land
Setting expectations to be consumed by Java is problematic
tisdag 6 december 11
The interface
package org.test;
public interface Quux { String one(); String two();}
tisdag 6 december 11
The class
package org.test;
public class Foo implements Quux { public String one() { return "hello"; }
public String two() { return "goodbye"; }}
tisdag 6 december 11
The consumerpackage org.test;
public class Bar { public void doFoo(Foo foo) { System.out.println("Foo one: " + foo.one()); System.out.println("Foo two: " + foo.two()); }
public void doQuux(Quux q) { System.out.println("Quux one: " + q.one()); System.out.println("Quux two: " + q.two()); }}
tisdag 6 december 11
Mocking an interface
describe "Foo and Bar with RSpec mocking" do it "can mock out parts of interface methods with RSpec" do f = org.test.Quux.new b = org.test.Bar.new f.should_receive(:one).and_return "Canned answer 1 from RSpec" f.should_receive(:two).and_return "Canned answer 2 from RSpec"
b.do_quux f endend
tisdag 6 december 11
Mocking a class
describe "Foo and Bar with RSpec mocking" do it "can mock out parts of instance methods with RSpec" do f = org.test.Foo.new b = org.test.Bar.new f.should_receive(:one).and_return "Canned answer 1 from RSpec" f.should_receive(:two).and_return "Canned answer 2 from RSpec"
b.do_foo f endend
tisdag 6 december 11
The output
Quux one: Canned answer 1 from RSpecQuux two: Canned answer 2 from RSpec.Foo one: helloFoo two: goodbyeF
1)Spec::Mocks::MockExpectationError in 'Foo and Bar with RSpec mocking can mock out parts of instance methods with RSpec'org.test.Foo@7570b819 expected :one with (any args) once, but received it 0 times./rspec_mocking_spec.rb:18:
Finished in 0.321 seconds
2 examples, 1 failure
tisdag 6 december 11
The JtestR solution
tisdag 6 december 11
CucumberBehavior driven development
Plain text stories
Used to describe high level behavior
“Business-readable domain specific language”
Serves as documentation, automated tests and dev aid
Supports table-based tests
tisdag 6 december 11
Erlang+Ruby
tisdag 6 december 11
Google AppEngineJRuby runs on it
JRuby-rack supports it
Google gems
Startup time
Merb, Ramaze and Sinatra easy options
Rails works
tisdag 6 december 11
Mobile
tisdag 6 december 11
tisdag 6 december 11
Questions?
OLA BINI
http://olabini.com
@olabini
tisdag 6 december 11