justin․searls․co

Did you come to my blog looking for blog posts? Here they are, I guess. This is where I post traditional, long-form text that isn't primarily a link to someplace else, doesn't revolve around audiovisual media, and isn't published on any particular cadence. Just words about ideas and experiences.


iCloud is Anti-Family

My spouse and I share an Apple ID. But we also maintain separate Apple IDs. Paradox.

Why? Because nearly a decade ago, it took us all of fifteen minutes to realize that we were purchasing the same songs multiple times from our separate computers.

That realization—and the subsequent decision to share an Apple ID for purchases—has made each new Apple software upgrade increasingly complex over the years. So I made a chart!

Turns out, there's more to it…

The Limits of Metaphors

All metaphors break down with sufficient mileage.

[And they often break down quite quickly, like that car metaphor I just made.]

Because metaphors break down, it's worth pondering the fact that most of humanity only comprehends software through the use of metaphors.

  • The metaphors most users experience are graphical user interfaces (desktops, folders, round-rect app icons, back buttons, etc.)
  • The metaphors our friends and family hear include our own attempts to describe how writing software is actually quite a lot like crafting sturdy Amish furniture
  • The metaphors conveyed to business people—at least, the ones that pay to have software developed—are as boundless as they are inane (and they're usually quite inane)
  • The metaphors that software developers themselves are steeped in are perhaps too complex to ever escape. We stand on the shoulders of giants: building domain-specific metaphors that rest atop dozens of other metaphoric layers. [If you're inclined to disagree, then I suppose that implies you can yet derive the 1's & 0's backing the software you use; or the logic gates; or the assembly operations.]

My proposal today is that we start treating software metaphors with greater skepticism.

Content warning: more content…

What's Wrong With Ruby's Test Doubles

Prologue

First things first: let’s square up terminology. For the sake of facilitating sane discussion on this topic, I’ve adopted the terms used in Gerard Meszaros’ XUnitPatterns book. He drew a complex table for this, but I’ll quickly summarize here:

  • Test Double — a generic term to describe an artifical stand-in for code (usually an object) upon which the subject code you’re specifying depends. Mocks, spies, stubs, fakes, etc. are all specific subtypes of test doubles.
  • Stub — a test double that can be configured to respond to certain invocations (e.g. `when(panda.poke()).thenReturn(“chuckle”)`) in order to facilitate downstream behavior within your subject code. However, a stub can’t do anything to verify that certain invocations take place.
  • Mock — a test double that can be configured to expect certain invocations in advance, raising exceptions if those interactions never occur. They add the bizarre wrinkle that if they receive any unexpected invocations, they’ll raise an exception. For convenience, the mock objects generated by most (all?) modern mock libraries can do double-duty as stubs, despite Martin Fowler’s best effort to explain all this.
  • Spy — a test double that records all of the invocations made against it, exposing some way to interrogate how it was interacted with after the fact (e.g. `verify(panda).eat(bamboo)`). Spies respond quietly when interacted with by your subject code, usually returning the bare minimum the language supports (`undefined` in JavaScript, `null` in Java, `nil` in Ruby). Of course, they respond less silently when they’ve been set up to stub an interaction, because most spies can stub too!
  • Partial Mock / Proxy — a real object for which only particular method interactions have been cherry-picked to be stubbed or expected. Partial mocks break unit test isolation (because your subject code is now interacting with a quasi-real dependency) and their controversial use has been known to incite nerdy fisticuffs.

When it comes to test doubles available to Ruby developers, something has puzzled me for a while. Many of the brightest minds in testing left Javaland to join the Ruby community. Because of this, I was shocked to find that Mockito—a test spy framework for Java—is a more expressive tool for working with generated test doubles than any of the numerous libraries available for Ruby.

You'll never guess what happens next…

The Power of Prompts

This post is partly in response to to this tweet, and partly a follow-up to a teaser I tweeted earlier this week.

We humans are suckers for suggestion. If you need evidence of this, consider something as seemingly innocuous as the order in which we ask people questions.

If I were to ask you: 

1. Does the following web site load properly in your browser? Make sure all the pictures load: cuteoverload.com

2. Do you support the euthanasia of stray bunnies brought to animal shelters?

Keep reading…

Open source interviewing

When someone applies to Pillar, we invite them to submit a code example that solves a particular problem. We review the code as an input early in the interview process.

It’s a helpful component of getting acquainted with a candidate, but a few things aren’t ideal:

  • For any toy project, the domain is going to be trivial enough that it isn’t likely to be very representative of a larger “real” project
  • As I review more and more submissions which solve the same handful of problems, I’m finding it harder to evaluate each with a fresh set of eyes
  • Ultimately, the code doesn’t have any utility—its lifecycle ends as soon as it has been reviewed and discussed. This despite the fact that many candidates invest a significant amount of time writing it

Here’s an idea that might address those concerns: let’s start asking candidates to submit something useful instead.

To be continued…

Succeeding with clients that don't want to change

Hypothetical: you find what seems to be the perfect prospective client. You’ve collaborated to develop an idea with the potential to realize outstanding value. They’ve decided they trust you to capitalize on the opportunity and achieve that value via some new software system.

*But!*

But the prospect makes a point to tell you they don’t want to be trained or changed (and that you can forget about “transformed”). They compensate by emphasizing that their only objective is to produce that set of value-creating widgets the two of you dreamed up in the (much cozier, in hindsight) first paragraph.

But wait, there's more…

Rushing to Forget Clean Code

Ron Jeffries just posted a terrific case for clean code, and decoupled a recently-emerged “code can be too clean” meme from a question that has actual merit, “can we spend too much time making code clean?”

Upon discussing the post with Kevin Baribeau this evening, an anecdotal correlation was identified between folks who’ve said things akin to “code can be too clean” and folks who tend to succumb to the pressure to rush development of features.

And before you knew it…

How I Write Java These Days

Over the last year, I’ve made an effort to better identify the styles, idioms, and smells I encounter when reading and writing new Java code. [And, already, a takeaway point! To some of my more successfully sheltered rubyist friends, it may be sorry news to hear that there continues to be new Java code written.]

In any case, I’ve made a concerted effort to internalize habits that I find valuable and to develop a reflex to resist those which I do not. This will be my first effort at documenting either, so I’ll just express them in terms of how my Java looks these days, replete with code snippets as needed.

Turns out, there's more to it…