<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8200285235757892384</id><updated>2012-01-16T06:06:04.109Z</updated><category term='node.js'/><category term='Heroku'/><category term='LINQ'/><category term='MVC'/><category term='appharbor'/><category term='javascript'/><category term='Spring.net'/><category term='XP'/><category term='vmware'/><category term='TFS'/><category term='Rails'/><category term='development'/><category term='Log4Net'/><category term='vs2008'/><category term='Wall'/><category term='Folds'/><category term='MSTest'/><category term='HTC Desire'/><category term='Azure'/><category term='Boot'/><category term='Virtual machine'/><category term='C#'/><category term='billing'/><category term='Story'/><category term='JQuery'/><category term='GRUB'/><category term='ado.net'/><category term='git'/><category term='unit test'/><category term='Agile'/><category term='Ruby'/><category term='generics'/><category term='Kanban'/><category term='Razor'/><category term='.net'/><category term='performance'/><category term='Ubuntu'/><category term='Android'/><category term='BIOS'/><category term='management'/><category term='System Thinking'/><title type='text'>Folding Air, Software Development With Damian Stanger</title><subtitle type='html'>Damian Is a software developer / consultant for ThoughtWorks and thinks sharing is good.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>35</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-2157576230082180932</id><published>2011-11-07T21:22:00.000Z</published><updated>2011-11-07T21:25:35.110Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='node.js'/><title type='text'>Installing node.js on windows 7 machine</title><content type='html'>Ive recently been looking for instructions on how to install node.js (the javascript powered web server) on windows, and it received some quite confusing answers involving cygwin, building things from source&amp;nbsp;etc.&lt;br /&gt;And yes it is possible to install node on windows 7, in fact.... Its really really easy actually.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1. download node.exe from &lt;a href="http://nodejs.org/dist/v0.6.0/node.exe"&gt;http://nodejs.org/dist/v0.6.0/node.exe&lt;/a&gt;&amp;nbsp;(link avaliable from &lt;a href="http://nodejs.org/"&gt;http://nodejs.org&lt;/a&gt;)&lt;/div&gt;&lt;div&gt;2. create a sample node app&lt;/div&gt;&lt;br /&gt;&lt;code&gt;var http = require('http');&lt;br /&gt;http.createServer(function (req, res) {&lt;br /&gt;&amp;nbsp; &amp;nbsp; res.writeHead(200, {'Content-Type': 'text/plain'});&lt;br /&gt;&amp;nbsp; &amp;nbsp; res.end('Hello World\n');&lt;br /&gt;}).listen(1337, "127.0.0.1");&lt;br /&gt;console.log('Server running at http://127.0.0.1:1337/');&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;save in a file 'example.js' and place in the same folder as node.exe (anywhere on your system)&lt;br /&gt;open a command prompt in the folder with node.exe and your .js file&lt;br /&gt;&lt;br /&gt;run &amp;gt;&amp;nbsp;&lt;code&gt;node example.js&lt;/code&gt;&lt;br /&gt;and thats it, now open your browser and goto:&amp;nbsp;&lt;a href="http://127.0.0.1:1337/"&gt;http://127.0.0.1:1337/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Hello World&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;how easy was that?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-2157576230082180932?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/2157576230082180932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2011/11/installing-nodejs-on-windows-7-machine.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/2157576230082180932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/2157576230082180932'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2011/11/installing-nodejs-on-windows-7-machine.html' title='Installing node.js on windows 7 machine'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-5762263521965324017</id><published>2011-10-20T18:52:00.000+01:00</published><updated>2011-10-20T18:52:50.089+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Wall'/><category scheme='http://www.blogger.com/atom/ns#' term='Story'/><category scheme='http://www.blogger.com/atom/ns#' term='XP'/><category scheme='http://www.blogger.com/atom/ns#' term='Kanban'/><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><category scheme='http://www.blogger.com/atom/ns#' term='management'/><title type='text'>Kanban inspired card wall. Our example</title><content type='html'>&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Overview&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Some call them 'card walls', some 'story walls', others just 'the wall'. There are many names given to the wall but its purpose is the same, to convey project information to the team and other interested parties / stakeholders. I work on a software development team but Kanban boards can be applied to any process, from manufacturing to household to-do lists. Honestly the uses are as wide ranging as your imagination. But this article concentrates on software development.&lt;br /&gt;&lt;br /&gt;Some teams practice 'scrum' and put tasks on the wall, some XP and run on weekly/2 weekly/4 weekly iterations, but we are running in a kanban mode at the moment, applying Work In Progress (WIP) limits as best we can.&lt;br /&gt;&lt;br /&gt;I've worked on many different teams, with many different types of wall/board, from scrum to xp, from big walls to tiny boards. I think the Kanban inspired wall we are currently running with is the best I've have the good fortune to use. So I thought I'd share - I'll try to run you through it as best as I can.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;The wall&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-SAFjfUoBpxQ/TpsWY2Z5HVI/AAAAAAAAA_c/K4tzKuNkR08/s1600/StoryWall-Overview.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="300" src="http://2.bp.blogspot.com/-SAFjfUoBpxQ/TpsWY2Z5HVI/AAAAAAAAA_c/K4tzKuNkR08/s400/StoryWall-Overview.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;We are fortunate enough to have a very big space for our card wall (3-4 metres wide). I have been on teams that have had to manage with a small white board. Having said that, we have still filled every&amp;nbsp;available&amp;nbsp;space, and it would be nice if we had even more.&lt;br /&gt;&lt;br /&gt;The size allows us to show lots of project&amp;nbsp;relevant&amp;nbsp;information and also include&amp;nbsp;plenty&amp;nbsp;of room for up stream activities like information architecture (IA), user experience (UX) and analysis. So we have lots of&amp;nbsp;visibility&amp;nbsp;as to the state of all aspects of the project.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;b&gt;The Columns&lt;/b&gt;&lt;br /&gt;The columns are detailed below in their own sections, but to summarise they are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Design&lt;/li&gt;&lt;ul&gt;&lt;li&gt;In visual design&lt;/li&gt;&lt;li&gt;In customer testing&lt;/li&gt;&lt;li&gt;In front end dev&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Analysis&lt;/li&gt;&lt;ul&gt;&lt;li&gt;In analysis&lt;/li&gt;&lt;li&gt;Selected for dev&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Development&lt;/li&gt;&lt;ul&gt;&lt;li&gt;In dev&lt;/li&gt;&lt;li&gt;Dev complete&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;QA&lt;/li&gt;&lt;ul&gt;&lt;li&gt;In QA&lt;/li&gt;&lt;li&gt;QA complete&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Done&lt;/li&gt;&lt;li&gt;Technical tasks&lt;/li&gt;&lt;li&gt;Risks&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;The WIP Limits&lt;/b&gt;&lt;br /&gt;Work In Progress limits help us to focus on the tasks currently in play. Too many tasks on the board at any one time can mean the team is spread too thinly. Traffic jams can occur and important bug fixes won't get through quickly.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Example without WIP limits:&lt;/i&gt;&lt;br /&gt;Two big stories have just been finished and so QA now gets to work on them, whilst the developers start on new stories. At this point all four dev pairs are busy, as are the two QAs. A day later the testing is still not complete and another pair finishes their story, this story gets queued up in waiting for QA. If there were no WIP limits the pair would start a new story and get on with that work. But what happens if there is then a bug in one of the stories, a big bug? Who should pick it up? A dev pair need to stop what they are doing mid flow, shelve all their current checked out work, context switch to the bug, investigate and fix it. I guess you know where this is going, with&amp;nbsp;effectively three stories in QA and four stories in dev everyone is going to be flip-flopping between stories and bug fixes. Context switching costs time and the whole process reduces our ability to respond to change. The main&amp;nbsp;consequence&amp;nbsp;being that throughput and velocity suffer, not to mention the headaches of leaving half finished code laying about whilst you fix something else.&lt;br /&gt;&lt;br /&gt;By limiting the number of stories in each column this does not happen (well, much much less so). Developers are always&amp;nbsp;available&amp;nbsp;for fixes and everyone&amp;nbsp;experiences&amp;nbsp;less context switching and more&amp;nbsp;uninterrupted&amp;nbsp;flow.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Story Cards&lt;/b&gt;&lt;br /&gt;We have four different&amp;nbsp;coloured cards on the wall: yellow, blue, white and pink. The different colours mean different things depending on where they are on the wall, but its quite straight forward.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Yellow: Design tasks, our UX guys work on the yellow cards in the first 3 columns, either working on the IA, wire frames, or styling of up coming stories.&lt;/li&gt;&lt;li&gt;Yellow: Development tasks, tech tasks and tech debt. All things that are not stories but need playing, e.g.: Set up performance test environment, or refactor X to remove duplication, or even spike out Y to prove integration points.&lt;/li&gt;&lt;li&gt;Blue: Features under analysis. These cards only appear in the analysis and done columns and represent whole features, big things. I think there are around 15 in release one.&lt;/li&gt;&lt;li&gt;Pink: Bugs, simples [sic].&lt;/li&gt;&lt;li&gt;White: Most of the cards flowing across the wall are white. These denote stories that require dev effort. We try to ensure that all the white cards can be finished in 1-4 days&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-ciEt4jOy5bI/Tp8tr-HfF9I/AAAAAAAAA_0/W751yuOzPF8/s1600/card02.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="240" src="http://3.bp.blogspot.com/-ciEt4jOy5bI/Tp8tr-HfF9I/AAAAAAAAA_0/W751yuOzPF8/s320/card02.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;i&gt;White Story Card&lt;/i&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Story number for reference in Mingle or TFS.&lt;/li&gt;&lt;li&gt;Story title, brief, must fit on one card in thick writing.&lt;/li&gt;&lt;li&gt;Days in play (the dots get added every morning before our daily stand up meeting) This allows us to see how long cards take to flow through the wall.&lt;/li&gt;&lt;li&gt;Story point estimate (size/complexity)&lt;/li&gt;&lt;li&gt;Relevant&amp;nbsp;notes can be captured on the reverse if needed.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-6BZddXeOXpA/Tp8trfmvj9I/AAAAAAAAA_s/nd4tqhTDVZw/s1600/card01.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="240" src="http://4.bp.blogspot.com/-6BZddXeOXpA/Tp8trfmvj9I/AAAAAAAAA_s/nd4tqhTDVZw/s320/card01.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;i&gt;Yellow Tech Card&lt;/i&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Usually these do not have reference numbers.&lt;/li&gt;&lt;li&gt;Usually no estimate either.&lt;/li&gt;&lt;li&gt;Just a&amp;nbsp;brief&amp;nbsp;description of the work required.&lt;/li&gt;&lt;li&gt;Again&amp;nbsp;relevant&amp;nbsp;notes can be captured on the reverse if needed.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;Flow across the wall&lt;/b&gt;&lt;/div&gt;Features start their life in the 'In analysis' column. All the features that are designated for release 1 are in this column in priority order. Whilst the BAs are working on splitting stories out, the UX and IA guys are also looking into how best to fulfil the users requirements from a design perspective, and they put their own cards up on the left of the board.&lt;br /&gt;Once a story is ready to be developed, a white card is placed in the 'Selected for dev' column and waits here until a dev pair is ready to pick them up. At which point they are moved in to 'In dev' until the pair has showcased the story to the QA and BA's satisfaction at which point it moves into dev complete (awaiting QA).&lt;br /&gt;The QAs pick up cards and work on them in the 'In QA' column. Cards NEVER move backwards, if there are bugs to fix a dev pair will move to fix it in the QA column, whatever they were doing will remain in the 'In dev' column. Once the QA is happy with the card it will move into 'QA complete' where the BAs now showcase the story to the product owner before moving it to 'Done'.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;The Columns In Detail&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-FuCRC8gN7kA/TpsVUD4kMnI/AAAAAAAAA-0/99mGOExb-WQ/s1600/StoryWall-Design.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="202" src="http://1.bp.blogspot.com/-FuCRC8gN7kA/TpsVUD4kMnI/AAAAAAAAA-0/99mGOExb-WQ/s400/StoryWall-Design.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;b&gt;Design&lt;/b&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Walls&amp;nbsp;I've&amp;nbsp;often worked with in the past have not had a design area on them. This project has a heavy design and UX aspect and so it was important to have this area on the wall so we can all see what features are at which point in the process.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;The columns we have here are: 'In visual design' for development of the wireframes and IA; 'In customer testing'; and 'In front end dev' for development of the UX including styling and image creating.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-Yrr6-Sv_yeM/TpsVTjT-O8I/AAAAAAAAA-s/0DkbTnI_Dfk/s1600/StoryWall-Analysis.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="202" src="http://2.bp.blogspot.com/-Yrr6-Sv_yeM/TpsVTjT-O8I/AAAAAAAAA-s/0DkbTnI_Dfk/s400/StoryWall-Analysis.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;b&gt;Analysis&amp;nbsp;&lt;/b&gt;&lt;b&gt;(WIP 6)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;The Analysis columns consist of 'In analysis' which list all the features of the current release (release one is about nine months) we keep stickies on the features (blue cards) to show how complete features are. The 'Selected for dev' column is used for the next stories to be picked up by the dev team (white cards), these stories should have been through the analysis process and be ready for devs to pick up, this column also serves as a heads up for the QAs so they can start getting ready for stories, working out acceptance criteria and so forth with the BAs and devs.&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/--gOAftX1jec/TpsVU0Tlk1I/AAAAAAAAA-8/_FvNZvtNfqY/s1600/StoryWall-Development.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="202" src="http://4.bp.blogspot.com/--gOAftX1jec/TpsVU0Tlk1I/AAAAAAAAA-8/_FvNZvtNfqY/s400/StoryWall-Development.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;b&gt;Dev (WIP 4)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;We currently have four dev pairs and so have set our WIP limit to four for the combination of the two dev columns. At the&amp;nbsp;beginning&amp;nbsp;of the project we set the WIP limit to three as we always had a pair on tech tasks, environment set up and the like, but now we are moving into the second half of the first release most of that type of task has been finished. If there are four white cards in the two dev columns the next pair to finish should help out with the testing effort or work on some tech tasks. This helps keep the actual work in progress on the board to a manageable amount.&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-joFjAZSLBXA/TpsVXYGRcLI/AAAAAAAAA_U/jiBaAicHOiA/s1600/StoryWall-Test.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="202" src="http://2.bp.blogspot.com/-joFjAZSLBXA/TpsVXYGRcLI/AAAAAAAAA_U/jiBaAicHOiA/s400/StoryWall-Test.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;b&gt;QA (WIP 2)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;The 'In QA' column has a WIP limit of two as we have two testers. If a story gets blocked due to a bug then devs need to come and help clear the blockage. The card can NEVER move back into dev and the QA can't pick up a new card from dev complete until the issues are resolved. This focuses attention and ensures that stories progress along the wall in a timly manner, always the empasis on getting completed work 'done done' so that we can claim the points, and move on.&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-R48lpO10Iuc/TpsVV2O0z2I/AAAAAAAAA_E/8lUBB56IXrg/s1600/StoryWall-Done.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="202" src="http://2.bp.blogspot.com/-R48lpO10Iuc/TpsVV2O0z2I/AAAAAAAAA_E/8lUBB56IXrg/s400/StoryWall-Done.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;b&gt;Done (Done Done)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;This column contains all the stories finished this week. Done Done. These stories are ready to be showcased to the product owner and will be demoed to the entire client user team (all stakeholders) on the Friday of each week. Every Monday all the cards are removed from this column so we can see what has been finished this week and so that the product owner and other stackholders can see the progress since last Friday's showcase.&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-ZJSWLh3GJRI/TpsVWvvhF-I/AAAAAAAAA_M/kmHFIUMX5qE/s1600/StoryWall-Metrics.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="202" src="http://2.bp.blogspot.com/-ZJSWLh3GJRI/TpsVWvvhF-I/AAAAAAAAA_M/kmHFIUMX5qE/s400/StoryWall-Metrics.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;b&gt;Metrics&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;/div&gt;This area contains all the different metrics, the different graphs and guides.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Cumulative Flow&lt;/li&gt;&lt;li&gt;Weekly Velocity&amp;nbsp;&lt;/li&gt;&lt;li&gt;Points Burn Up&lt;/li&gt;&lt;li&gt;Risk Count&lt;/li&gt;&lt;li&gt;Story points Guide&lt;/li&gt;&lt;li&gt;Done Done Guide&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-MNSVACzysrg/TpsXXUFHArI/AAAAAAAAA_k/CqO_xiF3HGw/s1600/StoryWall-Tech.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="320" src="http://4.bp.blogspot.com/-MNSVACzysrg/TpsXXUFHArI/AAAAAAAAA_k/CqO_xiF3HGw/s320/StoryWall-Tech.jpg" width="240" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;b&gt;Risks/Issues/Tech Tasks/Tech Debt Wall&lt;/b&gt;&lt;br /&gt;There are four columns to this section of the wall. The left most three are for 'tech debt', and tech tasks. The right most is for capturing risks and making them more&amp;nbsp;visible.&lt;br /&gt;&lt;br /&gt;Column 1 (Things we must do to make the project successful).&lt;br /&gt;Things like integrate with the corporate authentication system, spike asset management or setup performance testing environment.&lt;br /&gt;&lt;br /&gt;Column 2 (Things that would enable us to deliver faster)&lt;br /&gt;Includes things like&amp;nbsp;refactor&amp;nbsp;acceptance tests to reduce build time, and optimise windows configuration on all dev machines.&lt;br /&gt;&lt;br /&gt;Column 3 (Things that are not&amp;nbsp;essential&amp;nbsp;to the success of the project but will give us a better solution)&lt;br /&gt;Mainly includes lists of&amp;nbsp;refactorings&amp;nbsp;and areas we want to&amp;nbsp;achieve&amp;nbsp;better test coverage.&lt;br /&gt;&lt;br /&gt;Column 4 (Risk wall)&lt;br /&gt;Any risk to the project, from integration points, new technology, people, to computers and&amp;nbsp;hardware. Listed in highest risk at the top. The arrow represents whether the risk is increasing or decreasing as time passes.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Summary&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;So that is our wall. It saves us time, keeps us focussed on what's important, and neatly tracks our progress.&lt;br /&gt;&lt;br /&gt;How does your team work? I would be interested to know what other types of walls are out there. I've seen a few in my time but there is always another way of doing it - what does your wall do for you?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Glossary&amp;nbsp;&lt;/b&gt;&lt;br /&gt;BA - Business Analyst&lt;br /&gt;IA - Information Architecture&lt;br /&gt;Kanban -&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Kanban"&gt;http://en.wikipedia.org/wiki/Kanban&lt;/a&gt;&lt;br /&gt;Mingle -&amp;nbsp;&lt;a href="http://www.thoughtworks-studios.com/mingle-agile-project-management"&gt;http://www.thoughtworks-studios.com/mingle-agile-project-management&lt;/a&gt;&lt;br /&gt;QA - Quality Analyst&lt;br /&gt;Scrum -&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Scrum_%28development%29"&gt;http://en.wikipedia.org/wiki/Scrum_(development)&lt;/a&gt;&lt;br /&gt;Tech Debt -&amp;nbsp;&lt;a href="http://martinfowler.com/bliki/TechnicalDebt.html"&gt;http://martinfowler.com/bliki/TechnicalDebt.html&lt;/a&gt;&lt;br /&gt;TFS - Team Foundation Server&lt;br /&gt;UX - User eXperiance&lt;br /&gt;WIP - Work In Progress&lt;br /&gt;XP - eXtreme Programming -&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Extreme_Programming"&gt;http://en.wikipedia.org/wiki/Extreme_Programming&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-5762263521965324017?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/5762263521965324017/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2011/10/kanban-inspired-card-wall-our-example.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/5762263521965324017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/5762263521965324017'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2011/10/kanban-inspired-card-wall-our-example.html' title='Kanban inspired card wall. Our example'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-SAFjfUoBpxQ/TpsWY2Z5HVI/AAAAAAAAA_c/K4tzKuNkR08/s72-c/StoryWall-Overview.jpg' height='72' width='72'/><thr:total>2</thr:total><georss:featurename>Westminster, London, UK</georss:featurename><georss:point>51.5001524 -0.1262362</georss:point><georss:box>51.1838419 -0.7579502 51.8164629 0.5054778</georss:box></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-9174254839534748601</id><published>2011-08-31T22:38:00.000+01:00</published><updated>2011-08-31T22:38:23.150+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><category scheme='http://www.blogger.com/atom/ns#' term='management'/><title type='text'>How much does your slow machine cost your company?</title><content type='html'>&lt;br /&gt;&lt;b&gt;The problem&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I'm currently working at your standard large company. The computers are managed centrally and are replaced every 3 or 4 years or so. The machine I'm working on is a Dell running Windows 7 32bit with 3.21 GB of ram, an Intel core 2 duo CPU at 3GHz and on-board graphics running 2 monitors. Not a terrible machine you may say, but far far from good enough as a developer machine.&lt;br /&gt;&lt;br /&gt;We are developing an MVC 3 enterprise web app running on SQL Server 2008, LINQ to SQL, VS2010, Resharper 6, TFS integration. Javascript tests, unit tests, integration tests, feature tests and acceptance tests make up a sizeable testing suite. As you can imagine, this set-up can put quite a load on the machines especially as our app has been growing fast. Our team's velocity is still good, so the code base is growing quickly.&lt;br /&gt;&lt;br /&gt;We are finding that the machines hang periodically. All the dev machines are quite slow and all exactly the same spec but for some reason, a few are terribly slow, and we avoid pairing on those machines. Then there's the 30-60 second waits for visual studio builds, the 5 minutes for the check-in builds, the time to compile and run tests as you are doing TDD, the time our tests run for, the 10 seconds+ for visual studio and resharper to refactor things, find things. It all adds up, but how much does it cost? Not only does it cost in terms of wasted time but also in context switching. For example, you're doing TDD, you write a test, do some coding and hit run test but have to wait 30 seconds+ for it to run. This takes long enough to break your flow, you have a quick think about something else and then you realise the test has run and you need to switch you attention back. You might have a quick chat about something else with your pair.&lt;br /&gt;&lt;br /&gt;We know it's hurting our velocity but without numbers it's difficult to convince management of the true costs.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;So what did we do?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;We took a stop watch, kept it with us all day and recorded all the time that where we were waiting for the computer to do something - from opening apps, running builds and tests, searches and refactorings in visual studio - any time at all where the developer had to wait for the machine to work, be it 5 seconds or 5 minutes the stop watch was running. It took quite a lot of discipline. The results were startling.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Results&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I did this for a week, every day, and so did a colleague. Our results were very similar in that on average we were sitting unproductive for a collective time of 30 to 60 minutes a day with a couple of days at 15 minutes (mainly due to days with meetings) and a couple of days at a whopping 75 minutes (these were days when perversely we were going quite quick and getting things done, but running builds/tests/check-ins all day takes time).&lt;br /&gt;&lt;br /&gt;So lets say 40 minutes wasted per pair per day. That sounds like a lot, but it's how long the stopwatch said. You try it for a day. What are your numbers?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The machine&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;We are running Windows 7 on a machine that originally was running server 2003, so the requirements on the machine are different. We have turned off all the Aero UI elements from the machines (we have on board graphics). We've turned off the virus checking&amp;nbsp;(controversially, as this is a corporate environment), and followed numerous tutorials on the internet about improving the speed of windows, but all to no avail.&lt;br /&gt;&lt;br /&gt;If we had a faster, better, newer machine, then how much would we gain? Well that's subjective, but for arguments sake, say we had a great machine and could cut all the waiting/processing time in half &amp;nbsp;(*1)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Costs&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;What is the cost to the business of one dev per day? It depends on your company, your devs, their seniority, your support staff, building costs, electricity etc. There are many factors, but let's say £200 (this is a conservative estimate *2)&lt;br /&gt;&lt;br /&gt;Our team consists of 10 devs, 3 UI/UX/designers, 2 QAs/testers, 2 BAs (analysts), 1 PM (manager) = 18 people. If we assume they each cost a nominal £200 per day, that is £3600 a day for the team as a whole.&lt;br /&gt;&lt;br /&gt;Devs are the constraint on the throughput of the system (the bottleneck). That's 10 people losing 40 mins a day, so 400 minutes a day of lost development effort. We said a fast machine might cut this in half, so we have 200 mins of needlessly lost development effort per day. How much does that cost?&lt;br /&gt;&lt;br /&gt;We work an 8 hour day, 10 devs x 8 hours = 4,800 minutes of dev time available per day.&lt;br /&gt;&lt;br /&gt;So the cost per minute for the throughput is £3,600 / 4,800 = £0.75 per minute (Wait you say, you took the cost of the team, divided by the time of the developers? I shall explain *3)&lt;br /&gt;&lt;br /&gt;Finally £0.75 x 200 mins = £150 lost by the business every day&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;To sum up, it is costing the business £150 per day to have 10 developers using slow machines. Given we are paring on all dev work we only need 5 new fast machines. I know you can get a great machine for £1,000 (*4), which will be future proofed for the next 2 years or so. That's £5,000 in total.&lt;br /&gt;&lt;br /&gt;£5,000 / £150 = 33 days. That's the number of days it takes to pay off the new machines by not losing the developers time waiting every day.&lt;br /&gt;&lt;br /&gt;So is that £1,000 for a new dev machine worth it? I conclude it is, if the project is longer than 33 days. Is yours?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Appendix&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Theory_of_Constraints"&gt;Theory_of_Constraints&lt;/a&gt;&amp;nbsp;on&amp;nbsp;Wikipedia.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/The_Goal_(novel)"&gt;The_Goal_(novel)&lt;/a&gt;&amp;nbsp;is an&amp;nbsp;excellent&amp;nbsp;book that describes the theory of constraints at a manufacturing plant in a story format.&lt;/li&gt;&lt;li&gt;1 - We will only know how much better a great machine would be when we get one and use it on our project, but I suspect given the state of our current machines it will be half the time.&lt;/li&gt;&lt;li&gt;2 - This is a low estimate, especially as I'm a consultant and get charged out at a higher rate than £200/day, but this is likely to be a conservative estimate for any company employing developers.&lt;/li&gt;&lt;li&gt;3 - The theory of constraints says that the cost of the bottleneck is equal to the cost of the system as a whole. The goal of the system is to produce finished production ready functionality. Which part of the system is the bottleneck, stopping you from delivering more functionality? On our team it's us, the developers. We only release what is coded up every week. Nothing the testers or analysts can do can make us deliver more. So the output of the system is governed by the velocity of the devs. The cost of the team (in our case £3600) is the cost of the 20 story points we deliver that week, and it's the devs who control that velocity. That's not to say the other roles are not important, they are, critically important, but they are not the bottleneck.&lt;/li&gt;&lt;li&gt;4 - Yes you should get a good machine for that. You could actually get a great computer for £500 - £600. We have the monitors and peripherals, and given we are a big company we would qualify for Dell's corporate rates.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-9174254839534748601?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/9174254839534748601/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2011/08/how-much-does-your-slow-machine-cost.html#comment-form' title='14 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/9174254839534748601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/9174254839534748601'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2011/08/how-much-does-your-slow-machine-cost.html' title='How much does your slow machine cost your company?'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-1151439423827924730</id><published>2011-07-20T11:19:00.001+01:00</published><updated>2011-08-02T12:57:17.734+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='Razor'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>model dynamic causing unhandled exception</title><content type='html'>We are using ASP.MVC 3 with Razor views on one of the projects in currently working on. MVC3 uses C# 4.0 and so we get access to the dynamic types, this is really convenient when creating partial views, we can create a model in one partial and pass the new dynamic model into the partial, no need for strongly typed view models everywhere.&lt;br /&gt;&lt;br /&gt;But we have found that dynamic models can hide other errors with very time consuming consequence's. &lt;br /&gt;This is the partial "_topics" that was causing us problems:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;@model dynamic&lt;br /&gt;&lt;br /&gt;&amp;lt;ul&amp;gt;&lt;br /&gt;    @foreach (var topic in Model.Topics)&lt;br /&gt;    {&lt;br /&gt;        &amp;lt;li id=&amp;quot;@topic.Id&amp;quot; class=&amp;quot;@( Model.SelectedItems.Contains(topic.Id) ?  &amp;quot;selected&amp;quot; : string.Empty ) &amp;quot;&amp;gt;&lt;br /&gt;            &amp;lt;label&amp;gt;@topic.Name&amp;lt;/label&amp;gt;&lt;br /&gt;            @if (topic.HasChildren)&lt;br /&gt;        {&lt;br /&gt;                @Html.Partial(&amp;quot;_Topics&amp;quot;, new { Topics = topic.Children, SelectedItems = Model.SelectedItems });&lt;br /&gt;        }&lt;br /&gt;        &amp;lt;/li&amp;gt;&lt;br /&gt;    }&lt;br /&gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;as you can see _topics is called recursively.&lt;br /&gt;&lt;br /&gt;We made some changes to other areas of our project and got this error: (sorry for the very long stack trace, but i wanted to be complete)&lt;br /&gt;&lt;pre&gt;&lt;code&gt;Application information: &lt;br /&gt;    Application domain: /LM/W3SVC/3/ROOT-3-129566639908092111 &lt;br /&gt;    Trust level: Full &lt;br /&gt;    Application Virtual Path: / &lt;br /&gt;    Application Path: C:\projects\Foo\Bar\Src\Editor\ &lt;br /&gt;    Machine name: AAA20711 &lt;br /&gt; &lt;br /&gt;Process information: &lt;br /&gt;    Process ID: 5928 &lt;br /&gt;    Process name: w3wp.exe &lt;br /&gt;    Account name: IIS APPPOOL\Editor &lt;br /&gt; &lt;br /&gt;Exception information: &lt;br /&gt;    Exception type: RuntimeBinderException &lt;br /&gt;    Exception message: 'object' does not contain a definition for 'Topics'&lt;br /&gt;   at CallSite.Target(Closure , CallSite , Object )&lt;br /&gt;   at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)&lt;br /&gt;   at ASP._Page_Views_Shared__Topics_cshtml.Execute() in C:\projects\Foo\Bar\Src\Editor\Views\Shared\_Topics.cshtml:line 4&lt;br /&gt;   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()&lt;br /&gt;   at System.Web.Mvc.WebViewPage.ExecutePageHierarchy()&lt;br /&gt;   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)&lt;br /&gt;   at System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance)&lt;br /&gt;   at System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer)&lt;br /&gt;   at System.Web.Mvc.HtmlHelper.RenderPartialInternal(String partialViewName, ViewDataDictionary viewData, Object model, TextWriter writer, ViewEngineCollection viewEngineCollection)&lt;br /&gt;   at System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName, Object model, ViewDataDictionary viewData)&lt;br /&gt;   at System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName, Object model)&lt;br /&gt;   at ASP._Page_Views_Shared__ArticleTabs_cshtml.Execute() in C:\projects\Foo\Bar\Src\Editor\Views\Shared\_ArticleTabs.cshtml:line 42&lt;br /&gt;   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()&lt;br /&gt;   at System.Web.Mvc.WebViewPage.ExecutePageHierarchy()&lt;br /&gt;   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)&lt;br /&gt;   at System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance)&lt;br /&gt;   at System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer)&lt;br /&gt;   at System.Web.Mvc.HtmlHelper.RenderPartialInternal(String partialViewName, ViewDataDictionary viewData, Object model, TextWriter writer, ViewEngineCollection viewEngineCollection)&lt;br /&gt;   at System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName, Object model, ViewDataDictionary viewData)&lt;br /&gt;   at System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName)&lt;br /&gt;   at ASP._Page_Views_ArticleCreate_Create_cshtml.Execute() in C:\projects\Foo\Bar\Src\Editor\Views\ArticleCreate\Create.cshtml:line 23&lt;br /&gt;   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()&lt;br /&gt;   at System.Web.Mvc.WebViewPage.ExecutePageHierarchy()&lt;br /&gt;   at System.Web.WebPages.StartPage.RunPage()&lt;br /&gt;   at System.Web.WebPages.StartPage.ExecutePageHierarchy()&lt;br /&gt;   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)&lt;br /&gt;   at System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance)&lt;br /&gt;   at System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer)&lt;br /&gt;   at System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context)&lt;br /&gt;   at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)&lt;br /&gt;   at System.Web.Mvc.ControllerActionInvoker.&amp;lt;&amp;gt;c__DisplayClass1c.&amp;lt;InvokeActionResultWithFilters&amp;gt;b__19()&lt;br /&gt;   at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)&lt;br /&gt;   at System.Web.Mvc.ControllerActionInvoker.&amp;lt;&amp;gt;c__DisplayClass1c.&amp;lt;&amp;gt;c__DisplayClass1e.&amp;lt;InvokeActionResultWithFilters&amp;gt;b__1b()&lt;br /&gt;   at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)&lt;br /&gt;   at System.Web.Mvc.ControllerActionInvoker.&amp;lt;&amp;gt;c__DisplayClass1c.&amp;lt;&amp;gt;c__DisplayClass1e.&amp;lt;InvokeActionResultWithFilters&amp;gt;b__1b()&lt;br /&gt;   at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult)&lt;br /&gt;   at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)&lt;br /&gt;   at System.Web.Mvc.Controller.ExecuteCore()&lt;br /&gt;   at System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext)&lt;br /&gt;   at System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext)&lt;br /&gt;   at System.Web.Mvc.MvcHandler.&amp;lt;&amp;gt;c__DisplayClass6.&amp;lt;&amp;gt;c__DisplayClassb.&amp;lt;BeginProcessRequest&amp;gt;b__5()&lt;br /&gt;   at System.Web.Mvc.Async.AsyncResultWrapper.&amp;lt;&amp;gt;c__DisplayClass1.&amp;lt;MakeVoidDelegate&amp;gt;b__0()&lt;br /&gt;   at System.Web.Mvc.Async.AsyncResultWrapper.&amp;lt;&amp;gt;c__DisplayClass8`1.&amp;lt;BeginSynchronous&amp;gt;b__7(IAsyncResult _)&lt;br /&gt;   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()&lt;br /&gt;   at System.Web.Mvc.MvcHandler.&amp;lt;&amp;gt;c__DisplayClasse.&amp;lt;EndProcessRequest&amp;gt;b__d()&lt;br /&gt;   at System.Web.Mvc.SecurityUtil.&amp;lt;GetCallInAppTrustThunk&amp;gt;b__0(Action f)&lt;br /&gt;   at System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action)&lt;br /&gt;   at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)&lt;br /&gt;   at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)&lt;br /&gt;   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()&lt;br /&gt;   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean&amp;amp; completedSynchronously)&lt;br /&gt;&lt;br /&gt;Request information: &lt;br /&gt;    Request URL: http://editor/article/create &lt;br /&gt;    Request path: /article/create &lt;br /&gt;    User host address: 127.0.0.1 &lt;br /&gt;    User: Foo &lt;br /&gt;    Is authenticated: True &lt;br /&gt;    Authentication Type: Forms &lt;br /&gt;    Thread account name: IIS APPPOOL\Editor &lt;br /&gt; &lt;br /&gt;Thread information: &lt;br /&gt;    Thread ID: 9 &lt;br /&gt;    Thread account name: IIS APPPOOL\Editor &lt;br /&gt;    Is impersonating: False &lt;br /&gt;    Stack trace:    at CallSite.Target(Closure , CallSite , Object )&lt;br /&gt;   at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)&lt;br /&gt;   at ASP._Page_Views_Shared__Topics_cshtml.Execute() in C:\projects\Foo\Bar\Src\Editor\Views\Shared\_Topics.cshtml:line 4&lt;br /&gt;   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()&lt;br /&gt;   at System.Web.Mvc.WebViewPage.ExecutePageHierarchy()&lt;br /&gt;   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)&lt;br /&gt;   at System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance)&lt;br /&gt;   at System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer)&lt;br /&gt;   at System.Web.Mvc.HtmlHelper.RenderPartialInternal(String partialViewName, ViewDataDictionary viewData, Object model, TextWriter writer, ViewEngineCollection viewEngineCollection)&lt;br /&gt;   at System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName, Object model, ViewDataDictionary viewData)&lt;br /&gt;   at System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName, Object model)&lt;br /&gt;   at ASP._Page_Views_Shared__ArticleTabs_cshtml.Execute() in C:\projects\Foo\Bar\Src\Editor\Views\Shared\_ArticleTabs.cshtml:line 42&lt;br /&gt;   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()&lt;br /&gt;   at System.Web.Mvc.WebViewPage.ExecutePageHierarchy()&lt;br /&gt;   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)&lt;br /&gt;   at System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance)&lt;br /&gt;   at System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer)&lt;br /&gt;   at System.Web.Mvc.HtmlHelper.RenderPartialInternal(String partialViewName, ViewDataDictionary viewData, Object model, TextWriter writer, ViewEngineCollection viewEngineCollection)&lt;br /&gt;   at System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName, Object model, ViewDataDictionary viewData)&lt;br /&gt;   at System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName)&lt;br /&gt;   at ASP._Page_Views_ArticleCreate_Create_cshtml.Execute() in C:\projects\Foo\Bar\Src\Editor\Views\ArticleCreate\Create.cshtml:line 23&lt;br /&gt;   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()&lt;br /&gt;   at System.Web.Mvc.WebViewPage.ExecutePageHierarchy()&lt;br /&gt;   at System.Web.WebPages.StartPage.RunPage()&lt;br /&gt;   at System.Web.WebPages.StartPage.ExecutePageHierarchy()&lt;br /&gt;   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)&lt;br /&gt;   at System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance)&lt;br /&gt;   at System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer)&lt;br /&gt;   at System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context)&lt;br /&gt;   at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)&lt;br /&gt;   at System.Web.Mvc.ControllerActionInvoker.&amp;lt;&amp;gt;c__DisplayClass1c.&amp;lt;InvokeActionResultWithFilters&amp;gt;b__19()&lt;br /&gt;   at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)&lt;br /&gt;   at System.Web.Mvc.ControllerActionInvoker.&amp;lt;&amp;gt;c__DisplayClass1c.&amp;lt;&amp;gt;c__DisplayClass1e.&amp;lt;InvokeActionResultWithFilters&amp;gt;b__1b()&lt;br /&gt;   at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)&lt;br /&gt;   at System.Web.Mvc.ControllerActionInvoker.&amp;lt;&amp;gt;c__DisplayClass1c.&amp;lt;&amp;gt;c__DisplayClass1e.&amp;lt;InvokeActionResultWithFilters&amp;gt;b__1b()&lt;br /&gt;   at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult)&lt;br /&gt;   at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)&lt;br /&gt;   at System.Web.Mvc.Controller.ExecuteCore()&lt;br /&gt;   at System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext)&lt;br /&gt;   at System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext)&lt;br /&gt;   at System.Web.Mvc.MvcHandler.&amp;lt;&amp;gt;c__DisplayClass6.&amp;lt;&amp;gt;c__DisplayClassb.&amp;lt;BeginProcessRequest&amp;gt;b__5()&lt;br /&gt;   at System.Web.Mvc.Async.AsyncResultWrapper.&amp;lt;&amp;gt;c__DisplayClass1.&amp;lt;MakeVoidDelegate&amp;gt;b__0()&lt;br /&gt;   at System.Web.Mvc.Async.AsyncResultWrapper.&amp;lt;&amp;gt;c__DisplayClass8`1.&amp;lt;BeginSynchronous&amp;gt;b__7(IAsyncResult _)&lt;br /&gt;   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()&lt;br /&gt;   at System.Web.Mvc.MvcHandler.&amp;lt;&amp;gt;c__DisplayClasse.&amp;lt;EndProcessRequest&amp;gt;b__d()&lt;br /&gt;   at System.Web.Mvc.SecurityUtil.&amp;lt;GetCallInAppTrustThunk&amp;gt;b__0(Action f)&lt;br /&gt;   at System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action)&lt;br /&gt;   at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)&lt;br /&gt;   at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)&lt;br /&gt;   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()&lt;br /&gt;   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean&amp;amp; completedSynchronously)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Looks like there was a problem with the dynamic model, line 4 is the for each loop on model.topics. But debugging this code showed there was no problem with the model, it was fully populated with lots of topics and the debugger could see them and access them, so what gives?&lt;br /&gt;&lt;br /&gt;Well after investigating it turned out another partial that the razor view uses had a compilation error in it, we only found this after removing the _topics partial. Very strange that a compilation error in another partial would cause the error we got.&lt;br /&gt;&lt;br /&gt;To stop this ever happening again we made the project pre compile the views along with the rest of the web project but putting MvcBuildViews=true the .csproj&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;&amp;lt;Project ToolsVersion=&amp;quot;4.0&amp;quot; DefaultTargets=&amp;quot;Build&amp;quot; xmlns=&amp;quot;http://schemas.microsoft.com/developer/msbuild/2003&amp;quot;&amp;gt;&lt;br /&gt;  &amp;lt;PropertyGroup&amp;gt;&lt;br /&gt;  ....&lt;br /&gt;    &amp;lt;MvcBuildViews&amp;gt;true&amp;lt;/MvcBuildViews&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Now we get the real error at compile time, not an error in the dynamic model code at run time, much nicer.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-1151439423827924730?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/1151439423827924730/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2011/07/model-dynamic-causing-unhandled.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/1151439423827924730'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/1151439423827924730'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2011/07/model-dynamic-causing-unhandled.html' title='model dynamic causing unhandled exception'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-7284820237779257479</id><published>2011-07-03T09:02:00.003+01:00</published><updated>2011-08-02T11:49:10.377+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='LINQ'/><title type='text'>Linq to Sql many to many delete</title><content type='html'>My current project is using linq2sql, we had a small problem deleting a record from a many to many relationship that used a link table which only contained 2 required foreign key columns.&lt;br /&gt;&lt;br /&gt;product with productId&lt;br /&gt;order with orderId&lt;br /&gt;productOrder with 2 foreign keys productId and orderId&lt;br /&gt;&lt;br /&gt;System.Data.Linq.DuplicateKeyException : Cannot add an entity with a key that is already in use.&lt;br /&gt;System.InvalidOperationException : An attempt was made to remove a relationship between a product and a productOrder. &lt;br /&gt;&lt;br /&gt;However, one of the relationship's foreign keys (productOrder.productId) cannot be set to null.&lt;br /&gt;&lt;br /&gt;The trick was to add DeleteOnNull=&amp;quot;true&amp;quot; to the association&lt;br /&gt;&lt;br /&gt;to delete modify collections (many to many link tables)&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;Table Name=&amp;quot;dbo.product&amp;quot; Member=&amp;quot;product&amp;quot;&amp;gt;&lt;br /&gt;  &amp;lt;Type Name=&amp;quot;product&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;Column Name=&amp;quot;productId&amp;quot; Type=&amp;quot;System.Int32&amp;quot; DbType=&amp;quot;Int NOT NULL IDENTITY&amp;quot; IsPrimaryKey=&amp;quot;true&amp;quot; IsDbGenerated=&amp;quot;true&amp;quot; CanBeNull=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;    &amp;lt;Column Name=&amp;quot;Title&amp;quot; Type=&amp;quot;System.String&amp;quot; DbType=&amp;quot;VarChar(255)&amp;quot; CanBeNull=&amp;quot;true&amp;quot; /&amp;gt;&lt;br /&gt;    &amp;lt;Association Name=&amp;quot;product_productOrder&amp;quot; Member=&amp;quot;productOrders&amp;quot; ThisKey=&amp;quot;productId&amp;quot; OtherKey=&amp;quot;productId&amp;quot; Type=&amp;quot;productOrder&amp;quot; &lt;b&gt;DeleteOnNull=&amp;quot;true&amp;quot;&lt;/b&gt;/&amp;gt;&lt;br /&gt;  &amp;lt;/Type&amp;gt;&lt;br /&gt;&amp;lt;/Table&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;Table Name=&amp;quot;dbo.productOrders&amp;quot; Member=&amp;quot;productOrders&amp;quot;&amp;gt;&lt;br /&gt;  &amp;lt;Type Name=&amp;quot;productOrder&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;Column Name=&amp;quot;productId&amp;quot; Type=&amp;quot;System.Int32&amp;quot; DbType=&amp;quot;Int NOT NULL&amp;quot; IsPrimaryKey=&amp;quot;true&amp;quot; CanBeNull=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;    &amp;lt;Column Name=&amp;quot;orderId&amp;quot; Type=&amp;quot;System.Int32&amp;quot; DbType=&amp;quot;Int NOT NULL&amp;quot; IsPrimaryKey=&amp;quot;true&amp;quot; CanBeNull=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;    &amp;lt;Association Name=&amp;quot;product_productOrder&amp;quot; Member=&amp;quot;productId&amp;quot; ThisKey=&amp;quot;productId&amp;quot; OtherKey=&amp;quot;productId&amp;quot; Type=&amp;quot;product&amp;quot; IsForeignKey=&amp;quot;true&amp;quot; DeleteOnNull=&amp;quot;true&amp;quot;/&amp;gt;&lt;br /&gt;    &amp;lt;Association Name=&amp;quot;order_productOrder&amp;quot; Member=&amp;quot;order&amp;quot; ThisKey=&amp;quot;orderId&amp;quot; OtherKey=&amp;quot;orderId&amp;quot; Type=&amp;quot;order&amp;quot; IsForeignKey=&amp;quot;true&amp;quot; &lt;b&gt;DeleteOnNull=&amp;quot;true&amp;quot;&lt;/b&gt;/&amp;gt;&lt;br /&gt;  &amp;lt;/Type&amp;gt;&lt;br /&gt;&amp;lt;/Table&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;product.ProductOrders.Clear();&lt;br /&gt;product.ProductOrders.AddRange(myNewProductOrders);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;I found help on this matter here: &lt;a href="http://blogs.msdn.com/b/bethmassi/archive/2007/10/02/linq-to-sql-and-one-to-many-relationships.aspx"&gt;http://blogs.msdn.com/b/bethmassi/archive/2007/10/02/linq-to-sql-and-one-to-many-relationships.aspx&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-7284820237779257479?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/7284820237779257479/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2011/07/linq-to-sql-many-to-many-delete.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/7284820237779257479'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/7284820237779257479'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2011/07/linq-to-sql-many-to-many-delete.html' title='Linq to Sql many to many delete'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-8866511103947521920</id><published>2011-06-22T09:27:00.000+01:00</published><updated>2011-06-22T09:27:22.730+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='unit test'/><title type='text'>Unit testing your unity IOC wiring</title><content type='html'>I'm using Unity for the IOC container at the moment which is great, injecting in dependencies to the controller makes the dev cycle so quick, without it TDDing would be significantly more difficult. we can unit test everything including the controllers, but you all know that.&lt;br /&gt;&lt;br /&gt;There is a small downside to using unity, in that you only find out about problems to the wiring when you run your app, or your acceptance tests, and then you need to analyse the error and figure out what went wrong.&lt;br /&gt;&lt;br /&gt;So i thought wouldn't it be nice to have a unit test to test your unity configuration :-)&lt;br /&gt;Well here it is&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;using NUnit.Framework;&lt;br /&gt;using System.Reflection;&lt;br /&gt;using System.Web.Mvc;&lt;br /&gt;&lt;br /&gt;namespace Tests.Unit.Consumer&lt;br /&gt;{&lt;br /&gt;    [TestFixture]&lt;br /&gt;    public class ProductionWiringDefinitionTest&lt;br /&gt;    {&lt;br /&gt;        [Test]&lt;br /&gt;        public void ProductionWiringIsComplete()&lt;br /&gt;        {&lt;br /&gt;            IWiringDefinition wiringDefinition = new ConsumerProductionWiringDefinition();&lt;br /&gt;            WiringDefinitionAssertions.AssertWiringDefinitionAllDependenciesResolved(wiringDefinition);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;  &lt;br /&gt;    public static class WiringDefinitionAssertions&lt;br /&gt;    {&lt;br /&gt;        public static void AssertWiringDefinitionAllDependenciesResolved(IWiringDefinition wiringDefinition)&lt;br /&gt;        {&lt;br /&gt;            var unityDependencyResolver = UnityDependencyResolver.Instance;&lt;br /&gt;            unityDependencyResolver.Configure(wiringDefinition);&lt;br /&gt;            DependencyResolver.SetResolver(unityDependencyResolver);            &lt;br /&gt;            &lt;br /&gt;            var containerFieldInfo = unityDependencyResolver.GetType().GetField(&amp;quot;container&amp;quot;, BindingFlags.NonPublic &amp;#124; BindingFlags.Instance);&lt;br /&gt;            var container = (Microsoft.Practices.Unity.UnityContainer) containerFieldInfo.GetValue(unityDependencyResolver);&lt;br /&gt;&lt;br /&gt;            foreach (var registration in container.Registrations)&lt;br /&gt;            {&lt;br /&gt;                unityDependencyResolver.GetService(registration.RegisteredType);                   &lt;br /&gt;                unityDependencyResolver.GetService(registration.MappedToType);                   &lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }  &lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The lines that do the magic are 30 and 31 inside the for loop, basically we try and instantiate everything that unity knows about, if any dependencies are missing you will get a nice unit test failure and a very good error message telling you exactly what is wrong.&lt;br /&gt;&lt;br /&gt;You may have to change this example a little as it uses our abstraction of IWiringDefinition because we have multiple sites all doing the same thing but with different wiring.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;using Microsoft.Practices.Unity;&lt;br /&gt;namespace Framework.Ioc&lt;br /&gt;{&lt;br /&gt;    public interface IWiringDefinition&lt;br /&gt;    {&lt;br /&gt;        void Configure(IUnityContainer container);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;And an example of our wiring definition&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;using Diagnostics;&lt;br /&gt;using Microsoft.Practices.Unity;&lt;br /&gt;&lt;br /&gt;namespace Consumer.Application&lt;br /&gt;{&lt;br /&gt;    public class ConsumerProductionWiringDefinition : IWiringDefinition&lt;br /&gt;    {&lt;br /&gt;        public void Configure(IUnityContainer container)&lt;br /&gt;        {&lt;br /&gt;            RegisterViewModelMappers(container);&lt;br /&gt;            RegisterDatabaseContext(container);&lt;br /&gt;            RegisterControllers(container);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private static void RegisterDatabaseContext(IUnityContainer container)&lt;br /&gt;        {&lt;br /&gt;            container.RegisterType&amp;lt;IDatabaseManager, DatabaseManager&amp;gt;();&lt;br /&gt;            container.RegisterType&amp;lt;DatabaseManager&amp;gt;(new InjectionConstructor(new DbConnectionString().ForConsumer));&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private static void RegisterControllers(IUnityContainer container)&lt;br /&gt;        {&lt;br /&gt;            container.RegisterType&amp;lt;DiagnosticsController&amp;gt;(new InjectionConstructor(new ServerDiagnosticsController()));&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private static void RegisterViewModelMappers(IUnityContainer container)&lt;br /&gt;        {&lt;br /&gt;            container.RegisterType&amp;lt;ITopicWithArticleSummariesMapper, TopicWithArticleSummariesMapper&amp;gt;();&lt;br /&gt;            container.RegisterType&amp;lt;IArticleSummaryMapper, ArticleSummaryMapper&amp;gt;();&lt;br /&gt;            container.RegisterType&amp;lt;IToolsPageViewModelMapper, ToolsPageViewModelMapper&amp;gt;();&lt;br /&gt;            container.RegisterType&amp;lt;IToolViewModelMapper, ToolViewModelMapper&amp;gt;();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Like i said this example above is not entirely complete, you will need a little more than this to get your wiring working, but its a good introduction to actually testing your wiring.&lt;br /&gt;&lt;br /&gt;Good luck.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-8866511103947521920?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/8866511103947521920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2011/06/unit-testing-your-unity-ioc-wiring.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/8866511103947521920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/8866511103947521920'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2011/06/unit-testing-your-unity-ioc-wiring.html' title='Unit testing your unity IOC wiring'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-6849876849015401766</id><published>2011-03-22T12:02:00.002Z</published><updated>2011-03-22T17:31:41.330Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Heroku'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Ruby on Rails 3 - Installing Devise authentication on Heroku</title><content type='html'>A few days ago I decided to add authentication to my Rails 3 app. I came across a few alternatives but in the end opted for Devise as this seems to be the newest and from the documents I found apparently the easiest to implement.&lt;br /&gt;I needed users to be able to register new users, sign in and out and to have special admin users who could access restricted areas of the site, Devise hit all these requirements.&lt;br /&gt;&lt;br /&gt;So I found a couple of good tutorials including &lt;a href="https://github.com/plataformatec/devise"&gt;https://github.com/plataformatec/devise&lt;/a&gt; and associated wiki &lt;a href="https://github.com/plataformatec/devise/wiki/_pages"&gt;https://github.com/plataformatec/devise/wiki/_pages&lt;/a&gt; and found these really good at getting me up and going quickly.&lt;br /&gt;&lt;br /&gt;I got everything working locally but then when I pushed my git repo to Heroku I got the error when using the register page:&lt;i&gt; &lt;b&gt;We're sorry, but something went wrong.&lt;/b&gt; We've been notified about this issue and we'll take a look at it shortly.&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;so to the command line 'Heroku logs' revealed this error:&lt;br /&gt;&lt;code&gt;2011-03-21T14:03:09-07:00 app[web.1]: NameError (uninitialized constant Devise::Encryptors::Bcrypt):&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;It took me a while but after searching around any trying all sorts of things i hit the answer. and as usual it was simple, if you are deploying to heroku you need to add bcrypt-ruby to your gemfile like so:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;gem 'devise', '1.1.8'&lt;br /&gt;gem 'bcrypt-ruby', '2.1.4'&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Also remember to generate and commit your new gemfile.lock into git and send this to heroku as well as the new gemfile or you will get the following error, as i did:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;You have modified your Gemfile in development but did not check&lt;br /&gt;the resulting snapshot (Gemfile.lock) into version control&lt;br /&gt;You have added to the Gemfile:&lt;br /&gt;* bcrypt-ruby (= 2.1.4)&lt;br /&gt;FAILED: http://docs.heroku.com/bundler&lt;br /&gt;Heroku push rejected, failed to install gems via Bundler&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;My Devise Authentication Implementation&lt;/b&gt;&lt;br /&gt;I've added the following to the top of all my admin controller classes to ensure that only administrators can access them&lt;br /&gt;&lt;br /&gt;&lt;code&gt;before_filter :authenticate_user!&lt;br /&gt;before_filter :authorise_user!&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The method :authenticate_user! is a helper method built into Devise&lt;br /&gt;The method :authorise_user! is my own declared in ApplicationController as follows:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;def authorise_user!&lt;br /&gt;&amp;nbsp; if ! current_user.try(:admin?)&lt;br /&gt;&amp;nbsp; &amp;nbsp; flash[:alert] = "Unauthorised"&lt;br /&gt;&amp;nbsp; &amp;nbsp; redirect_to ''&lt;br /&gt;&amp;nbsp; end&lt;br /&gt;end&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;where admin is a boolean field on the devise created user table. (I used option 2 from&lt;a href="https://github.com/plataformatec/devise/wiki/How-To:-Add-an-Admin-role"&gt; this wiki page&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;For controllers which none admin users have access to I want to restrict them so that they can only see resources that they created. So for example, bob created an order-x, you don't want James to be able to access that order-x it belongs to bob not James.&lt;br /&gt;&lt;br /&gt;For this I've created methods similar to: &lt;br /&gt;&lt;br /&gt;&lt;code&gt;def authorise_as_owner!&lt;br /&gt;&amp;nbsp; order = Order.find(params[:id])&lt;br /&gt;&amp;nbsp; unless current_user.try(:admin?) || order.user_id == current_user.id&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; flash[:alert]&amp;nbsp; = "Not your order!"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; redirect_to ''&lt;br /&gt;&amp;nbsp; end&lt;br /&gt;end&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-6849876849015401766?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/6849876849015401766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2011/03/ruby-on-rails-3-installing-devise.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/6849876849015401766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/6849876849015401766'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2011/03/ruby-on-rails-3-installing-devise.html' title='Ruby on Rails 3 - Installing Devise authentication on Heroku'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-1435613466850584057</id><published>2011-03-11T10:42:00.003Z</published><updated>2011-03-12T10:27:21.092Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Folds'/><title type='text'>The DZone effect (how blog aggregation can affect traffic)</title><content type='html'>I recently used DZone for the first time to publicise my latest blog post to a wider audience. Oh my ... it worked rather well.&lt;br /&gt;&lt;br /&gt;So im on blogspot which gives some nice google analytics for free which i look at now and then to try and see what is popular and being read by other people.&lt;br /&gt;&lt;br /&gt;My blog is not all that widely read to be honest, it has a fair number of hits though, approximately 250 a month mainly coming from google searches, most traffic goes to a couple of my better/more interesting posts. But then i tried out submitting a post to dzone, mainly to see what happens.&lt;br /&gt;&lt;br /&gt;The result was instant, i got over 600 views in 2 days, for me thats a big number, was it the nature of the post (it was a little provocative) and maybe the summary on dzone made people want to see what i was on about, either way i got a large increase in my traffic %300 :-)&lt;br /&gt;&lt;br /&gt;Im not really hung up on loads of people seeing my posts, but its nice to know your are read :-) And dzone certainly seems to deliver.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-1435613466850584057?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/1435613466850584057/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2011/03/dzone-effect-how-blog-aggregation-can.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/1435613466850584057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/1435613466850584057'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2011/03/dzone-effect-how-blog-aggregation-can.html' title='The DZone effect (how blog aggregation can affect traffic)'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-7015618434081264365</id><published>2011-03-07T17:18:00.000Z</published><updated>2011-03-07T17:18:04.765Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='ado.net'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='appharbor'/><title type='text'>Appharbor, scripting sql server table creation using ado.net</title><content type='html'>So ive got a simple appharbor installation running, but need a database.&lt;br /&gt;I was half expecting a nice API I could use similar to herokus that would let me run my scripts against the hosted DB and thus deploy my DB at the command line, but not.&lt;br /&gt;&lt;br /&gt;What you need to do is connect to your DB through SQL server management studio (if using sql server) and do your DB work through that. All good and easy, but at work our corporate firewalls prevent us from getting out, or from external sources getting in, makes sense, and i as a lowly developer will never be able to change that, not that i would want to, it would be quite dangerous.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;So what to do?&lt;/b&gt;&lt;br /&gt;well i decided to write a page in my MVC app that (given the right credentials) will run a script that has been checked in, Here are the basics:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Create a DB on appharbor (use the web interface to create it, really simple)&lt;/li&gt;&lt;li&gt;Copy the connection settings and paste them into your web.config, here are mine (details changed to protect the innocent)&lt;/li&gt;&lt;/ul&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;connectionstrings&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add connectionstring="Server=db002.appharbor.net;Database=db1234;User ID=db1234;Password=lotsofrandomcharacters" name="mydb"&amp;gt;&amp;lt;/add&amp;gt;&lt;br /&gt;&amp;lt;/connectionstrings&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;now we need a controller with an action&lt;/li&gt;&lt;/ul&gt;&lt;code&gt; public ActionResult RunTheScript(string filename)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string connStr = ConfigurationManager.ConnectionStrings["mydb"].ToString();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; using (var conn = new SqlConnection(connStr))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; conn.Open();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string filePath = Server.MapPath("\\databasescripts\\" + filename);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FileInfo fileInfo = new FileInfo(filePath);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string script = fileInfo.OpenText().ReadToEnd();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlCommand cmd = new SqlCommand(script, conn);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cmd.ExecuteNonQuery();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; conn.Close();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return View();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch (Exception e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return View("ExceptionView", e);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/code&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Dont forget your routes in global.asax, Add the following before the default route.&lt;/li&gt;&lt;/ul&gt;&lt;code&gt;&lt;br /&gt;routes.MapRoute(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "admin_runthescript",  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "admin/runthescript/{filename}", &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new { controller = "admin", action = "runthescript" } // Parameter defaults&lt;br /&gt;);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And add a couple of views (your know how to do that), one for success and one for an exception.&lt;br /&gt;Yes there are better ways of doing this but its a quick and dirty demo, i expect people to use properly designed code when doing this live (Please dont mix your DB logic into your controllers people...)&lt;br /&gt;&lt;br /&gt;A note on the exception handling, you had better do this properly too as appharbor will not give you any logging out of the box, and will not spit back helpful errors to the user, not errors that can be used to debug anyway..&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Almost there, add a script, and save it in your databasescripts folder&lt;/li&gt;&lt;/ul&gt;&lt;code&gt;&lt;br /&gt;CREATE TABLE [dbo].[locations](&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [id] [int] IDENTITY(1,1) NOT NULL,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [name] [nvarchar](256) NOT NULL&lt;br /&gt;) ON [PRIMARY]&lt;br /&gt;&lt;br /&gt;INSERT INTO [dbo].[locations] ([name]) VALUES ('London')&lt;br /&gt;INSERT INTO [dbo].[locations] ([name]) VALUES ('Manchester')&lt;br /&gt;INSERT INTO [dbo].[locations] ([name]) VALUES ('Bristol')&lt;br /&gt;INSERT INTO [dbo].[locations] ([name]) VALUES ('Bath')&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Now add all the files to your git repo&lt;/li&gt;&lt;li&gt;commit&lt;/li&gt;&lt;li&gt;git push appharbor master&lt;/li&gt;&lt;li&gt;Run the migration through your web app using the url Controller/Action/Filename (scripts/runthescript/add_location_table.sql)&lt;/li&gt;&lt;/ul&gt;Thats pretty much it, its upto you to secure the page that can be used to create and destroy your db,dont blame me if someone gets in an messes with unsecured pages,&lt;br /&gt;&lt;br /&gt;Maybe there is something in the pipeline at app harbor that will help us out when scripting databases, but one thing is for sure using the management studio for building your applications database is not the way forward in the long run.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-7015618434081264365?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/7015618434081264365/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2011/03/appharbor-scripting-sql-server-table.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/7015618434081264365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/7015618434081264365'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2011/03/appharbor-scripting-sql-server-table.html' title='Appharbor, scripting sql server table creation using ado.net'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-7307346706743523393</id><published>2011-03-07T15:46:00.004Z</published><updated>2011-03-11T10:16:24.136Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='TFS'/><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><title type='text'>The true cost of TFS, is it really "free"?</title><content type='html'>You say you've got MSDN premium, so TFS is free, good for you, it is developed and supported by Microsoft, should be a great product then??&lt;br /&gt;&lt;br /&gt;Anyway in my personal opinion, it sucks, but try telling that to none technical people, its actually really hard, and they still insist you use it because its designed for enterprise use, isn't it?&lt;br /&gt;&lt;br /&gt;So i thought id do a 'back of the napkin' calculation of how much it actually costs.&lt;br /&gt;&lt;br /&gt;Our dev team is apparently worth ~40k a month, consisting of 4 devs, designer, tester, db admin, tester, ba,&lt;br /&gt;10 people, for arguments sake ~4 grand each per month.&lt;br /&gt;So if you take a dev pair thats 8 grand a month, or 2 grand a week.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Where is the waste (source control)?&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Check-ins&lt;/b&gt; :- We check in 7 to 10 times a day, each time it should be instant, but mostly TFS cant quite manage it, it needs user interaction to resolve the easiest of changes, some times it cant even manage to insert new lines. So estimate 3 minutes extra per check-in thats 20 minutes a day extra, or 2 hours per week. (Caveat, if you are working in the same area of code as another pair be prepared for this to at least double, ive had some awful merges in the past even when the conflicts weren't really that hard)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Get latest&lt;/b&gt; :- Sometimes get latest doesn't even get the latest, leaving files out or just getting it wrong?? how?? so now and then we need to sort it out, usually after wondering what on earth is going on and trying to debug your code only to find out my source is not up to date (10 - 20 mins per day on average, 1 hr per week)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Get specific&lt;/b&gt; :- So, often you start using get specific instead of get latest, this is slow so we try not to do it all the time, only when we think there might be a problem, the code base is big so this takes a lot longer than a get latest 2-3 minutes extra per check in, but only done 2-3 times a day (7 minutes per day, 30 mins per week)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Merge to main (feature branching) :-&lt;/b&gt;&lt;br /&gt;Depending on how often you merge to main, and how many other teams you  have also checking into main that is going to hit you quite hard. if you are a lone team with out any teams changing your code base you have it easy and can discount this step. for me its at least a 4 hour job of doing the merge to main once every month)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Where is the waste (Build management)?&lt;/b&gt;&lt;br /&gt;&lt;b&gt;MSBuild and TFS&lt;/b&gt; :- This is complex, significantly more complex than the same projects built with nant and cruse control, Team city, Go, et al. it sucks a lot of our time when we need to change the builds, its hard to say how much worse it is, our code base is quite old and complex, lots of build dependencies, this needs fixing, lets be conservative and say it only takes 1 hour extra per week to maintain TFS over any of the others.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Total Waste&lt;/b&gt;&lt;br /&gt;2 hrs + 1hr + .5 hrs + 1hr = 5.5 hours of waste a week, lets call it 5 for now, I like round numbers.&lt;br /&gt;&lt;br /&gt;So a pair of devs is on 2 grand a week, 35 hours = £60 per hour&lt;br /&gt;5 hours waste = £60 * 5 = £300 per week per pair&lt;br /&gt;2 pairs in our team = £600 per week * 4 = £2,400 per month on a £40,000 dev team&lt;br /&gt;&lt;br /&gt;Thats just a 2 pair team, if you have even a moderate size team of 4 pairs you are going to get even more pain, with developers effecting each others check ins.&lt;br /&gt;&lt;br /&gt;Oh and what about that merge to main hell we discussed (if you are feature branching), add 4 hrs * £60 per month = £240 extra.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Summary :-&lt;/b&gt;&lt;br /&gt;your "free" version control and build agent is not looking so "free" any more.&lt;br /&gt;Its costing us at least &lt;b&gt;25 grand a year&lt;/b&gt;... that sounds wrong? can you please check my math...&lt;br /&gt;&lt;br /&gt;How much is it costing you?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Disclaimer:-&lt;/b&gt;&lt;br /&gt;In my opinion I've been quite lenient in my estimates, but when you say the numbers and add it all up it sounds awful, but it is.&lt;br /&gt;Also the numbers above don't take into account other teams costs, if you have 3 dev teams (like ours) all working on the same source code, merging every month (feature branch style), all having the same pain, the figures quickly become a big drain on the business.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Problems &lt;/b&gt;:- &lt;br /&gt;The main problem I have is how to quantify the waste, often its small things here and there, they just add up, not all the time, but especially if the team is doing TDD properly and going through refactor cycles frequently, which we are.&lt;br /&gt;Any ideas on how to quantify the waste better would be appreciated.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Amendments &lt;/b&gt;(11-03-2011)&lt;br /&gt;Thanks to my reviewers (kat, skain) for pointing out my grammatical and spelling errors (now corrected). But i did just knock out this article in the gaps i had whilst waiting for TFS, i guess its good for something. Joking apart though this does lead me to something i didnt mention and that is context switching inefficiencies. So every now and then you get 5 minutes to do other tasks, email, ect, but this is a big context switch for the pair, it takes a little time to get back into the flow again, this cost is not accounted for in the above monetary costs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-7307346706743523393?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/7307346706743523393/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2011/03/true-cost-of-tfs-is-it-really-free.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/7307346706743523393'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/7307346706743523393'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2011/03/true-cost-of-tfs-is-it-really-free.html' title='The true cost of TFS, is it really &quot;free&quot;?'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-4561043608362987302</id><published>2011-03-03T10:10:00.000Z</published><updated>2011-03-03T10:10:46.519Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Heroku'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Heroku - Installing your app and sqlite3</title><content type='html'>So ive just installed a dummy rails app to Heroku to test it out, its very very similar to appharbor, unsupprising since appharbor was inspired by heroku.&lt;br /&gt;&lt;br /&gt;all went well untll i added a scaffold for my first admin page, when i tried to deploy this i got he error:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;Application Error&lt;/b&gt;&lt;br /&gt;&lt;i&gt;An error occurred in the application and your page could not be served.  Please try again in a few moments.&lt;br /&gt;If you are the application owner, check your logs for details.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;so i did check the logs 'heroku logs' (you need the logging add-on instaled for your app) and this is what i saw:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;2011-03-03T01:24:00-08:00 heroku[web.1]: State changed from crashed to created&lt;br /&gt;2011-03-03T01:24:00-08:00 heroku[web.1]: State changed from created to starting&lt;br /&gt;2011-03-03T01:24:01-08:00 heroku[web.1]: State changed from crashed to created&lt;br /&gt;2011-03-03T01:24:01-08:00 heroku[web.1]: State changed from created to starting&lt;br /&gt;2011-03-03T01:24:08-08:00 app[web.1]: /usr/ruby1.8.7/lib/ruby/gems/1.8/gems/bundler-1.0.7/lib/bundler/runtime.rb:64:in `require': no such file to load&lt;br /&gt;-- sqlite3 (LoadError)&lt;br /&gt;2011-03-03T01:24:08-08:00 app[web.1]:   from /usr/ruby1.8.7/lib/ruby/gems/1.8/gems/bundler-1.0.7/lib/bundler/runtime.rb:64:in `require'&lt;br /&gt;2011-03-03T01:24:08-08:00 app[web.1]:   from /usr/ruby1.8.7/lib/ruby/gems/1.8/gems/bundler-1.0.7/lib/bundler/runtime.rb:62:in `each'&lt;/code&gt;&lt;br /&gt;...&lt;br /&gt;...&lt;br /&gt;2011-03-03T01:24:08-08:00 app[web.1]:   from /home/heroku_rack/heroku.ru:1:in `new'&lt;br /&gt;2011-03-03T01:24:08-08:00 app[web.1]:   from /home/heroku_rack/heroku.ru:1&lt;br /&gt;2011-03-03T01:24:08-08:00 heroku[web.1]: State changed from starting to crashed&lt;br /&gt;&lt;br /&gt;so what went wrong? well looked like it was a problem loading sqlite3&lt;br /&gt;stackoverflow to the rescue :-)&lt;br /&gt;&lt;br /&gt;just make sure the references to sqlite3 are wrapped up as per the following line of code in your gemfile&lt;br /&gt;&lt;code&gt;&lt;br /&gt;group :development do&lt;br /&gt;&amp;nbsp;&amp;nbsp; gem 'sqlite3-ruby', :require =&amp;gt; 'sqlite3'&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;and that is it, just do a 'heroku rake db:migrate' to get your database on heroku and your should be good to go.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-4561043608362987302?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://heroku.com' title='Heroku - Installing your app and sqlite3'/><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/4561043608362987302/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2011/03/heroku-installing-your-app-and-sqlite3.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/4561043608362987302'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/4561043608362987302'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2011/03/heroku-installing-your-app-and-sqlite3.html' title='Heroku - Installing your app and sqlite3'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-2066222973263637079</id><published>2011-02-28T18:01:00.005Z</published><updated>2011-03-12T10:25:54.044Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='appharbor'/><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><category scheme='http://www.blogger.com/atom/ns#' term='unit test'/><title type='text'>AppHarbor - free .net hosting with continuous integration, Getting started tutorial</title><content type='html'>Ive been test driving appharbor recently and im very impressed.&lt;br /&gt;&lt;br /&gt;Its basically a host for your .net web apps, but with a difference.&lt;br /&gt;First you deploy to appharbor via a git push, as soon as you do this your app is built, your tests are run, and if all goes well (build succeeded and tests passed) your code is deployed to the hosting environment there and then.&lt;br /&gt;&lt;br /&gt;Thats all sounds pretty simple, and is very impressive, especially since its free for a single web instance and a 20MB database.&lt;br /&gt;&lt;br /&gt;So how do you go about doing it, how do you get a ASP.MVC 3 web app on the interweb in 15 minutes (if that) for free.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Create a solution with a single MVC 3 web app in it, im using VS2010 (1 minute)&lt;/li&gt;&lt;li&gt;Add a controller and a view, just static content will do (1 minute)&lt;/li&gt;&lt;li&gt;Create a git repository in the folder that contains your solution. Just run "&lt;code&gt;git init&lt;/code&gt;" (1 minute)&lt;/li&gt;&lt;li&gt;Add your web app to the local repository "&lt;code&gt;git add .&lt;/code&gt;" but be careful not to include the bin, obj or _resharper folders then Commit changes locally "&lt;code&gt;git commit&lt;/code&gt;"  (1-2 minutes)&lt;/li&gt;&lt;li&gt;Log into appharbor and create a new application (1-2 minutes)&lt;/li&gt;&lt;li&gt;Get your remote repository URL from the appharbor administration interface (1 minute)&lt;/li&gt;&lt;li&gt;Add remote repository to your git repo: "&lt;code&gt;git remote add appharbor https://UserName@appharbor.com/AppName.git&lt;/code&gt;" (1 minute)&lt;/li&gt;&lt;li&gt;Push your app to git: "&lt;code&gt;git push appharbor master&lt;/code&gt;" (1 minute)&lt;/li&gt;&lt;li&gt;Log on to appharbor and navigate to your new app, see the successful build (1-2 minutes)&lt;/li&gt;&lt;li&gt;Navigate to the live url and see the site live on the interweb (1-2 minutes)&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Superb&lt;br /&gt;I said 15 minutes, you can actually do it in a lot less, but you get my drift.&lt;br /&gt;&lt;br /&gt;So what can you do :-)&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Add test projects, your code will only be deployed if all the tests pass, brilliant.&lt;/li&gt;&lt;li&gt;Roll back to last deployment, very easy to do, if your not happy with the release, just click deploy on a older build and that older build gets redeployed, perfect.&amp;nbsp;&lt;/li&gt;&lt;li&gt;You can add your own host name&lt;/li&gt;&lt;li&gt;Add worker processors (at a cost)&lt;/li&gt;&lt;li&gt;Have multiple collaborators to the same project and use appharbor as the master repo (a bit like github) its really easy to get get the source on to a different machine, use "&lt;code&gt;git clone https://UserName@appharbor.com/AppName.git&lt;/code&gt;"&lt;/li&gt;&lt;/ul&gt;What cant it do :-(&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Acceptance tests, i use BDD style tests a lot, webdriver, selinium etc. it cant run these, and think about it, it makes sense. If a failing test stops deployment how can you run tests after you have deployed? I guess they need to develop a staging environment similar to Azure which gets deployed to first. I think that is on the pipeline of improvements but not at a high priority.&lt;/li&gt;&lt;li&gt;No file storage, only what is checked into your repo, you can save things to the file system, but they will get blown away with each deployment. i guess you could use amazon EC2, google or Azure to store your files using their REST APIs but that could be slow for the users, options exist though.&lt;/li&gt;&lt;li&gt;If/when tests fail you dont get a very good message, only a stack trace, you dont get the expected and actual values, not sure why this is, but its not a show stopper by any means.&lt;/li&gt;&lt;li&gt;Only one web app per solution is allowed, i guess this is because appharbor uses convention over configuration, and will automatically deploy the one web app there to the hosting environment. &lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-2066222973263637079?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/2066222973263637079/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2011/02/appharbor-free-net-hosting-with.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/2066222973263637079'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/2066222973263637079'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2011/02/appharbor-free-net-hosting-with.html' title='AppHarbor - free .net hosting with continuous integration, Getting started tutorial'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-6238833083109294942</id><published>2011-01-14T17:28:00.003Z</published><updated>2011-01-15T10:56:51.251Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='unit test'/><title type='text'>Acceptance Tests, Fluent Interfaces and a DSL</title><content type='html'>Lately ive been doing quite a lot of acceptance testing. We did give some BDD frameworks a try especially SpecFlow, but were left with a feeling that it was too complex for the benifits that it gave, was too inflexable and in the long run could turn into a bit of a mess. well that was the evaluation of the team, im sure there are good ways of doing it that is valuble but we decided not to go with a framework. &lt;br /&gt;&lt;br /&gt;So i came up with a DSL that gives the developer a simple 'Given When Then' syntax that im quite pleased with, it allows for the most readable / maintainable acceptance test ive seen to date.&lt;br /&gt;&lt;br /&gt;A small acceptance test follows as an example:&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: #eeeeee; font-family: 'Courier New',Courier,monospace;"&gt;using NUnit.Framework;&lt;br /&gt;using OpenQA.Selenium;&lt;br /&gt;using AcceptanceTests.Domain;&lt;br /&gt;&lt;br /&gt;namespace AcceptanceTests.Fixtures&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;[TestFixture]&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public class TagTests : BaseTestFixture&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;[Test]&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;public void ThisAndThatShouldDoSomeThings()&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;var resultsPage = Page.SiteABC.ResultsPage;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;given.WeAreOnThePage(resultsPage);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;when.I.Click.TheElement(By.LinkText("civil-engineering"));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;then.TheUrlShouldBe(Page.SiteABC.Article("civil-engineering"))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .And.TheTitleShouldBe("civil-engineering articles in ABC example page");&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;then.TheElement(By.ClassName("tag-wrapper")).ContainsTheText("Articles with the Tag:\r\ncivil engineering");&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; when.I.Type("london").Into(By.Id("txtLocation"))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .And.I.Click.TheElement(By.LinkText("search"));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;then ..... (You get the idea)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;The base class gives the test fixtures access to the Given When Then classes similar to this:&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: #eeeeee; font-family: 'Courier New',Courier,monospace;"&gt;public class BaseTestFixture&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;protected Given given;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;protected When when;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;protected Then then;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;[TestFixtureSetUp]&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public void SetUp()&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;given = new Given();&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;when = new When();&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;then = new Then();&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;The actual Given When Then classes delegate the actions to webdriver in the following manner:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: #eeeeee; font-family: 'Courier New',Courier,monospace;"&gt;public class Given&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;private readonly WebDriver webDriver;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public Given()&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;webDriver = WebDriver.GetCurrent();&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public Given And&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;get { return this; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public Given WeAreOnThePage(Page page)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;webDriver.Driver.Navigate().GoToUrl(page.Url);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return this;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public class When&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;private readonly WebDriver webDriver;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public When()&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;this.webDriver = WebDriver.GetCurrent();&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public When And&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;get { return this; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public When I&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;get {return this; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public IAction Click&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;get { return new Click(this); }&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public TypeText Type(string text)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return new TypeText(text);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;By writing the step classes like this we can write the tests in a fluent style, making for very readable. This is important as it enables none technical (business) people to read / understand the tests and have input on the creation of the tests, although i admit it still does not really enable them to write them, as you do need to know c# and visual studio, but in my&amp;nbsp;experience&amp;nbsp;they never write them anyway (especially on the contact im on), its&amp;nbsp;technical&amp;nbsp;people who write the automated acceptance tests.&lt;br /&gt;&lt;br /&gt;All in all im quite pleased who the suite of tests is progressing and how the DSL has evolved.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-6238833083109294942?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/6238833083109294942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2011/01/acceptance-tests-fluent-interfaces-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/6238833083109294942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/6238833083109294942'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2011/01/acceptance-tests-fluent-interfaces-and.html' title='Acceptance Tests, Fluent Interfaces and a DSL'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-3880981497522079953</id><published>2011-01-06T21:56:00.001Z</published><updated>2011-01-06T21:59:10.520Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='HTC Desire'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>LauncherPro has expired. 403 forbidden. Phone is locked out...</title><content type='html'>Ive been using LauncherPro for a couple of months now, its a nice homescreen replacement on the android phone, actually i really liked it.&lt;br /&gt;&lt;br /&gt;But this morning when i turned my phone on i got the error :-&lt;br /&gt;&lt;br /&gt;"This version of LauncherPro has expired. Please goto http://www.launcherpro.com/ to get the latest version."&lt;br /&gt;&lt;br /&gt;Then my web browser automatically opened so i could get it but i had a problem, i had no internet connection, no wifi, and no mobile connection.... arg.. Basically my phone was now a brick, well i could receive calls, but there was no way to access anything else as every time i hit the home key it would redirect to the internet...&lt;br /&gt;&lt;br /&gt;Then later on in the morning i went into london and got a connection on 3G but then i got a 403 forbidden page.... double arg, whats going on this is so shoddy, so i still cant use my phone.&lt;br /&gt;&lt;br /&gt;Only after getting to a PC with a decent internet connection did i managed to find a couple of solutions, the first was to download an app installer onto the pc and do a remote install of the new version of launcherPro, i didnt like this, it sounded too complex and i wanted rid of it not the latest version.&lt;br /&gt;&lt;br /&gt;Then i found the following solution&lt;br /&gt;browse to - http://bubiloop.com/download/org.adw.launcher&lt;br /&gt;this should open the market (app store)&lt;br /&gt;then search for launcherPro and finally update or uninstall. &lt;br /&gt;&lt;br /&gt;I recommend un-installing, seams like this is a rather shoddy product if it locks out your phone like this. even if the actual software does everything else well i dont think this sort of error is in any way acceptabe in any software ever, locking you out of your device, laptop, PC whatever it is, is just wrong, i appreciate the developers might want to force people to upgrade all the time, but this is just not on, i dont know i just cant warn you folks enough, i woudnt trust this app.&lt;br /&gt;&lt;br /&gt;morel of the story, dont use apps from random developers on major bits of your device, the home screen is quite major, if that dont work your stuffed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-3880981497522079953?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/3880981497522079953/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2011/01/launcherpro-has-expired-403-forbidden.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/3880981497522079953'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/3880981497522079953'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2011/01/launcherpro-has-expired-403-forbidden.html' title='LauncherPro has expired. 403 forbidden. Phone is locked out...'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-5884499714517572049</id><published>2010-12-13T16:49:00.001Z</published><updated>2010-12-14T13:07:30.513Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><category scheme='http://www.blogger.com/atom/ns#' term='System Thinking'/><title type='text'>Edward Deming and his Red Bead Experiment, in practice.</title><content type='html'>We had an&amp;nbsp;interesting&amp;nbsp;brown bag lunch meeting the other day about Edward Demings red bead&amp;nbsp;experiment. I've heard and read about it before but never got to participate, it was interesting, thought provoking and fun. Some good discussions&amp;nbsp;afterwards&amp;nbsp;as well.&lt;br /&gt;&lt;br /&gt;Edward Deming was a management consultant and statistician. He had a massive impact on the management styles and&amp;nbsp;philosophy of&amp;nbsp;Japanese business in the 50's and 60's. He used the red bead experiment to illustrate the impact that a system,  and traditional management approaches, can have on individuals who work  within a system, and how traditional management approaches (slogans, the usefulness of targets, annual appraisals and financial rewards) are not always (if ever) that effective at improving quality.&lt;br /&gt;&lt;br /&gt;Details on the red bead experiment and how it is performed can be found here&amp;nbsp;&lt;a href="http://www.redbead.com/"&gt;http://www.redbead.com/&lt;/a&gt;. For our results in the actual experiment read on.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Results&lt;/b&gt;&lt;br /&gt;The session was run by a thoughtworks&amp;nbsp;colleague, in a really good way, we had the workers, the management, the QA staff, and lots of fun.&lt;br /&gt;&lt;br /&gt;The workers were set targets of 5 defects max per person ( a total of 15 per iteration for the team)&lt;br /&gt;The 3 workers, were split into 2 average and 1 good (what ever that means)&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt; &lt;td&gt;Iteration&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;Developer Totals&lt;/td&gt; &lt;/tr&gt;&lt;tr&gt; &lt;td&gt;Dev1&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;26&lt;/td&gt; &lt;/tr&gt;&lt;tr&gt; &lt;td&gt;Dev2&lt;/td&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;29&lt;/td&gt; &lt;/tr&gt;&lt;tr&gt; &lt;td&gt;Dev3&lt;/td&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;36&lt;/td&gt; &lt;/tr&gt;&lt;tr&gt; &lt;td&gt;Iteration Totals&lt;/td&gt;&lt;td&gt;23&lt;/td&gt;&lt;td&gt;23&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;25&lt;/td&gt;&lt;td&gt;91&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;After iteration 1 workers were told that their efforts were not good enough, and basically told off by management. This made no difference, and so, after iteration 2 the workers were given incentives and&amp;nbsp;appraisals, if they upped their game they would be given hard cash. This worked and management were&amp;nbsp;encouraged&amp;nbsp;to do more of that, offering bigger rewards for better performance.&lt;br /&gt;But iteration 4 was the worst yet and so managers assumed that the incentives had failed because no one actually&amp;nbsp;achieved&amp;nbsp;them last time.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;So what does this actually tell us?&lt;/b&gt;&lt;br /&gt;That in a fixed system where the workers have no ability to manage or better themselves or their work, the management&amp;nbsp;effectively&amp;nbsp;can not effect workers performance though traditional carrot and stick management.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;How does this relate to Software?&lt;/b&gt;&lt;br /&gt;I have found that as software developers&amp;nbsp;we&amp;nbsp;don't&amp;nbsp;get to&amp;nbsp;change&amp;nbsp;the system as a whole very&amp;nbsp;often.&amp;nbsp;Often software is seen as the solution to business problems, when actually changing&amp;nbsp;the system would be a better approach. Just by making the process&amp;nbsp;electronic&amp;nbsp;doesn't&amp;nbsp;always work and often&amp;nbsp;makes things worse or masks the underlying problem. This is just another reason why software projects fail.&lt;br /&gt;&lt;br /&gt;The experiment also relates to the software development process. If software engineers work in a rigid system where QA and strict process is seen as putting the quality in. Where the engineers&amp;nbsp;don't&amp;nbsp;have the ability to change their environment (technology, process, physical environment, methodology) then no amount of incentives, slogans, rewards can make the software produced better (less defects, meeting business requirements more&amp;nbsp;effectively,&amp;nbsp;etc.). I have seen this at several clients, and can say that clients who have empowered workers have a big advantage, these companies have better motivated, more professional developers and in the end better software.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;br /&gt;Systems Thinking is a really interesting&amp;nbsp;field&amp;nbsp;at the moment and if you want to read more do a google for&amp;nbsp;Edward Deming, systems thinking and John Sedden.&lt;br /&gt;&lt;br /&gt;So even if you are CMM level 5 (i.e your processes are robust and repeatable) you can still have quality issues, The red bead experiment highlights that it is not process that produces quality, nor rewards, targets or incentives, its the system within which workers work that matters and their ability and motivation to help change and adapt the system.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-5884499714517572049?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/5884499714517572049/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2010/12/edward-deming-and-his-red-bead.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/5884499714517572049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/5884499714517572049'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2010/12/edward-deming-and-his-red-bead.html' title='Edward Deming and his Red Bead Experiment, in practice.'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-1212089026614895831</id><published>2010-12-07T09:43:00.000Z</published><updated>2010-12-07T09:43:02.150Z</updated><title type='text'>Selenium 2, webdriver for .net c#</title><content type='html'>Webdriver tests that are fast to write and fast to run are essential for BDD. I was really supprised at how fast your tests can actually run, even the setup is quick IE opens instantly, providing a very quick test code loop.&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;1. Download selenium 2 from&amp;nbsp;&lt;a href="http://code.google.com/p/selenium/downloads/list"&gt;http://code.google.com/p/selenium/downloads/list&lt;/a&gt;&amp;nbsp;i got&amp;nbsp;&lt;a href="http://code.google.com/p/selenium/downloads/detail?name=selenium-dotnet-2.0a6.zip&amp;amp;can=2&amp;amp;q=" style="white-space: nowrap;"&gt;selenium-dotnet-2.0a6.zip&lt;/a&gt;&amp;nbsp;for this exmple&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;2. Add project references to nunit.framework, webdriver.common and webdriver.IE or webdriver.firefox&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;3. Using NUnit (No tutorial for that here, google it) create a test class that uses webdriver&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="background-color: #eeeeee;"&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;using System;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;using NUnit.Framework;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;using OpenQA.Selenium.IE;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;namespace AcceptanceTests&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;[TestFixture]&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public class Class1&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;private InternetExplorerDriver _driver;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;[TestFixtureSetUp]&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;public void FixtureSetUp()&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;_driver = new InternetExplorerDriver();&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;_driver.Manage().Timeouts().ImplicitlyWait(new TimeSpan(0, 0, 30));&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;[TestFixtureTearDown]&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;public void FixtureTearDown()&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (_driver != null) _driver.Close();&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;[Test]&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;public void GoogleShouldBeInTheTitleWhenNavigatingToGoogleHomePage()&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;//Given&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;_driver.Navigate().GoToUrl("http://google.co.uk");&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;//When&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;//Then&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Assert.AreEqual("Google", _driver.Title);&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;4. Run your tests&lt;br /&gt;5. Done&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-1212089026614895831?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/1212089026614895831/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2010/12/selenium-2-webdriver-for-net-c.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/1212089026614895831'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/1212089026614895831'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2010/12/selenium-2-webdriver-for-net-c.html' title='Selenium 2, webdriver for .net c#'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-7188372212067401906</id><published>2010-11-03T14:54:00.004Z</published><updated>2010-11-03T15:11:43.948Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>Android, how easy is it to deploy or install your own app to your phone</title><content type='html'>The answer is very easy&lt;br /&gt;&lt;br /&gt;So you have spent a few hours developing a new android app (ive been using the eclipse IDE) and you have been testing using the adb emulator, but you want to see something on your very own android hardware (ive got a HTC Desire).&lt;br /&gt;&lt;br /&gt;These are the steps ive followed:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Build your .apk package.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Connect your phone to your pc in disk drive mode (this enables you to mount it on your pc).&lt;/li&gt;&lt;li&gt;Browse to your removable disk (this shows up as drive G: on my machine).&lt;/li&gt;&lt;li&gt;Copy the .apk file that was generated by the build to your phone and remember where you copied it to.&lt;/li&gt;&lt;li&gt;Disconnect the phone.&lt;/li&gt;&lt;li&gt;On the phone use a file manager app like 'ES File Explorer' or 'ASTRO File Manager' and browse to the .apk file you copied on in step 4.&lt;/li&gt;&lt;li&gt;Open the .apk file and select install.&lt;/li&gt;&lt;/ol&gt;It really is that easy, none of that iphone certificate nonsense, or limited use to tolerate, lets just do it :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-7188372212067401906?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/7188372212067401906/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2010/11/android-how-easy-is-it-to-deploy-or.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/7188372212067401906'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/7188372212067401906'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2010/11/android-how-easy-is-it-to-deploy-or.html' title='Android, how easy is it to deploy or install your own app to your phone'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-845621767391113885</id><published>2010-11-03T12:02:00.003Z</published><updated>2010-11-03T12:22:49.726Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>Setting the date on Android emulator adb</title><content type='html'>To set the date on your android emulator use the following command from the terminal&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;adb shell date -s 20101023.130155&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This sets the date to be Oct 23rd 13:01:55 2010&lt;br /&gt;easy&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-845621767391113885?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/845621767391113885/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2010/11/setting-date-on-android-emulator-adb.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/845621767391113885'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/845621767391113885'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2010/11/setting-date-on-android-emulator-adb.html' title='Setting the date on Android emulator adb'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-4873006769719485092</id><published>2010-10-29T12:25:00.011+01:00</published><updated>2010-10-29T13:16:58.162+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vs2008'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='TFS'/><title type='text'>20 things that are wrong with TFS, and counting</title><content type='html'>We have recently spent a lot of time using TFS 2008, im no expert with this tool but it seems to me that there are lots of issues with it. Its not that im trying to do some TFS bashing but my last project using subversion didn't have source control problems.&lt;br /&gt;&lt;br /&gt;As always though if anyone out there can put me right on any of these issues please do so.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Renames and deletes don't always properly get merged between trunk and branch and back.&lt;/li&gt;&lt;li&gt;We had really random deletion of files when doing a merge from a branch that has had a baseless merge applied to it, (files were randomly deleted off the trunk during merge) these files existed in our branch and the trunk before the merge, but were removed off the trunk after.&lt;/li&gt;&lt;li&gt;After doing a baseless merge (using power tools on the cmd prompt) you then can't reliably use the TFS GUI to do things like merges, you must use the command line tools.&lt;/li&gt;&lt;li&gt;Tooling just doesn't work when merging, files that have no conflicts just don't auto merge all the time and requires manual intervention for no reason. This is intolerable when refactoring and you have changed 100+ files.&lt;/li&gt;&lt;li&gt;No ability to create patch files which can be subsequently applied to other branches.&lt;/li&gt;&lt;li&gt;Changes to one branch cant be merged into another branch unless you go via the trunk.&lt;/li&gt;&lt;li&gt;You cant merge workitems between branch and trunk, even though workitems are the main unit of work in TFS.&lt;/li&gt;&lt;li&gt;Many standard features like rollback are not built in. It requires an additional 'power tools' download (There is no GUI for rollback)&lt;/li&gt;&lt;li&gt;Can't seem to rollback to a given point in time, you can only rollback 1 changeset at a time, this just seems wrong to us?&lt;/li&gt;&lt;li&gt;Using TFS built in diff tool reports lines that have no changes to have changes. And does not line up source and target very well making the tool very hard to use when trying to spot important differences.&lt;/li&gt;&lt;li&gt;Doesn't know that files or folders have been added unless you tell TFS in the GUI, This can easily lead to files not getting checked in if they were not created in visual studio.&lt;/li&gt;&lt;li&gt;The GUI doesn't always update to reflect the state of the source control, requires a refresh, this mainly effects the pending changes view.&lt;/li&gt;&lt;li&gt;The UI is confusing in that if you are browsing the source and click on a file to open it, it opens the local copy not the one in source control. Also it doesn't tell you that the local is different from the one in source control.&lt;/li&gt;&lt;li&gt;When you add a new mapping to your workspace the tool says 'do you want to update your workspace?' when you say yes it then goes and gets everything from your workspace and updates everything, you expect it to only get the changes due to the new mapping. this caused us quite a lot of confusion and wasted time, but luckily nothing was lost.&lt;/li&gt;&lt;li&gt;Sometimes labels disappear, completely, as if they were never created.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;A label to label comparison does not always give the same results as a date to date comparison, even though the dates used are the same as when the labels were created.&lt;/li&gt;&lt;li&gt;Checking out (not getting) the entire branch takes ages (40 minutes plus) even though the source is not really that big (70,500 files), we actually gave up in the end and 1/2 were checked out 1/2 were not.&lt;/li&gt;&lt;li&gt;Deleting a branch took 40 minutes. Did a delete in TFS of the branch folder (took 10 mins) got a pending delete dialogue box, tried to check in the delete which failed with the error  'the local copy is not up to date', so we then undid the delete which took 20 mins, got the latest source (3 mins) and finally did the delete again (10 mins). Why cant TFS tell us up front the delete wont work because our file system is not up to date? and why when doing it in the TFS GUI does our local file system matter? especially since we had no pending changes?&lt;/li&gt;&lt;li&gt;When you re-branch you lose your branch history.&lt;/li&gt;&lt;li&gt;If you tolerate this, then your code will be next...&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-4873006769719485092?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/4873006769719485092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2010/10/20-things-that-are-wrong-with-tfs-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/4873006769719485092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/4873006769719485092'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2010/10/20-things-that-are-wrong-with-tfs-and.html' title='20 things that are wrong with TFS, and counting'/><author><name>Damo (HTC)</name><uri>http://www.blogger.com/profile/17825817879648612276</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-6681457510127245511</id><published>2010-09-28T08:53:00.004+01:00</published><updated>2010-09-28T10:47:38.675+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>C# .net method call performance</title><content type='html'>I’ve recently been in a conversation with another dev about a code base and had an alarming exchange regarding method calls and performance.&lt;br /&gt;&lt;br /&gt;Alarming because he claimed that the reason that the methods in the system were so long was because someone higher in the dev chain 'tech lead' or 'architect' had claimed that it was expensive to make method calls???&lt;br /&gt;&lt;br /&gt;I’ve seen my fair share of long methods, awful things that destroy reuse, developer productivity, and introduce many, many tangled bugs. These usually evolve because the devs are under pressure to get things out of the door on tight schedules, or by inexperienced devs who unfortunately don’t know much better. Personally I like to try and keep my methods short &lt;20 lines, to keep to the principal that a method should only do one thing, do it clearly and well (so its easy to read, understand and change), you know all the usual stuff. But I’ve never seen the justification for long methods to be because of performance...&lt;br /&gt;&lt;br /&gt;so i thought what is this performance gain of long methods? After googling around I didn’t find anything (if you do let me know) so i wrote a program.&lt;br /&gt;&lt;br /&gt;Essentially it consisted of 2 loops, one to do a simple calculation in line and one to call a method to do the same calculation.&lt;br /&gt;&lt;br /&gt;for (int i = 0; i &lt; LoopCount; i++ )&lt;br /&gt;{&lt;br /&gt;    fakeCalculationVariable++;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;for (int i = 0; i &lt; LoopCount; i++ )&lt;br /&gt;{&lt;br /&gt;    Calculate();&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;i took timings before and after each loop and recorded the results&lt;br /&gt;&lt;br /&gt;LoopCount= 100000000&lt;br /&gt;elapsed time = 234.447 milliseconds&lt;br /&gt;elapsed time = 640.8218 milliseconds&lt;br /&gt;Method call loop took 406.3748 millisecs longer than inline loop for 100000000 calls&lt;br /&gt;Thats a cost of 0.0000041 millisecs per method call&lt;br /&gt;&lt;br /&gt;i wasn’t sure about the results so i decided to run it again, this time with ten billion iterations of the loop, these performance penalties must show up with that many calls.&lt;br /&gt;&lt;br /&gt;LoopCount= 1000000000&lt;br /&gt;elapsed time = 2250.6912 milliseconds&lt;br /&gt;elapsed time = 6376.9584 milliseconds&lt;br /&gt;Method call loop took 4126.2672 millisecs longer than inline loop for 1000000000 calls&lt;br /&gt;Thats a cost of 0.0000041 millisecs per method call&lt;br /&gt;&lt;br /&gt;its quite conclusive, method calls don’t really add up to all that much overhead, as we all expected.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-6681457510127245511?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/6681457510127245511/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2010/09/c-net-method-call-performance.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/6681457510127245511'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/6681457510127245511'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2010/09/c-net-method-call-performance.html' title='C# .net method call performance'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-8644389750991422794</id><published>2010-09-12T20:45:00.003+01:00</published><updated>2010-09-12T21:23:55.283+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='Azure'/><category scheme='http://www.blogger.com/atom/ns#' term='billing'/><title type='text'>Azure Learnings</title><content type='html'>A few months ago I played with Azure, experimented with all the storage options (table, queue, blobs) web and worker roles, made things interact and generally got to know what was possible, not possible and how to do things. It was interesting, i gave a few presentations to the company I was contracted to at the time but in the end it was all just exploration, they were never going to take it up (they own lots of their own hardware, i mean Lots, and besides in my view there are issues with going to Azure as a solution for that enterprise problem), also I didn't see any use for it in my own personal projects.&lt;br /&gt;&lt;br /&gt;I had a MSDN account which at the time entitled me to 750 compute hours a month (a compute hour is just a measure of how long your roles have been deployed in the cloud), and was careful with my deployments, always take test deployments down to minimise the total compute hours.&lt;br /&gt;&lt;br /&gt;Anyway two problems:&lt;br /&gt;&lt;br /&gt;1st. I didnt check my subscription(why would i?) it turned out i had the basic "starter" subscription (50 free compute hours) not the MSDN package (750 free hours).&lt;br /&gt;&lt;br /&gt;2nd. I did a demo and someone wanted to use it afterwards so i left it up (one web role and one worker role) and then forgot about it... opps. To add to my woes my hotmail account is not my primary email account so the billing was not coming to me, i only just found it when I happened to be on hotmail.&lt;br /&gt;&lt;br /&gt;To cut a long story short I got charged £50 + £120 + £120 for the honour of having my dummy website sat doing nothing on the azure application fabric... I;ve since talked to Microsoft and cancelled my azure account, i see no need for it, I'm not going to use it any time soon, and wanted to make double sure all my web instances were gone. but after talking to them i have got last months money back, better than nothing but still... i guess it was my fault for not checking my package, my running instances and my email, stupid boy.&lt;br /&gt;&lt;br /&gt;Morale of the story to all you perspective Azure developers out there, check your subscriptions, and always take down your test deployments, always.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-8644389750991422794?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/8644389750991422794/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2010/09/azure-learnings.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/8644389750991422794'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/8644389750991422794'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2010/09/azure-learnings.html' title='Azure Learnings'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-8252849904297404548</id><published>2010-09-01T15:13:00.004+01:00</published><updated>2010-09-01T15:19:08.020+01:00</updated><title type='text'>Site creation with google sites</title><content type='html'>Just been through the process of setting up a new website &lt;a href="http://sites.google.com/site/stangerphotography/"&gt;http://sites.google.com/site/stangerphotography/&lt;/a&gt; new picasa site and new flickr account &lt;a href="http://www.flickr.com/photos/oliverstanger/"&gt;http://www.flickr.com/photos/oliverstanger/&lt;/a&gt; for my brother who is setting up a photography business.&lt;br /&gt;&lt;br /&gt;It was actually quite easy to do once you get used to navigating your way around the site and the wysiwyg editors. Managed to fully set up google analytics and web master tools also.&lt;br /&gt;&lt;br /&gt;Now I just need to make sure my brother updates his content.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-8252849904297404548?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='https://sites.google.com/site/stangerphotography/' title='Site creation with google sites'/><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/8252849904297404548/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2010/09/site-creation-with-google-sites.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/8252849904297404548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/8252849904297404548'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2010/09/site-creation-with-google-sites.html' title='Site creation with google sites'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-6083566509806681523</id><published>2010-08-26T16:38:00.002+01:00</published><updated>2010-08-26T16:44:23.182+01:00</updated><title type='text'>Vodafone, HTC Desire fiasco update</title><content type='html'>Talked to Vodafone customer support again, (its my twice weekly activity now, well has been for 3 months) and have been told I'm not a priority, basically there is a supply problem (i know) and there is a waiting list (makes sense) but as I'm an existing customer (not a new one, or getting an upgrade) then i cant be put on the list, therefore the only way to get the phone is for me to ring up every other day and enquire if they have any stock to send me yet...&lt;br /&gt;&lt;br /&gt;They did get 3 HTC Desires in today, but all went to new customers on the list. What this tells me is this: If you receive your new phone from vodafone but there is a problem with it cancel your contract ASAP (before the 14 day cooling off period) and once you have sorted that out do the new customer thing again. it seams that if i had done this i would have the new phone by now. just a warning to you folks, don't accept the promise that a new one will be coming your way any time soon.&lt;br /&gt;&lt;br /&gt;On a slightly different note the Vodafone lady in the call centre was very nice, apologetic and honest, its definitely a system problem, not a people problem, why cant i be put on the list? clearly its a money problem, existing customers don't make the company any more money.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-6083566509806681523?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/6083566509806681523/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2010/08/vodafone-htc-desire-fiasco-update.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/6083566509806681523'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/6083566509806681523'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2010/08/vodafone-htc-desire-fiasco-update.html' title='Vodafone, HTC Desire fiasco update'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-8160266646652590231</id><published>2010-08-17T12:01:00.006+01:00</published><updated>2010-08-17T12:39:34.146+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HTC Desire'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>Vodafone, HTC Desire fiasco</title><content type='html'>So I've had a contract with Vodafone for over 3 months now. I think it was early may that I actually signed up for a contract with them and got my shiny new HTC Desire, I was pleased. Very pleased :-)&lt;br /&gt;&lt;br /&gt;But after a day or 2 I found it was broken :-( if you used it for any length of time it would just quit, turn off, then not turn on for a while whilst it cooled down, oh and there was the strange squeeze thing I mentioned in another blog post.&lt;br /&gt;&lt;br /&gt;I complained only 2 or 3 days after I received the original, I thought it would be straight forward, new for new, but unfortunately no stock, the desire is very desirable and there were supply problems.&lt;br /&gt;&lt;br /&gt;So I waited and waited, I rang back twice a week to check on progress, I was not using my desire at this point as it was unusable, switching itself off randomly. Back to my trusty old nokia (7 years and still going strong)&lt;br /&gt;&lt;br /&gt;And I waited.&lt;br /&gt;Finally, finally after ringing twice a week for 2 months i got a replacement phone :-) yay at last, but I was told to keep my batery, sim and memory card from my other phone, strange, oh well, got my new phone now. :-)&lt;br /&gt;&lt;br /&gt;But no, still broken, still with exactly the same problems as before.... ARRRRG, it was the battery all this time, i told them i thought it was, dam it.&lt;br /&gt;&lt;br /&gt;And wait what's this, there is as small scuff mark on the base of the phone, its brand new isn't it? &lt;br /&gt;&lt;br /&gt;So rang Vodafone back and said it still doesn't work, and also is this phone I have new? there is a scuff mark on it? after much a to-do I got the answer that its a reconditioned phone, and we will send you a battery (which they did but I suspect its not a new one as it came in a jiffy bag).&lt;br /&gt;&lt;br /&gt;Anyway after some challenging discussions I got agreement that it was an error to send me a reconditioned phone, apparently an error in the system (problems with phones over 1 month into the contract get refurbished replacements), since I was 2 months into my contract I get a reconditioned one... even though id reported the problem on day 3... But the supervisor on the other end was reasonable in the end and agreed I should have had a new phone sent not a reconditioned one, and so I'm waiting, again.&lt;br /&gt;&lt;br /&gt;And waiting and waiting, I ring back twice a week again, try to get a date but again they are out of stock, out of stock, out of stock.&lt;br /&gt;Do Vodafone ever sell the HTC Desire? I know its a popular phone, that there are supply problems but in effect its been over 3 months now, you cant tell me you have not had any stock in 3 months? really?&lt;br /&gt;&lt;br /&gt;I suspect its far more profitable to sell that new handset to a new customer than to sort out your existing ones?&lt;br /&gt;&lt;br /&gt;I'm a bit disappointed really, as you can imagine, cause I've been using Vodafone for all my mobile life, years and years, even whilst abroad, and always had excellent service. I've had friends with orange who had trouble and problems with the provider and I've always said come to Vodafone, they are great, but seams like things change, or just maybe I've just got really unlucky.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-8160266646652590231?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/8160266646652590231/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2010/08/vodafone-htc-desire-fiasco.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/8160266646652590231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/8160266646652590231'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2010/08/vodafone-htc-desire-fiasco.html' title='Vodafone, HTC Desire fiasco'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-6920280613560334979</id><published>2010-05-13T21:58:00.005+01:00</published><updated>2010-05-13T22:16:21.026+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HTC Desire'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>HTC Desire shut down problems</title><content type='html'>&lt;p&gt;So ive got a brand new HTC Desire, and instantly loved it, but its not right...&lt;/p&gt;&lt;br /&gt;&lt;p&gt;If you talk on the phone for 5-10 minutes the phone will just switch off? if you use the internet or any other functionality the phone will soon enough just switch off. sometimes if you just gently squeeze it will just shut down.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Once it has shut down the status light flashes green and orange, sometimes it wont even shitch back on for ages...&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So ive got in touch with vodafone, and they have been really good about sorting it out. they have quickly agreed to replace it :-) but there are none in stock at the moment, and none due in till the 23rd i think... boo&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;video of the squeeze&lt;/h2&gt;&lt;br /&gt;&lt;object height="525" width="660"&gt;&lt;param name="movie" value="http://www.youtube.com/v/quTY8v8Blaw&amp;amp;hl=en_GB&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x2b405b&amp;amp;color2=0x6b8ab6&amp;amp;border=1"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/quTY8v8Blaw&amp;amp;hl=en_GB&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x2b405b&amp;amp;color2=0x6b8ab6&amp;amp;border=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="525" width="660"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;p&gt;As you can see it works pretty well, quick navigation, just dont squeeze it.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-6920280613560334979?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/6920280613560334979/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2010/05/htc-desire-shut-down-problems.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/6920280613560334979'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/6920280613560334979'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2010/05/htc-desire-shut-down-problems.html' title='HTC Desire shut down problems'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-5541666774630315254</id><published>2010-01-27T21:38:00.010Z</published><updated>2010-01-27T22:18:00.188Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='vs2008'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring.net'/><title type='text'>Spring.net and asp.mvc, Getting started with dependency injection</title><content type='html'>This small tutorial gives you the quickest route (that i know) to getting microsofts mvc working with spring.net for simple DI (Dependency injection) or IOC (Inversion of control) to aid in testing and maintanance. Yes i know spring.net can do much more but this is just a very basic how to.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Download Prerequesits&lt;/span&gt;&lt;br /&gt;First get asp.mvc, download and install from here (im assuming you have vs2008 or like wise for this tutorial)&lt;br /&gt;http://www.asp.net/mvc/download/&lt;br /&gt;At the time of writing im using vs2008, xp and  mvc 1&lt;br /&gt;downloaded here&lt;br /&gt;http://www.microsoft.com/downloads/details.aspx?displaylang=en&amp;amp;FamilyID=53289097-73ce-43bf-b6a6-35e00103cb4b&lt;br /&gt;but im sure mvc 2.0 would be much the same to set up DI&lt;br /&gt;&lt;br /&gt;right click on your existing solution (or alternativly create a new one)&lt;br /&gt;then add, new project, web, pick 'asp.net mvc web appication' from the list of templates contained&lt;br /&gt;this will make a brand new mvc web app, all configured and ready to go, build and run it you should see the default mvc site out of the box.&lt;br /&gt;now to get spring running and injecting goodness into it.&lt;br /&gt;&lt;br /&gt;first download spring.net&lt;br /&gt;http://www.springframework.net/download.html&lt;br /&gt;im going for the latest production release 1.3.0&lt;br /&gt;&lt;br /&gt;then download MVCContrib from&lt;br /&gt;http://mvccontrib.codeplex.com/&lt;br /&gt;im using the latest stable release for mvc 1.0 here&lt;br /&gt;http://mvccontrib.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=33401&lt;br /&gt;get both the main download and the extras package (the spring IOC assembalies are contained in the extras package)&lt;br /&gt;&lt;br /&gt;reference the following assemblies from the solution: spring.core, mvcContrib and MCVContrib.spring&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Substitute the default controller factory for the spring factory provided by mvcContrib&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Add the following to the head of global.ascx&lt;br /&gt;using Spring.Context.Support;&lt;br /&gt;using MvcContrib.Spring;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;add IOC to your global.ascx so that application_start creates a spring context&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;protected void Application_Start()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      ConfigureIoC();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      RegisterRoutes(RouteTable.Routes);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    private static void ConfigureIoC()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            ContextRegistry.RegisterContext(new XmlApplicationContext(false, "assembly://MvcApplication1/MvcApplication1/objects.xml"));&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      var ctx = ContextRegistry.GetContext();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      SpringControllerFactory.Configure(ctx);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      ControllerBuilder.Current.SetControllerFactory(typeof(SpringControllerFactory));&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;add an objects.xml file that will hold all the spring configuration&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;objects xmlns="http://www.springframework.net"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         xsi:schemaLocation="http://www.springframework.net&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         http://www.springframework.net/xsd/spring-objects.xsd"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;/objects&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;This objects.xml must be an embedded resource into the assembly, right click the file, properties, and change it to an embedded resource. If you miss this step you will get an error stating 'Could not load file or assembly Spring.Core.....' basically stating that the assembly didn't contain the objects.xml, which is the dependency spring is looking for.&lt;br /&gt;&lt;br /&gt;at this point if you ran the code you would get the error&lt;br /&gt;No object named 'HomeController' is defined : Cannot find definition for object [HomeController]&lt;br /&gt;This is good, it means that spring is looking for a definition of your home controller but cant find one.&lt;br /&gt;so letes tell it about it&lt;br /&gt;&lt;br /&gt;add this to your objects xml&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;object id="HomeController" type="MvcApplication1.Controllers.HomeController, MvcApplication1"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &amp;lt;/object&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;now when you run the app you should get the same boring default mvc home page again, brilliant, looks like its working, now to test the dependency injection, this is what we have been waiting for.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Inject a custom object into the homeController&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;So the easiest way to demo this is to echo some text out onto the screen that comes from a dummy data&lt;br /&gt;add 2 objects to the model folder&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;using System;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;namespace MvcApplication1.Models&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  public interface IHelloDAO&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    String Hi();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;namespace MvcApplication1.Models&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  public class HelloDAO : IHelloDAO&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    public string Hi()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      return "This is data straight from HelloDAO";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;now we are going to use this DAO (Data Access Object) in the controller to get some data from the model by using the Hi method on the IHello interface.&lt;br /&gt;the class should now look like this&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;public class HomeController : Controller&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    public IHelloDAO HelloDAO { get; private set; }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    public HomeController(IHelloDAO helloDAO)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      HelloDAO = helloDAO;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    public ActionResult Index()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      //ViewData["Message"] = "Welcome to ASP.NET MVC!";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      ViewData["Message"] = HelloDAO.Hi();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      return View();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    public ActionResult About()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      return View();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We added a new constructor which takes an instance of IHelllo (this is the think that is being injected in), and we have used the instance to get the message by using HelloDAO.Hi()&lt;br /&gt;finally import the relevent model namespace at the top of the file.&lt;br /&gt;&lt;br /&gt;again if you were to run the app at this point you would get the following error:&lt;br /&gt;Cannot instantiate a class that does not have a no-argument constructor [MvcApplication1.Controllers.HomeController].&lt;br /&gt;which indicates quite clearly that the controller is not configured correctly. Basically spring is expecting a no argument constructor, but the real class dosent have one.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Configure Spring&lt;/span&gt;&lt;br /&gt;Now all that remains is to wire the dependencies in the objects.xml which should now look like this&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;objects xmlns="http://www.springframework.net"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         xsi:schemaLocation="http://www.springframework.net&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         http://www.springframework.net/xsd/spring-objects.xsd"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &amp;lt;object id="HomeController" type="MvcApplication1.Controllers.HomeController, MvcApplication1"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    &amp;lt;constructor-arg ref="HelloDAO" /&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &amp;lt;/object&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &amp;lt;object id="HelloDAO" type="MvcApplication1.Models.HelloDAO, MvcApplication1"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &amp;lt;/object&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;/objects&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;you can see we have added a parameterised constructor to the controller through wich we are injecting in an implementation of the HelloDAO interface.&lt;br /&gt;The index remains the same as it was out of the box and should display our message instead of the default 'Welcome to ASP.NET MVC!'&lt;br /&gt;&lt;br /&gt;lets run it.&lt;br /&gt;magic, you have configured your first and hopefully not last controller through spring.net and asp.mvc&lt;br /&gt;&lt;br /&gt;now your ready for part 2 (Spring.net and asp.mvc, even more dependency injection)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-5541666774630315254?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/5541666774630315254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2010/01/springnet-and-aspmvc-getting-started.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/5541666774630315254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/5541666774630315254'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2010/01/springnet-and-aspmvc-getting-started.html' title='Spring.net and asp.mvc, Getting started with dependency injection'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-3024316979903522938</id><published>2009-07-07T19:30:00.004+01:00</published><updated>2009-08-03T23:11:15.527+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='BIOS'/><category scheme='http://www.blogger.com/atom/ns#' term='XP'/><category scheme='http://www.blogger.com/atom/ns#' term='Boot'/><title type='text'>Death and life of a netbook (Acer Aspire One)</title><content type='html'>I've got an acer aspire one&lt;br /&gt;This isn't really a review but ever since i've got it, its been great. Small, light, perfect for travelling and storing photos on, its been round the world with us.&lt;br /&gt;&lt;br /&gt;I really don't have a bad word to say about it, the Intel atom 1.6 GHz processor is great and the 1 gig of ram perfect for running xp home (yes sorry i had to get the Microsoft XP version, i did really want the linux one, but it wasn't just me using it and everyone else knows xp so xp it was), and the 160gig HD is perfect for storing the photos on.&lt;br /&gt;&lt;br /&gt;small, fast, strong, light, good looking&lt;br /&gt;all good praise&lt;br /&gt;so why the post?&lt;br /&gt;&lt;br /&gt;well it broke, i didn't do anything to it, didn't install anything nasty, didn't mess with its innards (i know better than to do that to a perfectly good working laptop) but it broke. i shut it down one day, proper full shut down (not hibernation or sleep) and that was it, next time i pressed the power button nothing happened, no splash screen, no BIOS info, just a black screen :-/ eek.&lt;br /&gt;&lt;br /&gt;Well after searching the interweb it appears it happens now and again to this perfect specimen of a nettop laptop. luckily there were some instructions on how to fix it too :-) thank god for google...&lt;br /&gt;&lt;br /&gt;I wont go into details here, see the link below, i just thought id better let other unfortunates know that sometimes a dead laptop isn't really dead. i was dreading sending it back to the manufactures though...&lt;br /&gt;&lt;br /&gt;Detailed instructions here&lt;br /&gt;&lt;a href="http://www.qrpcw.com/2009/01/acer-aspire-one-bios-recovery.html"&gt;http://www.qrpcw.com/2009/01/acer-aspire-one-bios-recovery.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Download BIOS update from here&lt;br /&gt;&lt;a href="http://support.acer-euro.com/drivers/notebook/as_one_150.html"&gt;http://support.acer-euro.com/drivers/notebook/as_one_150.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;happy days&lt;br /&gt;now don't do that again. Speaking of which, if anyone knows why this happens could you let us know, im worried it might happen again, proper backups from now on then...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-3024316979903522938?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/3024316979903522938/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2009/07/death-and-life-of-netbook-acer-aspire.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/3024316979903522938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/3024316979903522938'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2009/07/death-and-life-of-netbook-acer-aspire.html' title='Death and life of a netbook (Acer Aspire One)'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-424943157424542587</id><published>2009-06-17T18:27:00.003+01:00</published><updated>2009-07-22T11:00:06.554+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='JQuery'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><title type='text'>JQuery and ASP.Net</title><content type='html'>Ive been playing with JQuery alot lately and am loving the ease of use and the feature rich toolset, you can get some realy good effects with it.&lt;br /&gt;&lt;br /&gt;i know sometimes .net developers get, i dont know scared about trying new things that arnt born of microsoft, but JQuery is now being actively endorsed by microsoft and is actually shipped with the latest versions of the framework, so how do you use it.&lt;br /&gt;&lt;br /&gt;1. If you dont have it get a copy of jquery.js its quite small (im currently using 'jquery-.3.2.min.js' which is 56Kb)&lt;br /&gt;2. Include it in your web app&lt;br /&gt;3. There are 2 ways to use it in a page&lt;br /&gt;3a Add a script reference into your head section of the aspx page&lt;br /&gt;      &lt;span style="font-family:courier new;"&gt;&amp;lt;script src="Js cript/jquery -1.3.2.min.js" type="text/javascript"&gt;&amp;lt;/script&gt;&lt;/span&gt;&lt;br /&gt;3b If you are using asp.net AJAX you can let the script manager handle it by:&lt;br /&gt;3b.1 Adding a script manager to the form in the body of the aspx page&lt;br /&gt;3b.2 Adding a scripts element&lt;br /&gt;3b.3 Adding a script reference to the jquery file&lt;br /&gt;3b.4 The result would look like this (remember it needs to go in side the pages form element&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;lt;asp:scriptmanager runat="server"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  &amp;lt;scripts&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    &amp;lt;asp:scriptreference path="~/Jscript/jquery-1.3.2.min.js"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    &amp;lt;/asp:scriptreference&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  &amp;lt;/scripts&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You are all set to use Jquery on the page&lt;br /&gt;&lt;br /&gt;4. The most common way to initialise things is through the body onload, but this executes when the page is fully loaded, images and all, JQuery uses a special piece of script that executes when the page DOM is ready.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;$(document).ready(function()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // do stuff when DOM is ready&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; });&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is where you can set styles, set up events to occur on different user actions all sorts of good stuff.&lt;br /&gt;1st a couple of notes on the above code block:&lt;br /&gt;1 it needs to be inside a sscript element&lt;br /&gt;2 it needs to be located AFTER the scrip ref we declared in step 3 so if using the script manager it needs to be located inside the form after the script manager elements.&lt;br /&gt;You can search the net for all the things you can do with JQuery, i wont repeat them all here, google is most definatly your friend.&lt;br /&gt;&lt;br /&gt;&lt;asp:radiobutton id="RBBus" runat="server" text="Bus" groupname="RB"&gt;&lt;asp:radiobutton id="RBTube" runat="server" text="Tube" groupname="RB"&gt;But for now a simple example.&lt;br /&gt;&lt;br /&gt;say you want to set up a click event to a group of radio buttons so that when clicked a javascript event is fired off to show or hide related DIV elements&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;lt;script type="text/javascript"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;$(document).ready(function(){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt; $(":radio").click(function(event){RBEvent(this)});  &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt; $(".radioClass").hide();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;});&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;function RBEvent(obj)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;{  &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt; $(".radioClass").hide("slow");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt; $("#Div" + obj.id).show("slow");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;lt;/script&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;And here is the aspx elements that go along with it&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;lt; asp:RadioButton ID="RBBus" runat="server" Text="Bus" GroupName="RB" /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/asp:radiobutton&gt;&lt;/asp:radiobutton&gt;&lt;span style="font-family: courier new;"&gt;&amp;lt; &lt;/span&gt;&lt;asp:scriptmanager style="font-family: courier new;" runat="server"&gt;&lt;asp:radiobutton id="RBBus" runat="server" text="Bus" groupname="RB"&gt;&lt;asp:radiobutton id="RBTube" runat="server" text="Tube" groupname="RB"&gt;asp:RadioButton ID="RBTube" runat="server" Text="Tube" GroupName="RB" /&gt;&lt;br /&gt;&lt;/asp:radiobutton&gt;&lt;/asp:radiobutton&gt;&lt;/asp:scriptmanager&gt;&lt;span style="font-family: courier new;"&gt;&amp;lt; &lt;/span&gt;&lt;asp:scriptmanager style="font-family: courier new;" runat="server"&gt;&lt;asp:radiobutton id="RBBus" runat="server" text="Bus" groupname="RB"&gt;&lt;asp:radiobutton id="RBTube" runat="server" text="Tube" groupname="RB"&gt;div id="DivRBBus" class="radioClass"&gt;&lt;br /&gt;Bus details&lt;/asp:radiobutton&gt;&lt;/asp:radiobutton&gt;&lt;/asp:scriptmanager&gt;&lt;span style="font-family: courier new;"&gt;&amp;lt; &lt;/span&gt;&lt;asp:scriptmanager style="font-family: courier new;" runat="server"&gt;&lt;asp:radiobutton id="RBBus" runat="server" text="Bus" groupname="RB"&gt;&lt;asp:radiobutton id="RBTube" runat="server" text="Tube" groupname="RB"&gt;br /&gt;&lt;br /&gt;&lt;/asp:radiobutton&gt;&lt;/asp:radiobutton&gt;&lt;/asp:scriptmanager&gt;&lt;span style="font-family: courier new;"&gt;&amp;lt; &lt;/span&gt;&lt;asp:scriptmanager style="font-family: courier new;" runat="server"&gt;&lt;asp:radiobutton id="RBBus" runat="server" text="Bus" groupname="RB"&gt;&lt;asp:radiobutton id="RBTube" runat="server" text="Tube" groupname="RB"&gt;/div&gt;&lt;br /&gt;&lt;/asp:radiobutton&gt;&lt;/asp:radiobutton&gt;&lt;/asp:scriptmanager&gt;&lt;span style="font-family: courier new;"&gt;&amp;lt; &lt;/span&gt;&lt;asp:scriptmanager style="font-family: courier new;" runat="server"&gt;&lt;asp:radiobutton id="RBBus" runat="server" text="Bus" groupname="RB"&gt;&lt;asp:radiobutton id="RBTube" runat="server" text="Tube" groupname="RB"&gt;div id="DivRBTube" class="radioClass"&gt;&lt;br /&gt;Tube details&lt;/asp:radiobutton&gt;&lt;/asp:radiobutton&gt;&lt;/asp:scriptmanager&gt;&lt;span style="font-family: courier new;"&gt;&amp;lt; &lt;/span&gt;&lt;asp:scriptmanager style="font-family: courier new;" runat="server"&gt;&lt;asp:radiobutton id="RBBus" runat="server" text="Bus" groupname="RB"&gt;&lt;asp:radiobutton id="RBTube" runat="server" text="Tube" groupname="RB"&gt;br /&gt;&lt;br /&gt;&lt;/asp:radiobutton&gt;&lt;/asp:radiobutton&gt;&lt;/asp:scriptmanager&gt;&lt;span style="font-family: courier new;"&gt;&amp;lt; &lt;/span&gt;&lt;asp:scriptmanager runat="server"&gt;&lt;asp:radiobutton id="RBBus" runat="server" text="Bus" groupname="RB"&gt;&lt;asp:radiobutton id="RBTube" runat="server" text="Tube" groupname="RB"&gt;&lt;span style="font-family: courier new;"&gt;/div&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The neat thing that JQuery gives us, as in this example, is the ability to put all your page script into one place, and to have JQuery attach the events dynamically at run time making your javascript much easier to maintain. You could of course put all your script into a separate file as well which can be cached on the browser making the pages even quicker to load up.&lt;br /&gt;&lt;/asp:radiobutton&gt;&lt;/asp:radiobutton&gt;&lt;/asp:scriptmanager&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-424943157424542587?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/424943157424542587/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2009/06/jquery-and-aspnet.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/424943157424542587'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/424943157424542587'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2009/06/jquery-and-aspnet.html' title='JQuery and ASP.Net'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-717043597353503581</id><published>2009-04-28T10:14:00.001+01:00</published><updated>2009-07-21T16:21:46.609+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='MSTest'/><category scheme='http://www.blogger.com/atom/ns#' term='unit test'/><title type='text'>Log4Net inside code run with MSTest unit testing</title><content type='html'>This was confusing me for a while so chances are it was also confusing someone else out there.&lt;br /&gt;&lt;br /&gt;I could not get logging using log4net to output to the configured logger inside my unit tests&lt;br /&gt;i tried&lt;br /&gt;[assembly: log4net.Config. XmlConfigurator()]&lt;br /&gt;in the unittest projects assembalyinfo but still log4net would not pick up the config&lt;br /&gt;&lt;br /&gt;i found that the answer is to place an assembly initialise inside the unit test project, only one mind in the whole project. In fact if you do add 2 its an error&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;[AssemblyInitialize]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;public static void AssemblyInitialize(TestContext testContext)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  log4net.Config.XmlConfigurator.Configure();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;}&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-717043597353503581?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/717043597353503581/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2009/04/log4net-inside-code-run-with-mstest.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/717043597353503581'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/717043597353503581'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2009/04/log4net-inside-code-run-with-mstest.html' title='Log4Net inside code run with MSTest unit testing'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-1715009296339761289</id><published>2009-04-03T13:00:00.001+01:00</published><updated>2009-07-21T16:12:40.775+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='LINQ'/><title type='text'>Brief intro to LINQ</title><content type='html'>Ive recently given a breif tutorial to the guys on our team on LINQ (Language integrated query)&lt;br /&gt;&lt;br /&gt;As with Generics, LINQ is a large subject that i cant write up properly without spending quite a lareg amount of time on, so i'll give a breif overview with an example of a common usage in the context of a generic list.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Overview&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;LINQ is a technology (or language construct) that allows you to process data using functional programming logic to perform an operation. The LINQ API is an attempt to provide a consistent programming model that allows you to manipulate data. Using LINQ we are able to create directly within the C# programming language entities called query expressions, these query expressions are created from numerous query operators that have been intentionally designed to look and feel similar (but not identical) like SQL. Using LINQ you can interact with many sources of data, listed below:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;LINQ implementations&lt;/span&gt;&lt;br /&gt;LINQ to objects&lt;br /&gt;Linq to SQL&lt;br /&gt;Linq to entities&lt;br /&gt;Linq to XML&lt;br /&gt;There are other LINQ enabled technologies but these are the most common, for a grater list look online.&lt;br /&gt;&lt;br /&gt;All of this means that you can interact with an XML dom in the same manner as you would with a list of objects or an ADO record set without having to learn different syntax for either.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;LINQ Example&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;List&lt;/span&gt;&lt;string&gt;&lt;span style="font-family:courier new;"&gt; names = new List&lt;/span&gt;&lt;string&gt;&lt;span style="font-family:courier new;"&gt;(){"George", "William Smith", "bob", "Fred"};&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  IEnumerable&lt;/span&gt;&lt;string&gt;&lt;span style="font-family:courier new;"&gt; subSetNames = from n in names&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                                      where n.Length &gt;= 4&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                                      order by n&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                                      select n;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  foreach(string name in subSetNames)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  Console.Write(name);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  }&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;The code above firstly creates a list of strings and places then in the names variable&lt;br /&gt;Then it takes that collection filters it where the length is greater than or equal to 4&lt;br /&gt;Sorts it based on the string&lt;br /&gt;Puts the resulting collection in the variable subSetNames?&lt;br /&gt;Finally it loops through all the strings in subSetNames? and prints them out&lt;br /&gt;&lt;br /&gt;The resulting string is "Fred George William Smith" In this example the collection being acted on was a simple list of strings but it could be a collection of any type of object, or indeed an ADO record set, or an XML document, its a very powerful technique and allows for very clear functional logic (no complex nested loops and temporary collections for ordering etc).&lt;br /&gt;&lt;br /&gt;This topic is massive and so im not going to go into it in any more depth, but in the most part ive not used any LINQ that is anymore complex than the example listed above. more advanced features such as lambdas and extension methods start to make things complex and ive so far managed to keep clear of using these techniques, for more info search google for the answer.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;LINQ Grouping&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;By way of an example this code below demonstrates the power of LINQ used with a simple grouping command&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;string[] names = {"Albert", "Burke", "Connor", "David", "Everett", "Frank", "George", "Harris"};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; //Defining the GroupBy logic (here it is lengthwise)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; var groups = names.GroupBy(s =&gt; s.Length);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; //Iterate through the collection created by the Grouping&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; foreach(IGrouping&lt;/span&gt;&lt;int,&gt;&lt;span style="font-family:courier new;"&gt; group in groups)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     //Branch on the condition decided&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     Console.WriteLine("Strings of Length {0}", group.Key);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     //Actual results&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     foreach(string value in group)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       Console.WriteLine(" {0}", value);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Produces this output&lt;br /&gt;&lt;br /&gt;Strings of Length 6&lt;br /&gt;Albert&lt;br /&gt;Connor&lt;br /&gt;George&lt;br /&gt;Harris&lt;br /&gt;Strings of Length 5&lt;br /&gt;Burke&lt;br /&gt;David&lt;br /&gt;Frank&lt;br /&gt;Strings of Length 7&lt;br /&gt;Everett&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;LINQ Resources&lt;/span&gt;&lt;br /&gt;&lt;a href="http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx"&gt;MSDN 101 LINQ samples&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/int,&gt;&lt;/string&gt;&lt;/string&gt;&lt;/string&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-1715009296339761289?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/1715009296339761289/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2009/04/brief-intro-to-linq.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/1715009296339761289'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/1715009296339761289'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2009/04/brief-intro-to-linq.html' title='Brief intro to LINQ'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-4263461364325077677</id><published>2009-04-01T04:00:00.000+01:00</published><updated>2009-07-21T15:55:24.710+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='generics'/><title type='text'>Quick intro to generics</title><content type='html'>Recently ive been teaching some new developers on the team about generics, its not a new concept i know, and when you know about them you cant quite figure how people sometimes just dont know about them, they are so helpfull.&lt;br /&gt;&lt;br /&gt;So tell me about them then!&lt;br /&gt;&lt;br /&gt;Generics came in at .net 2.0 and are used extensively through out the .net framework internally, if you do much .net dev work you will come across then at some point.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;What are generics&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Generics allow you to define a type (class or structure) while leaving some of the details unspecified.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Quick Tip&lt;/span&gt;&lt;br /&gt;When you see the following in code you know you are looking at code that uses generics&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  //C#&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  List&lt;int&gt; myArray = new List&lt;int&gt;();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  List&lt;myclass&gt; my2ndArray = new List&lt;myclass&gt;();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  'VB.Net&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  Dim myArray As New List(Of integer)();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  Dim my2ndArray As New List(Of myClass)();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The main benefits for using generics are:&lt;br /&gt;Type safety (you can only put ints in a collection of ints for example)&lt;br /&gt;Performance (boxing and unboxing of primitive types is eliminated)&lt;br /&gt;Clarity (you can see in visual studio what type of class is allowed in a generic collection, and intellisence will also help you out)&lt;br /&gt;&lt;br /&gt;The most common (and simple) usage is in the new (as of 2.0) generic collection classes.&lt;br /&gt;Previous to .net 2.0 you had ArrayList, HashTable, Queue and stack (to name just a few) these classes allow you to store collections of objects, and since every class in .net derives from object you can store any object in these classes.&lt;br /&gt;So if you can store any object in a collection what the point of limiting a collection to allow it to only store objects of a certain type? The main reason is for type safety and clarity. This is best discussed by example:&lt;br /&gt;&lt;br /&gt;  &lt;span style="font-family: courier new;"&gt;ArrayList myArray = new ArrayList();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  myArray.Add(1);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  myArray.Add(2);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  myArray.Add("3");&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  int counter = 0;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  foreach(Object o in myArray)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    int myInt = (int) o;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    counter += myInt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This code will compile fine, but will throw a runtime exception when trying to cast "3" (a string) to an int. you have to be careful when adding things to your collection and you have to make sure you handle exceptions that may arise from incorrect use. I often see code testing for the type of an object before doing a cast and if it is not of the correct type ignoring it, its bad practice, error prone, and is just unnecessary when using generics.&lt;br /&gt;&lt;br /&gt;So if we rewrite the above example using generics:&lt;br /&gt;&lt;br /&gt;  &lt;span style="font-family: courier new;"&gt;List&lt;int&gt; myArray = new List&lt;int&gt;();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  myArray.Add(1);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  myArray.Add(2);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  //myArray.Add("3"); //if uncommented will not compile&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  int counter = 0;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  foreach(int myInt in myArray)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    counter += myInt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The change to use generic list of type int has made the code type safe (you cant add anything other than an int to myArray, if you do you will get a compile time error. Also the foreach loop is much simpler, you know that all the objects in myArray are ints, so no need for explicit type casting. All in all generic collections make the code more robust and just plain easier to read and hence maintain.&lt;br /&gt;&lt;br /&gt;Now generics goes much deeper than just generic collections but in general you wont need to know how to create your own generic types and generic methods, but i would recommend every .net developer should know, its used all over the place. But i have not created any in any of my professional work projects.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Resources&lt;/span&gt;&lt;br /&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.collections.generic%28VS.85%29.aspx"&gt;Generics on MSDN&lt;/a&gt;&lt;br /&gt;Use MSDN documentation on your machine&lt;br /&gt;&lt;a href="http://www.google.co.uk/search?hl=en&amp;amp;q=generics+.net+3.5&amp;amp;btnG=Search&amp;amp;meta=&amp;amp;aq=o&amp;amp;oq="&gt;Google for Generics and .net&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-4263461364325077677?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/4263461364325077677/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2009/04/quick-intro-to-generics.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/4263461364325077677'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/4263461364325077677'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2009/04/quick-intro-to-generics.html' title='Quick intro to generics'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-3552027519486756051</id><published>2009-03-27T06:30:00.001Z</published><updated>2009-07-21T15:34:20.114+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='Log4Net'/><title type='text'>Introduction to Log4Net</title><content type='html'>&lt;span style="font-size:180%;"&gt;Log4net&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Log4net (&lt;a href="http://logging.apache.org/log4net/"&gt;http://logging.apache.org/log4net/&lt;/a&gt;) is a tool to help the programmer output log statements to a variety of output targets, i have used it handling all the logging requirements of the applications that i have developed recently. And have found it integrates very well with spring.net and NHibernate.&lt;br /&gt;&lt;br /&gt;In most cases i have set up the apps to log everything to a file and also log errors/warnings to an SMTP logger (which effectively sends an email out to me).&lt;br /&gt;There are loads of examples and manuals etc on the website http://logging.apache.org/log4net/ it gives loads of good config examples too.&lt;br /&gt;&lt;br /&gt;In order to get log4net working all you need is the log4net dll, configuration, and a small amount of code to get it started and logging. (this page is a good read &lt;a href="http://logging.apache.org/log4net/release/manual/configuration.html"&gt;http://logging.apache.org/log4net/release/manual/configuration.html&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;But the minimum to take away is:&lt;br /&gt;1. Reference the log4net dll&lt;br /&gt;2. Import the log4net classes&lt;br /&gt;   2.1. using log4net;&lt;br /&gt;   2.2. using log4net.Config;&lt;br /&gt;3. Add a config file (usually just a section to your web.config or app.config)&lt;br /&gt;4. Add a call to the configurator&lt;br /&gt;   4.1. log4net.Config.XmlConfigurator?.Configure();&lt;br /&gt;   4.2. Or [assembly: log4net.Config.XmlConfigurator?(Watch=true)]&lt;br /&gt;5. Create a logger&lt;br /&gt;   5.1. private static readonly ILog log = LogManager?.GetLogger?(typeof(MyClassName?));&lt;br /&gt;   5.2. each class should have its own logger, which should be private and static (log4net is thread safe)&lt;br /&gt;6. Use the logger to log&lt;br /&gt;   6.1. log.Info("my info message.");&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;TIP&lt;/span&gt;&lt;br /&gt;If you find you are getting double entries for log records it is probably due to you having duplicated entries in the log config. For example you might have the root set to debug logging and a named logger also set to debug, which will mean that 2 log entries get inserted for all debug messages from that named logger.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-3552027519486756051?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://logging.apache.org/log4net' title='Introduction to Log4Net'/><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/3552027519486756051/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2009/03/introduction-to-log4net.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/3552027519486756051'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/3552027519486756051'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2009/03/introduction-to-log4net.html' title='Introduction to Log4Net'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-6106463313305964834</id><published>2009-03-24T13:18:00.001Z</published><updated>2009-07-21T15:23:22.833+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vmware'/><category scheme='http://www.blogger.com/atom/ns#' term='Virtual machine'/><title type='text'>How to expand a virtual machines disk space</title><content type='html'>There comes a time when everyone who uses virtual machines runs out of space.&lt;br /&gt;I use virtual machines for my dev environment, which means i can mess around with them, install things to test them out safe in the knowledge that you can always get back to a previous state, or even back to the start with out any pain at all.&lt;br /&gt;ive got a VM for VS2003 one for VS2008, i used to have one for VS2005 (but i don't use that any more) and dare i say it one for VB6 (which thankfully ive not used for quite a while)&lt;br /&gt;But recently i ran out of space on the VS2008 install, id also got office installed, and i wanted the 3.5 framework sp1 installing, which is surprisingly large.&lt;br /&gt;well, this is what i did:&lt;br /&gt;open up a command line&lt;br /&gt;vmware-vdiskmanager.exe -x 16Gb "C:\VMWare\WinXPPro5\Windows XP Professional.vmdk"&lt;br /&gt;boot up from an ubuntu 8.04 live cd&lt;br /&gt;bring up command console&lt;br /&gt;type sudo gparted&lt;br /&gt;select your main partition&lt;br /&gt;right click partition to be expanded and hit resize&lt;br /&gt;move slider to the right for the whole of the disk&lt;br /&gt;apply&lt;br /&gt;exit ubuntu&lt;br /&gt;restart xp&lt;br /&gt;enjoy your new many gigs of space&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-6106463313305964834?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/6106463313305964834/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2009/03/how-to-expand-virtual-machines-disk.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/6106463313305964834'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/6106463313305964834'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2009/03/how-to-expand-virtual-machines-disk.html' title='How to expand a virtual machines disk space'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-8900374526106656295</id><published>2009-02-22T06:27:00.000Z</published><updated>2009-07-21T15:18:45.377+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GRUB'/><category scheme='http://www.blogger.com/atom/ns#' term='Boot'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Triple boot install problems and reinstall of GRUB</title><content type='html'>My main dev machine at home is a triple boot, XP, Vista, Ubuntu machine currently with Ubuntu 8.10, and XP Pro installed. I recently added a new hard drive and had all sorts of problems with getting the boot sequences sorted out.&lt;br /&gt;&lt;br /&gt;In a very breif nutshell this is what i did to fix it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1st get vista booting again&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To do this i used the vista boot disk and selected the repair your computer option followed by startup repair, i think i had to reboot and do it again as far as i recall but it did it in the end.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Finally reinstalled grub&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;First i used my ubuntu live cd and in a console ran&lt;br /&gt;&lt;div&gt;&lt;span style="font-family:monospace;"&gt;&lt;br /&gt;$ sudo grub&lt;/span&gt;&lt;/div&gt; &lt;div&gt;This puts you into a grub shell.&lt;br /&gt;&lt;/div&gt;  &lt;div&gt;&lt;span style="font-family:monospace;"&gt;&lt;br /&gt;grub&gt; find /boot/grub/stage1&lt;/span&gt;&lt;/div&gt; &lt;div&gt;This will return a value which looks like (hd?, ?) this is where you will find /boot/grub. '?' will point to the specific partition of your disc which contains the boot grub for example (hd0,1)&lt;/div&gt;  &lt;div&gt;&lt;span style="font-family:monospace;"&gt;&lt;br /&gt;grub&gt; root (hd?,?)&lt;/span&gt;&lt;/div&gt; &lt;div&gt;Use the value from the find command eg (hd0,1)&lt;br /&gt;&lt;br /&gt;Finally the command which will install GRUB into the MBR.&lt;/div&gt;  &lt;div&gt;&lt;span style="font-family:monospace;"&gt;&lt;br /&gt;grub&gt; setup (hd?)&lt;br /&gt;grub&gt; quit&lt;/span&gt;&lt;/div&gt; &lt;div&gt;&lt;br /&gt;Reboot and my Boot menu worked again :-) yay&lt;br /&gt;&lt;br /&gt;Hopefully this will help someone.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-8900374526106656295?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/8900374526106656295/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2009/03/triple-boot-install-problems-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/8900374526106656295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/8900374526106656295'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2009/03/triple-boot-install-problems-and.html' title='Triple boot install problems and reinstall of GRUB'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8200285235757892384.post-7815240410381566254</id><published>2009-01-20T00:29:00.000Z</published><updated>2009-07-21T15:18:06.366+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Folds'/><title type='text'>The first fold</title><content type='html'>As with so much in the world the first fold is the most important, you get the first fold even slightly misaligned or creased and you can forget getting fold 20 correct.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Well like the other billion folk in web universe i thought id better get a blog, well not just that, i do think i have something worth while to share. But Ive never been one to read other peoples random thoughts and so you wont get read many of mine (as if anyone really would want to anyways).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Its just that i do come across ways of doing things (in a coder by trade) that is new to me, interesting and sometimes useful, and so i thought i might as well share them with people, and maybe if I'm lucky they will find things useful that i found useful, we'll see. Actually the most useful thing i find about blogs are the comments, some guy tells you to solve a particular problem in this way on his blog and you see 10 posts below discussing the pro's and con's of the approach, that's what i like, there is never just one way round a problem, i like to see the other side of the fold before making that first crease.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8200285235757892384-7815240410381566254?l=foldingair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://foldingair.blogspot.com/feeds/7815240410381566254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://foldingair.blogspot.com/2009/03/first-fold.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/7815240410381566254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8200285235757892384/posts/default/7815240410381566254'/><link rel='alternate' type='text/html' href='http://foldingair.blogspot.com/2009/03/first-fold.html' title='The first fold'/><author><name>Damo</name><uri>http://www.blogger.com/profile/08902572365040420975</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-6tt3iWMRjbg/TgGbOSQ3YHI/AAAAAAAAA9Y/lnG921a5rxg/s220/IMAG0237.jpg'/></author><thr:total>0</thr:total></entry></feed>
