Archive for the 'agile' Category

Mocks that specify essential implementation

James Shore said something in two tweets that I’ve abbreviated as follows:

I’ve never liked mock objects. At best, they’re a necessary evil. At worst, a meaningless “test” that overspecifies the code under test.

I tweeted back that “I’m finding mocks that overspecify the code under test are a sign that I’m making code that doesn’t express intent well.”

Here’s something of what I mean by that. Suppose I want to describe, in English, what it means for a function to make an X509 certificate from some Base64-encoded text and store it in a particular file. The method is part of a Contact object. Here’s the description:

Contacts, as you know from an earlier description [test], are created with a pile of information contained in a hash. One bit of relevant information is the :organization. There are also some Base64-encoded keys. Let’s pick one at random, call it :a_key.

In order for the Contact to create and stash the certificate, it collaborates with two objects. One of them is the :certificate_maker; the other is a :folder that knows how to stash info into a named file. The :certificate_maker is hardwired into the Contact, but the :folder is passed in.

In order to stash :a_key in a :folder, the :stash_this_key method has to do two things:

  1. It has to hand the (Base64-decoded) certificate info (the key) to the :certificate_maker, which will return some sort of encoded gibberish.

  2. The :folder has to be told to stash the gibberish into one of its files. The filename is of the form organization-name.a_key.pem. (The organization name is made according to the rules I already told you for sanitizing organization names.)

Here’s the actual test. I think you can see how it parallels my description:

It does specify implementation. Most importantly, it says that there should be a completely separate CertificateMaker object. That’s a good thing. Had I not been committed to mocking, I would have been tempted to just copy-and-paste the code I was working from, which looked something like this:

Had I done so, I would have likely never bothered to figure out what sort of magic thing "openssl x509 -inform der" does. As it was, I had to know enough to make a decent class and method name, meaning I had to learn my domain.

Given that the hard part of object-oriented design is figuring out what objects should exist and how they should interact, something that forces me to think harder about interactions and responsibilities might well be a win.

That said, there’s a constant temptation to make the implementation “incidental”, to describe what does happen in this implementation rather than what ought to happen in any reasonable implementation that fits within the, uh, conceptual domain of the program. For example, Ruby already has abstractions for file systems: the Dir and File classes. If my mock tests for Contact talked about how File and Dir are called, … that would be bad. Instead, test expressiveness forced me to condense down everything Ruby lets me do into the more limited idea of a PreferredFolder that knows how to “stash” strings.

I grant you that I still feel like I’m going overboard when I start with 27 lines of sample code and later discover I’ve got a RemoteDirectory and a Directory and a Contact and a CertificateMaker — all just to snatch something off the network, convert it, and stuff it into a file. Certainly, I’m going slower than I could (in the early part of the project), but I don’t necessarily think that’s a bad thing. I trust that it’ll keep the cost of change curve flatter — though my trust in myself might be misplaced. Wouldn’t be the first time.

Macruby 0.6, mocks, TDD, Xcode, Interface Builder

It took me quite a while to figure out a comfortable way to do my now-comfortable style of mock-heavy TDD while using MacRuby, Xcode, and IB, so I thought I’d boil that work down into a skeleton others can reuse. Enjoy.

I have this urge to write a book…

It would begin like this:

On a bright Illinois morning on the sixth of November, 2010, Teresa Williams dragged a picture of her twins in their Halloween costumes into a mail message. She clicked a button to send it to their grandparents. Three minutes later, in Göteborg Sweden, Teresa’s mother’s phone buzzed discretely. The mail had arrived.

This book is about everything that happened between the click and the buzz.

It would be a popularization, hitting a technical level somewhere around Singh’s The Code Book—that is, technical enough that someone who really knows the details wouldn’t consider it incorrect, but accessible to the layperson.

What do you think?

Mocks and legacy code

While on my grand European trip, I stopped in for a day at a nice company with a fun group of people doing good work on a legacy code base. They challenged me to improve an existing test using mocks. The test was typical of those I’ve seen in legacy code situations: there was a whole lot of setup code because you couldn’t instantiate any single object without instantiating a zillion of them, and the complexity of the test made figuring out its precise purpose difficult.

After some talk, we figured out that what the test really wanted to check was that when a Quote is recalculated because it’s out-of-date, you get a brand-new Quote.

Rather than morph the test, I tried writing it afresh in my mockish style. A lot of the complexity of the test was in setting things up so that an existing quote should be retrieved. Since my style these days is to push off any hard work to a mocked-out new object, I decided we should have a QuoteFinder object that would do all that lookup for us. The test (in Ruby) would look something like this:

quote_finder = flexmock(”quote finder“)
quote = flexmock(”quote“)

during {
   some function 
}.behold! {
 quote_finder.should_receive(:find_quote).once.
              with(…whatever…).
              and_return(quote)
 
}

Next, the new quote had to be generated. The lazy way to do that would be to add that behavior to Quote itself:

quote_finder = flexmock(”quote finder“)
quote = flexmock(”quote“)

during {
   some function 
}.behold! {
  quote_finder.should_receive(:find_quote).once.
               with(…whatever…).
               and_return(quote)
  quote.should_receive(:create_revised_quote).once.
        with(…whatever…).
        and_return(”a new quote“)
}

Finally, the result of the function-under-test should be the new quote:

quote_finder = flexmock(”quote finder“)
quote = flexmock(”quote“)

during {
   some function 
}.behold! {
  quote_finder.should_receive(:find_quote).once.
               with(…whatever…).
               and_return(quote)
  quote.should_receive(:create_revised_quote).once.
        with(…whatever…).
        and_return(”a new quote“)
}

assert { @result == a new quote }

I felt a bit of a fraud, since I’d shoved a lot of important behavior into tests that would need to be written by someone else (including the original purpose of the test, making sure the next Quote was a different object than the last one.) The team, though, gave me more credit than I did. They’d had two Aha! moments. First, the idea of “finding a quote” was spread throughout the code, and it would be better localized in a QuoteFinder object. Second, they decided it really did make sense to have Quotes make new versions of themselves (rather than leave that responsibility somewhere else). So this test gave the team two paths they could take to improve their code.

In the beginning, the QuoteFinder and Quote#create_revised_quote would likely just delegate their work to the existing legacy code, but there were now two new organizational centers that could attract behavior. So this looks a lot like Strangling an App, but it avoids that trick’s potential “then a miracle occurs” problem of needing a good architecture to strangle with: instead, by following the make-an-object-when-you-hesitate strategy that mocking encourages, you can grow one.

I’ve not seen any writeup on using mocks to deal with legacy code. Have you?

P.S. It’s possible I’ve gotten details of the story wrong, but I think the essentials are correct.

About “Business Value”

I’m notoriously long-winded on Twitter. Here’s what I wrote earlier today:

Bv2

Bv3

What do I mean by that?

In my research into your species, I’ve noticed that humans are social animals. With the exception of ideologues and other damaged people, you work best when your work is oriented toward other people. Not “people” (in the abstract), but actual individuals. Because you’re quite good at personifying objects—look how many of you act like your boats are people—you can also do well when oriented toward improving those object’s “lives”. (That is, you treat your software the way you treat your pets, which is not that different from the way you treat [some of] your loved ones.)

When it comes to software development, I’ve seen teams that are extremely… nurturing toward the product owner. I’ve seen teams that treat the product itself as a person to be groomed and prepared for its entry into the world. I’ve seen teams that identify strongly with the prototypical, personified, or actual end user and want to make her life easier.

Quite often these teams, especially Agile teams, seem obsessively focused on “Business Value”, but that’s in the context of personal relationships. “Business Value” is a shorthand, a way of keeping conversations from going astray, of keeping people focused. It is a term that signals or reminds of other things—it is not a thing in itself.

Increasingly these days, when I hear people theorizing about Agile and Lean, they are treating “Business Value” as a thing in itself. It is treated as an end, rather than as a means. (This is in keeping with the decline of Agile as a bottom-up team-oriented insurgency.)

Who cares? The good thing about old-style Agile is that it tamped down teams’ tendency to be overbearing while still involving them in the conversation about what makes the product better. Code is generative, and programmers could—and did—suggest directions the business could take based on what the code “naturally” “wanted” to do. This could lead to wonderful and illuminating conversations.

When Business Value is determined from On High and is a discrete thing in itself—a product of expertise not accessible to the hoi polloi—this conversation is short-circuited. Analysis (the province of Business) populates swimlanes on the Kanban board or the product backlog. When Development takes an item from the Analysis backlog or swimlane, the signal it sends upstream is “I need a new chunk of work” not “Let’s talk about the next good idea.”

That is: your species has another skill. Just like you’re good at turning objects into people, you’re good at turning people into objects. It’s easy for you to subordinate actual humans to the beauty of a System. You’re terribly prone to slip into ideology, to elevate objects to totems-to-be-deferred-to. “Business Value” is, I fear, becoming one such totem.

To forestall the inevitable comment: I know (I know!) that in a well-functioning organization with Respect for People, the ugliness I describe wouldn’t happen because wise philosopher-kings wouldn’t let it. I just believe there is a shortage of such wise philosopher-kings and—in their absence—we should cut with the grain of human nature.

Attitude of the development team to the product

Back in the old days, most of my Agile consulting was coming into well-performing Agile teams who wanted to talk about improving their testing. So I got to see a lot of seasoned teams. What struck me most, and made me happiest, was their stance toward their product and the product owner. Proud. Enthusiastic. Engaged.

Dave Hoover of Obtiva has been working on a product called Mad Mimi for some time. At my request, he’s collected some of his tweets about it. He exemplifies that attitude I so enjoy. To pique your interest, here are some samples:

Wow, @madmimi has had a great 24 hours. Seems like a tipping point is coming soon. Really exciting to witness this stuff first-hand.
Thu Jul 10 17:34:40 +0000 2008

Sheesh, I’m really impressed by the emails that people are putting together with @madmimi: http://madmimi.com/promotions/3295200582152/raw
Thu Nov 20 13:47:40 +0000 2008

@ByENNEN: Your wish is @madmimi’s command. Have a look now. :)
Tue Dec 30 20:14:24 +0000 2008

In awe of @madmimi today. Went from $100k/year in revenue to $200k/year in revenue in just 2 months. Zero dollars spent on advertising, FTW!
Wed Jan 14 22:04:50 +0000 2009

Fell asleep at 9 last night in the living room “tent” with the boys. Up at 4 this morning. Couldn’t stop myself from hacking on @madmimi.
Mon Feb 16 13:31:44 +0000 2009

@Kellypaull Yes, I use @madmimi. I also built it. :)
Mon Apr 20 05:29:20 +0000 2009

Twitter Driven Development: 13 days ago @misterpowell complained about @mailchimp’s RSS-to-Email. Today, @madmimi released its RSS-to-Email!
Wed Jun 03 21:48:36 +0000 2009

I’m so biased nowadays. Every newsletter I receive via Constant Contact makes my stomach turn. Hard not to reply with @madmimi evangelism.
Mon Jun 22 21:34:06 +0000 2009

This song about @madmimi just made my day http://is.gd/1rnQ8
Wed Jul 08 19:54:48 +0000 2009

Can’t sleep after reading @mfeathers‘ blog post and checking the latest @madmimi subscription numbers…
Thu Sep 10 05:10:12 +0000 2009

Here’s the whole list.

Delivering value

It’s quite the rage today to talk about “delivering value” as opposed to “delivering software”. That scares me.

Consider the contractor who had our house in chaos for what seems like forever. We now have more counter space in the two upstairs bathrooms. I think you could make a strong argument that he would have delivered more value to us if he’d taught us–two of us in particular–how to more efficiently use the space we already had. And yet I’m glad he didn’t. I preferred him to deliver what we wanted to pay him to deliver.

On the other hand, my dad built houses. I remember him once telling a prospective client that the architect’s plans they had were wrong. Given the man’s job, he’d come home dirty every day, so he’d probably want to go directly to the shower. The plans had him tromping all through the house. Instead, he needed a doorway from the garage to a little hall with a bathroom one step away. I think they let him redraw the plans, thereby delivering more value.

So there’s a tricky balance here. Are we up to it?

As my wife put it the first time she met my friends, “You software people have really strong opinions… about everything!” The average software person is more likely than, say, the average veterinarian to talk to someone briefly about her job and immediately come up with ten ways she ought to do it better. Telling such a jumper-to-conclusions that the team should look beyond what the business wants to what it needs is… maybe tempting them to play to their weaknesses.

I would instead tell a team they must, over the course of many months, prove to the business that they are worthy of being invited to the larger conversation about what the business needs. And to do that, they must–first and foremost–deliver what the business wants, while also acting as a humble student of that business.

Want to pair with me?

I’ll be flying out of Miami for SpeakerConf. I’m thinking of taking the train there, and stopping to pair with people along the way (in the manner of Corey Haine’s pair programming tour). The basic idea is that we should pair on some real software that either you or I are working on right now. The type of software or programming language doesn’t matter. If you feed me or give me a place to sleep, that would be fine - but not necessary.

If you’d like to do that, send me mail.

I could take one of two trains to Washington, DC. The first follows this route:

Ord-Dc

or this one:

Chi-Dc2

From DC, I’d travel down the coast along this route:

Downward

Growing Object-Oriented Software - In Ruby!

I’m working through Steve Freeman and Nat Pryce’s Growing Object-Oriented Software, Guided by Tests, translating their Java into Ruby. I’ve put it up as a Github project if you’d like to follow along.

In praise of spiffy GUIs

Apps have business logic that hides behind a GUI. As a command-line person and a former tester who was always thwarted by the GUI when I wanted to test the business logic, I was always suspicious of GUIs. That’s perhaps the reason I once argued with Nathaniel Talbott that GUIs should be crude until a bunch of features were done. My argument was that (for most applications), the business logic is where the value comes from, so you should spend your money there first.

I now suspect I was wrong, for these reasons:

  • When the users and those who pay for the software are delighted by it, everyone benefits. For example, they become much more willing to spend time with the team. Most people won’t be delighted by even the greatest feature that’s hidden behind a cruddy GUI. Delight is an emotion: you can’t just turn it on with intellectual appreciation.

  • The team needs to be enthused by the app too. Visual and kinesthetic aesthetics contribute to that.

  • I thought that good business logic could support whatever GUI was needed. That is, I fell once more into the heresy of ideal forms and phase-ist thinking: our job as technical people was to find some perfect abstractions, and any old GUI could be layered onto that.

    I now believe that the presentation and content are much more intertwingled. It’s silly, really – I’ve been a successful speaker since about 1995, and I certainly knew that was true of presentations. Somehow I didn’t suspect it was true of software.