My iGoogle page helps me keep up to date with the latest .Net news, podcasts and blogs with many RSS feeds I have subscribed to.
Unfortunately I don’t have the time to check out all of them and so it can be difficult to decide what is worth reading.
It’s lucky for me then Chris Alcock does a really good job of giving a summary for each of the blog posts he thinks are worth reading on his Morning Brew posts.
Over the past four weeks I have been working with a new start up company where the owners (who are developers themselves) want to use pair programming to do everything.
In this blog post I want to share my experiences and opinions on pair programming.
This is not the first time I have done pair programming and it won’t be the last. I chose the title because when you read about pair programming in extreme programming books, the ideas look great on paper but can be difficult to implement and don’t work in the real word.
Two heads are better than one
Developers who have had positive pair programming experiences write about
how much more focused they were
increased productivity
better code quality
shared knowledge/less dependency on a single developer
In code reviews, people sit down to review someone’s code. Everyone has an opinion but not everyone is going to be working with the code on a daily basis. At the time, everyone seems to be involved in the process but there is no vested interest. They are just looking at some code and asking themselves “does this code look good and is it correct?”. It’s a very passive standpoint. On the other hand, pair programmers are completely invested (committed?) in the task at hand. They immediately are using the code they are writing together and collaborating their thoughts on design, code layout, etc. Both programmers are taking on an active role and are emotionally invested in the task at hand because they are attacking the same problem together.
Shared Code Ownership
Have you ever been in a situation where a ‘friend’ has become so attached to their code, they find it difficult to accept it doesn’t do what it’s supposed to or is no longer required?
My best experience of pair programming has been taking over the lead development of a project where the previous developer had been working alone.
When a colleague and I came to conclusion what had be done did not have anything to do with the problem domain, we decided to delete the code and pair together to ensure the same mistake did not happen again. We continued to pair until we had a solid foundation to build upon.
When code is written by a single developer, they will inevitably end up owning it. No doubt you’ve heard something like “that’s Bobs login controller”. If there’s a bug or issue with that code the developer can become very defensive.
When a pair is told the same thing I think it’s a lot easier to deal with because no one person owns the code. In addition developers working in a pair find it easier to accept the path they had followed has come to a dead end a lot quicker than a developer working alone.
Sounds great. Where do I sign?
Hold on comrade not so fast.
Pair programming can be a bit like communism, too good to be true.
One of the most difficult things in pair programming is finding a good pairing partner. The general consensus is that developers need be at similar skill levels, understand the domain and offer something their partner other can’t.
All good relationships are about give and take
Unless you’re a total idiot and couldn’t care what your pairing partner thinks, you will be conscious how your partner is feeling.
If you hog the keyboard too much your partner will become a chicken, involved but not committed. They will play with their phone, think about what to have for dinner, or even fall asleep.
If you’re too passive, not wanting to ‘rock the boat’ you will be putting your name against something you don’t necessarily agree with. This can even be an issue even when you have the keyboard, because all you’re doing is typing what the other is saying. Lets hope your secretarial skills are up to the job.
Some of you will be quick to point out the solution to this problem is to swap the driver/observer roles every 30 minutes or by adopting the ping pong pair programming pattern.
However this doesn’t always solve the issue especially if you’re working with a control freak who says something like “why don’t you try this?” before taking back the keyboard.
In addition to changing roles within a pair, the developers in the pair should be rotated.
In the Turning on a sixpence – No excuses: Concept To Cash Every Week video, developers working on a project for a broadcasting company changed pair in morning and afternoons. This means over a course of two days five different developers would have been involved.
For example in the morning developer A would be ‘driving’, and developer B would be the ‘observer’. In the afternoon developer A, would move onto something else, developer B would be ‘driving’ and developer C would be ‘observer’.
I know this is cynical but I can’t imagine that the first few minutes of a new pair starting aren’t spent bitching about the developer who has moved on, followed another half an hour taking out what they think is wrong and doing what they wanted to do.
Developer Values
There’s no doubt a developer has to make sacrifices when pairing. What if you like doing test driven development, but your partner doesn’t? You could
suggest to try it out – and then try to look pleased when they don’t.
raise the issue – because that’s really going to help you build a relationship.
do nothing – it’s the easiest thing to do and you simply can’t face another day at work wasting time fighting your corner.
A good developer in a pair can’t argue with everything they don’t agree with, they have to bite their lip and let things slide. After all how much value is there in arguing if underscores should be used for private member variables.
Thanks But No Thanks
Many developers have said that pair programming is that it’s not for them.
Lionel Messi European and soon to be crowned World footballer of the year is fantastic when he plays for Barcelona. But when he plays for Argentina things don’t go so well. The problem is the system he has to fit into.
Why should a developer who is able to write good quality code on time be forced to fit into a process? After all that isn’t agile about ‘Individuals and interactions over processes and tools’.
And if you believe ‘people work harder when there is someone looking over their shoulder’ (see Mendelt Siebenga’s post The dirty secret of pair programming), well that fits in with the Tayloristic view that workers are stupid, can’t be trusted because they don’t care about things and only managers know better.
When I’m working alone and have to solve a problem I can look on the internet Stack Overflow or ask a colleague.
Sometimes when you’re pair programming trying to find a solution is like having a back seat driver on board, you’re unable to concentrate and have to speed read because your partner wanted to click on a different link or search for something else. This clip sums up what I mean.
On a lighter note some developers have pointed out they don’t like pair programming because to hygiene issues. Sharing a keyboard and mouse with someone who doesn’t wash their hands, or having to sit in close proximity with someone who smells, is not a pleasant experience.
Jag Reehal’s Final Thought on ‘Pair Programming Is Not a Silver Bullet’
Should developers do pair programming all of the time? No.
Developers should be trusted and left to their own deceives. They should pair when they think it’s the right thing to do.
When pair programming works it’s very good, not only for the project but for individuals as well. The amount of keyboard shortcuts and tips and tricks I’ve picked up when pairing is amazing. Check out Keyboard Jedi when you are pairing, it shows a visual list of shortcuts as they are being typed.
It’s important that developers are able to read blogs, explore and experiment, which pair programming doesn’t really allow for because your partner has to agree with everything you want to do. In his PDC 09 ASP.NET MVC 2: Ninjas Still on Fire Black Belt Tips talk Scott Hanselman said ‘you can spot a good dev if their recent project list contains projects where they are just trying out stuff’.
For me code reviews come too late in the development process. Pair programming should seriously be considered if code reviews are of paramount importance to you.
As for the arguments about productivity and focus etc, yes it can help. But I also believe developers working alone and using the pomodoro technique could achieve similar results.
I will never dictate my team have to do pair programming. But I would be disappointed if they never tried.
The code used for creating the game in ASP.NET MVC, jQuery and jQuery UI can be downloaded here.
Getting Started
Instead of three animals used in the demo, the game now contains fourteen. I’ve created a repository which returns the animals. To keep things simple there’s no database here, instead the animals are hard coded.
using System.Linq;
using GameUsingAspNetMVCandJQueryUI.Core.Models;
namespace GameUsingAspNetMVCandJQueryUI.Core.Repository
{
public class AnimalsRepository : IAnimalsRepository
{
public IQueryable<Animal> GetAll()
{
return new Animal[]
{
new Animal(){Name = "Cow"},
new Animal(){Name = "Cat"},
new Animal(){Name = "Chicken"},
new Animal(){Name = "Dog"},
new Animal(){Name = "Elephant"},
new Animal(){Name = "Giraffe"},
new Animal(){Name = "Hippo"},
new Animal(){Name = "Lion"},
new Animal(){Name = "Monkey"},
new Animal(){Name = "Mouse"},
new Animal(){Name = "Owl"},
new Animal(){Name = "Penguin"},
new Animal(){Name = "Pig"},
new Animal(){Name = "Sheep"},
}
.AsQueryable();
}
}
}
Command Query Separation
One of the features I have added is to ensure a correct answer for the current game could not be the correct answer in the next. As the repository class was responsible for getting animals, having it contain any logic would violate good design principles.
So the logic goes into the service layer which returns a data transfer object for animals and the correct answer.
using System.Linq;
using GameUsingAspNetMVCandJQueryUI.Core.ExtensionMethods;
using GameUsingAspNetMVCandJQueryUI.Core.Models;
using GameUsingAspNetMVCandJQueryUI.Core.Repository;
namespace GameUsingAspNetMVCandJQueryUI.Core.Service
{
public class AnimalsService : IAnimalsService
{
private readonly IAnimalsRepository _animalsRepository;
public AnimalsService(IAnimalsRepository animalsRepository)
{
_animalsRepository = animalsRepository;
}
public AnimalsDto GetAnimalsForGameWithCorrectAnswer(int numberOfAnimals, string previousAnimal)
{
AnimalsDto animalsDto = new AnimalsDto();
animalsDto.Animals = _animalsRepository
.GetAll()
.Where(a => a.Name != previousAnimal)
.Shuffle()
.Take(numberOfAnimals);
animalsDto.CorrectAnswer = animalsDto.Animals.Shuffle().First().Name;
return animalsDto;
}
}
}
This also makes testing easier because the tests can focus on making sure the service is doing what it should like this
using System;
using System.Linq;
using GameUsingAspNetMVCandJQueryUI.Core.Models;
using GameUsingAspNetMVCandJQueryUI.Core.Repository;
using GameUsingAspNetMVCandJQueryUI.Core.Service;
using NBehave.Spec.NUnit;
using NUnit.Framework;
using Rhino.Mocks;
namespace GameUsingAspNetMVCandJQueryUI.Tests
{
[TestFixture]
public class AnimalsServiceTests
{
private IAnimalsService _animalsService;
private IAnimalsRepository _animalsRepository;
private readonly IQueryable<Animal> _animalsStub = new Animal[]
{
new Animal(){Name = "Cow"},
new Animal(){Name = "Pig"},
new Animal(){Name = "Sheep"},
}.AsQueryable();
[SetUp]
public void SetUp()
{
_animalsRepository = MockRepository.GenerateStub<IAnimalsRepository>();
_animalsService = new AnimalsService(_animalsRepository);
}
[Test]
public void Should_Exclude_Previous_Animal_When_Previous_Animal_Is_Passed_In()
{
// Arrange
_animalsRepository.Stub(a => a.GetAll()).Return(_animalsStub);
var previousAnimal = _animalsStub.First();
// Act
var result = _animalsService.GetAnimalsForGameWithCorrectAnswer(3, previousAnimal.Name);
// Assert
result.Animals.Count(a => a.Name == previousAnimal.Name).ShouldEqual(0);
}
[Test]
public void Should_Return_All_Animals_When_No_Previous_Animal_Is_Passed_In()
{
// Arrange
_animalsRepository.Stub(a => a.GetAll()).Return(_animalsStub);
string previousAnimal = String.Empty;
// Act
var result = _animalsService.GetAnimalsForGameWithCorrectAnswer(3, previousAnimal);
// Assert
result..Animals.Count().ShouldEqual(3);
}
[Test]
public void Should_Return_All_Animals_When_No_Previous_Animal_Is_Null()
{
// Arrange
_animalsRepository.Stub(a => a.GetAll()).Return(_animalsStub);
string previousAnimal = null;
// Act
var result = _animalsService.GetAnimalsForGameWithCorrectAnswer(3, previousAnimal);
// Assert
result.Animals.Count().ShouldEqual(3);
}
[Test]
public void Correct_Answer_Should_Not_Be_Empty()
{
// Arrange
_animalsRepository.Stub(a => a.GetAll()).Return(_animalsStub);
// Act
var result = _animalsService.GetAnimalsForGameWithCorrectAnswer(3, null);
// Assert
result.CorrectAnswer.ShouldNotBeEmpty();
}
}
}
The LINQ Shuffle
Even though we have removed the previous answer, if the animals were returned as they are the answer would just be the next one in the list. So to keep the game exciting, a shuffle extension method is used to shuffle the answers.
using System;
using System.Collections.Generic;
using System.Linq;
namespace GameUsingAspNetMVCandJQueryUI
{
public static class GameExtensions
{
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> items)
{
var rnd = new Random();
IEnumerable<int> numbers = Enumerable.Range(0, items.Count()).OrderBy(r => rnd.Next());
var randomItems = new List<T>();
foreach (int number in numbers)
{
randomItems.Add(items.Skip(number).First());
}
return randomItems;
}
}
}
This can be unit tested as shown below
using System.Collections.Generic;
using System.Linq;
using GameUsingAspNetMVCandJQueryUI.Core.Models;
using NUnit.Framework;
namespace GameUsingAspNetMVCandJQueryUI.Tests
{
[TestFixture]
public class GameExtensionsTests
{
[Test]
public void Can_Shuffle_Animals()
{
List<Animal> animals = new List<Animal>()
{
new Animal(){Name = "Cow"},
new Animal(){Name = "Pig"},
new Animal(){Name = "Sheep"},
};
IList<Animal> result = animals.Shuffle().ToList();
Assert.IsFalse(
animals[0].Equals(result[0]) &&
animals[1].Equals(result[1]) &&
animals[2].Equals(result[2]),
"Animals should have been shuffled");
}
}
}
What happens when a player opens the game in their browser?
When the page loads an Ajax call is made using jQuery to an Asp.Net MVC action method which returns a JsonResult.
Two parameters are passed to the action method, one for the previous answer and the other for the number of animals required. The reason for this is because we don’t want to transfer more data over the wire than required, why return fourteen animals when only six are required?
The ‘GetAnimals’ Asp.Net MVC action method shown below serializes the view model returned by the service layer into JSON.
using System.Web.Mvc;
using GameUsingAspNetMVCandJQueryUI.Core.Service;
namespace GameUsingAspNetMVCandJQueryUI.Controllers
{
[HandleError]
public class GameController : Controller
{
private readonly IAnimalsService _animalsService;
public GameController(IAnimalsService animalsService)
{
_animalsService = animalsService;
}
public ActionResult Index()
{
return View("Index");
}
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public JsonResult GetAnimals(int numberOfAnimals, string previousAnimal)
{
return Json(_animalsService.GetAnimalsForGameWithCorrectAnswer(numberOfAnimals,previousAnimal));
}
}
}
Notice how I have to be explicit about how I do NOT want the JsonResult to be cached. If you don’t add this Internet Explorer will cache the result and you will get the same animals.
Using the jQuery and jQuery UI in the ASP.NET MVC View
The JavaScript used the demo was good enough to perform the dragging and dropping of pictures so the good news is we can use it again here.
An additional feature I have added is to allow the player to change the difficulty of the game by choosing how many animals are shown on the screen.
To do this I used the jQuery UI slider and jQuery fade functionality. The reason I used fade rather show/hide in jQuery was because I didn’t want the animals to move position when a user changed the difficulty as this would have resulted in a poor user experience by confusing the player.
Currently the message which tells the player if they have selected an incorrect answer is shown when the user stops dragging the animal. This is a problem because if the user drags a correct animal but doesn’t drop it on the droppable a message isn’t shown. If I find a fix for this I’ll update the code and this post.
Jag Reehal’s Final Thought on ‘Creating the animals game using Asp.Net MVC, jQuery and jQueryUI’
I’ve been using jQuery for a while now and I still love it.
The jQuery UI library is very good and the jQuery UI team have done a fantastic job creating demos and documentation.
I really like how you can create your own custom javascript file which only contains the features you require from the library.
No doubt some people will question why the service is returning a data transfer object. I could have returned a collection of animals to the ASP.NET MVC controller and have it create an object to pass to the view. The reason I didn’t do this is because I know the data transfer object will be used by another user interface layer (Silverlight) and because this would have bloated the controller and that’s not good. A best practice for ASP.NET MVC is to have skinny controllers.