May 2008 Archives

The agony of Java unit testing

Java unit testing *sucks*!!!

There, I said it.

Come on, it does. I know, 8 years ago, JUnit was the bees knees. But let’s face it: when you’re working on a project, you’re behind schedule for whatever reason, and you have a deadline looming, where’s the first place that you cut corners?

Unit tests. Always.

Why?

  1. Lack of perceived value of testing (in other words: I see the happy path works so what’s your big problem?)
  2. No one is going to ever touch this code again after this release
  3. Java is just difficult to test

Let’s talk about these….

Why You Don’t Test (a.k.a., why you’re brain damaged)

Lack of perceived value of testing

If that’s the way you feel, then you shouldn’t ever call yourself an engineer. You’re just a hack. Still, I’ll assume that there’s hope for you yet because you’re reading this article in the first place.

The “Somebody Else’s Problem” Field

You’re leaving the project soon. Or you honestly believe that your shit doesn’t stink. Or you’re just going to leave it for the next guy. It’s somebody else’s problem. There’s one response to this: in this business, frequently, that somebody is you. If you can’t maintain your own code then you’ve just shot yourself in the foot. Congratulations.

But, now, to the heart of the matter.

Java is just difficult to test Now I know that I’m not the first one to say this. However, in my opinion, what makes difficult to test are the idioms and practices that developers have acquired over the 13 years that Java has been around. Many of these idioms and practices fly almost completely counter to testing – for in order to be able to test effectively, we must be able to isolate the unit under test. How do we do this in Java? Dependency injection. Come on, you knew I was going to say that, right?

Evil/Brain-Damaged/Detrimental Idioms/Practices

  • Enterprise Java Beans. Come on, already. Private variables mutated by the container based on an XML deployment descriptor (so we’re coding in XML now )? Are you testing your deployment descriptor? You probably should be. Have I ever done it. Not yet….
  • Spring. Yes, POJOs are good. Actually, I’ll amend that. POJOs are fucking awesome – especially when every member variable is exposed via a getter and a setter. Unfortunately, you’re now effectively writing code in XML. So are you going to write tests just to exercise your XML? If you aren’t, you should be. That XML creates and links objects together. As soon as you start coupling things dynamically, you have a relationship that could break and therefore warrants testing.
  • private/protected member variables. We need these, don’t we? Sometimes, yes, actually, we do. However, if they aren’t wrapped (see Spring above) then Houston we have a problem.
  • static final used for non-primtive/String constants. This is simply everywhere in the Java universe: developers statically initializing constants with Objects. This is awful. Why, you ask? Because how the hell are you ever going to be able to inject a value for that static final Object? It’s assigned at classloading time. So, basically, grab your ankles and BOHICA.

Unfortunately…

  • Some of these hurtful practices are necessary
    • Encapsulation
    • Spring XML (if you’re stuck coding Java in the first place)
  • Sometimes we’re working in legacy code
    • Limited ability to change existing code; stuck with bad practices
    • Existing unit tests are sometimes lacking

How do we get better?

Come back tomorrow. We’ll talk. Seriously.

Posted by evan on May 25, 2008

Avanced Ruby Studio, Day 3

Notes after the jump.

Aside: They brew insanely strong coffee at the Sheraton…

Domain Specific Language

  • Discussions comparing DSLs to expressive DSLs
    • Me: I don’t believe that there’s a difference but Ruby brings us closer to English in our DSLs
    • DT: Which causes a whole new level of confusion because while it reads easily it’s hard to write
    • DSLs, to him, represent a domain-specific form of abstraction
  • Rake
    • CF: Dependency-oriented DSL
    • Me: Now that is a nifty abstraction to capture the purpose of Rake
  • Dhaka
  • JDWP DSL CF: cites an example of a Java Debugger Wire Protocol implementation that Rich Kilmer wrote by copying the documentation into a Ruby file and simply reformatting the docs into valid Ruby code.

    • Readable to SUN developers
    • DT: DSL is retargetable – specifies intent, not implementation
  • Implementation tricks

    • method_missing
  • CF: Most DSLs are block based

  • To instance_eval or not to instance_eval
    • instance_eval is constraining because it redefines self
    • DT: The DSL is a promise (Me: a contract? interface…) that should be consistent
  • Consider context: who will use the DSL?

This is a good discussion.

  • DSL anti-patterns
    • False familiarity
    • method_missing and respond_to> together
    • If you support one then you should support the other
    • Cluttering namespaces (flexibility)

break & exercise (write a morse code generator for a given pattern

  class MorseEncoder
    CHARS = {
      :a => "._",
      :b => "_...",
      :c => "_._.",
      :d => "_..",
      :e => "."
    }

    def initialize
      @msg = []
    end

    def encode(&block)
      instance_eval(&block).reverse.join(" ")
    end

    def method_missing(name, *args)
      @msg << CHARS[name]
    end
  end

  morse = MorseEncoder.new
  puts morse.encode { b e a d }

Extremely pleased how much more comfortable I’ve become with my use of blocks and closures over the period of this class. This course has provided some good brain strengthening exercises.

Exotic Control Flow

  • DT: “I don’t know what BASIC is. The dribbling old fool of programming langauages”
    • Likens exception handling to “goto on steroids”
    • Implies that goto is not necessarily harmful
    • It’s up to the individual programmer
  • DT: “Experts know when to break the rules”
  • LOL: Don’t not use positive logic
  • throw and catch

    • This is not Java’s throw/catch – almost the opposite (that’s raise and rescue)
    • catch takes a label and executes a block
    • throw takes a label and optional arguments
    • Causes Ruby to unwind the call stack to the first catch that matches
      • The optional parameter is the return value to provide from the catch
    • Real use: open-uri
    • Me: This would elminate so much code from my current project in the office – if they hadn’t already writen it in Java…
  • Continuations

    • callcc
    • requires a block with one parameter (the conitnuation)
    • Executes the block
    • When a continuation is called, execution resumes immediately after the continuation’s block
    • All control structures can be implemented via continuations

Lunch and Exercise

# Write the methods start_loop and end_loop so that the following does what you'd expect:

i = 0

again = start_loop

puts i
i += 1

end_loop(again) unless i > 5

… which is solved by:

def start_loop
  callcc { |cont| cont }
end

def end_loop(continuation)
  continuation.call(continuation)
end

… which was less code than I expected. Admittedly, I didn’t know at the time that Continuation#call’s parameter is returned by callcc but it made sense so I tried it. Principle of least surprise FTW!

I won a gold star for niftiest continuation implementatio for this exercise. Yay, me!

Debugging & Profiling

  • ruby -d
    • Sets $DEBUG
    • caller: call stack, file names, and line numbers (Me: handy stuff!!)
  • ruby-debug gem
    • Insert a debugger call into Ruby code to dump into the debugger from the runtime
    • Also requires requiring the gem (duh)
    • Inside the debugger, can launch into irb in the current context
  • gdb

    • Attach to the running Ruby VM
    • gdb gdb_path_to_Ruby_bin Ruby_VM_PID
  • Ruby ‘profile’ library

    • Me: Woops, didn’t know about this library!
    • ruby -r profile my_program_name
    • Profiling specific parts of code
    • Profiler__::start_profile
    • Profiler__::stop_profile
    • Profiler__::print_profile
  • Question about memory profiling
    • No known available tools
    • ObjectSpace – roll your own
    • DT: modified new to add a timestamp to every Object to add a timestamp to allow searching for super-stale objects
  • Exploring how objects are interacted with
    • Slide 329
    • Undef all of the methods on an object and then see what errors occur

JRuby

  • Java garbage collection
  • Hotspot
  • Java threads (native)
  • rake war:standalone:create
  • IronRuby promises Ruby in the browser

Distributed Programming

  • DRb (Me: cake)
  • Rinda (Me: been there done that)
    • UDP broadcasts
  • Custom Protocol Implementation
    • Transport mechanism
    • Encoding mechanism
  • GServer
  • NetSSH
  • Slide 396 for Multicast in Ruby
    • IPs 224.0.0.0 to 239.255.255.255 are multicast reserved addresses
  • Slide 398 shows a simple proc running on a WEBRick server: 7 lines of code. ;)
  • Rack
    • Sits on top of any web server and provides a WEBRick-like API
  • open-uri
    • rest-open-uri – patches open-uri to support other HTTP methods

Posted by evan on May 09, 2008

Advanced Ruby Studio, Day 2

This morning session rocked my world. The afternoon session was better than yesterday but, for me, dragged a lot toward the end of the day.

I suspect that my less enthusiastic response to this class vice the Rails class has more to do with my significantly greater experience with Ruby the language than Rails the framework.

That said, I am still finding this class worthwhile to fill in the gaps in my understanding of Ruby to date.

Notes after the jump.

Ruby Object Model

NOTE: Parts of this portion of the class were presented to NoVaRUG in April by DT.

  • self is the only way to access member variables.
  • Changing self is key to Ruby
    • On a method call
    • self gets set to the receiver then the method is looked up
    • When defining a class
    • This is universal to all implementations of Ruby
  • Methods are stored on classes, data in objects. (Me: Nothing new there but important to note for below)
  • When defining a method on an instance of a class, Ruby creates an anonymous class (aka “singleton class”, “eigenclass”, “virtual class”, and “metaclass”) to contain the new method and has it inherit from the original parent class.
  • If reader == Java.WEENIE
    • Ruby classes are executable code
    • Ruby classes are Ruby Objects
    • Me: Imagining your brain ‘sploding. :D

Classes are executable code

puts "foo"

class Stuff
  puts "bar"
end

puts "blech"

… outputs:

  foo
  bar
  blech

Classes are objects

puts "foo"

class Stuff
  @v = 123
  def self.get_v
    @v
  end
end

puts Stuff.get_v
puts "bar"

… outputs:

  foo
  123
  bar

Matz says “don’t use @@ vars” and DT agrees.

  • Instance variables looked up in self
  • Methods looked up in self’s class

  • Method definition is different than method lookup

    • def foo is defined in the current class
    • def obj.foo is defined in obj’s singleton class

And the lightbulb goes off over my head

So this idiom that I’ve seen Giles use in his code somewhere doesn’t hurt my brain anymore:

  something = "42"
  class << something
    def say_something
      puts self
    end
  end
  something.say_something

… will output 42. class << something changes the current Class to the singleton class of something.

Although the below example behaves the same way, it is less explicit in that it obscures what’s happening under the covers. The below example seems to define a method on something; it’s actually defining the method on something’s singleton class.

  something = "42"
  def something.say_something
    puts self
  end
  something.say_something

Intrestingly, clone copies a singleton class as well but dup doesn’t.

Cute but not hugely relevant:

  class Person < Struct.new(:name, :state)
    # do stuff
  end

… is legal – and a nifty way to save lines of code if you want to add methods to a Struct (or other expression that evals to a Class).

  • include

    • Points this object’s singleton class to the referred to module
    • Does not copy methods from a module into a class
    • So modules are actually shared
  • extend

    • includes into this object’s class’ singleton class.

Metaprogramming

  • instance_eval
    • Changes self to the receiver of instance_eval
    • Me: Cheeky way to call private methods on objects
  • class_eval

    • Changes self to the receiver (a class) of class_eval
    • WTF is the current class? Still not clear on this – and DT was getting confused too! Oy vey!
  • “Top level” methods are defined on a singleton instance of Object

    • to_s is redefined here as well to return “main”
    • Slide 167 explains the toplevel environment (although you’re not really in instance_eval)
  • Me: I actually found the Object Model discussion far more intense than playing with define_method – probably because I’m already pretty comfortable with meta/reflective programming from Java and having already used a fair bit of define_method and eval.

  • DT: Use of method_missing involves two method calls so it’s a bit slower.

  • initialize_copy
    • Define this to override the behavior of dup – to possibly provide a deep copy
  • const_missing
    • Rails uses this to require files at runtime
    • const_getCan only call on one class at a time.
  class Foo
    class Bar
      class Blech
      end
    end
  end

  c = self.class.const_get "Foo"
  c = c.const_get "Bar"
  c = c.const_get "Blech"

  puts c
  # >> Foo::Bar::Blech

The below example was in the Rails class but makes even more sense today thanks to our discussions of include and extend:

Hooks

  • included

Mixin a Module containing both instance methods and “class” methods

module Foo
  def self.included(klass)
    klass.extend ClassMethods
  end

  def foo
    puts "foo"
  end

  module ClassMethods
    def class_foo
      puts "class foo"
    end
  end
end

class Person
  include Foo
end

Person.new.foo
Person.class_foo
  • inherited

  • Explain why garbage collection in MRI ‘sucks’ (Me: Certain individuals I know, who shall remain nameless, *cough*Toby DiPasquale*cough* have commented on this)

    • DT
    • Typically not a problem
    • However, if you have a LOT of loose objects (100s of thousands… try creating a String by concat’ing lots of Strings together).
      • Had a program that did this. Instead of concat’ing several times, accumulated the Strings in an Array and created it at the end
      • Performance went from two minutes to one second
    • JRuby uses the JVM garbage collector (GOOD)
    • Rubinius is better
    • 1.9 is better

… make it fast

  • CF rant about maintainability. No argument here.
  • benchmark.rb
    • Benchmark#bmbm (great name) does a rehersal run first and then a real run
  • For socket code
    • Socket::do_not_reverse_lookup = true
  • YAML
    • YAML#dump == slow
  • update_page in Rails

    • Calling in more than 15 times for a single page will cause a noticeable slowdown
  • ObjectSpace

    • Iterate through objects and ue Marshal#dump to determine amount of memory taken up by a certain class
  • To speed things up

    • C (and other) extensions
    • DL (dynamic linking) – link a library at runtime and use it directly
    • Requires mapping C function calls (and structs if used) to Ruby objects
      • Slide 115-6
  • Some lecture on good ol’ fashioned CS: O(n), O(n^2), and avoiding stupid loops

    • Wow, DT cites Sedgewick (Me: I learned wth Corman)
  • Now CF is talking about eager loading and caching as a way of optimizing runtime.
  • This afternoon just seems like… common sense programming/software engineering/computer science that every student in here ought to have.
  • “Memoization”
    • Caching values of expensive operations for later re-use
    • There are some gems/libraries out there to keep code cleaner
    • Basically just the use of the ||= idiom

Exercise Playing with memoization Fibonacci to run super-fast

Library Organization

  • Discussion of setup.rb and RubyGems
  • Having written a few gems and installed who knows how many, this section of the class is mind-numbing
    • Dr. Nic’s NewGem gem essentially obviates much of this section of the class. Just use NewGem, write your own little gem, play with it, and that will teach you plenty.

Posted by evan on May 09, 2008

Advanced Ruby Studio, Day One

Notes after the jump (as I write them) Review of the day: Morning session was excellent and intense. This afternoon has been theory. As of 3:45pm, it hasn't felt so "advanced". Blocks, Procs, and Closures --------------------------- * "Brace" form of block __always__ associates it self with the nearest method call. Not true of do ... end * break * break takes an optional parameter -- which becomes the return value of the block. * So it's behaving like a typical Proc return value except we're jumping the call stack * Freaky that we're all getting so bent out of shape on like the first slide or two of the real content. ;-) * next * Just return from the block early * Similarly, has an optional parameter that is the return value of the Proc * redo * Me: I've never used it * DT: Used it maybe 3 times in 8 yars of Ruby * Ooooh, I have softcopy of all of the code samples from the class (but almost certainly can't redistribute, sorry) * retry * Ok, didn't know this one... * Like redo except that it __reevaluates the CALL to the proc__ so the below example could be implemented with retry
  i = 0
  loop_until i == 3 do
    i += 1
  end
... because retry will reevaluate the loop\_write call which __reevaluates__ the i < 3 call. __And this is getting removed from Ruby 1.9__ (but will still be available for exception handling) Hrmph. Blocks aren't Procs in MRI unless you pass a & on the param to the method. DT: There are two kinds of Proc objects differentiated by a hidden flag * Using lambda, behaves like an anonymous method * Using Proc.new, get an object that behaves like an inline block * proc changed from an alias to lambda to * Me: Glad that I've always just used lambda * Bindings * Ruby stack frames point to Binding objects * Me: Used in the common Ruby implementations under the cover? * DT: They must * Closures * Whenever a block is creating, it automatically gets a Binding to the current stackframe * Me: So that's how we get closures. Cool. Follows like 1 + 2 = 3 * Blocks need the local Binding in order to be able to implement loop constructs * CF: Multiple calls to binding return different wrappers to the stack frame's Binding -- so they can't be compared at runtime. * Methods are not closures We were given a fun little exercise to write a counter method using a Proc. Below is my Java-ish solution initializing a counter to nil.
def counter(start = 0, increment = 1)
  count = nil
  lambda {
    count += increment if count
    count ||= start
  }
end

c = counter(10, 2)
p c.call
p c.call
p c.call
My neighbor today, Jimmy Baker, tried something that I liked. He passed a added a third parameter on the counter method and used that instead of defining a local variable in the method impl. I thought this was cute because the arguments to the method are also part of the Binding and so could save another line of code. :D Ruby Internals -------------- * Ruby C extensions are running in the same runtime * So ParseTree, for instance, can walk the parse tree * Me: I've read about ParseTree (and Ruby2Ruby). Cool stuff. * Now we're poking a little through Ruby 1.8.6's parse.y (written in yacc) looking at the definition of stmt and compstmt. Uf da! * eval.c * eval_node is how Ruby walks it's internal parsed tree of instructions Design in a Dynamic Language ---------------------------- * DT: ranting about OO programming really being about classes and not objects. * Experienced Ruby programmers prefer composition and rarely use inheritance * Me: At least I'm on the right track * Long argument about whether inheritance hierarchies (and static typing) are all that necessary. * DT: Cites how infrequently Java developers run into ClassCastExceptions when extracting Objects from collections (zero or one times per year) and how this problem was "fixed" with Java 1.5. * CF: Interesting minimalist view of the advantage of composition over inheritance: you only implement the methods that you need and can avoid exposing those that you don't. * DT: Forwardable in std lib * Declarative delegation, i.e., def\_delegator :@member, :member\_method, :exposed\_method is clearer than:
  def exposed_method
    @member.member_method
  end
* Logical delegation via method_missing (simple stuff) * Duck typing * DT gave an example of prototype-based programming in Ruby: defining Objects and having Objects inherit from other Objects by use of clone * CF: Why never to use kind\_of?: because objects can have methods remove at runtime just as easily as they can be added; it's more important to know if an object can respond\_to? a particular message. * Knew this already but I love this explanation. * CF: Points out how the Martin Fowler _Refactoring_ book really turned him on to OO with "Handle Conditions with Polymorphism". With Ruby, just reopen the class, add different impls to each possible object with the same method name, remove the conditional, and just invoke the method outright in the code. * Mixins * Look for "-able" descriptions (i.e., Loggable, Enumerable, Printable, etc.) and sometimes "-ing" * CF on splitting methods up: When I have comments in a method, that's a big hint * Me: Yup. And, wow, do I see a lot of code like that (No, I usually didn't write it!) * Minimize interaction between Mixin and including class -- otherwise coupling the including Class to the Mixin Messin' With Types ------------------ * to_x conversion methods just make a "best guess" * Coercion * Not supposed to be lossy * DT: Representation of one type in another type * Symbol.to_proc * coerce * DT: You'll probably never need it * DT: Good example of double-dispatch "Homework" ---------- * Use coerce to write 1 + "123" to return 124

Posted by evan on May 08, 2008

Advanced Rails Studio Day 3 (Live Blogging)

The day starts with a list of potential topics. The class body votes on the topics that they want to cover. All of my votes went to ‘file uploads’ for work reasons – and fortunately this pushed it over the top! :D

And the results in order are:

  1. AJAX
  2. File Uploads
  3. Perf & Scalability
  4. Deployment
  5. AR with unsupported DBs
  6. Debugging

Notes after the jump:

AJAX & RJS

  • Motherhood and apple pie describing RJS, Prototype, and Script.aculo.us at a high level
  • DT: Believes that fewer web developers (well, he said “Rails”) are trying to emlate desktop applications with AJAX
    • Me: Or those few that are do a better job? (i.e., Meebo)
ruby -e "self.javascript_guru?"
=> false
  • Hopefully this doesn’t surprise anyone (again, motherhood and apple pie here) but: RJS generates JavaScript server side and sends the JS back to Prototype which evals the generated JavaScript which updates the DOM.
  • For custom JS:
    • page << "raw javascript here" and it concatenates the JS in order with the other calls to page.
  • Interesting to me: the “Old Way” involves generating DOM IDs in the calling view and the RJS – been there done that
    • In Rails 2.0: the “simply_helpful” plugin provides a div_for and tag_for that generate the IDs for you. Sweet!
    • From the audience: JRails is a plugin that monkey-patches Rails to support JQuery. From toying with JQuery a little, I <3 it.
  • page.select takes a CSS selector and generates appropriate GS
  page.select("div.queston").each do |q|
    q.visual_effect ....
  end
  • I dig it.
  • DT: Refactor into a helper if you’re going to reuse this (yup yup)
    • page[:an_element].reload seeks out a partial “_an_element.erb” and updates the element
    • update_page { |p| p.alert("Hello!") } just generates a String
    • Can be called from controller, helper, or view
    • CF: puts his RJS in the controller! His RJS code tends to be very short. If you’re doing more than that, then you’re probably making a busy page. (This is a handy take away)

Example:

  render :update do |page|
    page[:foo].your\_rjs\_operation
  end
  • To ‘easily’ support AJAX and synchronous:
  respond_to do |format|
    format.html { do something }  # handles text/html http requests
    format.js                     # causes lookup of RJS if making an AJAX request
  end
  • CF: Can call update_page as often as you want unlike render
    • Makes it easy to mix JS, HTML, and Ruby in the view – but could get ugly
    • So write helpers to be called via link_to_function (Slide 205 and 206)
  • Audience remark: Testing a page that can respond to text/html and a JS request seems as though it can be brittle/hard to test

    • CF: Yes, it’s harder to test a site that does AJAX than one that does not
    • DT: Triple good point!: With AJAX, you have to consider how friendly your website is to screen readers. I hope that my current colleagues are reading this….
  • Writing your own RJS extensions:

    • The JS generators uses method_missing so page.lightbox.dosomething would invoke Lightbox.dosomething in JS.
    • Be careful of the page size resulting from all of the code generated into the HTML

break

File Uploads

  • Two basic solutions:

    • attachment_fu plugin
    • paperclip
    • Biggest recipe in the Advanced Recipes book and freely available on the book site
  • Topics interesting to audience

    • Performance (my question)
    • Custom Mongrel handler
      • CF: Should be about 10 lines of code
      • MC: Code should be out there somewhere
    • Merb (obvious solution but thicker than it used to be?) – started as a custom Mongrel handler
    • Multiple concurrent uploads (also of interest)
    • Me: See Ezra’s talk on this
    • Progress bars
  • attachment_fu (yes, I’ve never used it. Shoot me.)

    • In events_final web app:
    • User has a Portrait
    • Portrait has_attachment is monkey-patched into AR (See code sample in events_final)
    • Some columns in the DB are required by attachment_fu
      • parent_id
      • width
      • height
      • content_type
      • filename
      • thumbnail (can have several)
    • Interesting notion of creating a logical model (in that it is not represented by a table in the DB) “PortraitService” (crappy name) delegate to:
    • create a transaction to handle the tasks of:
      • destroying an existing portrait
      • assigning the portrait to a user
      • saving the portrait
    • handle updates to the portrait
  • Little disappointed that the PragProg guys weren’t prepared to discuss custom Mongrel handlers due to Rails single-threaded limitation. Mentioned it to Chad as a future add for the course. Merb wouldn’t even exist if this wasn’t a severe limitation with Rails; Ezra started it as just a simple custom Mongrel handler.

  • And, given my input, Chad is digging it into a little now. :D

    • mongrel_cluster.yml
    • config_script option allows specification of custom Mongrel handler
require 'mongrel'
class MyHandler < Mongrel::HttpHandler
  def process(req, res)
    res.start do |out|
      out.write something     # do something useful here
    end
  end
end

uri "/myuploadhandler", MyHandler, :in_front => true
  • And just post to the URI specified in the custom handler.
  • This will run in a separate thread (which is the point)

Performance and Scaling

Really only have conceptual knowledge of this myself so the nitty gritty examples here were really handy.

  • Key points
    • Measure performance often
    • Identify hotspots
    • Change one thing at a time
    • Iterate
  • This jibes with Ezra’s remarks about performance optimization when he first started talking about custom Mongrel handlers and led into Merb.
  • Corollary: Guessing at performance bottlenecks is a waste of time.
  • MC quoting Ezra: “Post-mature optimizations are the cost of most hosting bills”
  • Optimizing AR
    • Look at the log files
    • Obviously, AR-generated queries could be ugly – so look at log files early
    • DT: Requests/second is the most useless statistic in the log file
    • DT: AR makes life simple – and sometimes simple is stupid
    • Selective Columns
    • Custom finders:
      • Use the :select option to specify the columns to pull.
      • Pull the ID column to avoid possible silent DB failure (DB specific)
    • Preloading Child Rows
    • For N + 1 queries (i.e. has_many :line_items that may have products itself)
      • Use of :include => :product
      • MC mentioned yesterday, take care with use of :include
      • DT: Please, please, measure when using :include. It may not help performance.
      • MC: suggests having separate associations for explicitness (readability and performance)
  has\_many line\_items
  has\_many line\_items\_with\_products :include => product
  • Assigning query results to a constant in an AR class that will load the results at startup and cache the results in the object model
    • Great for things that don’t change such as countries, states, etc.
  • ActiveRecord Query Cache
    • Based in identical SQL
    • Cleared on CUD
  Event.cache do |e|
    e.find(1) # DB
    e.find(1) # Cache
    e.update
    e.find(1) # DB
  end
  • Cache Store (Rails 2.1 – so still Edge)
    • API for configuring default store
      • Supports memory, file system, DRb (WTF?), memcache
      • So I ask: For memcache, this means a shared cache for a Mongrel cluster?
      • MC: yes
      • Sweet! (Yes, I loved Dude, Where’s My Car)
  store = ActionController::Base.cache_store
  store.write(key, value)

  stuff = store.fetch(key) do
    ARClass.stuff(key)
  end
  • Note that this is not just for ActiveRecord
  • Allows for caching across requests
  • Even more complex examples on slide 309

lunch

  • Page Caching
    • Pages that don’t take any parameters
    • Pages that don’t change
    • Cron job for cleaning up cache
    • Can’t cache
      • Personalized pages, pages w/ params, pages w/ content changes, time-based content
        • Although, for the latter, you could cache and force a refresh by destroying the cache periodically…
class SomethingsController < ApplicationController
  caches_page :index, :show
end
  • Fragment Caching
    • Cache small parts of templates
    • cache can be further parameterized to cache per user, etc.
    • Expiring specification is available in 2.1
      • But also via plugin: (see Karen Gillison)
  <% cache('some label') do -%>
    Your HTML goes here
  <% end -%>
  • Expiring caches

    • expire_page
    • expire_action
    • expire_fragment
  • Sweepers

    • For cleaning up caches
    • Observes models
    • Lifecycle actions on Sweeper get invoked when the lifecycle actions on the observed Model get invoked
    • Slide 319
    • In the controller, have to specify the Sweeper (see below)
    • To avoid having observers impact performance of transactions, put the expirey on a queue and operate on it later.
      • Me: If this were J2EE, shove it into a JMS queue – but J2EE…. ick.

DT: Complaining about the number of moving parts that are now being integrated into Rails: memcached, Starling, multiple Mongrels, Ferret, etc. Deployment is more painful than J2EE (Sadly, agree violently). Waiting for a backlash to occur at the complexity of it. Look at Twitter and how often it fails due to some SPOF (single point of failure). People writing many of the tools/plugins do not have enterprise experience and so are not taking external dependencies into account.

class MyController....
  cache_sweeper :my_sweeper
end
  • Memcache

    • Basically an in-memory hash (that you do not always need to use depending on your app)
    • cache_fu at the model level
      • supports TTL
      • Probably less relevant as of Rails 2.1
  • HTTP Performance

    • javascript_include_tag(:all, :cache => true)
      • Combines (and possibly compresses) JS files
    • ActionController:Base.asset_host = 'asssets%d.example.com'
      • Allows for federating assets across servers to avoid browser-limited number of connections per server
    • Yslow Firebug plugin (Andrew Willis mentioned this to me at lunch on Monday)
    • Tools
      • httperf
      • Siege
      • Profiler
  • General Points

    • Don’t use file-based sessions
    • Don’t forget indices
    • Watch the log
    • Cache where useful
  • DT: Consider adding some automated monitoring tools to determine when the system is beginning to perform badly

break

  • Worth noting that AOL Photos uses Rails – if you’re looking for another example of a large company relying on Rails.

Deploying

  • Deploy early
    • Me: It was personal development, but I was impatient to deploy the first (and only so far) time that I’ve used Capistrano. Better if I had tried to deploy earlier to forego that. Similar to TDD/BDD: makes the behavior less painful.
  • How many Mongrels in a cluster?
    • MC: Varies but fewer than you think
  • Question about not needing Mongrels
    • CF/DT: mod_rails – still in beta
    • Ruby processes that Apache comunicates with via *NIX sockets
    • Forking a process – so as some point out its similar to FastCGI
    • MC: There’s also Thin, Ezra’s work tying Rack and Rails together
  • MC: They started by using Apache 2.2.x
    • mod_rewrite
    • mod_proxy_balancer
  • Nginx
    • Small memory footprint
    • Easier to configure than Apache
    • MC: unless you have a damn good reason, pick Nginx (I need to use this beast – been hearing about it for over a year…)
  • “Heartbeat”
    • Custom Mongrel handler excellent for this

Posted by evan on May 07, 2008

Advanced Rails Studio Day 2 (Live-blogging)

Notes follow after the jump.

Metaprogramming Rails

  • How to write “magic” (ha!) such as belongs_to
  • “Is there a way to track down the file where a modification was made to a class?”
    • DT: Cause it to raise an error. Otherwise, no.
    • OUCH
  • DT whips up a little example showing how Rails implements Numeric.kilobytes
class Numeric
  def kilobytes
    self * 1024
  end
end
  • Of course, ActiveSupport just includes a definition that does something similar.
  • Question: does it speed up start up time to cherry pick what you want to load?
    • DT: It’s pretty trivial to load active_support in the grand scheme of loading Rails
  • DT describing how a class definition is executable code (recap of NoVaRUG presentation from April)
    • Just reopening ActiveRecord::Base and adding class methods. Waiting for the Adv Ruby class. :D
    • More simple metaprogramming examples. Goofing off while waiting for the harder core stuff.
  • They should’ve called this section ‘Ruby eye for the PHP guy’. Boooooring……
    • But, in the meantime, I have Markdown working in WordPress now. Yay.
  • Ok, ok, the “lib” directory in Rails is in the LOAD_PATH. Not a huge surprise but there ya go.
  • Adding methods dynamically at the class level
    • DT is describing the use of Object#extend. Honestly, I haven’t used that in anger before; I’ve always been a class << self; do_stuff; send guy. But, yeah, definitely simpler if you just want to add methods to the singleton object on a Class.
  • Decent question: What if you have a module with both class and instance methods?
    • Don’t use Object#extend (makes sense)
    • Have to use Module#include
    • In the implementing Module, Rails will look for a method called included that contains the methods that should be put in the class.
Module Foo
  def self.include(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def method_that_will_be_a_class_method_shortly
    end
  end
end
  • Where the hell is Module#included called from?
    • Awesome question: Why is foo.__send__ :include, module used in some places instead of include module?
  • Because the former doesn’t cause a class to load if it isn’t already loaded. Fucking cool! If only it was a little more obvious…

Break

  • DT: ”Kernel#eval is the work of the devil.”
  • Didn’t realize: Kernel#eval accepts an optional Binding (Kernel#binding)…
  • DT is giving some examples of Bindings. Surprised that this came up in a Rails class.
    • And just as I was starting to ask “What’s the difference between Bindings and Continuations?” (other than having a stack…), DT mentions that a “Continuation is a Binding on steroids” and will be discussed in the Adv Ruby Studio later this week. Bring on the pain!
  • And now Object#instance_eval
  • DT is giving a nice simple example of closures:
def twice
  yield
  yield
end

name = "Evan"
twice do
  puts "Hello #{name}"
end
  • name is defined outside the block before twice is invoked. The yield call is evaluating name based on it’s definition at the time of the twice call.

Another example:

def hello(name)
  lambda {
    puts "hello #{name}"
  }
end

c = hello "Evan"
c.call

name is out of scope at the time of the call but name is stil referenced by the block’s Binding.

And….

  def hello(name)
    count = 0
    lambda {
      puts "Hello, #{name} with count #{count}"
      count += 1
    }
  end

  c = hello "Evan"

  c.call
  c.call
  c.call
  c.call
  c.call

…returns:

  Hello, Evan with count 0
  Hello, Evan with count 1
  Hello, Evan with count 2
  Hello, Evan with count 3
  Hello, Evan with count 4

… because count is referenced by the block’s Binding

DT mentions later: blocks are evaluated only when they are called

  • Module#define_method

Take 1:

  def definer
    def hello
      puts "I've defined a method inside of the execution of another method"
    end
  end

  definer
  hello

Or the better way of doing it…

  class Definer
    def self.define
      define_method(:hello) do
        puts "I've defined a method inside of the execution of another method"
      end
    end
  end

  Definer.define
  Definer.new.hello

The above example invokes Module#define_method inside of a class because it’s a Module method; you can’t access it unless you’re inside of a Module (or Class because Class extends Module).

And here we use a closure within the example:

  class Definer
    def self.define(name)
      define_method(name) do |p|
        puts "I've defined a method called #{name} that was passed an arg #{p}"
      end
    end
  end

  Definer.define("hello")
  d = Definer.new
  d.hello "Evan"
  d.hello "Spock"

Nifty. The string that we’re writing gets evaluated when hello is called.

DT says “I use define_method all over the place”. Ok, ok, no more Object#eval for me. “This is a closer to God way of doing Ruby duplication”. Nice.

Note to self: Slide 129 in the slide package has the Module#define_method example.

DT: Ruby is slower than most scripting languages because (1) it’s not written for speed and (2) it’s completely OO and classes are open. DT: The overhead of define_method versus def is “microscopic”. Question: When would you use define_method? It’s a little different than code generation.

  • Will be discussed more in the Adv Ruby Studio (GOOD!)

Lunch

ActiveRecord

  • Joining Models
    • Discussing notion of creating relational objects to handle a many-to-many
    • has_many :through on both sides (simple-ish stuff so far)
    • Simple example of Magazine with Readers joined via Subscriptions.
    • Note to self: Slide 137
    • Question: “Is there anything forcing you to “has many :through” on both sides of a relationship?
    • Honest question but nope. Although the DB may expose a bi-directional relationship, the code doesn’t have to represent it.
    • Worth noting: adding a Magazine to the Reader will automatically create a Subscription because of the has_many :through
    • Most people in the room aren’t using HABTM often
    • Join Model or HABTM?
    • Users and Groups
    • Attendees and Events
    • None of the above sell me on HABTM
    • Products and Tags
      • Tagging?
    • Products and Related Products
      • HABTM? Maybe….
    • HABTM if there isn’t a good name? I don’t know… I shun HABTM. Besides, there’s almost always qualitative and/or quantitive information that’s associated with the relationship. That warrants a join model.
    • CF mentions using :include => [:registrations => :event] to eager load all of the events assocaited with each registration
    • MC believes that the use of :include generally causes more problems than it solves
    • Self-referential HABTM
    • Example with Person and having friends
    • FUGLY (sixs hash entries to supply to HABTM to add and remove bidirectional relationships automatically – see slide 141)
    • I suggested a Join Model approach with Friendship
    • DT: enforced bi-directional relationships should be maintained by triggers.
      • In the context where the data may persist indefinitely (i.e., enterprise), enforcing the data constraints exclusively within the application is nonsense.
      • No one in the class pointed this one out. I know that I, for one, lose sight of this.
    • DT, MC, and CF: Don’t put raw finds in your controller. Tightly couples controller to model implementation. BAD.
      • Good sense if you want to possibly swap out ORM implementations – which is quite possile if you’re using ActiveRecord.
    • CF: Shows the Friendship example which is better but still doesn’t let the DB be responsible for the relationship.
      • MC example:
class Person
  has_many :friendships, :dependent => :destroy

will call destroy on the the Friendship when the Person object is destroyed.

  * Again, triggers would handle it better....
  • Polymorphic Associations
class Person < ActiveRecord::Base
  has_many :addresses, :as => :addressable
end

class Company < ActiveRecord::Base
  has_many :addresses, :as => :addressable
en

class Address < ActiveRecord::Base
  belongs_to :addressable, :polymorphic => true
end
  • The addresses table then needs “addressableid” and “addressabletype” columns to indicate which row in which table (persons or companies) is related.
  • I’ve used these before and, really, polymorphic associations, in Rails, hurt!
    • I hate them.
  • Someone else mentions single table inheritance as an option. I’m not keen on that either but it is far less ugly than PA.
  • CF: If you use PA, you have to index the type field because you’re going to be querying it often.

    • Single-Table Inheritance
  • When you want to have an AR object inherit from another
  • Type field in the DB which contains the constant name of the type
  • Has all shared and distinct fields must be in the table
  • MC: Your STI table can get very wide if the classes in the family have little commonality…
  • CF: if you change the class name, you have to update the DB
  • CF: Ideally, prefer composition over inheritance
    • STI makes a strong case for composition – because STI can get very ugly…
  • CF: Don’t use a column called “type” in AR – ever; bizarre-ass error messages.

break

Refactorings

  • Starting with an example controller action with a couple of raw finds
  • Interesting use of a code block on the AssociationProxy.
    • Below example seems reasonable if this query (i.e., recent) is only valuable on this relationship
  has_many :visits do
    def recent(limit = 5)
      find(:all, ...)
    end
  end
  • Someone just pointed out that this doesn’t return an AssociationProxy (see here and find “proxy”)
    • For example, it’s easy to believe that event.registrations is an Array (if both represent AR::Base objects)
    • It even says it’s an Array when you call event.registrations.class
    • Calling event.registrations.ancestors reveals more
    • It’s actually an AssociationProxy
    • See AR association_proxy.rb
      • Delegates everything to method_missing and from there to a wrapped target
    • To extend an AssociationProxy with a module (in the example, called RecentFinder):
class User < ActiveRecord::Base
  has_many :vists, :extend => RecentFinder
end

… which makes the former code sample, where we define a method to the AssociationProxy, much cleaner.

Active Record Scoping

  • ActiveRecord::Base#with_scope creates a block where all contained finder calls on the class use the specified scope
    • Slides 154 and 155 – want to review this more later
  • Named Associations
  has_many :registrations

  has_many :preregistrations,
           :class_name => "Registration"
           :conditions => "pre_register is true"
  • These are cached (slightly evil that this is implicit – but a handy feature)
  • So a cool use is to nest scopes to and conditions together (but this isn’t cached – could suck performance wise for complex access control)
    • How many queries would we be performing? One per scope?
    • Nested calls to with_scope accumulate a single SQL query so could be super awesome for complex access control (depending upon the SQL)
      • To be useful, this would have to be FAST!
  • Slides 159-160 lend themselves awesomely to access control (except need to know how to mark the cache dirty to force a refresh)

break

Custom Form Builders

  • Delegating the markup generation cleans up form code
  • FormHelper#form_for takes a :builder argument.
  • Subclass of ActionView::Helpers::FormBuilder
  • When we call formfor :builder => MyBuilder, formfor yields with an instance of our builder as the argument.
  • Slide 177 contains the sample code for a simple LabelFormBuilder that dynamically generates methods that overrides much of the behavior o the DefaultFormBuilder but with our custom implementation.
    • That’s it. Unless I need a form with a lot of unique formatting (which I can’t see happening often), I’m writing a customer FormBuilder.
  • MC/CF: I asked how often these guys write custom FormBuilders.
    • Both use a custom FormBuilder in every project; they just may get someone who generates better UIs than they do to write it.
    • Unless I need a form with bizarre/unusual formatting, I’m going to be using one of these in the future.
  • They also suggest writing a helper to wrap form_for to factor out the :builder option.
  • ActionView:Base.defaultformbuilder=: Go assign your own default. :D

  • content_for

    • Page-specific content
    • JS
    • CSS includes
    • Contributing content (HTML) to the layout or any other template.
    • Smacks a little of goto…. so mighty but take care!

Posted by evan on May 06, 2008

Advanced Rails Studio Notes: Day 1

Lovely start to the day. 2 miles from the hotel, my Prius breaks down and won’t start. WTF?! FAIL! Oddly, 30 minutes later (after perusing the sample app that we’re going to discuss during the class), the car starts again with a warning light. During the class, I’m fucking Grand Central Station: my cell phone rang 4 times before lunch. Again, WTF? I’m not a popular guy. Yeesh!

Hehehe… and Twitter went down just before lunch. Sometimes it’s nice to remember that I’m not the only one who is living in interesting times.

Regarding my notes, it’s worth mentioning that I’ve done a bit of Rails 1.2.x development but haven’t touched Rails 2.x until today. That said, as of this morning, I was comfortable with the theory of REST but not the Rails implementation.

Anyhoo, my notes from Day 1 of the class follow after the jump.

  • Session controllers to handle logins evidentally not uncommon.
  • Familiar from J2EE web app design.
    • Mildly surprised as that

Routing (cool — always felt a little clueless about routing) (Mike)

  • map.connect ‘:controller/:action/:id’
  • :controller and :action are just plain ol’ params; just used by the dispatcher to route the request
  • Can put default values in the routes (i.e., foo/show could default to FooController.show(:id => 1))
  • SPLAT tags:
    • map.connect(‘tag/*tags’, …. ) is valid for http://foobar.com/tag/foo/bar/blech/bla
    • results in params[:tags] => [“foo”, “bar”, “blech, “bla”]
    • Handy for default actions to handle 404s
  • map.show_event ‘event/:id’, :controller => ‘events’, :action => ‘show’, :id => 1
    • Results in:
      • showeventurl (good for externalization — absolute)
      • showeventpath (relative)
    • Mildly annoyed that there are still more conventions that I don’t know. At times, the Rails API sets off my Java-ridiculously-thick-API alert.
  • Chad is walking us through ActionPack
    • actionpack gem has ActionController::Dispatcher
      • Dispatcher#dispatch calls handlerequest which calls Routing.recognize(request)
      • named routes work off of methodmissing. Cute.
      • Creates an anonymous Module and removes all of the methods
      • defineurlhelper and a few other methods define all of the methods on the anonymous Module
      • named routes are mixed into views and controllers in routing.rb’s #install (neato)
      • Grateful for this’ lil TextMate bundle o’ joy for popping up gem source.
    • Code is (surprisingly) pretty clean

Break

Had a cool conversation about using subcontrollers — although the routing was painful. Suggested dynamically generating the routing at runtime for each “subsite”. Wonder if loading that would require a Rails monkey patch? SEP.

REST (Dave)

  • Dave is explaining the basics. I wonder how many ppl in the room already know this stuff and are just nodding their heads.
  • If request structure is predictable, simplifies caching
  • Fielding REST thesis: Everyone has read this but me, right?
  • ‘The HTTP verb is “fighting” the action verb in the Rails controller’ — Dave Thomas
  • Someone else mentioned my problem: mixing up PUT and POST
    • Mike: “PUT has a ‘U’ in it. So does update”. That will help me.
  • Good question about “How hard to try to be ‘pure’ in the use of REST” (i.e., avoiding an RPC-like API)
    • DT’s Pragmatic™ ;) opinion: rich user interfaces make REST complex; however, REST is a good fit for back ends and services. Makes sense.
    • DT compares REST to dynamic programming and WSDL/SOAP to static programming. REST requires a ‘leap of faith’ that you can handle whatever comes back.

RESTful Rails Conventions (Chad)

  • Describing some of my pain: Rails 2.0 rewrites a good chunk of what I learned from when I was using Rails 1.2.x.
  • map.resources just creates a bunch of named resources (resources.rb in ActionPack)
  • Someone asks what happens if you don’t want to support “destroy”
    • Deleting the action will result in a 404 — which means that the resource DNE. FAIL
    • Someone pips up that the correct code is 405 (method not supported)
    • Worth doing? I suppose it depends on what you know about your users; will the calling service handle 404 and 405 differently?
    • URIs are created for things like ‘formfor @event’ internally with something like @event.class.name.tolower.pluralize + “uri” to get the eventurl method name and call it.
    • Someone asks ‘What about with formtag’? Chad: doesn’t work with REST. We’ll cover it in a later section of the class.
    • formfor, with an existing id, hacks a hidden
      in indicating that the method would be a PUT. It’s actually accomplished via a POST; browsers don’t support PUT (didn’t know that one…).
      • The _method hack is recognized somewhere in the routing layer. Ick….
    • Rails does actually recognize a real PUT request as well for non-browser clients
    • RESTful destroy: don’t forget that :method is an HTML option… so :method => :destroy
  • RESTful routing:
    • map.resources :events, :collection => { :search => :get }, :member => { :copy => :post }
    • maps to http://foo.com/events/search?….
    • maps to http://foo.com/events/123/copy?….
    • Rails doesn’t cache the request parameters — therefore something like http://localhost:3000/events/search?term=foo isn’t idempotent so may not be truly RESTful (Note to self: look into this more later)
    • Great discussion ensuing over whether this is really RESTful or not.
    • Dave said that maybe he’d write a search controller
    • I pointed out that the above URL could just be /events/search/foo as a custom route addressing EventsController#search and then, *voila* RESTful. Chad thought the same thing.
    • DT: don’t use this as something to beat yourself with. It’s supposed to make your life easier.
    • Could just reuse an existing action that uses a parameter — if the view is essentially the same.
    • Chad just tried the idea that we both had; it doesn’t work with map.resources. DOH!
      • What about with just creating our own named resource? If map.resources is just generating a named route, we should be able to do the same thing.
      • Doesn’t consider the HTTP method per Chad. Fuck.
      • Where is the ued HTTP method checked? Hrm…..

Lunch

  • Andrew Willis, from CustomInk, mentioned that they use Pen for their load balancer. It queues up the requests itself rather than queuing them up on the Mongrels. Plus the load balancing algorithm is configurable. Sounds handy.
  • Good discussion at lunch about whether JRuby will become the preferred deployment environment for Rails by the end of the year. I have a hard time buying that until a language spec is agreed upon.
  • Dammit, not enough time to do the labs. Too busy talking about Ruby/Rails at lunch.

Handling RESTful Requests in Rails

  • xml simple gem makes it easy to go to/from hash/XML
  • #toxml, #toyaml (#to_json)
  • Set the HTTP accept header OR put a “.xml”. Either works. Motherhood and apple pie so far.
  • Ah, now #respondto
    • Some, including DT, complain about respondto living in the controller layer; it’s presentation related, really. Agreed. It’s largely irrelevant to the behavior but may effect the content of the results
    • Question about testing this: use “formattedFOOurl” which takes the format
  • Without a respond_to, Rails delegates the type to a rendering engine based on the view filename extensions (More apple pie — and how we use HAML :D )
  • DT: could use “m.mysite.com” in routes.rb to render an iPhone formatted page by setting the foramt in routes.rb. (Slick idea)
  • .json support is in trunk but not 2.0.2 (waaah — that could help on my current project)
  • mimetypes.rb
    • #register and #registeralias
  • Chad is trying to get the class to talk more. DC people are so damned reserve. I was born on the wrong coast. God damn I need to move to the Portland or San Fran ASAP…..

ActiveResource

  • Damn it looks so simply. Now if only all apps used this instead of *cough*motherfuckingJRMP*cough*.
  • Just a quick walkthrough; too simple to warrant a thorough treatment.
  • Chad and Mike were talking about how wonderful it would be if all applications supported the Rails .xml protocol.
    • All that I could think (and sing quietly) was cue John Lennon “Imagine all the applications living in harmony….”
  • 201 code is the status returned when an object is crated (quick google to here verified out of curiousity)
  • Ah, to call a custom resource: Event.get(:search, :q => ‘ruby’)
    • http://localhost/events/search.xml?q=ruby
    • Again, not necessarily RESTful but how Rails does it and so how ActiveResource does it….
  • Authentication: ARclass.authenticate
  • Pain point brought up: Using ‘from_xml’ tightly couples the XML to the model

break

Note to self: play with ActiveResource client to my own “events” web app tonight

Testing (all afternoon — AWESOME)

When asked, when asked if their ‘opposite number’ in the class tests, half as many people said ‘yes’ as said that they tested. Maybe 20% of the class considers themselves rigorous testers of their software. I will assume that they are very humble or else I will be very sad. * DT: Unit testing is useful for finding design flaws / finding where there is too much coupling (for instance, where the setup is onerous) * DT is lecturing people on why they should test. * DT: only uses integration tests to exercise particularly tricky cases * MC: Testing is 90% about discipline (you betcha). * DT: Preaching to keep tests DRY by factoring commonalities into test helpers and splitting helpers into multiple files when they get too big (more motherhood and apple pie) * Improves test readability * Makes tests more flexable * assertequals ‘musician programmer’, users(:fred).tagnames sucks compared to assrthastags ‘musician programmer’, :fred * Latter could allow for different tag ordering * Test is more readable * They throw up a slide using a Rails Integration Test that defines several methods on an IntegratonTest#open_session session to create an integration test DSL. Awfully damn readable. * I could see using RSpec Stories that way. However, Dave Chem and the RSpec team seem to advocate a Stories-first approach. I don’t quite feel that; My gut (large as it is) tells me that I would spend far more time writing stories than I would need — where need means that I could get by with using specs instead of stories.

Mocking/Stubbing

  • DT: Describing mocks and stubs (motherhood and apple again……)
  • MC: Describing mocking in controllers (getting a bit bored now; can we get back to the theory?)
  • Maybe was worth it? FlexMock is a little niftier than I thought.
  • Ok, better, now we’re debating about what makes a test more readable.
    • I mentioned my habit of using hashes to simulate named_args. DT accused me of being a Smalltalk programmer. Said that I evolved from a Java programmer. ;)
  • CF: Describing RSpec Stories
    • Ok, cool, they’ve split most of the text of the story from the tests for each step. Pretty cool.
    • “Sentences” from Story are mapped to code blocks in registration steps in a separate file. Makes the story readable — although separating the Story into two files bugs me slightly.
    • Why not replace the pseudo-English version with a full-on rule-based English version using Treetop? Then the “Ringrish” can be replaced by English?
  • MC: Describing Shoulda — not as powerful as RSpec but, well, not as powerful as RSpec

Update: Sorry for some of the crappy formatting. I had TextMate convert Markdown to HTML and, evidentally, it mutilated a lot of what I typed….

Posted by evan on May 05, 2008

Mocking core Java classes with jmockit

I know, I know. Java. Blech!

But if you have to work in Java, instead of something more elegant like Ruby, wouldn’t you like some of the same awesome mocking power that you have come to know and love in Java? Yeah, me too.

Toby DiPasquale turned me on to jmockit. It’s a little framework that provide RSpec-like mocking in Java. To those familiar with RSpec: jmockit allows developers to mock constructors as well as individual method on live objects. It accomplishes this courtesy of the java.lang.instrument package that was added in Java 1.5.

I was curious to see if it is possible to mock boot classloader loaded classes (i.e., java.lang.Integer, etc.). After a few minutes of tinkering, I found a way but it’s none to pleasant…

The primary annoyance is this: the core Java mocks appear to have to be in the bootclasspath. Why? I speculate however I believe the JVM needs the definition when the class is initial loaded – which, for core classes, can often happen at startup.

So, for example, this works:

Test.java:

  import mockit.*;
  import java.math.*;

  public class Test {
    public static void main(String[] args) {
      Mockit.redefineMethods(BigDecimal.class, new BigDecimalMock());
      System.err.println(BigDecimal.ONE.add(BigDecimal.ONE));
    }
  }

BigDecimalMock.java:

  import java.math.*;

  public class BigDecimalMock {
    public BigDecimal add(BigDecimal v) {
      return new BigDecimal("42");
    }
  }

And run the whole beast with this:

  java -Xbootclasspath/a:jmockit.jar: -javaagent:jmockit.jar Test

So, yes, Virginia, it is possible to mock core classes. But does it suck? Hell, yes. To make this work practically would likely necessitate launching a separate VM so as to “scope” the mock to a particular test.

Fugly.

Posted by evan on May 02, 2008