My objects are turning into zombies, check it out…
Recent Posts
-
Zombie attack
-
Enforcing coding standards when working with legacy code
I’ve been thinking about the best way to start getting a consistent coding style with our team. Mostly I’ve worked on new projects and this is a relatively trivial thing to do by setting up StyleCop with an agreed set of rules, and hooking it up to analyse all source files as part of the Continuous Build. Along with a culture based on sarcasm and peer abuse, this usually works out fine.
However in this instance I’m working with a large legacy codebase. Even with the best intentions people won’t stick to a convention unless it gets enforced, and based on the amount of code that doesn’t comply it isn’t very simple to start enforcing the standard.
The only solution I could really see was to swallow the pain and go and reformat all of the existing code, then start enforcing analysis on the projects that have been updated.
I don’t think this would have even been possible if it hadn’t been for Resharper 5 and the StyleCop for Resharper plugin. I’ve become massively more productive since using Resharper a few weeks back and in this instance it’s been simply awesome.
Code Cleanup
Once Resharper has been configured with the StyleCop plugin so all coding style conventions are set up, you can run the code cleanup feature against a file or folder (Ctrl-Shift-Alt-F) which will reformat all existing code based on the configured rules. In my case this will typically reduce a file from around 300 violations to about 8. You can set up a profile to control exactly what does or does not get changed as part of this process.
Cycle through code issues (F12)
The next most useful feature is that StyleCop violations are treated as code issues by ReSharper. Hitting F12 repeatedly within a code file will jump to the next issue making it very simple to navigate around all violations and clean them up.
Violation highlighting within editor
The plugin will also highlight any style violation as you code, and provide tooltips and messages in the status bar to indicate what the violation was.
It will still take a while to finish updating the existing codebase, but I’m not even sure it would be feasible to attempt this without these tools.
-
Persisting state on the client with the HTML5 Web Storage APIs
One of the specifications in the mix with HTML5 defines a new API to allow web authors to save data to the client, either for the duration of a session, or to persist after the window shuts. The official spec is available here, or there’s a more friendly example of how to use the localStorage API from Mozilla here.
I’ve just implemented this for a script based visual design tool which had a requirement to save drafts and work in progress to load back up at a later date. To achieve this, I’m using the localStorage object which is available from the window object like so…
function saveButtonClick(event) {
event.preventDefault();var data = $('#xmlData').val();
var key = $('#saveName').val();
localStorage.setItem(key, data);
alert("Saved!");}
To enumerate the items that have been saved to local storage, to present these in a load action panel, I’m doing the following…
function refreshSavedDesignList() {$('#load ul').remove();var $list = $('<ul />').appendTo($('#load div'));
for (var i = 0; i < localStorage.length; i++) {
$('<li />').append($('<span />').text(localStorage[i])).append($('<a />').attr('href', '#').text('Load').click(loadDesignClick))
.append($('<a />').attr('href', '#').text('Delete').click(deleteDesignClick))
.appendTo($list);
}
$('#load div').append($list);}
The key parts here are using localStorage.length to identify the number of items available and localStorage[index] to get the key stored against a particular item. This is a little simplistic, as it makes the assumption that everything available in local storage is a valid saved design.
To actually read data back out, I’m doing the following…
function loadDesignClick(event) {
event.preventDefault();var key = $(this).parents('li').find('span').text();
var data = localStorage.getItem(key);loadDomFromXml(data);
}
In addition to calling getItem(key), setItem(key, value) and removeItem(key), you can simply add properties directly like localStorage.foo = ‘bar’.
This spec is aiming to take web applications one step closer to the behaviour of native applications which can work offline – for example, email clients cache folders locally, calendars store events locally etc. The storage APIs form one part of this, along with a proposal for a client-side SQL database, and support around instructions for offline caching of pages and dependent resources.
A full description of the offline features is available here in the W3C spec.
-
Nibbling on HTML5
After reading the smallest technical book I’ve come across, I’ve switched to the HTML5 Doctype on my first site today. It looks like pretty much everything is backwards compatible and will degrade nicely, so we’re going to be reworking our markup to make use of a bunch of the additional semantic elements.
The most useful thing so far is having a valid way of stashing information in the DOM so it is available to client-side script via the data- attributes. An example would be storing an attribute like data-zoomimageurl=”http://blah” for use by an image zoom plugin.
Anyway, I’m off to shoot my friends now.
-
Managing IIS configuration in a web farm
We’re now running 4 web servers and it’s starting to feel like we should consider centralising the IIS configuration. It’s now enough manual work that I can see a situation where one server in the farm ends up configured very slightly differently.
We still need to manage a migration to Windows Server 2008 / IIS7, and it looks like it might be best to complete this first then look at shared configuration management in IIS7. The good news is that we now have enough capacity that it shouldn’t be a problem to take a single server out of the load balancer, get it rebuilt to IIS7, then added back in.
It looks like any centralisation of either the metabase or content files is based on serving from a network share. I’d be interested to know to what degree this impacts performance, and the best way to do this while avoiding a single point of failure.
I think I’ll probably worry about getting everything on to IIS7 then look at the best way to achieve this.
-
Web licensing direct from FontFont
Just noticed that FontFont are now selling fonts with a licensing agreement for hosting on your own site and serving up via @font-face – the licensing is based on average page impressions per licensed domain, and the pack you download contains both WOFF and EOT formats. This means at present these would just be supported in IE and Firefox.
-
Automating acceptance tests with BDD
I think we’re now running a pretty well-structured agile process, but one area that I’m interested in tightening up is how to express acceptance tests for user stories, and ideally how to automate the tests. A lot of the agile reading material talks in passing about acceptance tests without any real definition of the vocabulary or approach to use in expressing, organising and executing tests.
This fits in very nicely with some of the ideas in Behaviour Driven Design, which is like the next iteration of thinking around TDD. The idea is to express acceptance tests using a simple DSL vocabulary working in plain English, then hook up each acceptance test scenario to some automated tests which prove the scenario works as expected.
A simple example would be…
+Title: Customer withdraws cash+
As a customer,
I want to withdraw cash from an ATM,
so that I don’t have to wait in line at the bank.In BDD, an acceptance test would be along the lines of…
+Scenario 1: Account is in credit+
Given the account is in credit
And the card is valid
And the dispenser contains cash
When the customer requests cash
Then ensure the account is debited
And ensure cash is dispensed
And ensure the card is returnedI’ve lifted the example here from the key article published on BDD from Dan North – if you’re interested so far then you should stop reading now and go and check out the article.
BDD frameworks will then map each step expressed in the text above through to a method in a test class, so you have a great balance between expressing the acceptance tests in simple language, but having the ability to execute the tests.
I found the best way to learn about this so far was a TekPub video – you’ll need a subscription, but the video is under the ‘Concepts’ section > Concepts:5 Behaviour-driven Design with Specflow.
Overall it seems like a more natural way to approach proving the application behaviour, and makes it much easier for testers and analysts to work alongside you in defining acceptance tests. I’m quite keen to roll this into our day-to-day process.
-
Session cookies not expiring when Firefox closes
I’ve just been looking into a slightly strange issue where closing Firefox and opening again didn’t clear out session cookies. It looks like in the latest version of Firefox this behaviour is by design if you have certain preferences set.
They have introduced a feature where closing the browser can remember the tabs you had open, and rehydrates these again when you start Firefox. This feature is controlled in the Settings > General > Startup section. If you have this set to Show my windows and tabs from last time, Firefox will no longer expire session cookies when the browser is closed.
This seems to be a pretty big security concern, as you are prompted to switch this setting on the first time you try to close the browser, so the majority of users would have this set-up. I’m not entirely sure how it decides when a session cookie should expire under these conditions, any ideas?
-
Dynamic image endpoints – think about conditional GETs
I’ve been looking at an issue recently on a site where there is a dynamic endpoint that serves up an image that is stored in a SQL database. The endpoint added the Cache-control: public header, so on the face of it looked like it had added client-side caching support.
By default if you don’t send either Cache-Control: max-age, or Expires headers then the user agent has been told that the resource can be cached, but has no way to know whether it has changed on the server. Based on this the user agent will send a conditional GET request to the server to find out if the resource has changed, or if it can be served directly from the local cache (this would look like a 304 response).
A conditional GET will compare versions of a resource based on either the Last-Modified header, or the ETag header. Generally these would have been sent in the original response for a resource. The client will then send either the If-None-Match, or If-Modified-Since headers in the GET request to indicate the resource should ONLY be sent by the server if it has changed.
In this case the dynamic endpoint had not been coded to support conditional GETs, so the images were getting fully downloaded on each request as a 200 response.
The simplest solution is to send Cache-control: max-age in order to allow the user agent to serve the resource directly from the cache without bothering with a conditional GET. Alternatively the endpoint has to check for conditional GET requests and change it’s behaviour to support sending a 304 response if the image hasn’t changed.
The best diagnostic tool to see what is going on is the Net tab in Firebug. This will allow you to check the request and response headers, the response codes, and user agent caching behaviour.
-
FontShop are now selling webfonts directly
Just noticed this announcement today from FontShop – they are now selling font files in EOT / WOFF format directly along with a suitable licensing model. FontShop have been very progressive in supporting TypeKit to date, but this will provide a direct route for purchasing fonts from a foundry for use on the web.
TypeKit will still provide you access to a wide range of fonts for a low subscription fee, and will also go a long way to serving up the most appropriate format to different user agents.
Nice to see things moving forward and the industry starting to address the massive market that has been pretty much ignored to date.
