Sunday, 23 December 2012

Yadda yadda yadda

Rob Fletcher's excellent Grails For Hipsters session at this year's Groovy and Grails exchange inspired me to have a play with CasperJS. It's a super fast, super slick, headless web test tool built on PhantomJS. Unfortunately there is a price to pay.

1. PhantomJS is a headless webkit implementation so your tests won't run against Firefox or IE.
2. There's no BDD support.

I can't do much about #1 but there was something I could do about #2. Back in the day I wrote an extension to Selenium IDE providing cucumber/gherkin like language support. It was pretty clunky, but functional (no pun intended). I dusted it off, removed the Selenium cruft, renamed it "yadda" and github'd it here. You can now write your CasperJS tests like this...

   "When I open Google's fr search page",
   "then the title is Google",
   "and the search form exists",
   "When I search for foo",
   "then the title is foo - Google Search",
   "and the search for foo was made",
   "and 10 or more results were returned"
]); {

Since the yadda core is just a library for mapping steps (e.g. "When I search for foo"), to javascript functions, it will work without CasperJS and can hopefully be plugged into other JS testing frameworks without too much difficulty. Feel free to fork the project and send me a pull request if you do so.

Friday, 26 October 2012

I was wrong

I'm naturally a cynic. Sometimes this is a useful character trait, but it can also inhibit learning and dampen optimism. To combat this I try to replace my cynicism with genuine curiosity. It's a strategy that is paying off.

Last night I attended the 2012 Agile Awards. Before the event my cynicism meter was somewhere between DEFCOM 2 and 3. I had deep reservations about some of the shortlisted nominees and was concerned that the event would fall somewhere between an Agile nerd convention and an ego inflation exercise. Why would I want to attend something like that? The answer is curiosity - how would I know if my fears were legitimate unless I went and saw for myself. I'm very glad I did, because I couldn't have been more wrong.

Firstly all but one of the nominees I had reservations about had been nominated for work I was unaware of.

Secondly the nominees I knew and who did win were well deserving.

Third, the guests I spoke to were friendly and interesting. Not at all self inflated.

Fourth, I'd been dubious of the "Best Agile Newcomer" category. Unlike Most Valuable Player or Most Valuable Innovation, I didn't think that being "new" was a special cause for celebration. Once again I was wrong. The crowd's rousing cheer and Emma Hopkinson-Sparks obvious delight at winning was the highlight of my evening.

For the record, I was right about two things. The food and organisation were both excellent. I've known Simon Voice long enough to be confident that he wouldn't be so closely associated with anything that wasn't. It was however my first time for meeting his wife Julie, who was responsible for the event coordination (with credit to their daughter for choosing the music). So well done Julie, Simon and everyone else who worked so hard to put together a brilliant evening. I'm delighted to be proved so thoroughly wrong once again.

Friday, 5 October 2012

How Stages Of Learning Should Influence Coaching Style

The Japanese martial art concept of Shuhari identifies three stages required to reach mastery,
  1. Learn
  2. Detach
  3. Transcend
Another learning model, the Four Stages Of Competence, is defined as follows:
  1. Unconscious incompetence - The individual does not understand or know how to do something and does not necessarily recognise the deficit
  2. Conscious incompetence - Though the individual does not understand or know how to do something, he or she does recognise the deficit, as well as the value of a new skill in addressing the deficit.
  3. Conscious competence - The individual understands or knows how to do something. However, demonstrating the skill or knowledge requires concentration.
  4. Unconscious competence - The individual has had so much practise with a skill that it has become "second nature" and can be performed easily.
The Dreyfus model of skill acquisition (which I've selectively quoted for brevity) goes yet further with five stages,
  1. Novice - Rigid adherence to taught rules
  2. Advanced Beginner - Situational perception
  3. Competent - Formulates routines
  4. Proficient - Holistic view of situation
  5. Expert - Intuitive grasp of situations based on deep, tacit understanding
and some petition for inclusion of sixth stage, "Innovation".

There's clearly a degree of overlap between the models and I think it's important to be aware of these concepts when coaching. I've previously blogged about how autonomy is a key component for intrinsic motivation, and while I've not yet written on the subject am generally against Command and Control leadership styles. However I've begun to wonder if, considering the above learning models, whether an autocratic approach might be necessary for novices - those who require a prescribed process.

I suspect this might work well for individuals who are "Consciously incompetent" and may welcome a set of rules to follow, but less well for individuals who are "Unconsciously incompetent", and may feel undervalued or patronised.

It's also common for people to transition backwards from "Consciously incompetent" to "Unconsciously incompetent". They know enough to be dangerous as the saying goes. While in this state attempting to prescribe a process is likely to cause friction and harm morale. It might be better for the individual's personal development to let them fail. Not only will they hopefully revert to being "Consciously incompetent", but they may also acquire the valuable gift of humility.

Yet another possibility is that an individual may actually be competent, but lack confidence in their own ability, i.e. "Unknowingly competent". A skilled coach might recognise this, and assign some task that forces them out of their comfort zone, but I've also seen this backfire. It can cause the individual great anxiety and stress, so once again a culture that tolerates failure becomes important.

Once an individual reaches the level of "Conscious Competence" then I think the coaching style should focus on helping them detach from any previously prescribed process and ultimately lead to them transcending any formal process at all.

Sunday, 9 September 2012

In Your Face Build Alerts With Jinkies

I'm pleased to be presenting at this month's Energized Work Tek Talk on Wednesday the 12th September. During the session I'll discuss why I think audible build alerts are important and introduce Jinkies - an open source application for screaming at you when your build breaks and whispering sweet nothings when you fix it. I'll talk about our decision to develop the web interface on a set of RESTful services and how we implemented this in Grails. I'll take you through how our automated tests use Betamax to stub REST responses, and Cucumber for BDD. I'll also discuss the mistakes we made and what we'd do differently next time.

The session has already sold out, but it's not uncommon to have spaces open up last minute so it's still worth registering if you'd like to come.

Wednesday, 29 August 2012

A Case For Pair Programming - The Follow Up

A few days ago I presented a case for pair programming. Around the same time Gus Power forwarded Paul Graham's insightful article on the Maker's Schedule to the Energized Work mailing list. In response Kris Lander made the following statement...
This just adds to my growing belief that there are a lot of things we could do to improve the way we work both individually and as a team and that we might have to take a second look at a number of things we've been quite evangelical about. Pair Programming is one that I'm really starting to change my view on for example.
My ears pricked up. EW crew members are some of the best around, so when one of them makes a statement that appears to challenge my beliefs it's worth finding out more. I asked Kris to expand. He went on to explain while he valued pair programming, he thought it could be wasteful in some situations. He also suggested that when working alone, one may learn more effectively through trial and error than when working in a pair. It's well understood within Lean Software Development that it is not the fastest or biggest organisation that survives, but the one that adapts most quickly, hence great value should be place on learning, and this could potentially outweigh the benefits of full time pair programming. Furthermore learning (or mastery) is one of the key ingredients of intrinsic motivation, whereas working with someone always one step ahead of you can be demoralising. Finally Kris said he found that working in a full time pairing environment can lead to stagnation, since there is less opportunity to experiment. When working alone, you might permit yourself to briefly investigate something that catches your interest, even if it is not directly relevant to your story. Working in a pair this is less likely, and not everyone will have the time or desire to do this outside of office hours.

The discussion went on for days, with other Energized Workers supporting Kris' view. Simon Baker reminded us of what Kent Beck wrote in is original book on XP. I'm ashamed to say I don't have a copy to hand, but Simon summarised things nicely by saying...
He strongly advocates personal time for people to cut code, explore ideas, spike, make a mess, learn. Then to bring their ideas and discoveries back to the pair and cut the production code. This way people get a chance to at least have a crack at something once, then to do it again in a pair boosted by what they've tried previously, eliminated and learnt.
Kev Richards added that he's always found it hard to let other team members struggle over something, trying to get to grips with it and understand it. But the struggle is necessary - no pain no gain! By helping them understand, frequently he's getting in the way. However he also warned that the results of not pairing could be a nightmare.

Odette Power was reminded of a recent engagement where she learnt more in one day's pairing than in the first four weeks, but also said she often prefers to thrash a problem out on her own in order to really understand it.
In short, I think I'm with Simon (as Kent said) - pairing at the right time, and in a ready state of mind (fresh, new problem domain) is amazing. But not all the time. We know the what and the how- but let us not forget the WHY.
Tom Dunstan paid tribute to the benefits of pairing, but also believes that learning can be most effective when done alone...
Levelling up has to be personal trial and error. Even doing something badly and having someone point out a better way is still better than never having done it yourself.
Chris Pitts joined the party late,  but also agreed that pair programming should not be a full time activity...
When it works, it works beyond my wildest dreams, but it is fragile. Like a lot of agile techniques, it falls apart quickly if the wrong attitudes are present. The usual rules of honesty, humility, respect, and more than a bit of thick skin need to apply at all times. As always, the main problems are usually in the wetware. 
There does need to be downtime. Certainly I personally find it incredibly difficult to pair 100% of the time when there is uncertainty and doubt about the right route forward. When neither pair is familiar with a domain, or cannot see a solution to work towards (or cannot explain their logic!), I think that I can often learn much faster on my own; I can experiment faster, and rapidly try different solutions until I see something that is promising. Then I prefer to bring it back into the pair for validation and sanity checking.
Chris also expressed concern that pair programming (and Agile software development in general) requires a set of social skills that are not traditionally present in software developers.

Rob Fletcher backed up Chris' view that pairing is fragile and more suited to some tasks than others...
I've experienced it being incredibly productive and at other times felt like my pair or I (even both) are not involved. I'm not sure why it sometimes doesn't work. Sometimes it's the nature of the task, sometimes a personality clash, wrong mix of skills or abilities or just someone not in the right frame of mind. Even then I don't necessarily think pairing is _less_ productive than if those people were working individually. 
it's more suited to some tasks than others. I do a fair bit of coding in my spare time & find that I enjoy going solo when doing exploratory "spiky" stuff but find myself wishing for a pair when building code out from the results of such spikes. I miss the validation that I'm on the right track, the pressure to stay focused.
The discussion is still ongoing, but has made me realise that while presenting the benefits of pair programming, I had completely neglected to point out its problems or indicate in what situations it might not be appropriate. It's widely accepted that different people prefer different learning styles (but contested that teaching in the learning style preferred by the student is more effective). My preference is for learning by example, but I don't mind whether this example comes from a colleague, formal documentation, a blog post or my own trial and error. I wonder whether people with other learning styles find pairing more stressful and tiring than I do? It's worth considering.

I also agree that when spiking (the process of investigating one or more possible solutions to a design problem) can be more effective when pairs split up and work individually. I sympathise with Kris' point regarding stagnation. With two young kids, a long commute and a serious attempt to get fit before I hit 40, I'm finding it harder and harder to dedicate the time I would like to technology. Maybe this is another reason why organisations should adopt some variation of 20% time. If they did they might even end up inventing something as profitable as the post-it note. But that's another blog post.

Many thanks to the EW crew for drawing attention to pair programming's downsides and helping me level-up my thinking.

Friday, 24 August 2012

Emotionally Intelligent Messaging

Enter any railway station in England and you are likely to be greeted by a sign warning you that if you assault their staff you will be prosecuted to the full extent of the law. This unfortunately sums up the attitude the station management companies have towards their customers. I am not greeted by a sign like this when I walk into Tescos, Boots, or Marks & Sparks, and yet I have no doubt that these companies would also seek prosecution if I assaulted their staff. Nor have I seen one in pubs or nightclubs where you would think the possibility of violence is higher. By displaying these signs in prominent places the station management companies are telling us that the service they deliver is so poor, that they expect otherwise rational human beings to lose their tempers, but rather than attempt to improve their service they prefer to pre-judge, threaten and hopefully intimidate their customers.

In contrast I am reminded of a sign I saw in a playground cafe. It read, "Children left unattended will be given a double espresso and promised a puppy." It's neither threatening nor intimidating, in fact it's quite the opposite, but I suspect is far more successful at influencing behaviour. Given the choice, with which of these two companies would you rather do business? More importantly, how do your customers and staff perceive the messages you send them?

Tuesday, 21 August 2012

A Case For Pair Programming

Quite some time ago I blogged about why Test Driven Development is so useful. Today I present a sister argument for Pair Programming.

In other industries predictability is often seen as a bad thing, but in the context of software delivery it's the Holy Grail. If a team repeatedly ships new features every day / week / month, without fuss, rollbacks, bugs or any other kind of hoo-hah then quite frankly that team rocks. What's more, if a team has predictable delivery they can self tune and deliver faster. It's much harder to tune a system with a high degree of variation. Show me a customer or manager who wouldn't delight in a team like that, and yet rarely will they put their hand in their pocket and pay for it when the proposed method is pair programming. Why?

What Is Pair Programming?
Before I go any further, let me explain what I mean by pair programming. Two humans, two keyboards and two mice, working on the same feature, at the same time on the same PC. Why two keyboards and two mice? because there's a natural reservation to grabbing the keyboard while someone else is typing on it. It feels rude. If you have your own keyboard there's no such reservation and you will contribute far more. I should also point out I intentionally wrote "humans" not developers. Pair programming shouldn't just be limited to programming. It covers anything required to get the story done, including front-end work, dev ops, sys admin and crazy (why would you buy it!!!) middleware packages. No special cases.

There are different strategies for how pairing should operate. A method that's often floated is that one developer writes code while the other thinks about the bigger picture. Another idea is pair-ping-pong, where one developer writes a unit test and the other makes it pass. I'm not keen on either approach. I find pairing works best when it's like a conversation, which each party taking turns listening  (watching) and speaking (typing), but with the option of interjecting at any point.

What Is Pair Rotation?
Another ingredient that's vital to successful pair programming is pair rotation, and again there are multiple approaches. Without pair rotation both developers stay on a story for it's duration. This has the advantage of minimal handover but also comes with some severe drawbacks. The same pair of developers will end up on consecutive stories as there will be no-one else free to pair with when the first story is complete. Skills and ideas will not cross-pollinate throughout the team. Developers will build up expertise in some areas of the code, while being unfamiliar with others. There will be no common code ownership.

To counter this, teams sometimes allocate a permanent story owner to each feature and rotate a second developer in on a regular (e.g. daily or half-daily) basis. This maintains some consistency for the duration of the story, but also improves communication throughout the team. There's a problem though. The pairing is unbalanced. The story owner, being "responsible" for, and more knowledgeable of the feature becomes the dominant force. The second developer is less likely to challenge the story owner, and more likely to disengage.

Our solution is to roll the story owner off onto another feature, and promote the second developer to story owner. Now the second developer has skin in the game. They know that they have to understand enough about this feature to lead it when the next handover occurs. They won't allow the story owner to cut corners, because in a short while it will be their feature and their mess. Cross-pollination is twice as rapid as before, so the code base will be more consistent and familiar to everyone. This solution does come at a price however - occasionally information acquired through conversations and not documented on the story card may be omitted from the handover, and since both developers can roll off onto new stories, it's possible for this information to be lost, resulting in bugs and rework. We've been running with this approach for some time, and even with the occasional mistake the payoff has been worth it.

So that's how I advocate doing pair programming, and now it's time to look at the benefits. I've briefly mentioned predictability, cross-pollination of skills and ideas, common code ownership and if you read between the lines improved code quality. I'll expand on those areas now.

Key Man Risk And Flow
The most obvious benefit of pair programming (with rotation), is removal of key man risk. In traditional development teams it's common for developers to become experts in one area of the code base. It's even seen as a good thing since because those developers are experts they will be able to deliver features more quickly. The problem is that these developers become indispensable "heroes", leading them to become over worked, stressed and unhappy. In the worst cases I've seen them become arrogant and destructive. Team members don't keep tabs on what each other are doing and it's common for unit testing to be skipped over and for the code to get ugly. I've often had to re-write large chunks of an application because of exactly this situation. A similar set of problems occur when a minority of team members have a niche skill such as a dedicated DBA or front-end developer. Effective pairing eradicates the issue of key man risk completely.

Closely related to key man risk, is flow. If only one team member is familiar with a particular part of the  code or has a critical skill not shared by others, then they become a bottleneck. Work will not flow steadily and predictably through the system. Instead it will begin to back up and take longer to deliver, again leading to the "hero" anti-pattern. Whenever a bottleneck goes on holiday the whole project can grind to a halt. Both situations incur extra management effort, and can lead to some truly ridiculous solutions being imposed, like parachuting in green "resources" to ensure velocity doesn't drop.

In contrast if every team member learns to work on every part of the system and develops all the required skills to at least a competent level, there will be no major bottlenecks and no key man risk. You will start to achieve the predictable delivery I mentioned in the opening paragraph. Initially pairings will be unbalanced due to one member having greater skill or domain knowledge, but this will self correct over time and even while the pairing is unbalanced, the weaker member will often have a positive influence. Server side developers may find themselves coaching front-end developers resulting in cleaner Javascript and drier HTML. Front-end developers might find themselves demonstrating how a little bit of CSS magic can negate the need for some server side code entirely.

Cross-Pollination Of Ideas
The next obvious advantage of pair programming is cross-pollination of ideas. When developers work in isolation pockets of code evolve in overly specialist ways (think duck-billed platypus), and the code base loses coherence. When developers pair program and rotate, the ideas are validated and reuse increases. Significant work and rework are avoided.

Inherent Discipline
A more subtle, but equally important benefit of pair programming is that it stops blame. When a single developer works on a story, if that story takes significantly longer than expected, it isn't clear whether it's because the developer was inadequate, or because the story was more complex than originally thought. Even if no one is pointing the finger, the developer will start to feel pressure, and this can result in corner cutting. If however a story is taking longer than expected, but half the team have rotated through the story then it's clear that the team underestimated the complexity of the story when it was first introduced. This combination of a no-blame culture and the incentivising of the second developer to prevent the story owner taking shortcuts ensures that test driven development is done properly, and therefore leads to higher quality, sustainable code.

Cross-Pollination Of Skills
My final argument for pair programming is cross-pollination of skills. I was a specialist Java developer, with basic HTML, CSS, Javascript and SQL. Now, thanks to pair programming I'm a generalised specialist, able to do all this and more to a high standard. Many companies appreciate the value of this for permanent employees but baulk at the suggestion for on the job training for contractors. They're cutting off their nose to spite their face. In a previous blog post I wrote about the power of intrinsic motivation (you will work for someone you hate, but die for someone you love). One of the ingredients for intrinsic motivation is mastery. Permanent and contract staff alike will be more motivated if they are acquiring valuable skills. I witnessed this on a project some years ago, where despite having no looming deadlines or pressure to deliver, contractors were regularly working until 8pm on a Friday night, purely because they were enjoying the project so much.

Code Reviews Aren't A Substitute
One counter argument that is raised against pair programming is that similar results can be achieved through code reviews. In practise they can't. The problem with a code review is that feedback is too late. The code has been written. The time has gone. The money has been spent. The review feels like a chore. The reviewer wants to get back to their own work, they won't fully appreciate the context of the problem the developer was trying to solve. The reviewer avoids pointing out minor issues because they don't want to appear petty. Any change that requires significant rework must bring an equivalent benefit. Pair programming doesn't suffer from any of these problems, because the review is done in real time, the mistakes have not been cemented and so the code can be improved with little cost.

Why Is Pair Programming So Rare?
So with all this in favour of pair programming why is it the hardest agile practise to get accepted? The reason is that most organisations are setup with administrative staff in a position of control instead of providing a supporting role. It's hard to put a dollar value on the benefits of pair programming, but it's very easy to put one on its cost. In Predictably Irrational, Dan Ariely shows that when there are two options available, and one is easy to evaluate but the other not, human beings overwhelmingly make decisions based solely on the option that is easy to evaluate. Since doubling the burn rate is obviously bad, but the benefits of pair programming are hard to quantify in units of time or money, it doesn't get a look in. And this is why so few teams ship new features every day / week / month, without fuss, rollbacks, bugs or any other kind of hoo-hah.

Friday, 17 August 2012

Jinkies - Build Noises For Remote CI Servers

If you already know why build noises are a great idea and just want the software click here, otherwise...

Feedback is one of the original XP values. The more timely and accurate the feedback the better.  One symptom of a successful Agile project is that there are numerous and even redundant quality assurance systems in place that provide feedback when something goes wrong. Automated tests and CI servers are examples, however when it comes to CI servers many projects fall a little short. Often there's no system in place for monitoring builds. Some teams use a flat screen TV to display the jobs, other teams send notifications via email. In fact there are a whole host of other options from instant messaging to browser and IDE plugins, but by far the most effective system of alerting often goes overlooked.


We're wired for it. Think about the last time you needed to give some an urgent warning - did you write them a note that said "Look Out", or did you shout it?

Far better than a screen that you need to remember to check, or relying on people to

a. Use an email client as opposed to webmail
b. Respond to build related emails immediately, instead of deferring action as is the norm with other emails.

Noise has another advantage - it can carry with it a free layer of information we process without even thinking. Ever been on a plane when a baby starts crying? Not only is it impossible to ignore, but you are in no doubt that that baby is extremely upset.

But wait, there's more. Ivan Pavlov discovered that we can be conditioned to respond to noise. If you've ever worked in a team that dragged their heals when it was time for the daily stand up, try playing a build noise. Using negative effects for breaks and positive ones for fixes can also be motivational.

Finally choosing appropriate samples is fun. Imagine coming into the office and hearing this whenever your build breaks, or a shortened version of this when it's stand up time. I'm all for having more fun at work.

OK - so that's my argument for build noises, but the implementation can be tricky. CI servers are increasingly likely to be headless Linux VMs hosted in a data centre or the cloud. The latest version of the Jenkins Sound Plugin allows you to pipe sounds to a remote machine via your operating system or to play them through your browser, but if you'd like a little more control, have lots of build jobs (possibly across different CI servers) or would prefer the notification system to be a background process  rather than a web page then give Jinkies a try - it's a light hearted bit of software for playing sounds when a build on a remote build job breaks or gets fixed.

PS. There is an argument against build noises - they can interrupt and distract non project related staff. This may be a genuine concern, but can also be a symptom of a greater problem. Development teams can be constrained by administrative or managerial staff who wield power, but don't actually contribute value (like the douche from health and safety who said we couldn't use two keyboards when we pair programmed). It's wrong, but comical build noises is probably not the right battleground for that particular fight.

Tuesday, 10 July 2012

Rules vs Principles

I often hear people talking about rules in software development. The trouble with rules is that it is considered wrong to break them under any circumstance, even if common sense dictates otherwise. Rules can be useful when you are new to a subject and don't understand its principles but it doesn't make sense to follow them blindly when you do, or expect other people to do the same.

In places where I see rules enforced it's often because someone in authority needs to feel in control. They want all code to be formatted consistently, or everyone to operate under a clear desk policy. Now don't misunderstand me - I would love it if everyone wrote code that conformed to my own subjective preferences, but it's far more important to me that developers are free to express themselves, and providing the code they write is "clean" I can cope with a mixture of styles.

I've blogged before about how self direction is an important ingredient for intrinsic motivation. While I can see there's cost and risk associated with this (especially when people aren't as capable as they think they are), allowing others the freedom to make mistakes is a powerful learning tool that can both advance an individual's capability and teach them humility. There are other techniques that can help mitigate the risk and costs - pair programming is one, test driven development is another.

My final gripe against rules is that you can end up spending a great deal of time enforcing them, and doing so always feels like inflicting punishment. Good people don't want to come to work to be punished, they want to be creative and to feel proud of what they produce. So tear up that rule book, try being guided by principles instead.

Monday, 9 July 2012

Engaging Presentations

I'm pleased to be presenting at Energized Work on Wednesday 11th of July. The subject - a slightly recursive "Engaging Presentations". Register here.

Monday, 30 April 2012

No Bull

Simon Baker of Energized Work has just published a white paper entitled "No Bull" detailing his thoughts on the last 12 years of Agile software development. If you don't know Simon, he (and co-founder Gus Power) won the 2009 Gordon Pask award for contributions to Agile Practice. No one I've met comes close wrt thought leadership or actually getting this stuff working. Two soundbites I particularly liked...

"We can't solve problems using the same kind of thinking that created them" - Albert Einstein


"Developers are users of the code" - i.e. make the time and effort to keep the code base pleasing. I can think of a few developers who would benefit from remembering this.

You can download "No Bull" here.

Friday, 27 April 2012


My friend Frank Carver has launched a new service called bookpuddle for recommending books via blogs, tweets, facebook or anywhere you can put a URL. What makes bookpuddle worthwhile is that you can link to the book via it's ISBN10 number (ISBN13 support imminent) instead of using that nasty amazon url. Bookpuddle urls look like this...

Frank's following a Lean startup model, so don't expect a sexy ui or tonne of features. Right now all that's on offer is the minimal viable product (MVP). If he gets enough traffic, he'll start building out. One feature that's on the horizon is to optionally include an Amazon associate id in the url. This way you can start earning revenue from your referrals, but unlike Amazon URLs you don't have to chose whether you link to the, or amazon.etc web sites, meaning you won't miss out when a reader from the wrong territory clicks on the link.

Nice work Frank.