Archive for August, 2010

A proposed check’n'balance for certifications

Earlier today, I found myself talking to Andrew Shafer and Corey Haines about certification. Certifications provided by people who make good money off them beg for distrust. So do certifications of courses or trainers when the certifiers get revenue from that activity. On balance, I think we’d have been better off without the certifications we have, and I agree with the Agile Alliance’s position on certification. (Disclosure: I was the main author.)

However. Here we are, aren’t we?

To improve the current situation, I propose the following, roughly inspired by Consumer’s Union.

  • There should be an Agile Alliance program that applies to all courses, not just those that provide certifications.

  • This program will, with the Agile Alliance’s money, send spies to sign up for courses. They will anonymously write up detailed evaluations that will be posted on the Agile Alliance website.

  • It will also interview a random sample of course attendees. The ones contacted just after the course will be asked for their evaluation. The ones contacted a year after the course will be asked how valuable, in retrospect, the course was. These results will also be posted on the site.

  • These interviews and ratings will, over time, allow the writing of summary articles like the ones Consumer Reports Magazine runs. Expect articles about “What to Expect from a Certified ScrumMaster” or “How to select a TDD course”.

  • Those running the program will pay careful attention to maintaining the trust of their readers.

It’s possible I’d participate in this. I have no desire to run it. I don’t care that much.

An idea about testing inner functions in Clojure

While working on the “sweet” interface for Midge, I wrote this function:

(defn- define-metavars [form]
(let [metavars (filter metavar? (tree-seq form-branch? seq form))]
(doseq [metavar metavars]
(intern *ns* metavar (symbol metavar)))
metavars))
view raw gistfile1.clj hosted with ❤ by GitHub

metavar? and form-branch? are only useful within this function. I would have preferred to write it like this:

(defn- define-metavars [form]
(let [metavar? (fn ...) ; Inner function
form-branch? (fn ...) ; Inner function
metavars (filter metavar? (tree-seq form-branch? seq form))]
(doseq [metavar metavars]
(intern *ns* metavar (symbol metavar)))
metavars))
view raw gistfile1.clj hosted with ❤ by GitHub

I didn’t because I wanted those two functions tested before I relied on them. So I need a format for testing inner functions. I’ve sketched out a format and done (by hand) the transformation required to make it work.

I’ll start explaining it with this simple example:

(defn outer [a b]
(let [summer (fn [arg] (+ a b))]
(* (summer) (summer))))
view raw gistfile1.clj hosted with ❤ by GitHub

Before dealing with the daunting complexity of multiplication, I want to test summer with something like this:

(fact
(within (outer 1 2) (summer)) => 3)
view raw gistfile1.clj hosted with ❤ by GitHub

(I’m using the Midje sweet notation here. Read it as “It’s a fact that (within (outer 1 2)), (summer) produces 3.”)

To make this work, I’d redefine the defn macro for the duration of a test and have it produce a little extra metadata:

(defn outer [a b]
(let [summer (fn [arg] (+ a b))]
(* (summer) (summer))))
(alter-meta! (var outer) assoc :nested
{'summer (fn [a b] (fn [] (+ a b)))})
view raw gistfile1.clj hosted with ❤ by GitHub

I’m stashing away a function derived from summer. It creates the same lexical environment that outer does, and returns a function to call. Here’s the macro that would expand a within, together with a sample expansion:

(defn environment-creator [var name]
(((meta var) :nested) name))
(defmacro within [ [environment-function-symbol & environment-args]
[inner-function-symbol & inner-args] ]
`(((environment-creator (var ~environment-function-symbol) '~inner-function-symbol)
~@environment-args) ~@inner-args))
;; (within (outer 1 2) (summer))
;; expands to:
;; (((user/environment-creator (var outer) (quote summer)) 1 2))
view raw gistfile1.clj hosted with ❤ by GitHub

The expanded form is a little opaque, so here are the three steps:

  1. Retrieve the environment setting function from outer’s metadata.
  2. Call it with the outer arguments.
  3. Within that environment, call summer.

What if a later inner function uses a previously-defined one? Like this:

(defn outer [a b]
(let [summer (fn [arg] (+ a arg))
multiplier (fn [] (* (summer b) (summer b)))]
(multiplier)))
view raw gistfile1.clj hosted with ❤ by GitHub

One option would be to drag the earlier parts of the let into the metadata:

(alter-meta! (var outer) assoc :nested
{'summer (fn [a b] (fn [arg] (+ a arg)))
'multiplier (fn [a b]
(let [summer (fn [arg] (+ a arg))]
(fn [] (+ (summer b) (summer b)))))})
view raw gistfile1.clj hosted with ❤ by GitHub

In that case, the test would look like this:

(fact
(within (outer 1 2) (multiplier)) => 6)
view raw gistfile1.clj hosted with ❤ by GitHub

This test is a little not-thrilling because it’s clearer what multiplier does if you can see how it relies on summer. That could look like this:

(fact
(within (outer 1 2) (multiplier)) => 9
(provided (summer 2) => 3)
view raw gistfile1.clj hosted with ❤ by GitHub

However, dragging the previous let clauses into the metadata has to be done anyway (in case non-function values are bound), so I’d be inclined not to gild this lily.

Creating the metadata wouldn’t be too hard in the common case where the let is the outermost form in the function’s definition. I doubt I could be persuaded to care about other cases.