<?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'><id>tag:blogger.com,1999:blog-4264713515752050911</id><updated>2009-11-04T15:52:13.820Z</updated><title type='text'>Mintox</title><subtitle type='html'>C#, Javascript, CSS, SEO, and all that goodness</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mintox.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4264713515752050911/posts/default'/><link rel='alternate' type='text/html' href='http://mintox.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Brad</name><uri>http://www.blogger.com/profile/01366305015757070204</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4264713515752050911.post-8274012250489596855</id><published>2009-03-15T18:14:00.002Z</published><updated>2009-03-15T18:38:45.554Z</updated><title type='text'>DVLA Bites</title><content type='html'>Ok so I'm at work and I get a call from my housemate saying "There are some guys out the front of the house loading your bike onto a truck". So the long and the short of it is that I didn't pay my road tax due to the fact that I never received the notice. This really bothers me as the DVLA clearly knows where the bike is, what my name is, what my email is, what my phone number is etc. Instead trying - just once - to get hold of me they put the bike on the back of a truck, haul it half way across London and then expect me to pick it up. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Why not just give me a parking ticket?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Anyway I pay the tax and then go to pick the bike up, and guess what the guy serving me has so much attitude I actually have to say "you don't need to be so hostile towards me". No doubt most people that come to collect their vehicle are pretty pissed off. And so was I, though I was still polite (at that point). &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I get to the bike and see they have cut the auxiliary chain that is &lt;span class="Apple-style-span" style="font-style: italic;"&gt;not&lt;/span&gt; used for securing that bike to anything, only to my other bike. Why? No idea, it wasn't stopping them moving it in any way. Also my housemate would have given them the key if they had asked. They also seem to have damaged the rear tire, which I noticed quite abruptly as I turned a corner on the exit of the impound lot and nearly went tits up. Jackasses.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So after all this I'm down a huge fine, a very expensive lock, and a rear tire. What for?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Not paying my £15 - yes only £15 tax, within 2 months, when the bike had not been ridden over winter. Maybe if I was riding it at the time I might think differently but really this is too much. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The punishment does not fit the crime, in my opinion anyway.&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4264713515752050911-8274012250489596855?l=mintox.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mintox.blogspot.com/feeds/8274012250489596855/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4264713515752050911&amp;postID=8274012250489596855' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4264713515752050911/posts/default/8274012250489596855'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4264713515752050911/posts/default/8274012250489596855'/><link rel='alternate' type='text/html' href='http://mintox.blogspot.com/2009/03/dvla-bites.html' title='DVLA Bites'/><author><name>Brad</name><uri>http://www.blogger.com/profile/01366305015757070204</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='11776816494914582434'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4264713515752050911.post-4064649140108431377</id><published>2009-03-15T18:11:00.001Z</published><updated>2009-03-15T18:12:57.471Z</updated><title type='text'>Credit Crunch Explained</title><content type='html'>I just came across this great video for explaining the credit crunch - very informative!&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;object width="400" height="225"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=3261363&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1"&gt;&lt;embed src="http://vimeo.com/moogaloop.swf?clip_id=3261363&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="225"&gt;&lt;/embed&gt;&lt;/object&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/4264713515752050911-4064649140108431377?l=mintox.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mintox.blogspot.com/feeds/4064649140108431377/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4264713515752050911&amp;postID=4064649140108431377' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4264713515752050911/posts/default/4064649140108431377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4264713515752050911/posts/default/4064649140108431377'/><link rel='alternate' type='text/html' href='http://mintox.blogspot.com/2009/03/credit-crunch-explained.html' title='Credit Crunch Explained'/><author><name>Brad</name><uri>http://www.blogger.com/profile/01366305015757070204</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='11776816494914582434'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4264713515752050911.post-2069842858029273029</id><published>2008-12-11T19:33:00.003Z</published><updated>2009-02-04T10:47:00.180Z</updated><title type='text'>Html/Url/Javascript Encoding made easy</title><content type='html'>&lt;p&gt;When developing a web application one of the key security issues to remember is to make sure you apply the correct encoding to any text that is written to the page - either from a resources file, content management system or user generated input. Without this generally two problems can happen. Firstly any external content can produce invalid markup that at its worst can break the layout of your page or prevent JavaScript from executing. For example forgetting to escape a single quotation in a string used in a JavaScript function&amp;nbsp;- such as in the word &amp;quot;won't&amp;quot; will start or end&amp;nbsp;a string. That&amp;nbsp;sounds pretty bad right, as your JavaScript will throw a compilation error and not run.&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;The second problem you can face is much more sinister however.&amp;nbsp;By making use of this problem&amp;nbsp;a malicious attacker can post some information to your&amp;nbsp;site&amp;nbsp;that will in turn be viewed and executed by unsuspecting users. There are two prominent forms of attacks that developers need to be aware of - &lt;a href="http://en.wikipedia.org/wiki/Cross-site_scripting"&gt;XSS (Cross site scripting)&amp;nbsp;&lt;/a&gt;and &lt;a href="http://en.wikipedia.org/wiki/Cross-site_request_forgery"&gt;XSRF or CSRF (Cross site request forgery)&lt;/a&gt;.&amp;nbsp;To very briefly surmise the &lt;a href="http://ha.ckers.org/xss.html"&gt;XSS&lt;/a&gt; involves the attacker injecting script&amp;nbsp;that&amp;nbsp;is directed at&amp;nbsp;stealing a users&amp;nbsp;details of your website or otherwise manipulate&amp;nbsp;the users browser. XSRF has been getting a bit of media attention lately, in the context of encoding it is a&amp;nbsp;specialisation of XSS&amp;nbsp;whereby the attacker exploits&amp;nbsp;your website to&amp;nbsp;execute requests on&amp;nbsp;another site that the user &lt;em&gt;&lt;span style='font-family:"Calibri","sans-serif"'&gt;may&lt;/span&gt;&lt;/em&gt; be a registered member of. In this sense your site becomes a vehicle for malicious attacks, and in much the same way that an open SMTP relay will get your mail server blacklisted, you may start to find your site flagged as potentially dangerous. Not good!&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;Anyway I'm not going to dwell on these topics as there is plenty of good information on the net already - although the statics on the number of sites vulnerable and the time to patch aren't great. The sites that are most at risk are the ones that allow the users to firstly submit information that other readers can view - which is pretty much all the good ones!&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;  &lt;p class=MsoNormal&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;So we need an easy way to prevent this,&amp;nbsp;and the first level of protection is to encode all of your user&amp;nbsp;input. Unfortunately &lt;a href="http://msmvps.com/blogs/calinoiu/archive/2006/06/13/what-s-wrong-with-asp-net-html-encoding.aspx"&gt;ASP.NET is incredibly inconsistent&lt;/a&gt; in the way that text is encoded. In general myself and my team stay away from ASP.NET web controls (such as &lt;span style='font-family:"Courier New"'&gt;Label&lt;/span&gt;, &lt;span style='font-family:"Courier New"'&gt;Linkbutton&lt;/span&gt; etc), and instead favour clean html with the ASP.NET &lt;span style='font-family: "Courier New"'&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.htmlcontrols.aspx"&gt;HtmlControls&lt;/a&gt; &lt;/span&gt;namespace (any standard tag with &lt;span style='font-family:"Courier New"'&gt;runat=&amp;quot;server&amp;quot;&lt;/span&gt;) and the odd &lt;span style='font-family:"Courier New"'&gt;&amp;lt;asp:Literal&amp;nbsp;/&amp;gt;&lt;/span&gt;&amp;nbsp;control. This works well and produces markup that is very similar the final output, which always&amp;nbsp;helps when comparing rendered HTML to an&amp;nbsp;ASPX page, or writing some CSS.&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;  &lt;p class=MsoNormal&gt;&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;  &lt;p class=MsoNormal&gt;&amp;nbsp;This takes us back to manual encoding (or using innerText of an &lt;span style='font-family:"Courier New"'&gt;HtmlControl&lt;/span&gt;). I was looking at the &lt;span style='font-family:"Courier New"'&gt;String.Format &lt;/span&gt;method and realised that a good way to implement encoding would be with an implementation of &lt;span style='font-family:"Courier New"'&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.iformatprovider.aspx"&gt;IFormatProvider&lt;/a&gt;&lt;/span&gt; for each of the encoding types. &lt;span style='font-family:"Courier New"'&gt;IFormatProvider &lt;/span&gt;allows the formatting of an object to a string &amp;#8211; the standard ones are &lt;span style='font-family:"Courier New"'&gt;NumberFormatInfo&lt;/span&gt;, &lt;span style='font-family:"Courier New"'&gt;DateTimeFormatInfo&lt;/span&gt; and &lt;span style='font-family:"Courier New"'&gt;CultureInfo&lt;/span&gt;. You can build your own by implementing ICustomFormatter &amp;#8211; which only requires one method implementation &amp;#8211; &lt;span style='font-family:"Courier New"'&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.icustomformatter_members.aspx"&gt;Format()&lt;span style='font-family:"Calibri","sans-serif"'&gt;.&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;  &lt;p class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;  &lt;p class=MsoNormal&gt;My basic implementation makes use of a modified version of the &lt;a href="http://www.codeplex.com/AntiXSS"&gt;AntiXSS 2.0 library&lt;/a&gt; (I have added extra Unicode characters that are safe). After getting it all up and running it is as simple as &lt;span style='font-size:10.0pt;font-family:"Courier New"'&gt;String.Format&lt;span style='color:#2B91AF'&gt;(EncodingInfo&lt;/span&gt;.JavascriptEncoder, &lt;span style='color:#A31515'&gt;&amp;quot;function() {alert('{0}')}&amp;quot;&lt;/span&gt;, myString)&lt;/span&gt; - and&amp;nbsp;voila &amp;#8211; all your text is encoded. &lt;/p&gt;  &lt;p class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;  &lt;p class=MsoNormal&gt;There is only one problem however, String.toString(IFormatProvider) is a no-op! This makes sense really when you think about it &amp;#8211; why would you need to format a string to string. Encoding text seems like the only instance I can think of so this fair enough but it would have been great to go &lt;span style='font-size:10.0pt;font-family:"Courier New"; color:#A31515'&gt;&amp;quot;unsafe &amp;lt;script&amp;gt; string&amp;quot;&lt;/span&gt;.ToString(&lt;span style='font-size:10.0pt;font-family:"Courier New";color:#2B91AF'&gt;EncodingInfo&lt;/span&gt;&lt;span style='font-size:10.0pt;font-family:"Courier New"'&gt;.HtmlEncoder)! &lt;/span&gt;So I&amp;#8217;m left with probably creating an extension method for that case &amp;#8211; along the lines of &lt;span style='font-size:10.0pt;font-family:"Courier New";color:#A31515'&gt;&amp;quot;unsafe &amp;lt;script&amp;gt; string&amp;quot;&lt;/span&gt;.Encode(&lt;span style='font-size:10.0pt; font-family:"Courier New";color:#2B91AF'&gt;EncodingInfo&lt;/span&gt;&lt;span style='font-size:10.0pt;font-family:"Courier New"'&gt;.HtmlEncoder)- w&lt;/span&gt;hich is not too bad either.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4264713515752050911-2069842858029273029?l=mintox.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mintox.blogspot.com/feeds/2069842858029273029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4264713515752050911&amp;postID=2069842858029273029' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4264713515752050911/posts/default/2069842858029273029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4264713515752050911/posts/default/2069842858029273029'/><link rel='alternate' type='text/html' href='http://mintox.blogspot.com/2008/12/htmlurljavascript-encoding-made-easy.html' title='Html/Url/Javascript Encoding made easy'/><author><name>Brad</name><uri>http://www.blogger.com/profile/01366305015757070204</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='11776816494914582434'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4264713515752050911.post-3669269648876730742</id><published>2007-06-24T21:37:00.000Z</published><updated>2007-06-26T21:37:25.561Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Sever'/><title type='text'>More SQL</title><content type='html'>&lt;span style="font-family:courier new;"&gt;OPTION (Fast X)&lt;/span&gt; hint optimises for returning the first X number of rows first before executing the rest of the query. This can have an effect on overall performance however the tradeoff is that the user can see some results while the rest of the query is executing.&lt;br /&gt;&lt;br /&gt;Create Calendar Table&lt;br /&gt;In Visual Studio -&gt; New Project -&gt; Analysis Services Project -&gt; New Data Source&lt;br /&gt;then New Dimension -&gt; Date Template and go from there&lt;br /&gt;&lt;br /&gt;Always name table outputs with AS so that the developer is abstracted from the actual table and column names&lt;br /&gt;&lt;br /&gt;SQLStressTest - good for testing performance and even debugging.&lt;br /&gt;&lt;a href="http://www.apress.com/book/supplementDownload.html?bID=10220&amp;sID=4251"&gt;http://www.apress.com/book/supplementDownload.html?bID=10220&amp;amp;sID=4251&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Date Time:&lt;br /&gt;ISO Format is:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;yyyy-MM-ddThh:mm:ss.mmm&lt;/span&gt;&lt;br /&gt;SQL Server also accepts:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;yyyyMMdd hh:mm:ss&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Hashing:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SELECT HashBytes('MD2MD4MD5SHASHA1', 'Text')&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:lucida grande;"&gt;Dynamic SQL:&lt;/span&gt;&lt;br /&gt;sp_executesql - can make use of parameters and hence a) reuse quer planss b) most importantly prevent sql injection.&lt;br /&gt;Useage:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;EXEC sp_executesql @sqlStatement, N' @String VARCHAR(255), @Int INT', @SomeString, @SomeNumber&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Concurrency Control:&lt;br /&gt;Read Blocking: &lt;span style="font-family:courier new;"&gt;READ COMMITTED, REPEATABLE READ, SERIALIZABLE&lt;/span&gt;&lt;br /&gt;Non Blocking: &lt;span style="font-family:courier new;"&gt;READ UNCOMMITTED, SNAPSHOT&lt;/span&gt;&lt;br /&gt;Usage: &lt;span style="font-family:courier new;"&gt;SET TRANSACTION ISOLATION LEVEL REPEATABLE READ&lt;/span&gt;&lt;br /&gt;&lt;br /&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/4264713515752050911-3669269648876730742?l=mintox.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mintox.blogspot.com/feeds/3669269648876730742/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4264713515752050911&amp;postID=3669269648876730742' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4264713515752050911/posts/default/3669269648876730742'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4264713515752050911/posts/default/3669269648876730742'/><link rel='alternate' type='text/html' href='http://mintox.blogspot.com/2007/06/more-sql.html' title='More SQL'/><author><name>Brad</name><uri>http://www.blogger.com/profile/01366305015757070204</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='11776816494914582434'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4264713515752050911.post-6325912689067666894</id><published>2007-06-06T19:24:00.000Z</published><updated>2007-06-06T19:30:04.833Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='google'/><title type='text'>Google Source Code</title><content type='html'>If someone stole the source code to Microsoft Windows it might cause a few security issues, but they couldn't do much with it. I would imagine they would get sued pretty hard by the MS team of lawyers. But what about the source to Google Search and Indexing? You could tweak it and then create a rival service without a huge risk of getting busted...well maybe. &lt;br /&gt;&lt;br /&gt;I would like to make a search engine one day, its pretty hard though. I wrote some of the blinkBox search engine and its given me a new appreciation for good search results and how difficult they are to achieve. Those blokes at google are pretty sharp I would say.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4264713515752050911-6325912689067666894?l=mintox.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mintox.blogspot.com/feeds/6325912689067666894/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4264713515752050911&amp;postID=6325912689067666894' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4264713515752050911/posts/default/6325912689067666894'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4264713515752050911/posts/default/6325912689067666894'/><link rel='alternate' type='text/html' href='http://mintox.blogspot.com/2007/06/google-source-code.html' title='Google Source Code'/><author><name>Brad</name><uri>http://www.blogger.com/profile/01366305015757070204</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='11776816494914582434'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4264713515752050911.post-2222582864566266490</id><published>2007-06-06T18:07:00.000Z</published><updated>2007-06-06T19:24:51.216Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='TFS'/><category scheme='http://www.blogger.com/atom/ns#' term='scrum'/><title type='text'>Lessons in Agile</title><content type='html'>We have been using an agile based methodology at work for a few months now. Overall it has been a good experience for the developers and the upper management. From a technical management point of view certain areas have worked out very well, such as morning standup meetings and enforcing test and customer reviews. My biggest problem however is that we have used paper cards for the majority of tracking. This has made it quite difficult to plan, view and log work. In retrospect all this information probably needs to be backed by some kind of data store. One of our devs would spend quite a long time saving this info in Excel to produce burn up charts, but historical information was not centrally stored. &lt;br /&gt;&lt;br /&gt;We are now investigating Team Foundation Server, though the price has really surprised me, and not in a good way. Hopefully using TFS we can track requests, work items, bugs and even feedback from a central store. I also really like the source control features, such as shelving and advanced branching - although I am yet to see this in a work environment.  &lt;br /&gt;&lt;br /&gt;Anyway back to agile. I thought I would document some of the lessons that we learned along the way:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Morning Standups - otherwise known as scrums - are great. One of the common scenarios we have is that some devs will get caught up in the problem at hand.  Anyone can just say "take it offline" (or similar) when they are not interested, ending that conversation and indicating that the relevant parties should continue after the meeting.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;As I mentioned, make sure you have a central data store for all the work that is carried out. While a card based system works ok for the work in progress, previous or upcoming work can be hard to track.&lt;/li&gt; &lt;br /&gt;&lt;li&gt;Get a large board, with columns divided up into stages (Not Started, Development, Review, Testing, Customer Review, Complete), while on the other axis divide the rows up by developer. This should make each developer a lot more accountable for any work they have outstanding. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Maintain good visibility for the team regarding where they are and what the goals are. This can be achieved verbally in the standup and also by generating a burn up or burn down chart that should be displayed near the tracking board. One of our devs was very good at this and it helps a lot when trying to motivate the team.&lt;/li&gt; &lt;br /&gt;&lt;li&gt;Get card printed and make sure they are small enough! We used colour coded cards, they are very good and it is easy for anyone from managment or dev to understand. White for &lt;em&gt;Functionality&lt;/em&gt;, Red for &lt;em&gt;Bugs&lt;/em&gt;, Blue for &lt;em&gt;Technical Debt&lt;/em&gt; (When a job will needs to be revisited) and Green for &lt;em&gt;Infrastructure&lt;/em&gt;. &lt;/li&gt; &lt;br /&gt; &lt;li&gt;Enforce testing. We used stickers (shiny stars - like back in school if you did well) on each card indicating the type of test. Red for manual testing, gold for unit tests and silver for selenium tests. Work should not be accepted until the tests have been written.&lt;/li&gt; &lt;br /&gt;&lt;li&gt;Track work done! Both the time worked, time remaining and the stages the work item has been through (e.g. Development -&gt; Review -&gt; Development -&gt; Review -&gt; Test). This can be easily achieved by colour coded stickers on the top of the cards.&lt;/li&gt; &lt;br /&gt;&lt;li&gt;Issue a priority for each work item. This makes it easy for devs in a self organised team to override each other without causing an upset. "Can you please work on this with me now, as you can see it is a priorty one bug and I need your input" won't result in anyone getting upset.&lt;/li&gt; &lt;br /&gt;&lt;li&gt;Make sure you still do appropriate requirements analysis, agile does not mean that the development team can do it their way. Good requirements make for good acceptance criteria.&lt;/li&gt; &lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4264713515752050911-2222582864566266490?l=mintox.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mintox.blogspot.com/feeds/2222582864566266490/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4264713515752050911&amp;postID=2222582864566266490' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4264713515752050911/posts/default/2222582864566266490'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4264713515752050911/posts/default/2222582864566266490'/><link rel='alternate' type='text/html' href='http://mintox.blogspot.com/2007/06/lessons-in-agile.html' title='Lessons in Agile'/><author><name>Brad</name><uri>http://www.blogger.com/profile/01366305015757070204</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='11776816494914582434'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4264713515752050911.post-3418324469768087906</id><published>2007-06-05T21:37:00.000Z</published><updated>2007-06-06T17:46:19.017Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='http'/><category scheme='http://www.blogger.com/atom/ns#' term='huffman'/><category scheme='http://www.blogger.com/atom/ns#' term='gzip'/><category scheme='http://www.blogger.com/atom/ns#' term='google'/><category scheme='http://www.blogger.com/atom/ns#' term='compression'/><title type='text'>HTTP Compression</title><content type='html'>I often wonder how does Google compress their pages on every request (Do they compress every request?). Some ideas that have come up with are:&lt;br /&gt;&lt;br /&gt;All pages are generated and then compressed once, subsequent requests are issued from a cache - but it troubles me that they would do this. My main issue is that&lt;br /&gt;a) according to the original white paper from Google all pages are stored compressed in the gzip format, hence requiring some decompression before processing. This combined with&lt;br /&gt;b) the search results are highlighted with the exact phase searched.&lt;br /&gt;&lt;br /&gt;If this is true then each result must be processed, requiring decompression, then compressed again to send back to the client. This just seems like a waste of processing and given the number of requests they need to serve it just doesn't seem likely.&lt;br /&gt;&lt;br /&gt;But can we improve on this, I think so. While I am somewhat familiar with Huffman encoding, I do not know much more about LZ other than what I have read on Wikipedia. These techniques can be used to make up gzip, a likely compression technique used by google. Huffman and LZ both based on generating a key table that maps a common series of bits (or letters) to a shortened binary version&lt;br /&gt;i.e &amp;lt;strong&amp;gt; is 6*8 = 48bits in ASCII (and UTF-8 I think), however a table may map that sequence to a much smaller series of bits, say 12bits due to its relatively high freqency in HTML documents. The basis for this compression is in making frequent patterns short while infrequent pattern are longer, and space is not wasted on non-existent pattens resulting in a shorter overall length. In fact UTF-8 appears to be based on Huffman coding, but that's for another post. &lt;br /&gt;&lt;br /&gt;This key table generally changes for every block of data encoded, but then lets think about what Google are compressing - HTML. They may have a predetermined table (or set of tables, perhaps indicated by a header) that is used for all documents. I think that makes sense, and fits with Google publishing statistics on common web tags and attributes, as they may use these statistics to generate new encoding tables.&lt;br /&gt;&lt;br /&gt;Now lets assume they don't encode strings with spaces as a combination of characters. For example " we " is 4 characters including spaces, and is hence not a subset of " welcome". These two strings would have completely unrelated compressed character codes. So if we accept the assumption that spaces are not integrated into a keyed entry in a compression table we can do some powerful text manipulation while the content is compressed - although only on full words.&lt;br /&gt;&lt;br /&gt;If we compress the search text (or tokens/words) then we can easily compare this to the compressed results - they should have the exact bit pattern if they use the same key table. It may not be quite this simple - a series of other concatenated bit patterns may match your search bit pattern so some parsing logic may be involved. I can't think of a great way of achieving this yet because in order to have unique bit pattern we would have to have a long code. Else we would have to perform some processing on each extended code when generating our key table to make sure that this bit pattern does not repeat. This would adversely affect the compression ratio that could be acheived, although it may be a small trade off overall. Using fixed length key codes may help. For example if each key code resulted in a length that is multiple of 4 bits then this means 8 times (2^4) fewer possible occurences of the unique code in longer codes. &lt;br /&gt;&lt;br /&gt;If this process does work then you may now inject some compressed bits into the stream - namely some compressed &amp;lt;strong&amp;gt; tags to highlight the search word(s). Viola, we have read and manipulated the string pattern while it is still compressed without fully decompressing or re-compressing it!&lt;br /&gt;&lt;br /&gt;The other reason I like this idea is that by using a common and constant compression table they can make each page request be constructed from parts of HTML. If the key table is the same for all requests, then generating the header is simple and blocks can be concatenated, which is not normally possible as they are based on different key tables. For example a single search result can be concatenated to the previous result, which taking a step back makes a good platform for distributed processing and caching. Once they have built this type of compression engine they can use it for pretty much any page, from news to mail. Maybe that is the Google advantage?&lt;br /&gt;&lt;br /&gt;Maybe they don't do anything like this, I really have no idea, but this sounds like a possible solution and meets all the functional and performance requirements that I can think of right now. I might go and investigate it some more.&lt;br /&gt;&lt;br /&gt;Any thoughts?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4264713515752050911-3418324469768087906?l=mintox.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mintox.blogspot.com/feeds/3418324469768087906/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4264713515752050911&amp;postID=3418324469768087906' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4264713515752050911/posts/default/3418324469768087906'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4264713515752050911/posts/default/3418324469768087906'/><link rel='alternate' type='text/html' href='http://mintox.blogspot.com/2007/06/http-compression.html' title='HTTP Compression'/><author><name>Brad</name><uri>http://www.blogger.com/profile/01366305015757070204</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='11776816494914582434'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4264713515752050911.post-6582355888049305307</id><published>2007-06-03T21:50:00.000Z</published><updated>2007-06-06T18:06:32.987Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Error Handling'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Sever'/><category scheme='http://www.blogger.com/atom/ns#' term='raiserror'/><category scheme='http://www.blogger.com/atom/ns#' term='go'/><category scheme='http://www.blogger.com/atom/ns#' term='XACT_ABORT'/><title type='text'>SQL Tips</title><content type='html'>I'm reading a book on SQL Server at the moment, I just thought I would make a few notes as I go:&lt;br /&gt;&lt;br /&gt;Exceptions should be thrown when the function or procedure is in a state that is outside of its handlable states - it is in exception. I don't think that I see code throw exceptions often enough. If it can't handle that state just &lt;span style="font-family:courier new;"&gt;throw&lt;/span&gt; (Or RAISERROR).&lt;br /&gt;&lt;br /&gt;In order to make a statement, parsing and scope-resolution exception behave like batch exceptions - and hence terminate the current batch (to the next GO statement) use:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SET XACT_ABORT ON&lt;/span&gt;&lt;br /&gt;I can see that this might be useful with a transaction (Hence the name "Transaction Abort" = XACT_ABORT). I have seen that a number of our update statements are running all the way through when really an exception should be thrown and the batch aborted and rolled back. Now that I know about it I'm sure I'll find more uses.&lt;br /&gt;&lt;br /&gt;In SQL Server error messages less than 11 are minor, 11 to 16 are serious, and greater than that you better speak to a DBA. User errors triggered by the &lt;span style="font-family:courier new;"&gt;RAISERROR&lt;/span&gt; function are warnings if they have a serveritiy less than 11, while normal is 11 to 18, and 18+ are severe. Over 18's can only be called by members of the &lt;span style="font-family:courier new;"&gt;sysadmin&lt;/span&gt; role. 20 and over cause the connection to break, be careful!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;RAISEERROR&lt;/span&gt; messages can be formatted similar to &lt;span style="font-family:courier new;"&gt;String.Format&lt;/span&gt; (actually it's much closer to &lt;span style="font-family:courier new;"&gt;printf &lt;/span&gt;in C) using %i (integer) and %s.&lt;br /&gt;For example: &lt;span style="font-family:courier new;"&gt;RAISEERROR('Problem with FilmId: %i', 16, 1, @FilmId )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Row numbers are from the last &lt;span style="font-family:courier new;"&gt;GO&lt;/span&gt; statement, which is obvious once you know that &lt;span style="font-family:courier new;"&gt;GO&lt;/span&gt; is not a T-SQL command, its a directive to send the commands to SQL Server serially.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4264713515752050911-6582355888049305307?l=mintox.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mintox.blogspot.com/feeds/6582355888049305307/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4264713515752050911&amp;postID=6582355888049305307' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4264713515752050911/posts/default/6582355888049305307'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4264713515752050911/posts/default/6582355888049305307'/><link rel='alternate' type='text/html' href='http://mintox.blogspot.com/2007/06/sql-tips.html' title='SQL Tips'/><author><name>Brad</name><uri>http://www.blogger.com/profile/01366305015757070204</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='11776816494914582434'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry></feed>