<?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-6005490725222948439</id><updated>2011-11-28T01:37:23.237+01:00</updated><category term='c#'/><category term='visual studio'/><category term='xml'/><category term='episerver'/><category term='ood'/><category term='agile'/><category term='debugging'/><category term='asp.net'/><category term='.net'/><category term='methodology'/><category term='philosophy'/><category term='syntax'/><category term='xp'/><title type='text'>The Tommy Code</title><subtitle type='html'>A Senior Software Developer Sharing My Experience</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.tommycode.se/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://www.tommycode.se/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Tommy</name><uri>http://www.blogger.com/profile/02987079709890896170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_l-LLksOg9eE/R9bjxIwpurI/AAAAAAAAAAM/24-1aJgI-VI/S220/tommy2.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>15</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6005490725222948439.post-5249756351577249634</id><published>2011-10-17T20:01:00.001+02:00</published><updated>2011-10-18T09:44:19.887+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='methodology'/><title type='text'>Story Points vs Hours</title><content type='html'>&lt;div&gt;In the Agile methods many suggest using something called Story Points instead of time when estimating the time a task would require for implementation. Rather than saying that it will take two days they would say it takes, for example, four Story Points. They then track what is called Velocity to see how many Story Points the team can complete in a week and suggest that about that many Points, let's say 20, is what the team can implement in a week.&lt;br /&gt;&lt;br /&gt;I find this very awkward. Is it just a technique to hide the hours? Because, after all, most of us are still payed by the hour, and we also want to have an idea about the dates we might expect things to be finished. Story Points take this away. What would you say to the carpenter who you pay by the hour if he said he will have your bathroom done in 80 Story Points? He expects to burn about 20 Story Points per week, he adds. I would think he was a freak!&lt;br /&gt;&lt;br /&gt;The only reasonable reason I find to use Story Points instead of Hours (or Days) is the notion that different coders may need different amounts of time to solve a task. With Story Points two coders may estimate a task to, for instance, four, while using days one might need two days and the other three days. That would implicitly say that coders are linear to each other in skill difference, since for the equation to sum up you'd need them to agree that the next task, estimated to two Story Points, would take the former one day and the later one and a half. Something I strongly disbelieve.&lt;br /&gt;&lt;br /&gt;The more unreasonable reason is that as estimates are hard to do, you put a metric on them that is hard to understand to get away with them easier. If you say that something will take three days it's easy to see if you were right, while estimating it will take three Story Points will keep you safe. Who are to say how long a Story Point is? Hardcore agilists laughs at such a silly question.&lt;br /&gt;&lt;br /&gt;I guess I'm missing something, but I have a hard time seeing the Point of Story Points. Feel free to enlighten me using the comment field!&lt;br /&gt;&lt;br /&gt;p.s. I've never tried Story Points, so I might be totally wrong. It may be Gods gift to software developers. d.s.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6005490725222948439-5249756351577249634?l=www.tommycode.se' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.tommycode.se/feeds/5249756351577249634/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6005490725222948439&amp;postID=5249756351577249634' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/5249756351577249634'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/5249756351577249634'/><link rel='alternate' type='text/html' href='http://www.tommycode.se/2011/10/story-points-vs-hours.html' title='Story Points vs Hours'/><author><name>Tommy</name><uri>http://www.blogger.com/profile/02987079709890896170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_l-LLksOg9eE/R9bjxIwpurI/AAAAAAAAAAM/24-1aJgI-VI/S220/tommy2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6005490725222948439.post-8865306236459860972</id><published>2011-10-14T22:47:00.000+02:00</published><updated>2011-10-14T22:47:53.487+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='episerver'/><category scheme='http://www.blogger.com/atom/ns#' term='debugging'/><title type='text'>EPiServer 6.0 compare bug</title><content type='html'>&lt;div&gt;I've spent most of today, and a couple of hours yesterday, to figure out a weird problem with the function that allow you to compare two versions of a page in the EPiServer 6.0 edit mode. As soon as I clicked the compare button I got the YSOD telling me&amp;nbsp;that&amp;nbsp;a NullReferenceException was thrown from the method ComputeVaryCacheKey deep down in the ASP.NET rendering.&lt;br /&gt;&lt;br /&gt;I hooked up the debugger and found that everything seemed to be in order. Altho, we had a few customized renderings in the chain so I started by disabling them one by one to find the cause. Once they were all removed I still had the problem tho, so I started on another track. Next thing I did was to look at the output caching used. Starting with simplifying the&amp;nbsp;GetVaryByCustomString method in Global.asax so it should be almost impossible to have a problem there didn't help. Next thing was removing the OutputCache directives on my controls one by one and in the end - bingo! When the last OutputCache directive was removed I got some other error instead from the compare button.&lt;br /&gt;&lt;br /&gt;So it comes down to that adding&amp;nbsp;an OutputCache directive&amp;nbsp;with VaryByCustom would make that&amp;nbsp;ComputeVaryCacheKey crash when trying to compare two pages... I really need my output caching, but for the sake of coming to the bottom of this I left them out looking at the new error message. Maybe it could be the root course and if that was solved I could add the caching again?&lt;br /&gt;&lt;br /&gt;The new error said "']]&amp;gt;' is not allowed within '&amp;lt;!CDATA[' blocks" or something like that. Well, fair enough. I looked at the source of the page being compared and there were a couple of CDATA blocks in the scripts generated by ASP.NET but none of them seemed to be malformed. At this point I decided to fire up another EPiServer site and see if the CDATA blocks looked the same, and if they would like being compared on that site. The CDATA blocks looked the same and they did like being compared in that context... Odd. Here I decided to add the OutputCache directive to a control on this site and see if it would work here - And it DID! There was a difference tho - this site was build on EPiServer 6 R2.&lt;br /&gt;&lt;br /&gt;At this point I contacted the EPiServer support that within an hour reported back to me that this was a known bug in EPiServer 6.0 that had been solved in R2. The general advise was to upgrade to R2, but in case I couldn't do that I also was send a custom "CompareProvider" written by the support guy that should work with 6.0. So I put that in the bin directory, configured the site as he instructed me for activating this new provider and gave it a go. I still got that&amp;nbsp;"']]&amp;gt;' is not allowed within '&amp;lt;!CDATA[' blocks"... but the good part was that I could add my OutputCache directives again and still getting that error!&lt;br /&gt;&lt;br /&gt;Well, now at least I had my own custom code running closer to the problem. I reflected the provider that the support guy sent me and it was only one class. I copied the code to a class in my own project allowing me to set a breakpoint in there. When I had the code it was also obvious that the CDATA issue was addressed in it, but apparently it didn't address the problem well enough. I started by just removing the CDATA start and end block from the input to the compare function and then it worked! Or well, kind of. It didn't seem to have support for css being added with @import so I got a comparison of the page without styling... still, it was the best yet!&lt;br /&gt;&lt;br /&gt;Hacking away even more I hardcoded an addition of the primary css to the source, and now it looked good too! A bit too hacky tho, for my taste, it struck me that I could reflect the source from the EPiServer 6 R2 binaries to see how they solved it there. The first line in that version was the Obsolete attribute - use "HtmlDiffProvider" instead it said. Wonder if that works with 6.0 I pondered, and reflected that source and added it to my project next to the code from the support guy. Then executed... and boom! That first NullReferenceException from the caching again! Dang. But, with the code from these two providers I managed to create a one provider that worked fine with EPiServer 6.0!&lt;br /&gt;&lt;br /&gt;During this entire episode I did of course do a lot of searching on the web for guidance... getting none! Hence I decided to write this post to help the next person that enters this moat. It's not your fault! It's a bug in the platform! Stop wasting your time looking for problems in your project, and instead add your own CompareProvider.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6005490725222948439-8865306236459860972?l=www.tommycode.se' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.tommycode.se/feeds/8865306236459860972/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6005490725222948439&amp;postID=8865306236459860972' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/8865306236459860972'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/8865306236459860972'/><link rel='alternate' type='text/html' href='http://www.tommycode.se/2011/10/episerver-60-compare-bug.html' title='EPiServer 6.0 compare bug'/><author><name>Tommy</name><uri>http://www.blogger.com/profile/02987079709890896170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_l-LLksOg9eE/R9bjxIwpurI/AAAAAAAAAAM/24-1aJgI-VI/S220/tommy2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6005490725222948439.post-6779119253518459790</id><published>2011-02-24T12:47:00.003+01:00</published><updated>2011-02-24T12:59:58.970+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='philosophy'/><title type='text'>If you can't reproduce it, you can't fix it</title><content type='html'>&lt;div&gt;Every now and then you will be assigned a bug that seems impossible. You try to reproduce it, but you fail. You look at the code, and what happened seems impossible. It may now be tempting to add some if-statement to just make sure the object isn't null (for example) and close the bug. Don't Do That!&lt;br /&gt;&lt;br /&gt;Doing that will cause a lot more trouble down the road. The problem will most likely come up again in some other part of your code, and then you'll be on yet one unplanned rescue mission. Maybe you'll be tempted once again to add a quick-fix and before you know your code will be full of them - all added with your best intention.&lt;br /&gt;&lt;br /&gt;Then come the day when you find the real bug! Hooray! Finally your days of applying that dirty fix on different spots around your projects is over. But will you go back and revert your qd:s? No. Either there is no time, or you don't want to touch what works, or you just leave them there to take care about if this would happen again - but if you are like most people you will surely leave them there to rot. Don't Do That!&lt;br /&gt;&lt;br /&gt;Leaving them mean more code to maintain, more things that can go wrong and more useless processor cycles. If there is an "if" in your fix (and it usually is) there will also be more forks in the code, which is very error prone.&lt;br /&gt;&lt;br /&gt;So what should you do? You should put all your effort into being able to reproduce the bug. If you still fail, ask someone to help you reproduce the bug. If it seems to be a timing issue, write something that pushes your code so much that you cause the error within reasonable time before you try to solve it. Once again, how can you be sure you've solved the problem if you can't test if the problem disappeared when you're done?&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6005490725222948439-6779119253518459790?l=www.tommycode.se' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.tommycode.se/feeds/6779119253518459790/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6005490725222948439&amp;postID=6779119253518459790' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/6779119253518459790'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/6779119253518459790'/><link rel='alternate' type='text/html' href='http://www.tommycode.se/2011/02/if-you-can-reproduce-it-you-can-fix-it.html' title='If you can&apos;t reproduce it, you can&apos;t fix it'/><author><name>Tommy</name><uri>http://www.blogger.com/profile/02987079709890896170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_l-LLksOg9eE/R9bjxIwpurI/AAAAAAAAAAM/24-1aJgI-VI/S220/tommy2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6005490725222948439.post-3199828975557702397</id><published>2010-12-21T17:20:00.000+01:00</published><updated>2010-12-21T17:20:05.373+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><title type='text'>Toedipping in ASP.NET MVC</title><content type='html'>Today I've finally had time to have a closer look at ASP.NET MVC, getting my hands dirty and actually doing something with it. I have vacation and the kids are at day care - so this was my chance!&lt;br /&gt;&lt;br /&gt;I started up downloading the Visual Web Developer Express 2010 and created an ASP.NET MVC 2 template project. I executed it on the development web server, saw it worked, changed a couple of texts and reloaded to see my changes were applied. They were!&lt;br /&gt;&lt;br /&gt;Then&amp;nbsp;I googled to see if my web host, Binero, had support for ASP.NET MVC at all. I found that they had a &lt;a href="http://blogg.binero.se/2009/11/publicera-en-asp-net-mvc-2-losning-med-visual-studio-2010-microsoft-del-4/"&gt;blog entry with an instructional movie&lt;/a&gt; showing exactly how to make it work, so it shouldn't be a problem I figured.&lt;br /&gt;&lt;br /&gt;I followed the instructions and uploaded my modified template site. It turned out the template site is using .NET 4.0 though, which Binero doesn't support, so it didn't work out of the box. Changing target version for the project to .NET 3.5 should do the trick I figured, so I did that and tried to run the project - and got some strange error. The page said Error CS1525 about a line in the View where the code was something about "Html.ActionLink". Google didn't quite help me, but pretty soon I noticed the&amp;nbsp;obvious problem. It was marked "&lt;em&gt;&amp;lt;%:&lt;/em&gt;" which is new in ASP.NET 4. Changing all "&lt;em&gt;&amp;lt;%:&lt;/em&gt;" in the&amp;nbsp;views to "&lt;em&gt;&amp;lt;%=&lt;/em&gt;" made it work with the .NET 3.5 framework and I was back in game!&lt;br /&gt;&lt;br /&gt;Playing around adding my own models, views and controllers was all pretty straight forward. Nowhere near as much magic as I had expected. I got a hold of it pretty fast and only had one thing stopping me so much I had to go googling again. Adding " - MySite" after the &lt;em&gt;ContentPlaceHolder&lt;/em&gt; inside the &lt;em&gt;title&lt;/em&gt;-element was not doing the trick for some reason.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&amp;lt;title&amp;gt;&amp;lt;asp:ContentPlaceHolder ID="TitleContent" runat="server" /&amp;gt; - MySite&amp;lt;/title&amp;gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;All I got in the title was the content from the placeholder... I first thought it was some update problem and started recompiling, reloading, refreshing, re-everything, but no luck. Finally I went to google who could help me instantly. It has to do with the &lt;em&gt;head&lt;/em&gt;-tag having &lt;em&gt;runat="server"&lt;/em&gt; set. Full description and solution can be found here: &lt;a href="http://haacked.com/archive/2009/04/03/tipjar-title-tags-and-master-pages.aspx"&gt;TipJar: Title Tags and Master Pages&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A couple of hours resulted in a very simple web site, but never the less a ASP.NET MVC web site. &lt;br /&gt;&lt;br /&gt;My first!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6005490725222948439-3199828975557702397?l=www.tommycode.se' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.tommycode.se/feeds/3199828975557702397/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6005490725222948439&amp;postID=3199828975557702397' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/3199828975557702397'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/3199828975557702397'/><link rel='alternate' type='text/html' href='http://www.tommycode.se/2010/12/toedipping-in-aspnet-mvc.html' title='Toedipping in ASP.NET MVC'/><author><name>Tommy</name><uri>http://www.blogger.com/profile/02987079709890896170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_l-LLksOg9eE/R9bjxIwpurI/AAAAAAAAAAM/24-1aJgI-VI/S220/tommy2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6005490725222948439.post-6080238304695222112</id><published>2010-11-18T13:09:00.003+01:00</published><updated>2010-11-18T13:33:27.155+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='philosophy'/><title type='text'>How to commit code</title><content type='html'>When you commit (check in) your code to the source control system there are some things you should do to ensure quality and trackability.&lt;br /&gt;&lt;br /&gt;1) If your source control system supports change sets, that is commiting a set of files as a bundle, make sure you just include one issue in that bunch. You shouldn't fix a bunch of things in all ends of the project and then commit them all in the same change set. The change set may well span over multiple projects tho, because one change set should include all the changes done to resolve that particular issue. A change set should also be compilable upon commit and not rely on the next one to be able to work.&lt;br /&gt;&lt;br /&gt;2) Before you commit your change set you should diff every file against the repository version and see that you only commit things that were intended to commit. It's pretty easy to commit code you commented out, temporary variable names or debugging code if you don't review your own commits. If your commit is in central parts of the application or very large it is good to have another team member sit next to you when reviewing the changes.&lt;br /&gt;&lt;br /&gt;3) When you've limited your change set to include only one issue and reviewed all the changes done, you should write a short description of the content in your change set. This is written as the "commit comment" and will be visible when you look at the log for your repository. Since your change set only should deal with one issue it is easy to write a brief description of what you've done. It's also good to include an issue id if you have an issue tracking system.&lt;br /&gt;&lt;br /&gt;I guess many readers might think that this takes a lot of time - but think of all the time you save due to the higher quality instead! I've done this with all commits for many years now and it is very uncommon that I add bad code to the repository. It's not at all uncommon that I notice bad code while doing my personal code review upon commit tho!&lt;br /&gt;&lt;br /&gt;My biggest problem when converting to this more professional approach was to limit my changes to only one issue. Yet today there are times when I can't commit only one change as I've fixed two (or more) issues in parallell without commiting the first one - and when they touch the same file it isn't possible to have only one change in the change set. If one of the fixes are small I usually solve this by reverting the changes for that issue temporarily while commiting the first change and then redo the changes for the next commit - but once in a while I need to write a commit comment with the dreaded word "... and ...".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6005490725222948439-6080238304695222112?l=www.tommycode.se' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.tommycode.se/feeds/6080238304695222112/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6005490725222948439&amp;postID=6080238304695222112' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/6080238304695222112'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/6080238304695222112'/><link rel='alternate' type='text/html' href='http://www.tommycode.se/2010/11/how-to-commit-code.html' title='How to commit code'/><author><name>Tommy</name><uri>http://www.blogger.com/profile/02987079709890896170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_l-LLksOg9eE/R9bjxIwpurI/AAAAAAAAAAM/24-1aJgI-VI/S220/tommy2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6005490725222948439.post-5608761403441478156</id><published>2010-11-11T13:25:00.003+01:00</published><updated>2010-11-11T13:45:24.144+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xp'/><category scheme='http://www.blogger.com/atom/ns#' term='philosophy'/><title type='text'>I love deleting code</title><content type='html'>Yesterday I read a tweet saying "the next best thing after writing code is deletig code". My response was fast, saying "personally i like deleting code more. ;)". Let me elaborate on that!&lt;br /&gt;&lt;br /&gt;Deleting code means that you either:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;found a better way to do something&lt;/li&gt;&lt;li&gt;found unneeded abstractions&lt;br /&gt;&lt;/li&gt;&lt;li&gt;found unneeded functionality&lt;/li&gt;&lt;/ul&gt;So, deleting code (at least when it's done on purpose ;)) is always done because you don't need it. Taking away code that you don't need is great, because the less code you have, the less can go wrong, and after the code is removed there is less to test and less to maintain.&lt;br /&gt;&lt;br /&gt;Therefore, always strive to have as little code as possible doing the  job. As they say in Extreme Programming, "Pay as you go: Build just  enough to meet today's requirements".&lt;br /&gt;&lt;br /&gt;You could get sad when removing code because it means that you or someone else have done something that could be considered a waste. Well, sometimes it was a waste but it won't be less a waste because you keep it. Most times the code you're about to delete served a purpose though, leading you to find the better solution.&lt;br /&gt;&lt;br /&gt;So summing it up; Don't be sad about deleting code, love it like I do!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6005490725222948439-5608761403441478156?l=www.tommycode.se' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.tommycode.se/feeds/5608761403441478156/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6005490725222948439&amp;postID=5608761403441478156' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/5608761403441478156'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/5608761403441478156'/><link rel='alternate' type='text/html' href='http://www.tommycode.se/2010/11/i-love-deleting-code.html' title='I love deleting code'/><author><name>Tommy</name><uri>http://www.blogger.com/profile/02987079709890896170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_l-LLksOg9eE/R9bjxIwpurI/AAAAAAAAAAM/24-1aJgI-VI/S220/tommy2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6005490725222948439.post-4386795868339066942</id><published>2010-10-07T22:07:00.003+02:00</published><updated>2010-10-07T22:17:06.413+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><title type='text'>Odd way to fill your mailbox</title><content type='html'>On a site of mine I get an email every time an invalid url is requested. The purpose of that is mainly to find broken links. Sometimes a misconfigured crawler may spam me with a hundred mails, but they're pretty easy to delete and it doesn't happen frequently.&lt;br /&gt;&lt;br /&gt;Tonight however, from 21.08 to 21.53, I received more than 3.500 such, all from the same ip. It would probably have been more if i didn't block that ip at 21.53, as I luckily was at the computer. The requested url:s were all directories and pages that exist on the site, but combined in odd ways, primarily stacking directories in long chains that doesn't exist.&lt;br /&gt;&lt;br /&gt;As I don't have access to the firewalls of my hosting company I had to figure out a way to block the weirdo myself. My solution was to just terminate requests from that host in my asp.net page like this (but the real ip instead of the x:es):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  protected void Page_Load(object sender, EventArgs e)&lt;br /&gt;  {&lt;br /&gt;      if (Request.UserHostAddress == "x.x.x.x") {&lt;br /&gt;          Response.End();&lt;br /&gt;          return;&lt;br /&gt;      }&lt;br /&gt;      ...&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6005490725222948439-4386795868339066942?l=www.tommycode.se' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.tommycode.se/feeds/4386795868339066942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6005490725222948439&amp;postID=4386795868339066942' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/4386795868339066942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/4386795868339066942'/><link rel='alternate' type='text/html' href='http://www.tommycode.se/2010/10/odd-way-to-fill-your-mailbox.html' title='Odd way to fill your mailbox'/><author><name>Tommy</name><uri>http://www.blogger.com/profile/02987079709890896170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_l-LLksOg9eE/R9bjxIwpurI/AAAAAAAAAAM/24-1aJgI-VI/S220/tommy2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6005490725222948439.post-2817674267610651679</id><published>2010-03-17T13:14:00.004+01:00</published><updated>2010-10-07T14:32:16.227+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ood'/><title type='text'>The Anti-IF Campaign</title><content type='html'>When I first found Francesco Cirillo's &lt;a href="http://www.antiifcampaign.com/" target="_blank"&gt;Anti-IF Campaign&lt;/a&gt; I signed up almost instantly. Over the years I've learned that the if-statement is best used sparsely. Neither the campaign, nor I, strives to eliminate all if-statements but rather wants you to think twice before using them. Unfortunately I don't think the web site does a good job explaining why if is bad, so I'm going to make a try on my own.&lt;br /&gt;&lt;br /&gt;Every if-statement creates another path through the code. That opens up for a lot of additional cases to test and hence harder to test. Harder to test means there will likely be more bugs. For example you need to add at least one Unit test for each if you add to your code. A nice technique for testing your code coverage is to comment out either the if or the content and see if any test fails. If it doesn’t the code is either unnecessary or not covered by your tests.&lt;br /&gt;&lt;br /&gt;That being said code is a lot about different paths, and must be, so you can’t take away all if-statements. But consider your options!&lt;br /&gt;&lt;br /&gt;There’s the redundant if:&lt;br /&gt;&lt;pre&gt;if (flag) {&lt;br /&gt; flag = false;&lt;br /&gt;}&lt;/pre&gt;Just replace that with&lt;br /&gt;&lt;pre&gt;flag = false;&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;There’s the horrible null check:&lt;br /&gt;&lt;pre&gt;if (filter != null) {&lt;br /&gt; filteredList = filter.Filter(list);&lt;br /&gt;}&lt;br /&gt;else {&lt;br /&gt; filteredList = list;&lt;br /&gt;}&lt;/pre&gt;Create a null object filter and always filter, like this.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;If don’t have a interface for your filter already, create one.&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;interface IFilter {&lt;br /&gt; Array Filter(Array list);&lt;br /&gt;}&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;Make a implementation of that interface that just returns the argument.&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;class NullFilter : IFilter {&lt;br /&gt; Array Filter(Array list) {&lt;br /&gt;   return list;&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;Where you used to decide not to set the filter field, create a NullFilter.&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;IFilter filter = new NullFilter();&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;Now remove the if and the else and just filter.&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;filteredList = filter.Filter(list);&lt;/pre&gt;&lt;br /&gt;Now lets round up with the case that Francesco lists on the Campaign site where you refactor your code to use strategy objects.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.antiifcampaign.com/2009/04/the-simplest-anti-if-code.html" target="_blank"&gt;The Simplest Anti-IF Code&lt;/a&gt; (Anti-IF Campaign)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There's a lot of other cases, but I can't go through them all. I hope that you've learned that if should be avoided and that you will try to do so in the future.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'll end this article with a Twitter quote from @garybernhardt.&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;Let's rename the "if" construct to "ponder" and impose a one-second busy wait per use. That'll teach those branchers! ;)&lt;/blockquote&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6005490725222948439-2817674267610651679?l=www.tommycode.se' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.tommycode.se/feeds/2817674267610651679/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6005490725222948439&amp;postID=2817674267610651679' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/2817674267610651679'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/2817674267610651679'/><link rel='alternate' type='text/html' href='http://www.tommycode.se/2010/03/anti-if-campaign.html' title='The Anti-IF Campaign'/><author><name>Tommy</name><uri>http://www.blogger.com/profile/02987079709890896170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_l-LLksOg9eE/R9bjxIwpurI/AAAAAAAAAAM/24-1aJgI-VI/S220/tommy2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6005490725222948439.post-8424973850761796998</id><published>2009-11-14T19:20:00.004+01:00</published><updated>2009-11-14T22:52:34.958+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ood'/><title type='text'>SRP subsumes ISP</title><content type='html'>Yesterday I listened to a friend who held a presentation about the SOLID principles. You know, the five principles in object oriented design that Uncle Bob put together.&lt;br /&gt;&lt;br /&gt;Single Responsibility Principle&lt;br /&gt;Open/Closed Principle&lt;br /&gt;Liskov Substitution Principle&lt;br /&gt;Interface Segregation Principle&lt;br /&gt;Dependency Inversion Principle&lt;br /&gt;&lt;br /&gt;If you're not familiar with them you should read up right now. Here's a &lt;a href="http://www.davesquared.net/2009/01/introduction-to-solid-principles-of-oo.html"&gt;good place to start&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Anyway, when my friend reached the I of SOLID it struck me that ISP is only interesting if you've violated SRP to start with. I've always thought of it as a refactoring pattern, but all the definition says is that "make fine grained interfaces that are client specific". Adhering to the SRP it would be difficult to make interfaces any other way... I decided to confront Bob with this, and he seems to agree:&lt;br /&gt;&lt;br /&gt;I asked:&lt;br /&gt;would you agree that ISP is self-fulfilled if SRP is used? ie, ISP only has a value on its own when working with bad design?&lt;br /&gt;&lt;br /&gt;And he replied:&lt;br /&gt;Strictly speaking, SRP subsumes ISP. The problem is you can't always be as strict about SRP as you'd like.&lt;br /&gt;&lt;br /&gt;So, ISP is mainly an option if you fail to design by the most important principle. But as Bob states, it's not at all uncommon that you do that so there's still value in the principle.&lt;br /&gt;&lt;br /&gt;Also, I think ISP is a great principle when dealing with legacy code. If you have a huge class it may be both difficult and very time consuming to refactor it to meet SRP. Here I use ISP as a lightweight SRP, creating the interfaces that I'd like the objects to be in a good SRP design and then have the same class implement them all. It takes virtually no time, and then I can start writing good code from that point on. It also helps me if I want to refactor out one of the many parts this legacy class may contain.&lt;br /&gt;&lt;br /&gt;If I'd end up with some kind of conslusion it would be that you shouldn't think much about ISP when designing new software, but it's a great principle for refactoring!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6005490725222948439-8424973850761796998?l=www.tommycode.se' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.tommycode.se/feeds/8424973850761796998/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6005490725222948439&amp;postID=8424973850761796998' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/8424973850761796998'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/8424973850761796998'/><link rel='alternate' type='text/html' href='http://www.tommycode.se/2009/11/srp-subsumes-isp.html' title='SRP subsumes ISP'/><author><name>Tommy</name><uri>http://www.blogger.com/profile/02987079709890896170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_l-LLksOg9eE/R9bjxIwpurI/AAAAAAAAAAM/24-1aJgI-VI/S220/tommy2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6005490725222948439.post-9040173637713660102</id><published>2009-10-15T17:55:00.003+02:00</published><updated>2009-10-15T18:07:20.910+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xp'/><title type='text'>Learning XP</title><content type='html'>I'm currently having a great time at work, developing a web application from scratch using Extreme Programming. You can follow our stumbling steps in a new blog, &lt;a href="http://xpcreuna.blogspot.com/"&gt;XP Creuna&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6005490725222948439-9040173637713660102?l=www.tommycode.se' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.tommycode.se/feeds/9040173637713660102/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6005490725222948439&amp;postID=9040173637713660102' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/9040173637713660102'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/9040173637713660102'/><link rel='alternate' type='text/html' href='http://www.tommycode.se/2009/10/learning-xp.html' title='Learning XP'/><author><name>Tommy</name><uri>http://www.blogger.com/profile/02987079709890896170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_l-LLksOg9eE/R9bjxIwpurI/AAAAAAAAAAM/24-1aJgI-VI/S220/tommy2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6005490725222948439.post-6903589441671482368</id><published>2009-01-19T22:27:00.006+01:00</published><updated>2009-01-19T22:40:57.489+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='syntax'/><title type='text'>String versus string in C#</title><content type='html'>A month ago I had a developer that I'm currently in the same project with questioning me about my use of string versus my use of String. She found it confusing that I didn't just use one of them consistently. I told her my idea, which is that I'm using String when accessing static members and string otherwise, but she still found it confusing.&lt;br /&gt;&lt;br /&gt;I then decided to consult the &lt;a href="http://www.idesign.net/" target="_blank"&gt;IDesign C# Coding Standard&lt;/a&gt;, and looking there I found some inconsistency. I decided to ask them about it, and they seem to share my belief. See my mail and answer below.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;From: Juval Lowy&lt;br /&gt;Sent: den 19 december 2008 15:51&lt;br /&gt;To: Tommy Bryntse&lt;br /&gt;Subject: RE: Contacting IDesign&lt;br /&gt;&lt;br /&gt;You should use String for the static members.&lt;br /&gt;&lt;br /&gt;________________________________________&lt;br /&gt;From: Tommy Bryntse&lt;br /&gt;Sent: Friday, December 19, 2008 6:27 AM&lt;br /&gt;To: sales@idesign.net&lt;br /&gt;Subject: Contacting IDesign&lt;br /&gt;&lt;br /&gt;Hello IDesign!&lt;br /&gt;&lt;br /&gt;I noticed an inconsistency in your C# Coding Standard.&lt;br /&gt;&lt;br /&gt;In section 1.10 it says&lt;br /&gt;&lt;br /&gt;Always use … string NOT String.&lt;br /&gt;&lt;br /&gt;While in section 2.52 it says&lt;br /&gt;&lt;br /&gt;Use String.Empty instead of "":&lt;br /&gt;&lt;br /&gt;Myself I’ve always used String for accessing static members in string, and string &lt;br /&gt;otherwise, just as your example. Section 1.10 was about to make me change that to &lt;br /&gt;always use string, but after seeing section 2.52 I’m confused. What should I do?&lt;br /&gt;&lt;br /&gt;Kind regards,&lt;br /&gt;&lt;br /&gt;Tommy&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6005490725222948439-6903589441671482368?l=www.tommycode.se' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.tommycode.se/feeds/6903589441671482368/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6005490725222948439&amp;postID=6903589441671482368' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/6903589441671482368'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/6903589441671482368'/><link rel='alternate' type='text/html' href='http://www.tommycode.se/2009/01/string-versus-string-in-c.html' title='String versus string in C#'/><author><name>Tommy</name><uri>http://www.blogger.com/profile/02987079709890896170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_l-LLksOg9eE/R9bjxIwpurI/AAAAAAAAAAM/24-1aJgI-VI/S220/tommy2.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6005490725222948439.post-1394732722800522916</id><published>2008-04-10T11:57:00.002+02:00</published><updated>2008-04-10T13:59:12.265+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><title type='text'>Deserializing non printable characters</title><content type='html'>Today I got on my desk to fix a problem with our import and export functionality. In an interface open to customers one of them had entered non printable characters in a string property which caused the import to fail if the item had been exported.&lt;br /&gt;&lt;br /&gt;My first thought was that it seemed strange that the XmlSerializer of the .NET Framework didn't automatically encode string properties to proper XML. Looking at the XML file it was correct tho. Or, proper XML format at least. To be proper XML it seems you may not use control characters other than CR, LF and TAB.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.w3.org/TR/2000/REC-xml-20001006#charsets"&gt;XML Spec 1.0&lt;/a&gt; says:&lt;br /&gt;Char ::= #x9  #xA  #xD  [#x20-#xD7FF]  [#xE000-#xFFFD]  [#x10000-#x10FFFF]&lt;br /&gt;&lt;br /&gt;Considering this it seems like the Serialize method that generated with XML should be the one complaining, but in this case the problem is reported by the Deserialize method. It throws an &lt;em&gt;InvalidOperationException&lt;/em&gt; saying it encountered an invalid character in a call to ScanHexEntity.&lt;br /&gt;&lt;br /&gt;With the help of Google I did however find a simple solution to the problem. Calling Deserialize with an XmlTextReader instead of a StringReader. Since the former has a constructor that take the latter as argument it has minimum inpact on the code too.&lt;br /&gt;&lt;br /&gt;Solution:&lt;br /&gt;    xmlSerializer.Deserialze(new XmlTextReader(sr));&lt;br /&gt;&lt;br /&gt;The reason is that this XmlTextReader contructor initiates with the Normalization property set to false, while the XmlTextReader created under the hood from other calls to Deserialize is created with the property set to true.&lt;br /&gt;&lt;br /&gt;A more sophisticated solution would be to base64 encode the string, but I'll stick with the simple solution. More than having very limited inpact and being a very quick solution it also has the benefit that old export files will work.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6005490725222948439-1394732722800522916?l=www.tommycode.se' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.tommycode.se/feeds/1394732722800522916/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6005490725222948439&amp;postID=1394732722800522916' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/1394732722800522916'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/1394732722800522916'/><link rel='alternate' type='text/html' href='http://www.tommycode.se/2008/04/deserializing-non-printable-characters.html' title='Deserializing non printable characters'/><author><name>Tommy</name><uri>http://www.blogger.com/profile/02987079709890896170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_l-LLksOg9eE/R9bjxIwpurI/AAAAAAAAAAM/24-1aJgI-VI/S220/tommy2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6005490725222948439.post-825566978321487579</id><published>2008-04-04T09:04:00.002+02:00</published><updated>2008-04-04T10:13:23.598+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='visual studio'/><title type='text'>MSBuild Error MSB3171</title><content type='html'>Converting a solution from VS2003 to VS2008 today caused me almost an hour of headache. It seems that there is some bug with changing the manifest settings in managed C++.&lt;br /&gt;&lt;br /&gt;The solution contains a number of C# projects and one Managed C++ project. I converted its debug configuration many month ago and today I was finally going to build it in release mode!&lt;br /&gt;&lt;br /&gt;One problem in the conversion was that most assemblies, including the C++ project, used the attribute &lt;em&gt;assembly:AssemblyKeyFileAttribute.&lt;/em&gt; With the new studio signing is invalidated by adding the manifesto if the key file is given with this attribute, which in turn causes a binding failure when trying to load the assembly in runtime.&lt;br /&gt;&lt;br /&gt;I remembered solving it by setting the key file in the project settings when I converted the solution in debug mode earlier. Obviously I had failed to make the change in the release configuration at that point but it should be a quick fix.&lt;br /&gt;&lt;br /&gt;At the first glance, though, I failed to find the box where it should be entered in the C++ project settings and thought I might have removed the manifesto instead. I tried setting "Embed manifesto" to "No" in &lt;em&gt;Manifest Tool\Input and Output&lt;/em&gt; and kept the key file as an attribute. This made the MSB3171 appear, so I tried to also set "Generate Manifest" to "No" in &lt;em&gt;Linker\Manifest File&lt;/em&gt;. No better. Looking for other things to change I f0und the place to add the key file in the project settings and decided to go with the initial idea.&lt;br /&gt;&lt;br /&gt;I reverted my changes regarding manifesto, but the MSB3171 problem remained. I then reverted my project files using the source control system, but the problem still remaind. Outch! I restarted Visual Studio, but the problem refused to go away.&lt;br /&gt;&lt;br /&gt;Next step was to ask Google. I found someone that had a similar experience, but I found no answer. Others trying to reproduce his problem failed and the common conclusion was that there was something wrong with his Studio.&lt;br /&gt;&lt;br /&gt;My next move did how ever solve the problem. I closed the Studio. I reverted all files I had changed this morning, and deleted all intermediate files in the solution that had been changed today. That is, all &lt;em&gt;bin&lt;/em&gt; and &lt;em&gt;obj&lt;/em&gt; directories, &lt;em&gt;.ncb&lt;/em&gt; files, &lt;em&gt;.suo&lt;/em&gt; files and all other files that the Studio generates. Now when I started the Studio again I got the same error as first thing in the morning, I then added the key file on the correct place in the settings for the Managed C++ projects Release configuration and now it all works!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6005490725222948439-825566978321487579?l=www.tommycode.se' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.tommycode.se/feeds/825566978321487579/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6005490725222948439&amp;postID=825566978321487579' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/825566978321487579'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/825566978321487579'/><link rel='alternate' type='text/html' href='http://www.tommycode.se/2008/04/msbuild-error-msb3171.html' title='MSBuild Error MSB3171'/><author><name>Tommy</name><uri>http://www.blogger.com/profile/02987079709890896170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_l-LLksOg9eE/R9bjxIwpurI/AAAAAAAAAAM/24-1aJgI-VI/S220/tommy2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6005490725222948439.post-6906293829710332183</id><published>2008-03-14T09:05:00.001+01:00</published><updated>2008-03-14T17:20:30.997+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='syntax'/><title type='text'>Never Skip Curly Brackets</title><content type='html'>In the book that I'm currently reading the author continuously skips curly brackets where they are not &lt;em&gt;needed&lt;/em&gt;. That is, in &lt;em&gt;if&lt;/em&gt;, &lt;em&gt;for&lt;/em&gt;, &lt;em&gt;while&lt;/em&gt; etc. statements controlling only one line of code. I would have thought that all experienced software developers always used the curly brackets.&lt;br /&gt;&lt;br /&gt;I can't come up with any reason not to use them, except maybe "less to type" or "less lines of code". Both reasons equally lame.&lt;br /&gt;&lt;br /&gt;How much of your programming hours are spent typing? And whats the purpose to strive for less lines of code? The purpose must be readability, and I would not agree that it is increased by not using curly brackets. Rather the opposite. If your readability problem is caused by functions having many lines it is the design that is the problem, not the brackets.&lt;br /&gt;&lt;br /&gt;Instead, not using curly brackets is very error prone.&lt;br /&gt;&lt;br /&gt;Consider that you want to add something to the code block of an &lt;em&gt;if&lt;/em&gt;-statement, now you'll need to add the curly brackets anyway. And if you fail to notice this it will cause weird errors in your program since the second line will always be executed.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;if( foo )&lt;br /&gt;  foo = false;&lt;br /&gt;  &lt;span style="color:#ff0000;"&gt;bar = true;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Or lets say that you temporarily want to remove the executed statement with a comment. Now you'll need to add the brackets, or comment the &lt;em&gt;if&lt;/em&gt;-statement too. If you don't do any of this the &lt;em&gt;if&lt;/em&gt;-statement will instead control the next line of code.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;if( foo )&lt;br /&gt;  &lt;span style="color:#ff0000;"&gt;//foo = false;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;ASSERT(!foo);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As you see from these examples you may very well be fooled by the indentation of the code.&lt;br /&gt;&lt;br /&gt;So, to all of you out there that aren't using those curly brackets unless you're forced too - start using them always!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6005490725222948439-6906293829710332183?l=www.tommycode.se' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.tommycode.se/feeds/6906293829710332183/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6005490725222948439&amp;postID=6906293829710332183' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/6906293829710332183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/6906293829710332183'/><link rel='alternate' type='text/html' href='http://www.tommycode.se/2008/03/never-skip-curly-brackets.html' title='Never Skip Curly Brackets'/><author><name>Tommy</name><uri>http://www.blogger.com/profile/02987079709890896170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_l-LLksOg9eE/R9bjxIwpurI/AAAAAAAAAAM/24-1aJgI-VI/S220/tommy2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6005490725222948439.post-5612397565963298046</id><published>2008-03-11T21:14:00.000+01:00</published><updated>2008-03-11T22:12:21.503+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ood'/><title type='text'>Solving Bob's Problem</title><content type='html'>Reading up on Liskov Substitution Principle last night finaly put me over the top to start blogging about software development. I had a copy of Robert C. Martin's article published on the Object Mentor webpage (&lt;a href="http://www.objectmentor.com/resources/articles/lsp.pdf" target="_blank"&gt;direct link&lt;/a&gt;) where he suggest that deriving Square from Rectangle violated LSP.&lt;br /&gt;&lt;br /&gt;Here is his code example:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class Rectangle {&lt;br /&gt;public:&lt;br /&gt;  virtual void SetWidth(double w) {itsWidth=w;}&lt;br /&gt;  virtual void SetHeight(double h) {itsHeight=h;}&lt;br /&gt;  double GetHeight() const {return itsHeight;}&lt;br /&gt;  double GetWidth() const {return itsWidth;}&lt;br /&gt;private:&lt;br /&gt;  double itsWidth;&lt;br /&gt;  double itsHeight;&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Sparing you the declaration of the Square class, which inherits Rectangle, here's how it differs. It overrides SetWidth and SetHeight, calling them both in the base class.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;void Square::SetWidth(double w) {&lt;br /&gt;  Rectangle::SetWidth(w);&lt;br /&gt;  Rectangle::SetHeight(w);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void Square::SetHeight(double h) {&lt;br /&gt;  Rectangle::SetHeight(h);&lt;br /&gt;  Rectangle::SetWidth(h);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This will violated LSP since a client may call SetHeight with one number and SetWidth with another and presume that GetHeight will return what ever number SetHeight was called with - which will of couse not be the case.&lt;br /&gt;&lt;br /&gt;He leaves us no solution in his article, so we're left to think that a Square never should inherit a Rectangle. I myself should in this simple case make the objects immutable. Aside from all other benefits it will also make the objects pass the LSP test.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class Rectangle&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt; Rectangle(double w, double h) {itsWidth=w; itsHeight=h;}&lt;br /&gt; double GetHeight() const {return itsHeight;}&lt;br /&gt; double GetWidth() const {return itsWidth;}&lt;br /&gt;private:&lt;br /&gt; double itsWidth;&lt;br /&gt; double itsHeight;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;class Square : public Rectangle&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt; Square(double side) : Rectangle(side, side) {}&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6005490725222948439-5612397565963298046?l=www.tommycode.se' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.tommycode.se/feeds/5612397565963298046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6005490725222948439&amp;postID=5612397565963298046' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/5612397565963298046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6005490725222948439/posts/default/5612397565963298046'/><link rel='alternate' type='text/html' href='http://www.tommycode.se/2008/03/solving-bobs-problem.html' title='Solving Bob&apos;s Problem'/><author><name>Tommy</name><uri>http://www.blogger.com/profile/02987079709890896170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_l-LLksOg9eE/R9bjxIwpurI/AAAAAAAAAAM/24-1aJgI-VI/S220/tommy2.jpg'/></author><thr:total>0</thr:total></entry></feed>
