The End of Endotesting?
September 14, 2008
…or why Mockito is my new friend.
So what’s endotesting?
The pioneers of the technique we now know as mocking presented a paper at the XP 2000 conference, where they first introduced the idea to a wider audience. They prefaced it with the quote:
bq. “Once,” said the Mock Turtle at last, with a deep sigh, “I was a real Turtle.”
The Lewis Carroll reference appeals to me because I often cite Humpty Dumpty as the real creator of behaviour-driven development:
bq. “When I use a word, ” said Humpty Dumpty in a rather scornful tone, “it means just what I choose it to mean, neither more nor less.”
These folks – Tim Mackinnon, Steve Freeman and Philip Craig – realised that you could drop in a fake instance of an object that you could get to “fail fast” if it received a method call it wasn’t expecting:
bq. We propose a technique called Mock Objects in which we replace domain code with dummy
implementations that emulate real code. These Mock Objects are passed to the target domain
code which they test from inside, hence the term Endo-Testing.
This approach – endotesting – led to the creation of a number of open source frameworks, most notably JMock (written by Tim and Steve among others) and EasyMock. The basic premise of these frameworks was to make it easy to create a mock object and prime it with a number of expectations. (Your makeCheese method will be called with the parameter @”brie”@. When this happens, return the value BRIE.)
Having set up a mock object with its expectations, you wire it up into a bunch of objects and then poke the outermost object. If all goes well you can interrogate your mock and it will tell you its makeCheese method was called. If it doesn’t go well – well that’s when the magic happens. If you call an unexpected method on a mock it will fail during the test, giving you a stack trace from exactly where the unexpected method call happens. You don’t have to start rummaging through the call sequence trying to work out where it all went wrong, and your test doesn’t carry on running after the unexpected method call to produce a bogus result that doesn’t make any sense.
How we use mocks
Now if you are wiring together a complex group of objects to do something, endotesting-style mock objects are invaluable. I had a situation a while ago where we had a suspect XML message being sent over the wire to an external system. We wrote an integration test where we injected a mock for the external system into a complex object structure – the mock was primed to only accept a valid XML message – and when it failed the stack trace gave us a direct line into the failure. It turned out one of the eight objects wired together was doing an incorrect transformation on part of the XML which meant the outbound message was invalid. By using a mock object in this way we were able to identify exactly where the error was occurring.
However nowadays mocks are mostly used for describing interactions between objects in the context of test-driven development. Your object under test interacts with one or two other objects that you represent by interfaces (roles) that you probably inject into its constructor as mocks. Your test is verifying that the object calls the appropriate methods on its collaborators. In this simplistic scenario, the reason for a failure is usually pretty obvious – you haven’t written the code yet or you are passing the wrong parameters into the method call.
Say you are developing a simple calculation where you expect the answer to be 7 but the code is producing the answer 10, then it isn’t that difficult to work out where the problem is. You don’t need the code to fail as soon as the value of 10 is produced. The fact that the answer is 10 and you expected 7 is enough to triangulate the error. This is classic post hoc state-based testing. Similarly, if you expect your object to call makeCheese on the CheeseFactory and it doesn’t, well you are likely to have a pretty good idea where it doesn’t. So all you really need your mocking library to do is act like a flight recorder black box. You can ask it after the fact: hey CheeseFactory, did my object call your makeCheese method? If it didn’t you probably know why. (And if you don’t it may be an indication that your test is too complicated.)
A more intuitive approach to mocking
This then means that you can treat assertions on method calls just like you treat assertions on state changes, asking the various collaborators what happened after the fact rather than priming your mock objects ahead of time, which in turn means you don’t need to turn your brain inside-out creating a flow like this:
// Given
// ... create mocks
// ... wire up my object
// Expect (eh?)
funky.dslWith("stringsForMethods")
// When
myObject.makeBrie();
// Then
verifyExpectationsSetTwoParagraphsEarlier(); // you remember right?
where it is much more intuitive to write something like:
// Given
// ... create mocks
// ... wire up my object
// When
myObject.makeBrie();
// Then
verify(CheeseFactory).makeCheese("brie"); // how nice is that?
This, then, is the premise of Mockito. It uses a similar syntax to EasyMock – which means my generics-aware IDE is able to do proper completions and refactorings – but it doesn’t have any of that record/playback nonsense. Nor does it require me to do any of the clever @{{ anonymous constructor }}@ gymnastics that JMock 2 introduced. It just sets up mocks on interfaces (although it allows me to mock concrete classes which I think is a retrograde step – remember kids, mock roles, not objects) and gives me a black box recorder that I can interrogate after the fact.
When I asked Mockito’s author, Szczepan Faber, how he came up with the insight that mocking in the context of TDD was a completely separate problem from endotesting, he replied: what’s endotesting?
It turned out that in order to create a mocking framework to support TDD it helped to have no idea where the encumbent frameworks – JMock and EasyMock – had come from. In the same way that a unit testing framework got co-opted as the enabler for TDD in Java, an endotesting framework became the enabler for method assertions in interaction-based testing. But if you start from the ground up – with a nod to EasyMock and with a pragmatic dose of Java 5 generics – you can get a simple, elegant and intuitive framework for verifying interactions between collaborators. There’s still a place for traditional endotesting in the context of gnarly integration tests, but I’m liking Mockito. I think you will too.
JBehave 2.0 is live!
September 8, 2008
Some ancient history
Back in 2003 I started work on a framework called JBehave. It was an experiment to see what JUnit might have looked like if it had been designed from the ground up for TDD rather than as a unit testing framework. I was also starting to use the phrase “behaviour-driven development” to describe what I meant. The jbehave.org domain was registered and the first lines of code written on Christmas Eve 2003, much to my wife’s bemusement. Over time JBehave grew a much more interesting aspect in the form of a framework for defining and running scenarios, or automated acceptance tests.
Since JBehave wasn’t based on JUnit there was always going to be a barrier to adoption in the form of IDE integration and build tools, among other things. It also failed the First Law of Frameworks in that it wasn’t harvested from real life – it was just an extended thought experiment. As a result it turns out it was a bit of a cow to use. Mea culpa.
Some recent history
Many of the ideas from JBehave have since appeared in other BDD frameworks, particularly in the lovely rspec. Although I wrote the first cut of the scenario runner in rspec it has since been thoroughly reworked and improved beyond all recognition1 by the efforts of David Chelimsky and his team. The biggest single improvement has been the introduction of plain text stories, which allow you to separate the scenario text from any of the automated steps they refer to.
Over the last few months, Liz Keogh and Mauro Talevi have completely rewritten JBehave from the ground up, taking advantage of new Java 5 language features and using JUnit 4 as the underlying execution framework.
By using real project examples to drive the design – including using it in their day jobs – they have produced what I believe is a powerful and very usable behaviour-driven development framework for Java. In particular Liz decided she wanted plain text scenarios and the idea of a “pending” scenario – something that you have identified but not yet implemented.
And now…
We’ve released it! JBehave 2 has only been live for a few days and already ThoughtWorks colleague Ryan Greenhall has written an excellent tutorial demonstrating how to use it. Quoting the release announcement on the site, JBehave 2 supports the following feaures:
- Plain text scenarios
- Support for multiple scenarios in a file
- Pending scenarios (the “Amber Bar”)
- Clear, easy-to-read output from failures and pending scenarios
- Maven support
- Parameter capture from scenarios
- Conversion of parameters to your own objects
- Support for multiple languages and scenario terminology
- A high degree of configurability
Go download JBehave 2 and take it for a spin, and let me know what you think. The mailing lists are waiting for you too.
1. Aslak Hellesøy is currently working on a replacement for the rspec scenario runner called Cucumber which looks very promising.
Let your examples flow
June 30, 2008
Should examples/tests/specs/whatever be DRY(Don’t Repeat Yourself)? I’ve been thinking (and talking and arguing) about the value of test names recently and whether they are just unnecessary duplication, but that’s the subject of a future discussion. This is about the actual content of your examples. So, should your examples be DRY?
In a word, no. DRY zealotry is a classic example of an over-adherence to Best Practices, which as James Bach argues are a bogus concept anyway. When you are writing software, including executable examples, your focus should be on clarity of intent. If the code could be any more obvious, you’re probably not done yet. And given that code is created once but read and changed many more times, it is healthy to develop a strong sense of responsibility to the guys coming along after you.
In tests, flow trumps DRY
The DRY principle says that the definition of any concept should appear once and only once in your code. This is an admirable aim in that if you have to change the behaviour of a Flooble, you want to be able to change it in one place and be reasonably confident that your change will apply consistently across the codebase. If there are multiple definitions of a Flooble, the chances are that not only will you not catch them all, but that someone before you didn’t catch them all and the multiple definitions are already inconsistent, and who wants that?
However, when you are using examples to drive your code – a process I call Coding By Example but which most other people insist on calling Test-Driven Development – there is another principle in play that I believe trumps the DRY principle. The examples tell a story about what the code does. They are the documentation narrative that will guide future programmers (including yourself when you come back to change this code in three months time and you’ve forgotten what it does). In this case, clarity of intent is found in the quality of the narrative, not necessarily in minimising duplication.
Some years ago I had my first experience of pair programming with Martin Fowler. That is, I had done quite a bit of pair programming, just not with Martin before. We were looking at some ruby code I had written test-first, and Martin asked to see the tests, “to find out what the code does”. Then he did a rather odd thing. He started moving the tests around. I had a few helper classes and utility methods in the source file, neatly at the end out of the way. He moved them up and dropped them inline just ahead of the first test that used them.
Madness! I thought – now the supporting code is all over the place! It really offended my sense of tidiness. But then I saw a pattern beginning to emerge. The test code was starting to read like a story. He would introduce these little methods and classes just before their one walk-on line in the narrative. It was quite an eye-opener for me. The test code flowed, and unfolded the story of the class under test. (I know I’m using TDD vocabulary – this was in my pre-BDD days.)
Go with the flow
The A-ha! moment for me was when I imagined reading a story book where the plot and characters had been DRYed out. Everything would be in footnotes or appendices. All the character descriptions, plot elements, subtexts etc. would be carefully extracted into fully cross-referenced paragraphs. Great if you are “reading” an encyclopaedia, not so appropriate if you want to get into the flow and find out what happens. You would be forever flicking back and forth in the book and you would very quickly forget where you even were in the story. In the words of the old joke, a dictionary has a lousy plot but at least they explain all the words as they go.
So here’s my challenge to you. When you read through a test case, or spec file, does the story unfold? Does it start by introducing the object’s most important responsibilty? Does it then introduce the edge cases in descending order of priority? If the test uses helper classes and methods are they tucked away at the end, or worse yet in an entirely different file that I am expected to “just know” is there?
Try to avoid using before blocks or setUp methods – especially in an abstract test class. Just call the method that does the setting up directly from the example. Don’t leave me to guess there might a magic method in a different class that is being invoked before the test even runs – that’s just not fair.
Also thanks to Mikel Lindsaar from the rspec mailing list for an excellent article about the perils of slavishly following DRYness.
[mikel]http://www.lindsaar.net/2008/6/24/tip-24-being-clever-in-specs-is-for-dummies
Learning to Lean
June 29, 2008
A discussion unfolded recently on an internal mailing list that tied together two of my favourite topics, namely learning theory and Lean.
Someone was asking how they might apply Lean to setting up and running a new project. A number of people made suggestions, all of which were the kind of good common sense I would expect from my ThoughtWorks peers, but what particularly struck me was the way the answers exemplified the different stages of the Dreyfus Model of Skills Acquisition. (The link is to an interview with pragmatic programmer Andy Hunt, whose forthcoming book Pragmatic Thinking and Learning contains an excellent chapter on it).
[prag-book]http://pragprog.com/titles/ahptl/pragmatic-thinking-and-learning
The Dreyfus Model of Skills Acquisition
As well as providing a useful description of each stage of learning, the Dreyfus model describes how best to help the learner progress to the next stage in their learning.
[cc-model]http://en.wikipedia.org/wiki/Four_stages_of_competence
[shu-ha-ri]http://en.wikipedia.org/wiki/Shuhari
According to the Dreyfus model there are five distinct stages, as the learner gains experience and develops insight and intuition. Very briefly:
The Novice wants recipes, best practices, quick wins
The Advanced Beginner wants guidelines, a safe environment to make mistakes
At the Competent stage you want goals, freedom to execute
The Proficient learner wants maxims, war stories, metaphors
The Expert wants philosophies, discussions and arguments with other experts(!)
So back to the mailing list discussion, here’s what I saw in amongst a number of responses. (I’m paraphrasing and summarising for effect.)
Novice: I like the sound of Lean and I want to apply it to my next project. Where should I start?
…
Competent: Here’s my cheat sheet of Lean practices and behaviours.
…
Expert: Lean isn’t a process, it’s a philosophy.
Perfect!
So why such a wide spread of different answers? The problem is that when it is applied to software delivery, Lean is a metaphor, which means it’s too abstract for a novice to “just use” without making it situationally specific, and too concrete for an expert to articulate easily. For example, the Lean concept of inventory applies in a number of subtle ways to software delivery.
It is worth mentioning that the Dreyfus model is about describing the acquisition of a specific skill – in this case applying Lean theory to software delivery – and not a general categorisation of an individual. For instance the author of the reply from which I took the “competent” fragment above is an accomplished agile coach and developer, so be careful not to take the Dreyfus descriptions out of context. (But you wouldn’t do that, would you? I meant the others.)
Getting started with Lean
So then I thought, what would be the most useful advice to an experienced Agile team lead to get started? To kick a project off in a Lean way, I would suggest the following:
p(. 1. Get everyone immersed in some Lean theory. Use workshops with lots of interactive exercises. Be aware they are at the novice stage so they will find rules and recipes – and quick wins – more useful than context at this stage, even if the specifics aren’t strictly correct. “It depends” is never helpful here. Ship in your local Lean expert – Richard Durnall or David Anderson in my case – and steal some collateral from the intertubes. Share with the team that you’re new to this too – it will make them less afraid.
[david-anderson]http://www.agilemanagement.net/Articles/hidden/Biography.html
p(. 2. Think about how Lean applies to software delivery. For instance, there are three “flavours” of Lean, namely Manufacturing, Supply and Product Design. Although they all focus on minimising waste, they also have specific targets in mind.
- Lean Manufacturing is about minimising variance (you want all the cars to come out the same). This is analogous to build, deployment and running automated test suites. The same code should always produce the same deployable artefacts. Test runs should be idempotent (rerunnable with the same results).
- Lean Supply is about minimising inventory. This is analogous to deferring decisions, doing enough up-front analysis and design but no more (and certainly not none, otherwise you starve your supply). Have a nominal backlog of features but don’t bother planning out 3 months of detailed Master Story List (that term should never have made it out of the gate). Carry out exploratory testing soon after the feature is code complete, when it’s still fresh in the developers’ heads.
- Lean Product Design is about maximising discovery. Everything is an experiment, and if you don’t learn anything it wasn’t useful. This is analogous to writing software, understanding and articulating requirements, user experience workshops, designing effective tests, identifying corner cases. Foster an environment where it’s ok – in fact encouraged – to try new stuff “just in case”, or run two or three ideas in parallel to see which one fits best. That isn’t waste, it’s a good discovery habit that you can position as due diligence. Read up on innovation techniques and creating an innovative working environment. Your programmers aren’t building cars – they’re designing cars. Let them. Make it fun.
p(. As a example of mis-applying the metaphor, methodologies like six sigma mistake innovation (discovery) for waste (variance) so they squeeze the innovation right out of the process. (They call innovation, sorry variance, “defects” – cute.)
[six-sigma]http://www.isixsigma.com/sixsigma/six_sigma.asp
p(. 3. Break down your process into swimlane steps. It doesn’t matter whether it’s right (it won’t be) or whether it fully describes your process (it won’t). What matters is that people are thinking in terms of moving something from an idea to signed off, deployed code (“from concept to cash” as Mary Poppendieck describes it). Use simple index cards to represent work on a big visible wallchart. Moving a card across swimlanes is a small win. People like frequent small wins.
p(. 4. Keep track of where the cards back up. This is a clue to bottlenecks. It may not be that the backlog itself is the problem – it’s just a starting point for your investigation. Apply a systems thinking approach – what could be causing that? What else?
p(. 5. (once you’re getting the hang of it) Apply Lean thinking to your process itself. That’s one of the cool things about Lean. It’s not just about getting work done – it’s about getting better at getting work done. This is when you start looking at your process and identifying the actual value stream as opposed to “the stuff you do”. Are there activities that are just there because “we always do that”? Are there things you spend time on that are so “obvious” you didn’t bother capturing them as their own swimlane?
There’s a ton of literature out there about Lean – and some of it is quite good – and a small-but-growing body of Lean practitioners within the software industry. We can’t actually clone Richard Durnall, but we can learn from him. As long as we choose to believe we’re always learning, we should be in pretty good shape.
ps. Another quote from the Lean expert on that email thread – Richard again – was that there aren’t Agile projects or Lean projects, “there are just projects”. This reminded me of a famous Bruce Lee quote. “Before I studied the art, a punch to me was just like a punch, a kick just like a kick. After I learned the art, a punch was no longer a punch, a kick no longer a kick. Now that I’ve understood the art, a punch is just like a punch, a kick just like a kick.”
[bruce-lee]http://www.fightingmaster.com/masters/brucelee/quotes.htm#On%20simplicity
Raising money for Leukaemia Research
June 18, 2008
Right now I have a whole pile of blog articles backed up that I’m in the middle of writing. This post jumped the queue because it is by far the most important.
Leukaemia and other blood cancers are the main cause of cancer death in the under 35s (a demographic of which I am sadly no longer a member, but some of my best friends are under 35). Leukaemia itself is the most common form of cancer in children in the UK.
On 13th July – only three weeks away – I will be taking part in the 2008 London Bikeathon, cycling 26 miles (about 42km – coincidence? I think not) through East London and out the other side. And back.
Please sponsor me – as much as you can spare, or as little as you can find. If you are in the UK, tick the appropriate boxes and our fine tax officials will donate an extra 25% on top of your donation.
Thank you.
Hacked!
May 25, 2008
If you are reading this with Internet Explorer 6 you are at risk
Ok, first things first. If you read this blog using IE6, you should check your machine for malware using Microsoft’s anti-malware tool or your favourite anti-virus suite. You should also consider installing Firefox with its ad-blocking goodness and lack-of-ActiveX-ness.
For several weeks I’ve been unsuspectingly handing out evil in the form of a hidden @ <iframe> @ tag, as well as having loads of poker-related links hidden in another article. According to my friend Joe Walnes, the iframe exploit installs a tiny “zombie” service through vulnerable IE6 browsers that hides in your Windows machine awaiting instructions.
I am hugely grateful to “noreply” at Google who mailed me to tell me this was the case – I really had no idea. It turns out Google were prefixing any search results to my site with a big sign saying “this man is a cheesy purveyor of malware”. Good for them – I was! And doubly good for them, they told me. Also thanks to a chap called David who pointed out the poker links.
You can never be too careful
I like to think I run a reasonably tight ship in terms of security. My server is sitting behind a firewall, running a solid Linux distribution with @/bin/su@ disabled (in favour of the more secure sudo), which you can only log into as a non-root user with an ssh key. In other words I could give you the root password and it would be pretty much useless unless you were sitting at the console. I upgrade WordPress whenever they produce a new version. I use mercurial to allow me to roll forward or backward across upgrades, because, well, why wouldn’t you?
However it seems some evil pondscum used an exploit in a file called xmlrpc.php to inject hidden badness into the body of a number of blog posts. I’ve now disabled xmlrpc.php, but anyone using WordPress should be aware that there are lots of exploits some of which are still unresolved, and should lock down their installation accordingly. Naturally something as popular as WordPress is going to be a target for hackers. I certainly learned a lesson about being over-confident.
Better Best Practices at ExpertZone Stockholm
April 1, 2008
Next week I’ll be talking about Best Practices, a current favourite topic, at the ExpertZone Developer Summit in Stockholm. Last year I ran a half-day workshop about SOA and gave a keynote with Erik Dörnenburg about simplicity in software, and this year I wanted to do something a little different. So when I heard there was a track called called “People Matters Too” I was keen to get involved.
This talk will be completely non-technical, aimed at anyone interested in how we learn and why we rebel when faced with Yet Another Change Programme.
BDD and DDD at Stockholm Javaforum
As an added bonus – for me at least – I’m going to be talking to the Stockholm Javaforum on Tuesday 8th April at 7pm. When I initially agreed to this I thought it would be a handful of geeks hanging out and talking about Java. It turns out they regularly draw around 200 people. And they’ve sold out. Yikes.
I’ve got an hour to talk about the relationship between Domain-Driven Design and Behaviour-Driven Development. I have no idea how I’ll be able to limit that to one hour but I’m going to try my best. This is timely because I am also working on an article explaining my take on DDD and BDD. Honest.
Better Best Practices
March 23, 2008
Last October I was privileged to give a keynote talk at the Øredev conference in Malmö, Sweden. It was a late substitution. The original speaker, testing guru James Bach, had to cancel at the last minute for personal reasons. I felt pretty intimidated stepping into his shoes, especially since the other keynote presenters were Joel Spolsky and Andy Hunt, but I figured since no-one had heard of me I’d probably slip under the radar.
James was planning to talk about best practices, and it seems we have similar opinions about them. I would encourage you to read his wonderful blog article where he rigourously deconstructs the phrase1, and then just as eloquently picks apart the arguments of anyone who disagrees. So I thought I would do something around the same topic.
I wrote it up as an article and the kind folks at InfoQ published it, and the Øredev team has put up a video of the talk. (For some reason I can’t get it to work in firefox on ubuntu, but I’m pretty sure the guy on the left is me).
1. I didn’t realise until long after Øredev that he was the author of that article. It made me very happy when I found out.
Awesome Acceptance Testing at SPA 2008
February 22, 2008
I’ve been pretty slack at letting people know about upcoming talks. I could blame workload or burnout or any number of other plausible-sounding reasons, but a lot of it is just down to not prioritising very well. I should fix that.
A couple of years ago Joe Walnes and I gave a talk at an XP Day entitled “Awesome Acceptance Testing” (blame Joe for the title). We looked at motivations for acceptance testing and discussed various strategies, tools and techniques. But mostly it was an opportunity to get a bunch of people in a room and find out what they thought and what they were up to in the acceptance testing space.
If you didn’t get to see it and it sounds like fun, we’ll be rerunning the session at SPA 2008 in March. I hope to see you there.
Goal-oriented vocabulary – saying what you mean
February 12, 2008
I was in a hotel in Stockholm recently and I noticed a bottle opener attached to the wall in the bathroom. There was a bilingual sign under it which got me thinking about the term “bottle opener” itself. (I was giving a talk about BDD the next day so I was already thinking about how language is used.)
It occurred to me that “bottle opener” is a great example of goal-oriented vocabulary. The device itself is actually a cap remover, and it only works on one particular design of metal cap. The reason I use it, however, is to enable me to get to the beer in the bottle. Hence “bottle opener” rather than “cap remover”.
The task is just detail
There is more to this than just linguistic curiosity. If you use task-oriented vocabulary it can cause you to focus on the means rather than the goal, which in turn can limit your options. My favourite example of this is the term “search engine”. Searching is the activity I have to do because I’ve misplaced my keys and I’m locked outside. What I want is a find engine!
Google realises this. When I type something into Google, it guesses what I’m likely to be trying to find, not what I happen to be typing into the box. If I type in “Stockholm map”, I’m likely to be looking for a map of Stockholm (first three results are actual maps – presented as pictures) or some information about the town itself. If I type “hotels Stockholm” I’m probably planning a trip there and voila! lots of useful results for the traveller. Other “search” engines do just that – they search, and produce lists of results. It’s then down to me to sift out the ones I care about to get me closer to my goal.
“Blur” on a problem
We talk about “focusing on a problem” in order to solve it. This is a task-oriented phrase. An alternative would be to stand far enough back that you see the problem in its proper perspective. If anything you are “blurring” on the problem – deliberately losing focus on the detail to see if any larger-scale structure emerges.
I often describe BDD as outside-in development. You start at the outside with an automated scenario, and work inwards, discovering services and collaborators as you go, until you’re done. With a legacy application it can be difficult to remain outside enough, or to get a good enough frame of reference for “done”. Blurring can help with this.
For the last six months I’ve been involved in restructuring and re-architecting a legacy code base. It’s been quite a major undertaking, and has involved a number of false starts and dead ends. (I’m planning to write it up as an experience report at some point, but given my current throughput of things I plan to write, don’t expect it any time soon.) During this project, I’ve often found myself struggling to choose between alternative strategies, or unsure of where to go next. In these situations I’ve found that stepping back and “blurring” gives me enough perspective for one of the alternatives to become “obvious”. In fact a couple of my teammates have picked up on this and will actually suggest it as an activity when we are pairing. “We’re thrashing here – let’s step back and start from the outside again.”
It could be as simple as asking “whose responsibility is this feature?” or “who is the actual client of this method call?”. You don’t need to know the answers – just verbalising the questions can give you enough “blur” to gain a better perspective.
Blur on time as well as space
Linus Torvalds recently gave a talk where he said the problem with source control isn’t branching, it’s merging. Again, by taking a broader perspective – in this case temporal rather than spatial – his insight is that the goal is a successful merge some time in the future, not the task of branching now.
As a final thought, while I was thinking about this I realised the term “behaviour-driven” contrasts with “test-driven” in a similar way. My goal as a developer is to deliver a system that behaves in a particular way. Whether or not it has tests is an interesting metric, but not the core purpose. “Test-driven” development will cause me to have lots of tests, but it won’t necessarily get me nearer the goal of delivering business value through software. So you can use goal-oriented vocabulary in your development process as well as your code to help maintain perspective on what you are trying to achieve.
_Props to James Lewis for helping me formulate these ideas. And for being really good at perspective._
