Feeds:
Posts
Comments

Posts Tagged ‘pairing’

Pair programming is a great way to share knowledge. But every developer is different, does pairing work for everyone?

Pairing helps a team normalise its knowledge – what one person knows, everyone else learns through pairing: keyboard shortcuts, techniques, practices, third party libraries as well as the details of the source code you’re working in. This pushes up the average level of the team and stops knowledge becoming siloed.

Pairing also helps with discipline: it’s a lot harder to argue that you don’t need a unit test when there’s someone sitting next to you, literally acting as your conscience. It’s also a lot harder to just do the quick and dirty hack to get on to the next task, when the person sitting next to you has taken control of the keyboard to stop you committing war crimes against the source code.

The biggest problem most teams face is basically one of communication: coordinating, in detail, the activities of a team of developers is difficult. Ideally, every developer would know everything that is going on across the team – but this clearly isn’t practical. Instead, we have to draw boundaries to make it easier to reason about the system as a whole, without knowing the whole system to the same level of detail. I’ll create an API, some boundary layer, and we each work to our own side of it. I’ll create the service, you sort out the user interface. I’ll sort out the network protocol, you sort out the application layer. You have to introduce an architectural boundary to simplify the communication and coordination. Your architecture immediately reflects the relationships of the developers building it.

Whereas on teams that pair, these boundaries can be softer. They still happen, but the boundary becomes softer because as pairs rotate you see both sides of any boundary so it doesn’t become a black box you don’t know about and can’t change. One day I’m writing the user interface code, the next I’m writing the service layer that feeds it. This is how you spot inconsistencies and opportunities to fix the architecture and take advantage of implementation details on both sides. Otherwise this communication is hard. Continuous pair rotation means you can get close to the ideal that each developer knows, broadly, what is happening everywhere.

However, let’s be honest: pairing isn’t for everyone. I’ve worked with some people who were great at pairing, who were a pleasure to work with. People who had no problem explaining their thought process and no ego to get bruised when you point out the fatal flaw in their idea. People who spot when you’ve lost the train of thought and pick up where you drifted off from.

A good pairing session becomes very social. A team that is pairing can sound very noisy. It can be one of the hardest things to get used to when you start pairing: I seem to spend my entire day arguing and talking. When are we gonna get on and write some damned code? But that just highlights how little of the job is actually typing in source code. Most of the day is figuring out which change to make and where. A single line of code can take hours of arguing to get right and in the right place.

But programming tends to attract people who are less sociable than others – and let’s face it, we’re a pretty anti-social bunch: I spend my entire day negotiating with a machine that works in 1s and 0s. Not for me the subtle nuances of human communication, it either compiles or it doesn’t. I don’t have to negotiate or try and out politick the compiler. I don’t have to deal with the compiler having “one of those days” (well, I say that, sometimes I swear…). I don’t have to take the compiler to one side and offer comforting words because its cat died. I don’t have to worry about hurting the compiler’s feelings because I made the same mistake for the hundredth time: “yes of course I’m listening to you, no I’m not just ignoring you. Of course I value your opinions, dear. But seriously, this is definitely an IList of TFoo!”

So it’s no surprise that among the great variety of programmers you meet, some are extrovert characters who relish the social, human side of working in a team of people, building software. As well as the introvert characters who relish the quiet, private, intellectual challenge of crafting an elegant solution to a fiendish problem.

And so to pairing: any team will end up with a mixture of characters. The extroverts will tend to enjoy pairing, while the introverts will tend to find it harder and seek to avoid it. This isn’t necessarily a question of education or persuasion, the benefits are relatively intangible and more introverted developers may find the whole process less enjoyable than working solo. It sounds trite: but happy developers are productive developers. There’s no point doing anything that makes some of your peers unhappy. All teams need to agree rules. For example, some people like eating really smelly food in an open plan office. Good teams tend to agree rules about this kind of behaviour; everyone agrees that small sacrifices for an individual make a big difference for team harmony.

However, how do you resolve a difference of opinion with pairing? As a team decision, pairing is a bit all or nothing. Either we agree to pair on everything, so there’s no code ownership, regular rotation and we learn from each other. Or we don’t, and we each become responsible for our own dominion. We can’t agree that those that want to pair will go into the pairing room so as not to upset everyone else.

One option is to simply require that everyone on your team has to love pairing. I don’t know about you: hiring good people is hard. The last thing I want to do is start excluding people who could otherwise be productive. Isn’t it better to at least have somebody doing something, even if they’re not pairing?

Another option is to force developers to pair, even if they find it difficult or uncomfortable. But is that really going to be productive? Building resentment and unhappiness is not going to create a high performance team. Of course, the other extreme is just as likely to cause upset: if you stop all pairing, then those that want to will feel resentful and unhappy.

And what about the middle ground? Can you have a team where some people pair while others work on their own? It seems inevitable that Conway’s law will come into play: the structure of the software will reflect the structure of the team. It’s very difficult for there to be overlap between developers working on their own and developers that are pairing. For exactly the same reason it’s difficult for a group of individual developers to overlap on the same area of code at the same time: you’ll necessarily introduce some architectural boundary to ease coordination.

This means you still end up with a collection of silos, some owned by individual developers, some owned by a group of developers. Does this give you the best compromise? Or the worst of both worlds?

What’s your experience? What have you tried? What worked, what didn’t?

Read Full Post »

Writing good software is all about getting feedback, quickly. Does it compile? Does it function? Does it build? Does it deploy? Does it do what the customer wanted? Does it actually work? Every step of the way we have feedback loops, to improve the software. The faster these feedback loops are, the faster the software improves.

Builds

Don’t you hate waiting for your code to compile? Or, if you use a language from this century: do you remember back in the olden days when you had to wait for the compiler? Until recently, I’d actually forgotten that incremental compilers are a relatively new invention. I remember when JBuilder (my IDE of choice back in those distant times) first introduced me to incremental compilation – it was something of a revelation! You mean, I don’t have to hit compile? It just does it? In the background? Like magic?!

A few years ago I joined a company who had something of a byzantine build process. As was the fashion at the time, they used ant for their build. Unfortunately, nobody had told them that Eclipse could also compile code. So all code was built with ant. Made a change? Run the ant build to build the relevant library (may require guesswork). Copy it (by hand) to the app server. Quickly restart WebSphere (note: not quick). Test. Lather. Rinse. Repeat. Die of boredom.

Eventually, I replaced this with an Eclipse workspace that could run the application. No more build step. No more copying things by hand. No more mistakes. No more long delays in getting feedback.

Just recently I started working with C++ again after nearly a decade in byte code / interpreted languages. I’d actually forgotten what it was like to wait for code to compile. I’d got so used to working in Eclipse where you press Go and Things Happen(tm). Now instead I have to wait for a build before I can do anything. Every little change involves minutes of my life waiting for Visual Studio.

Then, if I’m really lucky – it will even compile! Remember when your IDE didn’t give you little red squiggles or highlight broken code? How fast is that feedback loop now? Before I’ve even finished typing the IDE is telling me I’m a moron and suggesting how to fix it. Assuming my code compiles, next I run the gauntlet of linking. Normally that means some godawful error message that googling just gives decade old answers and stack overflow posts that might as well be discussing religion.

TDD

I suspect this is why TDD is less common in the C++ world. Not only does the language feel ill-suited to doing TDD (to be honest, it feels ill-suited to writing software at all), but if you have to wait minutes after each change – TDD just doesn’t work.

  • Write a failing test
  • Wait minutes for the compiler to check your work, maybe go for a cuppa
  • Write code to make the test pass
  • Wait minutes for the compiler to check your work, perhaps its lunchtime?
  • Refactor

Actually, scrap the last step – since C++ is basically entirely devoid of automated refactoring tools – just leave whatever mess you’ve created because it’s about as good as it will get.

But with a red, green, refactor cycle that takes approximately 2.6 hours – it would be impossibly slow. No wonder TDD happens less.

Pairing

I’ve been arguing recently about whether pairing or code review is the best way to improve code quality. I always used to be a huge believer in code review – I’d seen it have a massive impact on code quality and really help the team learn both the code and how to code better.

But now, after spending months pairing day in day out – I think pairing is better in every conceivable way than code review. Why? Because it’s so much more immediate. How many times have you heard feedback from code review getting left because “we don’t have time right now” or “we’ll come back to that just as soon as we’ve got this release out”.

But with pairing, you have your reviewer right there offering feedback, before you’ve even finished writing the line of code. Just like your modern IDE – giving you feedback before you’ve even had chance to get it wrong. And, just like the IDE, if the smart ass sitting next to you thinks he knows better, pass over the keyboard and let him show you.

This is just impossible with code review. The feedback cycle is necessarily much slower and, worse, it’s too easy to ignore. You can add a story to the backlog to fix code review comments. You can’t so easily add a story to the backlog to make the argumentative bloke next to you shut up! (More’s the pity, sometimes)

But either way – whether you get feedback from code review or pairing, the important thing is to get feedback. If you’re not getting feedback: you’re not learning and neither you nor your code are improving.

Read Full Post »

Agile places an emphasis on the importance of the team. The team make the decisions: what do we work on today, how do we tackle our constraints, even who should be in the group. But yet some research seems to suggest that individuals are more effective than teams.

For example in “59 seconds” Richard Wiseman questions the effectiveness of brainstorming – groups tend to focus on mundane, easily agreed upon suggestions; or be swayed by uncreative, charismatic team members.

How do we reconcile this conflict? If groups tend to lack creativity and flexibility in their thinking, why do agile teams appear to be more creative, more flexible and above all more effective? Is it an illusion, or does agile actually help teams achieve more?

Just one developer?

The trouble with software is its rarely a lone sport anymore. There aren’t many fields where one developer on his own can make a significant contribution. But where one developer can make meaningful progress you will get the best bang for buck. As soon as you add a second team member you need much more communication (ok, I might sit and talk to myself sometimes, but I talk much more when there’s another human being there). By the time you’re adding a third, fourth or fifth developer, you’re spending loads of time just talking and drawing on whiteboards and standing around having meetings.

If I’m the only person to have touched the code, when it crashes – I know exactly whose fault it is. As soon as there are more developers, we get to play blamestorming. “Well it works fine on my PC”, “It worked last time I ran it”, “You checked in last – it must be your bug”. You start to get the diffusion of responsibility that Wiseman talks about. People don’t feel personally responsible for the output, so they don’t feel compelled to make it better: half assed is good enough, it’s not my problem.

The truth is most activities of any size nowadays require a team of people to work on, which immediately raises the question of who works on what, when.

Fluidity

Maybe agile helps teams be more effective by letting the team be more fluid. Rather than the smartest people getting stuck on one problem or in one area, the fluidity and constant reassessment of agile allows the smart people to automatically refocus to where they need to be. But critically, it doesn’t need someone to micromanage the situation and tell them to work on the most important things – people will “self-organise” and naturally gravitate to where they can help most.

At the daily standup Harry says:

Jim – are you doing ok with the checkout flow? You’ve never done anything like that before so would it help if I came and paired with you today? The order history page can wait until next week so we can hit our target for Friday.

Magic: a “self-organising team”. Imagine some asshat manager had said that! Jim would feel like an idiot, Harry gets to feel awkward so tries not to ride roughshod over Jim’s work – both get dragged down and demotivated; the end result is slow, sloppy work and a miserable team. Instead, because the team came up with the idea, everyone’s happy about it and the work gets done as quickly as possible.

Because different people are always offering help – either because they’re nosy and want to know how something works, or because they’re some smartass know-it-all that’s good at everything – the fact that the smartest people are quickly rotating round the group’s biggest problems isn’t always plain to see. Everyone is moving around; but most of the movement is noise: the important thing is that the brightest, most capable people are moving to where they are needed most.

Maybe the fluidity simply creates a socially acceptable way for the smart people on the team to leap from problem to problem without the rest of the team feeling stupid.

Who’s the rockstar?

I hate the term, but if agile teams are more effective because the “rockstar” developers are working on all the important stuff – that suggests everyone else is working on the unimportant stuff. Now, if your company has time to pay idiots to work on stuff that nobody wants – maybe I can offer you some overpriced consultancy?

But that doesn’t happen, does it? Perhaps because the “rockstar” on the team, is probably only good at playing guitar (stretching the tortured analogy). I’ve heard him play a drum solo: it’s shit. But the drummer? Yeah, he’s not too bad at that. Everyone on a team has different strengths, and will do best at certain tasks. As a manager, it’s almost impossible to try and assign people to tasks to get the best out of everyone and deliver the most value possible. You’re basically trying to allocate resources centrally, which turns out to be pretty hard.

Instead by delegating resource allocation to the team, the team decide who would be best on each activity; the team take responsibility for delivering as much value as quickly as possible. Even if that sometimes means people are working on tasks they’re not suited for – those who are better at it might be working on something more valuable. Sometimes you need a drummer, even if they’re not the best drummer in the band.

Costs

Regular task switching and lots of pairing is great for creating an environment where developers can move from task to task easily. But this comes with a cost – I can’t immediately pick up where James left off, I need to talk to him to find out what he was doing and where he got to, I need to learn and understand the code he wrote yesterday before I can write more. This has a cost to it.

What about the diffusion of responsibility? If six different people all work on the same feature, won’t we find that nobody really cares whether it works, because everyone blames the other guys? Well, assuming we’re all professional developers, I’m sure we wouldn’t sink to such childish behaviour. But it’s surprising how easy you can become detached from the goal you’re aiming for – the overall benefit you’re trying to deliver for the customer. You know what’s left to do, so you do your little bit. You don’t think about the overall goal and what the customer actually wanted. You take your eye off of quality for a split second and bang! You screwed up.

I suspect diffusion of responsibility is a genuine problem in agile teams – which is why shared ownership is emphasised. We all own this code – so treat it as your own. In another light, it’s the craftsmanship ethic – to leave the code a little better than you found it. Don’t just assume the other guy knew what he was doing: fix it, properly. Without this, the diffusion of responsibility would lead to chaos.

To tolerate all these costs: task switching, diffused responsibility, communication and coordination overhead – there simply must be a massive benefit. The upside of having the right people on the right task at the right time must outweigh all those downsides.

But does it always? Does it on your team?

Read Full Post »

%d bloggers like this: