The Good, The Bad & The Ugly (Clojure & JRuby) Allen - - PowerPoint PPT Presentation

the good the bad the ugly
SMART_READER_LITE
LIVE PREVIEW

The Good, The Bad & The Ugly (Clojure & JRuby) Allen - - PowerPoint PPT Presentation

The Good, The Bad & The Ugly (Clojure & JRuby) Allen Rohner @arohner @circleci Clojure/West 2012 Monday, March 19, 12 Who Am I Using Clojure in production since 2008 Author of Scriptjure, a DSL for writing javascript, two


slide-1
SLIDE 1

The Good, The Bad & The Ugly

(Clojure & JRuby)

Allen Rohner @arohner @circleci Clojure/West 2012

Monday, March 19, 12

slide-2
SLIDE 2

Who Am I

  • Using Clojure in production since 2008
  • Author of Scriptjure, a DSL for writing

javascript, two years before ClojureScript

  • Commits in Clojure core, contrib, ring,

compojure, noir, lein, swank-clojure, pallet...

Monday, March 19, 12

slide-3
SLIDE 3

Circle

  • Founder
  • CircleCI.com
  • Easy Continuous Integration for web apps

Monday, March 19, 12

slide-4
SLIDE 4

When this talk was accepted....

Monday, March 19, 12

slide-5
SLIDE 5

TL;DR

Monday, March 19, 12

slide-6
SLIDE 6

It Is NOT about:

  • “Ruby sucks”
  • “JRuby sucks”

Monday, March 19, 12

slide-7
SLIDE 7

It Is NOT about:

  • “Ruby sucks”
  • “JRuby sucks”

Monday, March 19, 12

slide-8
SLIDE 8

It IS about

Ruby != Clojure

Monday, March 19, 12

slide-9
SLIDE 9

My Biases

  • 2006-2009: Rails 1.x
  • 2008-2012: Clojure
  • Expert in Clojure, Intermediate in Ruby

Monday, March 19, 12

slide-10
SLIDE 10

My History

Monday, March 19, 12

slide-11
SLIDE 11

How did we get into this mess?

Monday, March 19, 12

slide-12
SLIDE 12

Mongo Clojure JRuby Trinidad

Architecture

Monday, March 19, 12

slide-13
SLIDE 13

The Good

Monday, March 19, 12

slide-14
SLIDE 14

Calling just works

(require ‘foo.bar) (foo.bar/baz 3) foo = JRClj.new(“foo.bar”) foo.baz(3) (-> (r/module “Foo”) (r/class “Bar”) (r/send :baz 3)) Foo::Bar.baz(3)

Monday, March 19, 12

slide-15
SLIDE 15

Fork Me

  • https://github.com/kyleburton/jrclj
  • https://github.com/circleci/cljr

Monday, March 19, 12

slide-16
SLIDE 16

The Clojure REPL makes Ruby better

Monday, March 19, 12

slide-17
SLIDE 17

Individual tests

  • (r/rspec “specs/controllers/foo.rb”)
  • (r/rspec “-e” “that one test”)*

Monday, March 19, 12

slide-18
SLIDE 18

Fine-grained reloading

  • (r/eval “load ./foo.rb”)

Monday, March 19, 12

slide-19
SLIDE 19

Clojure Concurrency from JRuby

  • Worker.send_email()
  • concurrency with no queues

Monday, March 19, 12

slide-20
SLIDE 20

Runtimes!

  • (r/new-runtime)
  • (def server (r/rails-server))

Monday, March 19, 12

slide-21
SLIDE 21

JRuby Runtimes

The JVM Ruby 1 Ruby 2 Ruby 3

Monday, March 19, 12

slide-22
SLIDE 22

Combining WARs

  • Warbler
  • lein war
  • Deploy both on tomcat/jetty
  • (Not tested)

Monday, March 19, 12

slide-23
SLIDE 23

JRuby

  • Impressive technology
  • awesome maintainers

Monday, March 19, 12

slide-24
SLIDE 24

The Bad

Monday, March 19, 12

slide-25
SLIDE 25

But...

  • Stuck on 1.6.5, couldn’t upgrade or

downgrade due to different bugs

Monday, March 19, 12

slide-26
SLIDE 26

1.9

  • 1.9 support not finished
  • Encoding
  • SSL

Monday, March 19, 12

slide-27
SLIDE 27

Complexity

kLOC Java Self- hosted Clojure (1.3.0) JRuby (1.6.5)

51 28 291 600

Monday, March 19, 12

slide-28
SLIDE 28

Gems

  • Often not tested against JRuby
  • ExecJS
  • Some just can’t work in JRuby
  • FFI

Monday, March 19, 12

slide-29
SLIDE 29

Slow Startup

  • Ruby likes to restart, early & often
  • helpers, rack middleware

Monday, March 19, 12

slide-30
SLIDE 30

Slow Startup

  • 1:03 macbook pro
  • 1:45 macbook air
  • 3:00 ec2 m1.small

Monday, March 19, 12

slide-31
SLIDE 31

Slow Startup Matters

  • need to RSpec all the time
  • Spork & Guard didn’t work
  • rake tasks (generate, etc)
  • rake assets:precompile (8m)

Monday, March 19, 12

slide-32
SLIDE 32

Dilemma:

  • slow restart
  • strangeness caused by Ruby code not

expecting to reload

  • Restart often, just in case

Monday, March 19, 12

slide-33
SLIDE 33

Setup

  • Paul lost 2 days

Monday, March 19, 12

slide-34
SLIDE 34

CRuby in Dev, JRuby in production

Doesn’t work!

Monday, March 19, 12

slide-35
SLIDE 35

Different Views

  • Clojure likes one big process, lots of

threads

  • Ruby prefers lots of small processes
  • Multithreaded JRubyOnRails: works in

theory, not in practice. Weird classloading bugs, unsupported gems.

Monday, March 19, 12

slide-36
SLIDE 36

Duplication

  • DB connections
  • DB models
  • Test data

Monday, March 19, 12

slide-37
SLIDE 37

Classpath

  • Different depending on whether you ran

‘rails console’ or ‘lein repl’

  • => different behavior
  • Can be fixed, but it’s one more headache
  • If you didn’t understand that, yes

Monday, March 19, 12

slide-38
SLIDE 38

Rails Env

  • DB connection
  • Email policy
  • Class reloading
  • error reporting
  • Airbrake

Monday, March 19, 12

slide-39
SLIDE 39

Clojure Environment

  • Clojure leaves that to you
  • * (yes there’s Noir’s env, but it’s minor

compared to what Rails does)

Monday, March 19, 12

slide-40
SLIDE 40

Testing

  • Rails loves to mock
  • Clojure prefers pure fns

Monday, March 19, 12

slide-41
SLIDE 41

Rails Testing Env

  • FactoryGirl returning fake objects
  • DB Cleared between tests
  • But who told Clojure?
  • Are you both talking to the same DB?

Monday, March 19, 12

slide-42
SLIDE 42

The Ugly

Monday, March 19, 12

slide-43
SLIDE 43

Naming

  • project.git-url =>

project[“git-url”]

  • (mongo/update! :project

{:git_url git-url}))

Monday, March 19, 12

slide-44
SLIDE 44

Symbols vs. Keywords

  • Wrappers
  • Clojure :foo != Ruby :foo

Monday, March 19, 12

slide-45
SLIDE 45
  • Rails code, calls Clojure
  • Clojure calls back into Rails
  • But might not be the same runtime
  • might not have the same classpath
  • might not be talking to the same DB
  • might not be the same ruby version

Monday, March 19, 12

slide-46
SLIDE 46

Monday, March 19, 12

slide-47
SLIDE 47

Lessons Learned

Monday, March 19, 12

slide-48
SLIDE 48

Complexity is Multiplicative

Monday, March 19, 12

slide-49
SLIDE 49

Rails Magic

The closer you are to the ‘standard’ environment, the better things work

Monday, March 19, 12

slide-50
SLIDE 50
  • Rails 3 (ok)
  • using Mongo/Mongoid (not bad)
  • and JRuby (hrm...)
  • and Clojure (OMGWTF)

Monday, March 19, 12

slide-51
SLIDE 51

Avoid Mixing Paradigms

(In the same process)

Monday, March 19, 12

slide-52
SLIDE 52

Don’t duplicate Models

Monday, March 19, 12

slide-53
SLIDE 53

Don’t overestimate the value of code reuse

Monday, March 19, 12

slide-54
SLIDE 54

Understanding Devise + OmniAuth

>

Writing Oauth2 login in Clojure

Monday, March 19, 12

slide-55
SLIDE 55

Yes, you will write more code

But you’ll understand it!

Monday, March 19, 12

slide-56
SLIDE 56

Yes, you will read Clojure source

But it’s simpler!

Monday, March 19, 12

slide-57
SLIDE 57

The Future

  • Clojure REST API
  • Fat Javascript Client
  • Knockout JS
  • Sammy JS
  • HamlCoffee
  • Clojurescript?

Monday, March 19, 12

slide-58
SLIDE 58
  • https://github.com/circleci/mongofinil
  • https://github.com/edgecase/dieter

Monday, March 19, 12

slide-59
SLIDE 59

Questions?

@circleci circleci.com

Monday, March 19, 12