Does an organisation need to be fully committed to agile/lean/scrum?
Alan Atlas has a recent blog post where he discusses agile, lean and scrum and suggests that you can't truly achieve agility unless your company is fully committed to it which differs slightly from my experiences.
Alan makes a valid point that we're not really following an approach just because we use all the practices:
Many people make the mistake of viewing Scrum and Agile and Lean as sets of practices. “If I do kanban, I’m Lean.” “If I do sprints, I’m scrummy.”
It's quite easy to put our work up on a story wall, run a daily standup and unit test our code and not really get the full benefit that those practices are supposed to give us.
As I've mentioned before though I think it is part of the learning process that we start out focusing on practices and not principles.
However, at some stage we need to start thinking for ourselves about the value those are giving and making adjustments to them if we're not seeing much value i.e. we need to look beyond the practice and to the principle or outcome that we are trying to achieve by using that practice.
The part of the post which is different to my experiences is this bit:
So I smile to myself (I think it’s to myself) when I hear management say things like “We’ll never be totally Agile in this company. There will always be waterfall projects.” I smile because what that really means is that they’ll never be Agile at all.
I haven't heard conversations like this before but I think it is still possible to deliver software in a team working in an 'agile' way even if the rest of the organisation which that team operates in follows a different approach.
It won't be as smooth sailing as if the whole organisation buys into the lean/agile approach and there will still be some reporting and bureaucracy that you need to deal with but it's not a lost cause.
My colleague Lindy Stephens and a couple of others covered some of the issues around project governance in the enterprise in a ThoughtWorks QTB in Sydney last year. The slides from that presentation are available on slideshare.
If your company is not fully committed to agility then you won’t achieve it, and your results will be a self-fulfilling prophecy of unrealized potential.
Even if an organisation decides that it wants to be agile I think it still takes time to get used to the approach and it always seems to take a few successful deliveries to see that some of the worries that heavy weight processes and paperwork try to protect you against are not necessarily valid.
I've spent a lot of time being indignant that people didn't buy into the agile approach but the more I spend time in different organisations the more it becomes clear that even for the people with the best intentions in wanting to learn this approach it will still take time to get there.
I'm coming to the conclusion that it's a good thing that people have some level of skepticism because it forces you to really understand why an agile approach is more effective and then try and persuade other people of that.
It's also helpful to note that it makes sense to vary our approach depending on the context that we're operating in. For example if the team is distributed across different cities then we might have more written documentation than with a co-located team.
It's very rare that an organisation or group of people will just 'get it' straight away – in many ways it's quite an iterative/incremental journey.
Javascript: Function scoping
My colleague John Hume wrote an interesting post about his experience with the 'const' keyword in ActionScript where he describes the problems with trying to capture a loop variable in a closure and then evaluating it later on in the code.
Since ActionScript and JavaScript are both dialects of ECMAscript, this is a problem in JavaScript as well, and is due to the fact that variables in JavaScript have function scope rather than block scope which is the case in many other languages.
This problem would tend to reveal itself in code where we try to capture a loop variable in an anonymous function and use it later on, like so:
function getValues() {
var x = new Array();
for(var i=0; i < 10; i++) {
x[i] = function() { return i; }
}
return x;
};
var values = getValues();
for(var j=0; j < values.length; j++) {
console.log(values[j]());
}
We might expect that to print the sequence of numbers 0-9 on the screen but what we actually get is '10′ printed 10 times.
There are a couple of things that I initially found strange about this:
- Why doesn't it print out the numbers 0-9?
- Given that it doesn't do that why does it print out '10′ 10 times instead of '9′ 10 times?
The answer to the first question is that 'i' gets assigned a new value on each iteration of the loop and we don't evaluate 'i' until we evaluate the anonymous function on line 11.
The value when we do evaluate it would be the last value that it was set to by the loop which in this case that would be '10′ because that's the value that 'i' has to be in order for the loop to terminate.
This is actually a problem in C# as well – the following code will output '10′ 10 times as well:
[Test]
public void ClosureOnTheSameValue()
{
var values = new List<Func<int>>();
for(int i=0; i < 10; i++)
{
values.Add(() => i);
}
foreach (var value in values)
{
Console.WriteLine(value());
}
}
Again we capture 'i' inside a closure and since we only evaluate that value when it's actually used it will always refer to the last value that 'i' was set to which in this case means that it will always output a value of 10.
To fix this in C# we could just create a temporary variable – something which Resharper will actually suggest to us:
[Test]
public void ClosureOnDifferentValue()
{
var values = new List<Func<int>>();
for(int i=0; i < 10; i++)
{
var idash = i;
values.Add(() => idash);
}
foreach (var value in values)
{
Console.WriteLine(value());
}
}
This works in C# because variables have block scope which means that we have a new version of 'idash' for each of the functions that we add to the 'values' collection.
Sadly the same trick doesn't work in JavaScript because variables have function scope in Javascript:
function getValues() {
var x = new Array();
for(var i=0; i < 10; i++) {
var idash = i;
x[i] = function() { return idash; }
}
return x;
};
var values = getValues();
for(var j=0; j < values.length; j++) {
console.log(values[j]());
}
The 'idash' temporary variable that we created to try and solve the problem gets assigned a new value in each iteration of the loop because that variable is only declared once for the whole function.
The code above could be written like this to make that clearer:
function getValues() {
var x = new Array();
var idash;
for(var i=0; i < 10; i++) {
idash = i;
x[i] = function() { return idash; }
}
return x;
};
var values = getValues();
for(var j=0; j < values.length; j++) {
console.log(values[j]());
}
As John points out:
Here's something I either never knew or at some point forgot about JavaScript: variables are lexically scoped, but only function bodies introduce new lexical scopes.
In this case we actually end up printing '9′ 10 times because that's the maximum value that gets assigned to 'idash'.
One solution is to create a temporary variable inside an anonymous function that we execute immediately, like this:
function getValues() {
var x = new Array();
for(var i=0; i < 10; i++) {
(function() {
var idash = i;
x[i] = function() { return idash; } })();
}
return x;
};
var values = getValues();
for(var j=0; j < values.length; j++) {
console.log(values[j]());
}
Now 'idash' is scoped inside the anonymous function and we therefore end up with a new value each time like we want.
Raph pointed out that we could achieve the same thing in a simpler way with the following code:
function getValues() {
var x = new Array();
for(var i=0; i < 10; i++) (function(i) {
x[i] = function() { return i; };
})(i);
return x;
};
var values = getValues();
for(var j=0; j < values.length; j++) {
console.log(values[j]());
}
Here we define a for loop with just a single statement so we can lose the '{}' and just call an anonymous function passing in 'i'.
Of course this example is truly contrived but I wanted to pick something simple enough that I could try and follow exactly how it worked.
I'm not entirely sure of the terminology around closures and scoping so if I've described anything incorrectly then please correct me!
Pair Programming: Some thoughts
Mark Wilden pointed me to a post he's written about his experience pair programming at Pivotal Labs where he makes some interesting although not uncommon observations.
When you pair program, you're effectively joined at the hip with your pair. You can't pair if only one of you is there.
I've previously written wondering what we should do if our pair isn't around where I was leaning more towards the opinion that we should try to continue along the same path that we were on when working with our pair if they're gone for a short amount of time and to find a new pair or work alone if they're gone for longer.
On the projects I've worked on we'll still have times working alone when there's an odd number of people around or if someone just feels like working on their own and I think that's fine as well. I don't think we need to pair 100% of the time.
You have to be able to think out loud – 8 hours a day. Then you have to type in code while someone is watching you. They'll catch your typos (hopefully after giving you a chance to spot them yourself) and they'll see when you're floundering for how to do something.
I find that this is quite a useful practice for explaining things to yourself although I can see how it would initially exhausting.
Even now there are times when I just want to write some code instead of having to explain what I want to do to someone else. Sadly almost every time I explain something it turns out that my pair has a better idea of how to do it than me so I'm always glad pairing encourages this conversation.
Pair programming doesn't encourage quiet reflection and exploration. You can't just sit back and read some code. You can't just sit and think. I mean, you can, but then your pair is just sitting there.
This is a bit of a double edged sword – pair programming does encourage us to get things done but it's also true that sometimes we need to get the whiteboard out.
Often just sketching out the problem on a piece of paper to check your understanding is enough to trigger a conversation which might result in a better solution.
It does tend to need one person to drive this process though. I haven't seen it just happen organically.
We rarely pair 100% of the time so there are often times when you get a bit of time to play around a bit with the code and see whether specific approaches would work out and I often use this time for reflection and exploration.
One thing which a couple of the commenters on the original blog suggested is that perhaps more rotation was needed to help overcome some of the problems and from my experience it's vital that we do rotate otherwise the pair will end up hating each other!
I recently worked on a story with 3 other people across its life and each person pointed out something that I hadn't previously considered and which led to an eventual output that was much better than it would have been otherwise.
I think rotating different people onto a story can help lead to more innovative design as long as we have people working together who are relatively flexible and open to trying out new ideas.
Mark's post is certainly interesting though and helps identify some of the things we need to be aware of when pair programming – we don't just want to follow the practice blindly.
Getting real: Book review
I recently came across 37 Signals 'Getting Real' book where they go through their approach to building web applications and there have certainly been some good reminders and ideas on the best way to do this.
These are some of my favourite parts:
- Ship it!
If there are minor bugs, ship it as soon you have the core scenarios nailed and ship the bug fixes to web gradually after that. The faster you get the user feedback the better.
Often on projects I've worked on we've taken the approach that bugs get worked on before new stories which makes sense in a way because it means that we are fixing problems quickly and keeping the quality of the application high.
In reality what often happens is that low priority bugs just end up not getting looked at but I like the fact that we can choose to make that an explicit approach rather than just allowing it to happen to us.
Prioritize your bugs (and even ignore some of them)
Just because you discover a bug in your product, doesn’t mean it’s time to panic. All software has bugs – it’s just a fact of life.
I find it interesting that there might be more value in getting something out the door and then getting feedback on it rather than spending extra time perfecting it up front.
- Fix Time and Budget, Flex Scope
You have to figure out what’s really important. What’s going to make it into this initial release? This forces a constraint on you which will push you to make tough decisions instead of hemming and hawing.
From my experience a lot of times we end up implementing features just because that's what was agreed in the initial release plan and there is often a reluctance to change that even if a feature isn't really that useful anymore.
It becomes even more problematic if we get to the stage where it's not possible to deliver all the features promised in the remaining time so it certainly makes sense to me that in that situation we would look to focus on getting the absolutely essential things in first.
- Choose any enemy
Sometimes the best way to know what your app should be is to know what it shouldn’t be. Figure out your app’s enemy and you’ll shine a light on where you need to go.
This seems to be a much better idea than just copying the ideas of your competitor which might seem the obvious thing to do if you're working in the same area.
The problem with that approach of course is that when you do copy you have no actual vision of what you're doing with your application anyway so you'll always be playing catch up.
- Don't overcomplicate the application
There are a few parts of the book where the authors talk about keeping the application simple and then letting the users play with it:
The harder we tighten things down, the less room there is for a creative, emergent solution. Whether it’s locking down requirements before they are well understood or prematurely optimizing code, or inventing complex navigation and workflow scenarios before letting end users play with the system, the result is the same: an overly complicated, stupid system instead of a clean, elegant system that harnesses emergence.
Keep it small. Keep it simple. Let it happen.
Andrew Hunt, The Pragmatic Programmers
The users can then decide for us where we need to fill in more details:
Details reveal themselves as you use what you’re building. You’ll see what needs more attention. You’ll feel what’s missing. You’ll know which potholes to pave over because you’ll keep hitting them. That’s when you need to pay attention, not sooner.
In particular they suggest that focusing on very specific details about the page layout/colour/wording can be left until later because it will only serve to hinder forward progress if we concentrate on it too early.
- Scaling an application
You don’t have a scaling problem yet
“Will my app scale when millions of people start using it?”
Ya know what? Wait until that actually happens.
On several projects that I've worked on there often seems to be a desire to focus on performance and scaling an application very early on which seems wasteful when we could be focusing on actually building something that has so many users that we need to scale it later on. I think this advice is spot on.
- Write less software
A common theme throughout the book is that of writing less software to achieve our goals:
The best designers and the best programmers…are the ones that can determine what just doesn’t matter.
That’s where the real gains are made.
Most of the time you spend is wasted on things that just don’t matter. If you can cut out the work and thinking that just don’t matter, you’ll achieve productivity you’ve never imagined.
Innovation is not about saying yes to everything. It’s about saying NO to all but the most crucial features.
Throw away customer feature requests – if they're really important then they'll come back anyway
Don’t worry about tracking and saving each request that comes in. Let your customers be your memory. If it’s really worth remembering, they’ll remind you until you can’t forget.
The authors ideas around preferences were particularly interesting to me:
Preferences are also evil because they create more software.
More options require more code. And there’s all the extra testing and designing you need to do too.
I hadn't appreciated until recently quite how much complexity we can add to an application by allowing users to play around with the display of information on a screen.
It seems like a nice feature to have but it would be interesting to see statistics that could tell us what percentage of users actually that type of thing when it's not the core idea of the application.
I also quite liked the following and I think it's something that we need to do more often on teams:
Encourage programmers to make counteroffers.You want to hear: “The way you suggested will take 12 hours. But there’s a way I can do it that will only take one hour. It won’t do x but it will do y.” Let the software push back. Tell programmers to fight for what they think is the best way.
- Decisions are temporary so make the call and move on
So don’t do the “paralysis through analysis” thing. That only slows progress and saps morale.
Instead, value the importance of moving on and moving forward. Get in the rhythm of making decisions. Make a quick, simple call and then go back and change that decision if it doesn’t work out.
I think a big part of this is getting the mentality that it's fine to make changes after we've 'finished' something. Any other approach doesn't work from my experience.
- Reduce meetings
Meetings usually arise when a concept isn’t clear enough. Instead of resorting to a meeting, try to simplify the concept so you can discuss it quickly via email or im or Campfire.
I find it interesting that they prefer communicating by email because I've often found that it's not the best communication mechanism since it's really easy to misinterpret what people mean.
Having said that if we can make concepts clearer and the need for a meeting is an indicator that we need to do that then perhaps we can still meet in person and just make the meeting much shorter.
- Design the interface before you start programming
Too many apps start with a program-first mentality. That’s a bad idea. Programming is the heaviest component of building an app, meaning it’s the most expensive and hardest to change. Instead, start by designing first.
I've certainly fallen into this trap a lot but I've been trying to follow the outside in approach more strictly recently and so far I'm finding that it reduces the feedback cycle quite substantially which is only a good thing.
- Design for regular, blank, and error states
For each screen, you need to consider three possible states:
Regular
The screen people see when everything’s working fine and your app is flush with data.Blank
The screen people see when using the app for the first time, before data is entered.Error
The screen people see when something goes wrong.I'd never even though of this at all and I'm certainly guilty of only ever considering applications when all the data is filled in so this is certainly something else to consider.
- Tear down the walls between support and development
In the restaurant business, there’s a world of difference between those working in the kitchen and those out front who deal with customers. It’s important for both sides to understand and empathize with the other. That’s why cooking schools and restaurants will often have chefs work out front as waiters so the kitchen staff can interact with customers and see what it’s actually like on the front lines.
My colleague Chris Read and some others seem to be trying to close this gap with the devops movement which also has a track at QCon London this week.
The idea of working in support to see what an application is like from that perspective is something that more experienced colleagues often recommend although I've not done it as yet.
Overall I found this book a really interesting and quick read and although many of the ideas suggested seem like common sense it's strange that we often don't do all of them.
The 37 Signals guys also have a new book coming out in the UK tomorrow titled 'Rework' which sounds like it could be quite a good read as well.
Javascript: The 'new' keyword
I came across an interesting post by John Resig where he describes a 'makeClass' function that he uses in his code to create functions which can instantiate objects regardless of whether the user calls that function with or without the new keyword.
The main reason that the new keyword seems to be considered harmful is because we might make assumptions in our function that it will be called with the new keyword which changes the meaning of 'this' inside that function.
For example in my Bowling Game example I assume that the 'BowlingGame' function will be called with the new keyword.
I wanted to see if I could refactor that code to use the module pattern instead so as a first step I changed the instantiation of the 'bowlingGame' variable in the tests to not call the function with 'new' to see if it would make any noticeable difference:
Screw.Unit(function() {
describe("bowling game scorecard", function() {
var bowlingGame;
before(function() {
bowlingGame = BowlingGame();
});
There is no noticeable difference in the way any of the tests work but in fact all of the functions I defined have been added to the global object (in this case window) instead of onto 'BowlingGame'.
I changed one of the tests to check that this was the case…
...
it("should score a single throw", function() {
console.log(window.roll);
bowlingGame.roll(5);
(19).times(function() { gutterBall(); });
expect(bowlingGame.score()).to(equal, 5);
});
...
…which logs 'undefined' to Firebug if the new keyword is used to instantiate 'bowlingGame' and 'function()' if it wasn't.
The danger here is that you could change the meaning of the 'roll' function outside of the 'BowlingGame' if you wanted to.
To give a contrived example perhaps we could change 'roll' so that it actually called the original function twice instead of once:
...
it("should score a single throw", function() {
var originalRoll = window.roll;
window.roll = function() {
originalRoll.apply(this, arguments);
originalRoll.apply(this, arguments);
console.log("roll isn't what you'd expect anymore")
};
bowlingGame.roll(5);
(19).times(function() { gutterBall(); });
expect(bowlingGame.score()).to(equal, 5);
});
...
In this case you would probably never do that because it's just a small bit of code but you wouldn't want to add random functions to the global object in any reasonably sized javascript application.
BowlingGame = function() {
if ( !(this instanceof arguments.callee) )
throw Error("Constructor called as a function");
...
When 'BowlingGame' is called without the new keyword then 'this' will refer to 'window' which means that it won't be an instance of 'arguments.callee' which in this case is the 'BowlingGame' function.
Functional C#: Using Join and GroupJoin
An interesting problem which I've come across a few times recently is where we have two collections which we want to use together in some way and get a result which could either be another collection or some other value.
In one which Chris and I were playing around with we had a collection of years and a collection of cars with corresponding years and the requirement was to show all the years on the page with the first car we found for that year or an empty value if there was no car for that year.
We effectively needed to do a left join on the cars collection.
This is an imperative way of solving the problem:
public class Car
{
public int Year { get; set; }
public string Description { get; set; }
}
var years = new[] { 2000, 2001, 2002, 2003 };
var cars = new[] { new Car { Year = 2000, Description = "Honda" }, new Car { Year = 2003, Description = "Ford" } };
var newCars = new List<Car>();
foreach (var year in years)
{
var car = cars.Where(x => x.Year == year).FirstOrDefault() ?? new Car { Year = year, Description = ""};
newCars.Add(car);
}
We can actually achieve the same result in a more declarative way by making use of 'GroupJoin':
var newCars = years.GroupJoin(cars,
year => year,
car => car.Year,
(year, theCars) => theCars.FirstOrDefault() ?? new Car { Year = year, Description = "" });
'GroupJoin' is useful if we want to keep all of the items in the first collection and get a collection of the items in the second collection which match for the specified keys.
In this case it allows us to identify where there are no matching cars for a specific year and then just set a blank description for those years.
One nice side effect is that if we later want to include multiple cars for a year then we shouldn't have to change the code too much to achieve that.
Another example which I came across is where we have one collection which contains filter criteria which it needs to apply against the other collection.
We have a collection of years and need to indicate whether there is a matching car for each of those years.
[Test]
public void JoinExample()
{
var years = new[] { 2000, 2003 };
var cars = new[] { new Car { Year = 2000, Description = "Honda" },
new Car { Year = 2003, Description = "Ford" },
new Car { Year = 2003, Description = "Mercedes"}};
Assert.That(AreThereMatchingCars(years, cars), Is.True);
}
public bool AreThereMatchingCars(IEnumerable<int> years, IEnumerable<Car> cars)
{
foreach (var year in years)
{
if(cars.Where(c => c.Year == year).Count() == 0)
{
return false;
}
}
return true;
}
We can rewrite this function like so:
public bool AreThereMatchingCars(IEnumerable<int> years, IEnumerable<Car> cars)
{
var distinctCars = cars.GroupBy(x => x.Year).Select(x => x.First());
return years.Join(distinctCars, y => y, c => c.Year, (y, c) => c).Count() == years.Count();
}
This actually become more complicated than we expected because we were working out if there were matching cars for each of the specified years by checking the number of filter items and then comparing it to the number of items when we joined that collection with our collection of cars.
If we have more than one car for the same year that logic falls down so we needed to get just one car per year which is what the first line of the function does.
I can't decide whether or not the code is easier to read and understand by making use of these functions but it's an approach that I picked up when playing around with F# so it's interesting that it can still be applied in C# code as well.
Riskiest thing first vs Outside in development
I had an interesting conversation with my colleague David Santoro last week where I described the way that I often pick out the riskiest parts of a story or task and do those first and David pointed out that this approach didn't seem to fit in with the idea of outside in development.
The idea with outside in development as I understand it is that we would look to drive any new functionality from the UI i.e. the outside and work our way inwards through the various layers and probably eventually end up with persistence i.e. the inside.
In the particular example that were basing our discussion on I described a story that I was working on with my pair where we needed to apply some constraints to certain items in our data set and then display them differently on the UI as a result of that.
We went through the existing domain model to see if there was anything in there that we could make use of, and having realised that there wasn't anything we mapped out the tasks we would need to do to implement this functionality.
The most difficult/tricky task was to handle the data migration as we realised that we would need to add an extra column to one of the tables. We also needed to do the associated Hibernate mapping and the code from the UI and controller level downwards to make use of this.
We did the data migration and associated work first and one we were happy that was working we went and coded from the UI downwards until we reached the persistence layer.
In this situation it seemed like it worked out reasonably well and I couldn't see that we would have ended up with a different solution if we had started off driving through the UI.
In fact we did end up spending most of our time doing the data migration so to me it seemed somewhat justified doing that first since we did run into a couple of problems.
Outside in development in general seems a good thing to me so I'm curious as to whether I'm justifying a sub optimal approach to myself or whether there are some situations where we can vary the approach a bit?
A reminder about context switching
I've spent most of my time working on agile software development teams over the last few years so for the most part each pair is only working on one story, keeping the work in progress low and allowing them to focus on that piece of work until it's completed.
My pair and I ended up in a therefore somewhat unusual situation last week where we were attempting to work on three things at the same time and weren't doing a particularly great job on any of them.
It wasn't immediately obvious to me that we were doing this since the two extra tasks that we were working on were related to deployment issues on different environments.
However we eventually started making mistakes and in rushing to rectify those made even more mistakes since we were still trying to concentrate on three different things.
It became much more obvious at this point that we needed to just pick one of the items and focus on that until we were done which also served as a reminder that it's good to use the story board as an indicator of what everyone is working on.
In this case two of the tasks we were working on weren't on the story board otherwise it would have been more obvious to the rest of the team that we shouldn't have been working on two of them.
I've never really noticed the problems of context switching before so it was interesting to get such a stark example to remind me of its dangers.
Javascript: Confusing 'call' and 'apply'
I wrote a couple of weeks ago about using the 'call' and 'apply' functions in Javascript when passing functions around and while working on our IE6 specific code I realised that I'd got them mixed up.
We were writing some code to override one of our functions so that we could call the original function and then do something else after that.
The code was roughly like this:
Foo = {
bar : function(duck) {
console.log("bar " + duck.quack());
}
};
The code that I originally wrote to capture the original function, call it and then do the additional behaviour was like this:
(function() {
var originalBar = Foo.bar;
Foo.bar = function(duck) {
originalBar.call(this, arguments);
console.log("new bar");
};
})();
When we call the function:
Foo.bar({ quack : function() { return "quacking" } });
We get the following error:
TypeError: duck.quack is not a function
'arguments' is a local variable in any Javascript function which contains all the arguments passed to the function stored in an array type structure.
However, I had forgotten that when using the 'call' function we need to pass the full list of parameters individually rather than as an array so in this case we would need to pass 'duck' in specifically:
(function() {
var originalBar = Foo.bar;
Foo.bar = function(duck) {
originalBar.call(this, duck);
console.log("new bar");
};
})();
Now when we run the function we get the expected behaviour:
Foo.bar({ quack : function() { return "quacking" } });
bar quacking new bar
This is where apply comes in handy because apply allows us to pass in 'arguments' as the second parameter and it will send all the arguments of the function that we're inside to the function that we're calling which is exactly what we want in this case.
Using 'apply' we would end up with the following code:
(function() {
var originalBar = Foo.bar;
Foo.bar = function(duck) {
originalBar.apply(this, arguments);
console.log("new bar");
};
})();
In this case the function only takes in one argument so there's not much noticeable improvement in the code but when a function takes multiple arguments then using 'apply' is certainly a cleaner approach.
Javascript: Isolating browser specific code
One thing we've found on my current project is that despite our best efforts we've still ended up with some javascript code which we only want to run if the user is using Internet Explorer 6 and the question then becomes how to write that code so that it doesn't end up being spread all over the application.
jQuery has some functions which allow you to work out which browser's being used but I've noticed that when we use those you tend to end up with if statements dotted all around the code which isn't so good.
An approach which I was shown recently involves using CSS conditionals to identify when we're using Internet Explorer instead.
We can then include an IE6 specific javascript file like so:
<!--[if lt IE 7]> <script type="text/javascript" src="/path/to/ie6.js") %>"></script> <![endif]-->
Since we're building an ASP.NET MVC application we include this bit of code in our master page so that it gets picked up by all the web pages.
We've either needed to override existing functions or call the existing function but then do some extra work afterwards as well.
In order to do this we have to make sure that the IE6 specific file is included after our other javascript files since the interpreter will use the last definition of a function that it finds.
Given an existing function defined like so:
Foo = {
Bar : function() {
console.log("original bar call");
}
};
If we want to override this function to do something else we could include the following code in our IE6 specific file:
Foo.bar = function() {
console.log("overriding bar call");
}
When we call 'Foo.bar()' we'd only see the second 'console.log' statement.
It becomes a bit more interesting if we want to call the original function and then do some other functionality.
We can make use of the proxy pattern to allow us to do this cleanly.
Foo = {
bar : function() {
console.log("original bar call");
}
};
(function() {
var originalBar = Foo.bar;
Foo.bar = function() {
originalBar.apply(this, arguments);
console.log("overriding bar call");
};
})();
If we call 'Foo.bar()' in IE6 we'd now see both of those 'console.log' statements.
The reason that we wrap the reassignment in a function is so that we can hide the 'originalBar' function from the rest of our code. We save 'Foo.bar' in a closure and then override it and delegate calls to the original before logging the extra message.
I quite like this approach although I'm not sure if it's the most intention revealing code because it's not necessarily obvious that the function is being rewritten unless you happen to know about the IE6 only file.
Is there a better way to do this than the approach I've described?
Shu Ha Ri harmful?
I came across a blog post by Rachel Davies where she wonders whether the Shu-Ha-Ri approach to learning/teaching is actually harmful and I found Rachel's thoughts around the teaching of principles and practices quite interesting.
Quoting Jeff Sutherland:
Only when you have mastered the basic practices are you allowed to improvise. And the last and most important – Before you have gained discipline, centering, and flexibility, you are a hazard to yourself and others."
I'm uncomfortable with approaches that force students to follow agile practices without questioning. These approaches seem to violate the first value of the Agile Manifesto "Individuals and interactions over processes and tools."
What I find interesting about this is that when I first started learning about agile I would read the principles and they would all make sense but I didn't know what to do with that knowledge.
It was only after I'd used the practices frequently and in most cases taking the practices too far that I reached the stage where I could start asking questions that actually had any relevance.
For example Test Driven Development is one practice that I learnt and one of the principles which encourages this approach to coding is the need to get quick feedback on our work.
It would be quite easy to question whether we should test drive everything and you could quite correctly have the opinion that we shouldn't use this approach for absolutely everything.
However, without spending some time following this practice that opinion wouldn't be particularly useful because you would lack the experience that tells you which type of code we should or should not look to test first.
Having decided that TDD was the only approach to writing code I eventually got into situations where it didn't seem to make sense to stick so rigidly to this practice and it was only then that the value of the underlying principle became clear to me.
I don't think I was ever forced not to ask questions but I was just so concentrated on learning how to do the practices properly that I focused on that.
I often find that it's useful to use practices too much until you cause yourself pain.
Martin Fowler has a nice graph which shows how people adopt meta programming when coding Ruby and I think this links quite closely to my experiences when learning a new practice.
For me at least this seems to be a necessary learning step before I eventually step back and think about the principle that originally led me to following that practice. I can then start using the practice again but in a more effective or intelligent way.
What I've described above is often the way that I learn new things but I'm sure that others' experiences will vary so it'd be interesting to hear about other approaches too!
Coding: Shared libraries
On a few projects that I've worked on one of the things that we've done is create a shared library of objects which can be used across several different projects and while at the time it seemed like a good idea, in hindsight I'm not sure if it's an entirely successful strategy.
I'm quite a fan of not recreating effort which is generally the goal when trying to pull out common code and within one team this seems to be a good approach the majority of the time.
When it comes to sharing across teams then I think we need to consider the perceived benefits a bit more because it doesn't come without costs.
These are some of the types of code that we've shared previously:
Domain objectsI think this is the most dangerous type of code to share because although we often do have the same domain concepts in different projects, it's quite rare that they mean exactly the same thing.
In addition there is an implicit coupling created with our database since we pretty much now have to make sure that our database schema matches up with the current version of that domain object.
Either that or we do have a shared database for all the applications which use that shared domain object in which case we have an even stronger coupling between applications.
We're assuming that the two application have exactly the same domain concept and from my experience quite often that isn't the case – even if there is a concept with the same name it may be used in different ways or mean something completely different in different applications.
This is quite similar to the problem with having a universal domain model which Dan points out in his classic SOA article.
In general I don't think it makes sense to share this type of code.
Test codeThis one seems like it should fairly universally a good idea – after all we often import 3rd party testing libraries so it seems like just sharing some common testing code shouldn't be much different.
One piece of code that we shared was the Selenium bootstrapping code and this approach worked reasonably well until we wanted to adjust the amount of time between each command because commands were being sent to the browser before elements had the chance to load.
Apart from the fact that the other users of the library didn't want anything change with respect to how they used the code we had to go and make the change in another project, build that and then update the reference that we had to the library.
Certainly this process would have been made easier if we'd used something like Ivy but the amount of duplication of code that we were saving didn't seem worth the hassle it caused so we ended up inlining the code.
Infrastructure codeGeneral infrastructure code e.g. code to handle NHibernate transactions which is quite unlikely to change seems one candidate which can work quite well in a shared library and so far I haven't seen many problems arise from doing this.
I think the key with these bits of reusable code is that we keep them quite small and ensure that they have only one responsibility which will be useful for all the applications.
We eventually ended up slimming down our shared library and the majority of the code that remains in there is solving specific infrastructure type problems which will be the same across any applications using the same technical stack.
Things to be careful about when sharing codeOne reason that we may share code is so that if there is a change then it only needs to be done in one place.
We need to have a degree of confident that if we put code in a shared library that this is actually the case.
If it's likely that different applications might need shared code to change in different ways then we might not want to make that bit of code shared otherwise we'll just end up with application specific code in a shared library.
From what I've noticed it makes most sense to put code which is unlikely to change and is generic enough to be useful across several applications as is into shared libraries.
For any other code it might actually be beneficial to accept that there will be some duplication between applications in the same organisation and not try and pull out a common piece.
Pair Programming: In interviews
I came across a couple of quite interesting blog posts recently which described some approaches to interviewing which suggest a more empirical approach to interviewing whereby the interview is treated more like an audition for the person being interviewed.
I like this idea and it's something that we do when recruiting developers in a pair programming interview.
The general idea is that we pair with the candidate as they go through a coding problem. It's perhaps a little different from a normal pairing session in that the interviewee is more than likely driving for the majority of the session.
Sometimes we might also have another interviewer observing the pairing session and giving input where necessary.
While many people may not have specifically pair programmed before nearly everyone has worked with someone else at one computer on a problem so I haven't ever found that a candidate finds it too much of a leap because they're used to working alone.
One of the really cool things about a pair programming interview is that it's much closer to what a real situation on a project would be like which I think helps you to gain a more accurate picture of the skill level and potential of the interviewee.
As an interviewer you get the chance to see how quickly the interviewee will pick up new ideas, to an extent how well they work with other people and first hand experience of their level of expertise when it comes to coding.
From my experience of other types of interviews it can be quite difficult to tell exactly how much knowledge someone has in a specific topic but in a pair programming you can just see for yourself so it works out quite well in that sense.
It's certainly not fool proof and I quite like the way that Hash Rocket have taken this idea to the next level and get people to come there and pair program with them for a week before they get hired.
This seems like the next logical step and I guess if you have the ability to do this and candidates are prepared to give up their time then it's a really useful approach.
As Knut Haugen points out, the interview process is as much an opportunity for the employee to work out if they actually want to work for the potential employer and I think having the opportunity to pair with some of the people who work there is a great chance to assess this.
Dave Nicolette suggests that the pairing part of the interview process is considered the only meaningful part of the interview process in the team he's coaching and while I'm not I'd go that far I do think it's a very valuable approach and one I'd recommend even if you don't pair program all the time on your team.
Refactoring: Small steps to pull out responsibilities
I wrote previously about how I've been using effect sketches to identify responsibilities in objects so that I can pull them out into other objects and once I've done this I often find that I can't see a small next step to take.
At this stage in the past I've often then stopped and left the refactoring until I have more time to complete it but this hasn't really worked and a lot of the time I end up only seeing the code change in my mind and not in the actual code.
I came across this problem again last week in an object which had 8 dependencies when I came across it.
Having drawn the effect sketch I realised that 3 of those could be pulled out into a new object which could then be injected into the original object and help to encapsulate those other 3 dependencies.
The code that I wanted to change was something like this:
public class TheObject
{
private readonly DependencyA;
private readonly DependencyB;
private readonly DependencyB;
...
public Foo FooCreation()
{
var dependencyAValue = dependencyA.GetSomething();
var dependencyBValue = dependencyB.GetSomething();
var dependencyCValue = dependencyC.GetSomething();
return new Foo(dependencyAValue, dependencyBValue, dependencyCValue);
}
...
}
I wanted to pull the 'FooCreation' method out into another object and then change all the places that were calling 'TheObject'FooCreation' to just call this new object directly.
The first step was to create a 'FooFactory' and just have that delegated to internally:
public class FooFactory
{
private readonly DependencyA;
private readonly DependencyB;
private readonly DependencyB;
...
public Foo Create()
{
var dependencyAValue = dependencyA.GetSomething();
var dependencyBValue = dependencyB.GetSomething();
var dependencyCValue = dependencyC.GetSomething();
return new Foo(dependencyAValue, dependencyBValue, dependencyCValue);
}
}
public class TheObject
{
...
public Foo FooCreation()
{
return new FooFactory(dependencyA, dependencyB, dependencyC).Create();
}
...
}
I ran out of time at this stage to finish off the refactoring but it was obvious where the refactoring was going so the next time I got the chance I injected the 'FooFactory' into 'TheObject':
public interface IFooFactory
{
Foo Create();
}
public class TheObject
{
private readonly IFooFactory;
...
public TheObject(IFooFactory fooFactory)
{
this.fooFactory = fooFactory;
}
public Foo FooCreation()
{
return fooFactory.Create();
}
...
}
To do this I had to go and change the tests on 'TheObject' and move some of them to go directly against 'FooFactory'.
The third stage of the refactoring was to change all the places which called 'TheObject.FooCreation()' to just call 'FooFactory.Create()' directly.
Some of those places were also using other methods on 'TheObject' so those objects now have an extra dependency although I think at least the code is more intention revealing than it was previously.
I'm sure there are some other patterns for this type of small step refactoring but this is just one that I've noticed so far.
Coding: Effect sketches and the Mikado method
I've written previously about how useful I find effect sketches for helping me to understand how an object's methods and fields fit together and while drawing one a couple of weeks ago I noticed that it's actually quite useful for seeing which parts of the code will be the easiest to change.
I was fairly sure one of the object's in our code base was doing too many things due to the fact that it had a lot of dependencies.
However, it wasn't obvious to me from looking at the code which would be the easiest place to start in pulling out some of those responsibilities.
I therefore drew out an effect sketch which looked something like this:

From the diagram I could see more clearly that 'MethodC' is using 3 fields which are not used by any of the other methods in the object.
This therefore seemed like the perfect method to pull out since I could do so really easily and get rid of 3 of the object's fields since noone else used them anyway.
This reminded me a lot of the Mikado method for addressing technical debt which I've read about but haven't used yet.
As I understand it, the goal with the Mikado method is to locate areas of the code base that we can change easily because there are no dependencies on this piece of code.
When using effect sketches the goal is to try and use the sketch to work out how we can group functionality and I think the idea of making initial changes that have a low impact is a good one to follow.
I drew my initial effect sketch on paper but I noticed that drawing it up in graphviz actually makes it even more obvious which bits of functionality are related.
For example I hadn't realised that 'fieldB' was used by so many methods until I typed this up.
It's quite a neat tool and easy to pick up. This is my 'dot' file for the above sketch:
blog.dot
digraph effectgraph {
size="8,8";
"MethodA" -> "fieldA";
"MethodA" -> "fieldB";
"MethodA" -> "fieldC";
"MethodB" -> "fieldB";
"MethodB" -> "fieldE";
"MethodB" -> "fieldF";
"MethodC" -> "fieldG";
"MethodC" -> "fieldH"
"MethodC" -> "fieldD"
"MethodD" -> "fieldB"
"MethodD" -> "fieldI"
}
And to generate a png I ran the following command from the terminal:
dot -Tpng -blog.png blog.dot
Javascript: Bowling Game Kata
I spent some time over the weekend playing with the bowling game kata in Javascript.
I thought I knew the language well enough to be able to do this kata quite easily so I was quite surprised at how much I struggled initially.
These are some of my observations from this exercise:
- I was using screw-unit as my unit testing framework – I originally tried to setup JSTestDriver but I was having problems getting that to work so in the interests of not shaving the yak I decided to go with something I already know how to use.
I don't think I quite get the idea of the 'describe' and 'it' blocks which I believe are inspired by Rspec.
I like the idea of describing the behaviour of an object for the different contexts in which it's used but I found myself putting all my examples/tests in the same describe block without realising!
I went back and tried to find the different contexts but the only obvious distinction I noticed was that some tests seemed to be covering fairly basic bowling combinations while others were covering specific types of games:
- normal games
- should score a single throw
- should score two throws which do not add up to a strike or spare
- should score a spare
- should score multiple spares
- should score a strike
- should score back to back strikes
- should score a combination of strikes and spares
- special combinations
- should score a full house of strikes
- should score a full house of spares
- should score a gutter game
- should score a dutch 200
There's no specific setup unique to these two contexts which I've often noticed is a tell tale sign when writing tests in C# that we need to split our tests out a bit so I'm not sure whether I've added much value by doing this refactoring.
Following Esko Luontola's terminology the tests that I've written follow example style test names rather than specification style test names.
This means that in order to understand the scoring rules of bowling you would need to look at the implementation of the test rather than just read the name.
I think this might be a key difference in the way we write tests in JUnit/NUnit and RSpec/screw-unit.
- normal games
- At one stage I was making use of the Array 'splice' function to get an array with an element removed and I had expected that I would be returned a new array with those elements removed.
In actual fact that function mutates the original array so if we're going to do anything using 'splice' then it seems like we need to get a copy of the original array by using 'slice' otherwise we may end up with some quite unexpected behaviour later on in the program.
The other thing I found strange is that 'splice' returns the elements that have been removed from the array rather than the newly mutated array.
To get an array with the first element removed we'd do something like this:
function removeFirstItemFrom(theArray) { var copy = theArray.slice(0); copy.splice(0, 1); return copy; } var anArray = [1,2,3,4,5]; var anArrayWithFirstItemRemoved = removeFirstItemFrom(anArray);After my time playing around with functional approaches to programming it's quite strange to see APIs which mutate values and don't return the results that I'd expect them to. Interesting though.
- Since a lot of the test setup involved rolling gutter balls I had a lot of calls to 'bowlingGame.roll(0)' which was making the test quite convoluted and not adding much value.
I wrote a function to extend 'Number' so that I could use a Ruby style '10.times' syntax:
Number.prototype.times = function(f) { for(var i=0; i < this; ++i) { f(); } return this; };When I tried to use this function like this:
10.times(function() { bowlingGame.roll(0); });I kept getting the following error:
SyntaxError: missing ; before statement
I couldn't work out what I was doing wrong but skim pointed out that in Javascript we need to wrap number literals in parentheses in order to call functions on them:
(10).times(function() { bowlingGame.roll(0); });works much better!
I wrote a couple of other general use functions and one thing which I'm not sure about is whether or not I should do validation on the input parameters or is it down to the user of the function to use it correctly?
I'm more used to static languages where it would be more difficult to pass in an unexpected value so I'm not sure what the normal approach would be in a dynamic language.
- I took quite a lot of ideas from the way Brett Schuchert solved the problem in Ruby.
In particular I really like the way that he's broken down the problem into smaller and smaller functions which all do only one thing. It's quite easy to end up writing really complicated functions which are difficult to understand so it was good to see that it is possible to keep it this simple.
It would be quite interesting to see how this type of solution evolved.
- This wasn't my most incremental bit of coding ever – I found that some of the examples I introduced e.g. scoring a strike often resulted in quite a lot of code needing to change to make the test pass.
My current thinking is that for this problem we perhaps need to have some idea of the way that we want the code to evolve before we start writing our solution. A solution doesn't just evolve in front of us when we add in the next test. Either that or I'm not taking steps which are small enough to allow that evolution to happen.
C#: Overcomplicating with LINQ
I recently came across an interesting bit of code which was going through a collection of strings and then only taking the first 'x' number of characters and discarding the rest.
The code looked roughly like this:
var words = new[] {"hello", "to", "the", "world"};
var newWords = new List<string>();
foreach (string word in words)
{
if (word.Length > 3)
{
newWords.Add(word.Substring(0, 3));
continue;
}
newWords.Add(word);
}
For this initial collection of words we would expect 'newWords' to contain ["hel", "to", "the", "wor"]
In a way it's quite annoying that the API for 'Substring' throws an exception if you try and get just the first 3 characters of a string which contains less than 3 characters. If it didn't do that then we would have an easy 'Select' call on the collection.
Instead we have an annoying if statement which stops us from treating the collection as a whole – we do two different things depending on whether or not the string contains more than 3 characters.
In the spirit of the transformational mindset I tried to write some code using functional collection parameters which didn't make use of an if statement.
Following this idea we pretty much have to split the collection into two resulting in this initial attempt:
var newWords = words
.Where(w => w.Length > 3)
.Select(w => w.Substring(0, 3))
.Union(words.Where(w => w.Length <= 3).Select(w => w));
This resulted in a collection containing ["hel", "wor", "to", "the"] which is now in a different order to the original!
To keep the original order I figured that we needed to keep track of the original index position of the words, resulting in this massively overcomplicated version:
var wordsWithIndex = words.Select((w, index) => new { w, index });
var newWords = wordsWithIndex
.Where(a => a.w.Length >= 3)
.Select((a, index) => new {w = a.w.Substring(0, 3), a.index})
.Union(wordsWithIndex.Where(a => a.w.Length < 3).Select(a => new { a.w, a.index }))
.OrderBy(a => a.index);
We end up with a collection of anonymous types from which we can get the transformed words but it's a far worse solution than any of the others because it takes way longer to understand what's going on.
I couldn't see a good way to make use of functional collection parameters to solve this problem but luckily at this stage Chris Owen came over and pointed out that we could just do this:
var newWords = words.Select(w => w.Length > 3 ? w.Substring(0, 3) : w);
I'd been trying to avoid doing what is effectively an if statement inside a 'Select' but I think in this case it makes a lot of sense and results in a simple and easy to read solution.
C#: A lack of covariance with generics example
One of the things I find most confusing when reading about programming languages is the idea of covariance and contravariance and while I've previously read that covariance is not possible when using generics in C# I recently came across an example where I saw that this was true.
I came across this problem while looking at how to refactor some code which has been written in an imperative style:
public interface IFoo
{
string Bar { get; set; }
}
public class Foo : IFoo
{
public string Bar { get; set; }
}
private IEnumerable<IFoo> GetMeFoos()
{
var someStrings = new[] { "mike", "mark" };
var someFoos = new List<IFoo>();
foreach (var s in someStrings)
{
someFoos.Add(new Foo { Bar = s });
}
return someFoos;
}
I changed the code to read like so:
private IEnumerable<IFoo> GetMeFoos()
{
var someStrings = new[] { "mike", "mark" };
return someStrings.Select(s => new Foo { Bar = s });
}
Which fails with the following compilation error:
Error 1 Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<Test.Foo>' to 'System.Collections.Generic.IEnumerable<Test.IFoo>'. An explicit conversion exists (are you missing a cast?)
I thought the compiler would infer that I actually wanted a collection of 'IFoo' given that I was returning from the method directly after the call to Select but it doesn't.
As I understand it the reason that we can't downcast an IEnumerable of 'Foo' to an IEnumberable of 'IFoo' is that we would run into problems if we worked of the assumption that our original collection only contained Foos in it later on in our program.
For example it would be possible to add any item which implemented the 'IFoo' interface into the collection even if it wasn't a 'Foo':
// this code won't compile List<Foo> foos = new List<Foo>(); // add some foos List<IFoo> ifoos = foos; foos.Add(new SomeOtherTypeThatImplementsIFoo());
It's not possible to convert 'SomeOtherTypeThatImplementsIFoo' to 'Foo' so we would run ourself into problems.
Rick Byers has a post from a few years ago where he explains how this works in more detail and also points out that covariance of generics is actually supported by the CLR, just not by C#.
In the case I described we can get around the problem by casting 'Foo' to 'IFoo' inside the 'Select':
private IEnumerable<IFoo> GetMeFoos()
{
var someStrings = new[] { "mike", "mark" };
return someStrings.Select(s => (IFoo) new Foo { Bar = s });
}
C#: Causing myself pain with LINQ's delayed evaluation
I recently came across some code was imperatively looping through a collection and then mapping each value to go to something else by using an injected dependency to do that.
I thought I'd try to make use of functional collection parameters to try and simplify the code a bit but actually ended up breaking one of the tests.
About a month ago I wrote about how I'd written a hand rolled stub to simplify a test and this was actually where I caused myself the problem!
The hand rolled stub was defined like this:
public class AValueOnFirstCallThenAnotherValueService : IService
{
private int numberOfCalls = 0;
public string SomeMethod(string parameter)
{
if(numberOfCalls == 0)
{
numberOfCalls++;
return "aValue";
}
else
{
numberOfCalls++;
return "differentValue";
}
}
}
The test was something like this:
[Test]
public void SomeTest()
{
var fooOne = new Foo { Bar = "barOne" };
var fooTwo = new Foo { Bar = "barTwo" };
var aCollectionOfFoos = new List<Foo> { fooOne, fooTwo };
var service = new AValueOnFirstCallThenAnotherValueService();
var someObject = new SomeObject(service);
var fooBars = someObject.Method(aCollectionOfFoos);
Assert.That(fooBars[0].Other, Is.EqualTo("aValue"));
// and so on
}
The object under test looked something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
public class SomeObject
{
private IService service;
public SomeObject(IService service)
{
this.service = service;
}
public IEnumerable<FooBar> Method(List<Foo> foos)
{
var fooBars = new List<FooBar();
foreach(var foo in foos)
{
fooBars.Add(new FooBar { Bar = foo.Bar, Other = service.SomeMethod(foo.Bar) };
}
// a bit further down
var sortedFooBars = fooBars.OrderBy(f => f.Other);
return fooBars;
}
}
I decided to try and incrementally refactor the code like so:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
public class SomeObject
{
...
public IEnumerable<FooBar> Method(List<Foo> foos)
{
var fooBars = foos.Select(f => new FooBar { Bar = f.Bar, Other = service.SomeMethod(f.Bar) };
// a bit further down
var sortedFooBars = fooBars.OrderBy(f => f.Other);
return fooBars;
}
}
I ran the tests after doing this and the test I described above failed – it was expecting a return value for 'Other' of 'aValue' but was actually returning 'differentValue'.
I was a bit confused about what was going on until I started watching what the test was doing through the debugger and realised that on the 'OrderBy' call on line 10 the 'Select' call on line 7 was being reevaluated which meant that the value returned by 'service.SomeMethod' would be 'differentValue' since it was being called for the 3rd and 4th time and it's set up to return 'aValue' only on the 1st time.
The way to get around this problem was to force the evaluation of 'fooBars' to happen immediately by calling 'ToList()':
1 2 3 4 5 6 7 8 9 10 11
public class SomeObject
{
...
public IEnumerable<FooBar> Method(List<Foo> foos)
{
var fooBars = foos.Select(f => new FooBar { Bar = f.Bar, Other = service.SomeMethod(f.Bar) }.ToList();
...
}
}
In this case it was fairly easy to identify the problem but I've written similar code before which has ended up reordering collections with thousands of items in because it's been lazy evaluated every time the collection is needed.
In Jeremy Miller's article about functional C# he suggests the idea of memoization as an optimisation technique to stop expensive calls being made more times than they need to be so perhaps this would be another way to solve the problem although I haven't tried that approach before.
Rules of Thumb: Don't use the session
A while ago I wrote about some rules of thumb that I'd been taught by my colleagues with respect to software development and I was reminded of one of them – don't put anything in the session – during a presentation my colleague Luca Grulla gave at our client on scaling applications by making use of the infrastructure of the web.
The problem with putting state in the session is that it means that requests from a specific user have to be tied to a specific server i.e. we have to use a sticky session/session affinity.
This reduces our ability to scale our system horizontally (scale out) i.e. by adding more servers to handle requests.
If, for example, we have a small amount of users (whose first request went to the same server) making a lot of requests (perhaps through AJAX calls) then we may quickly put one of our servers under load while the others are sitting there idle.
In addition we have increased complexity around our deployment process.
If we want to do an incremental deployment of a new version of our website across some of our servers then we need to ensure that we create a copy of any sessions on those servers and copy them to the ones we're not updating so that any users still on the system don't experience loss of data.
There are no doubts products which can allow us to do this more easily but it seems to me to be an unnecessary product in the first place since we can just design our application to not rely on the session.
As I understand it the web was designed to be stateless i.e. each request is independent and all the information is contained within that request and the idea of the session was only something which was added in later on.
How does the way we code change if we don't use the session?One thing we've often used the session for on projects that I've worked on is to store the current state of a form that the user is filling in.
When they've completed the form then we would probably store some representation of what they've entered in a database.
If we don't use the session then we need to store this intermediate data somewhere and include a key to load it in the request.
On the project I'm working on at the moment we're storing that data in a database but then clearing out that data every other day since it's not needed once the user has completed the form.
An alternative perhaps could be to store it in a cache since in reality all we have is a key/value pair which we need to keep for a relatively short amount of time.
Advantages/disadvantages of this approachThe disadvantage of this approach is that we have to make more reads and writes to the database to deal with this temporary data.
Apart from the advantages I outlined initially, we are also more protected if a server handling a user's request goes down.
If we were using the session to store intermediate state then that information would be lost and they would have to start over.
In the approach we've using this isn't a problem and when the request is sent to another server we can still query the database and get whatever data the user had already saved.
As with most things there's a trade off to be made but in this case it seems a fair one to me.
Alternative approachesI've come across some alternative approaches where we avoid using the session but don't store intermediate state in a database.
One way is to store that state in hidden fields on the form and another is to send it in the request parameters.
Neither of these approaches seem particularly clean to me and they give the user an easier way to change the intermediate data in ways that the form might not allow them to do.
From my experience our server side code becomes more complicated since we're always writing all of the data entered so far back into the page.
In addition the url becomes a complete mess with the second approach.