<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CkcASXs5eSp7ImA9WxNaGE4.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558</id><updated>2009-12-03T03:47:28.521-05:00</updated><title>Chapman's Coding Corridor</title><subtitle type="html">Software development focussed technology blog revolving mostly around C#, ASP.NET and NHibernate.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://jaychapman.blogspot.com/" /><link rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>47</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/ChapmansCodingCorridor" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry gd:etag="W/&quot;DkEFRn4zcSp7ImA9WxVVFUs.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-3651484985398656711</id><published>2009-03-08T22:10:00.001-04:00</published><updated>2009-03-08T22:10:17.089-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-08T22:10:17.089-04:00</app:edited><title>YAGNI Abuse</title><content type="html">&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/You_Ain%27t_Gonna_Need_It"&gt;YAGNI&lt;/a&gt; &amp;quot;You Ain't Gonna Need It&amp;quot; is one of those principles I usually say I hate.&amp;#160; Truthfully, I suppose I don't hate the YAGNI principle, I think I typically hate when people try to pull it out in a discussion/argument.&amp;#160; I feel that sometimes people use YAGNI either as an excuse to write poor code or as an excuse for why they don't need to improve as a developer.&lt;/p&gt;  &lt;p&gt;Somewhat recently, &lt;a href="http://codebetter.com/blogs/jeremy.miller/"&gt;Jeremy Miller&lt;/a&gt; wrote a post titled &amp;quot;&lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2009/02/17/a-quick-example-of-yagni-simplest-thing-possible-in-action.aspx"&gt;A Quck Example of YAGNI / Simplest Thing Possible In Action&lt;/a&gt;&amp;quot; which completely annoyed me.&amp;#160; I think it got under my skin so much because of how highly I view Jeremy.&amp;#160; I spoke with some people after a recent &lt;a href="http://migang.org"&gt;Great Lakes Area .Net User Group&lt;/a&gt; meeting about this.&amp;#160; To be fair, after that post and after my discussions Jeremy did make a second post titled &amp;quot;&lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2009/02/20/update-on-the-yagni-episode.aspx"&gt;Update on the YAGNI Episode&lt;/a&gt;&amp;quot; where he explains that he was wrong in the prior post.&amp;#160; I probably should have written this post earlier.&lt;/p&gt;  &lt;p&gt;In Jeremy's original post he discusses an argument he had with another member of his team regarding how to build a simple web layout which included a 2x2 arrangement of panels which will hold various content.&amp;#160; Jeremy uses YAGNI to argue that this layout should be done using an HTML table with 2 rows and 2 columns.&amp;#160; It's relatively simple, it works, why try to complicate things?&amp;#160; He argued that this was the simplest thing to do which would satisfy the current requirement.&lt;/p&gt;  &lt;p&gt;To me, this shows that Jeremy is not an expert at HTML design, and was trying to use YAGNI to defend it.&amp;#160; I think there should be a new principle for Jeremy, and for others trying to use YAGNI.&amp;#160; Let's call it &amp;quot;Use What You Know&amp;quot;.&amp;#160; Maybe we could call it WYK or something like that.&amp;#160; Jeremy knows how to lay out web sites using tables.&amp;#160; If he's working on a project where he needs to lay out panels, that's probably what he should do.&amp;#160; However, in cases where someone else on the team understands a superior approach which allows more flexibility to be replaced in the future, that's what they should use.&lt;/p&gt;  &lt;p&gt;To me, YAGNI needs to be about features, not the technical approach.&amp;#160; The technical approach needs to be clean and easily replaceable.&amp;#160; This is a big reason why I'm such a big fan of the &lt;a href="http://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;Single Responsibility&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Open/closed_principle"&gt;Open-Closed&lt;/a&gt; and the &lt;a href="http://en.wikipedia.org/wiki/Inversion_of_control"&gt;Inversion of Control&lt;/a&gt; principles.&amp;#160; When used correctly these principles, not meaning to exclude many other solid principles, result in maintainable and easily replaceable code.&amp;#160; Code which follows these principles is not necessarily hard to write (sometimes it does involve some different ways of thinking), and it doesn't typically take any more time, but the benefits really pay off when you actually do &amp;quot;Need It&amp;quot; and have to change a piece of your software.&amp;#160; In cases before I have written extremely simple services which work for the current functionality only to require that they be fully replaced with more advanced functionality in the future.&amp;#160; This is fine, simply swapping out that service for the newer service was a simple switch which didn't require breaking the rest of the application.&lt;/p&gt;  &lt;p&gt;That's how YAGNI should be used.&amp;#160; Only build the functionality that you need, but leave it easy to enhance or even replace.&amp;#160; &lt;/p&gt;  &lt;p&gt;In many cases I feel that developers use arguments against Inversion of Control, or the Open-Closed principle because of YAGNI.&amp;#160; They argue you don't need that flexibility.&amp;#160; You don't need to replace your services easily.&amp;#160; It's a simple application, it works without it, why are you pushing this?&amp;#160; To me that's using YAGNI to fight continuous improvement.&amp;#160; As developers we should strive to constantly hone our craft.&amp;#160; We should always look to find ways to better do our job.&amp;#160; It's the same argument I make all the time.&amp;#160; Doing things the &amp;quot;clean&amp;quot; way is usually not more work, or more time consuming than the &amp;quot;quick and dirty&amp;quot; way.&amp;#160; However, not understanding how to do it cleanly, does result in it being significantly easier and faster to do things the &amp;quot;quick and dirty&amp;quot; way.&lt;/p&gt;  &lt;p&gt;Getting back to the &amp;quot;Use What You Know&amp;quot; point.&amp;#160; I'm not advocating that every time a problem comes up you research what the cleanest way is to do it.&amp;#160; I'm advocating that you find time to learn about new approaches to solving software development problems before you have to use it on the job.&amp;#160; The employer typically requires fast turn around on the software problems you face.&amp;#160; Deliver the solution that you know how to deliver.&amp;#160; That gives the employer or customer the solution that works the fastest and for the least cost.&amp;#160; However, if we could have spent earlier months learning new techniques and solutions, the employer could receive superior products while developers are able to enjoy working on a cleaner code base.&lt;/p&gt;  &lt;p&gt;Ideally you find employers that allow for time up front for you to lean and continuously improve.&amp;#160; That way when the problem comes you are better suited to solve it with a larger toolbox.&amp;#160; Some employers do not allow time for this, and instead developers are forced to improve on their own time.&amp;#160; Regardless, I would advocate that we all put in the extra effort to learn on our own time.&amp;#160; The ones with employers that pay for this time are lucky, but that doesn't let the rest of us off the hook.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-3651484985398656711?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=-LkcQk5SPFQ:HktAiwJ5GBA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=-LkcQk5SPFQ:HktAiwJ5GBA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=-LkcQk5SPFQ:HktAiwJ5GBA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/-LkcQk5SPFQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/3651484985398656711/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=3651484985398656711" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/3651484985398656711?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/3651484985398656711?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/-LkcQk5SPFQ/yagni-abuse.html" title="YAGNI Abuse" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2009/03/yagni-abuse.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0EGQXk6eSp7ImA9WxVVEU4.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-2921605748765243190</id><published>2009-03-03T20:53:00.001-05:00</published><updated>2009-03-03T20:53:40.711-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-03T20:53:40.711-05:00</app:edited><title>Spoke at GANG</title><content type="html">&lt;p&gt;I finally gave my talk at &lt;a href="http://migang.org"&gt;GANG&lt;/a&gt;.&amp;#160; I was originally scheduled to speak in September (&lt;a href="http://jaychapman.blogspot.com/2008/09/speaking-at-gang.html"&gt;Speaking at GANG&lt;/a&gt;), but came down with food poisoning which prevented me from talking.&amp;#160; That same talk, an Introduction to Rhino Mocks, was made last month in February.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;I really enjoyed giving the talk.&amp;#160; The crowd was great, and overall I had a good time.&amp;#160; I hope others enjoyed the talk and were able to learn about how Rhino Mocks may come in handy with their software testing needs.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;At the end of the talk I said I would post my example application online.&amp;#160; I have decided to place the file on savefile.com.&amp;#160; You will have to put up with an ad in order to download the file.&amp;#160; Download the sample &lt;a href="http://www.savefile.com/files/2025591"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;In the near future, I plan to post in detail about some parts of the application application.&amp;#160; If readers would like an explanation of any piece in particular, please leave a comment on this post.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-2921605748765243190?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=BPSe8sE2c24:hdo24QsZG2o:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=BPSe8sE2c24:hdo24QsZG2o:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=BPSe8sE2c24:hdo24QsZG2o:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/BPSe8sE2c24" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/2921605748765243190/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=2921605748765243190" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/2921605748765243190?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/2921605748765243190?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/BPSe8sE2c24/spoke-at-gang.html" title="Spoke at GANG" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2009/03/spoke-at-gang.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE8BRXc_cCp7ImA9WxRTFEk.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-8825830422733945138</id><published>2008-09-03T07:54:00.001-04:00</published><updated>2008-09-03T07:54:14.948-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-09-03T07:54:14.948-04:00</app:edited><title>Speaking At GANG</title><content type="html">&lt;p&gt;I'm going to be speaking at the &lt;a href="http://www.migang.org/home.aspx"&gt;Great Lakes Area .NET User Group&lt;/a&gt; in Southfield on September 17th.&amp;#160; I will be giving a talk about Rhino Mocks, and the how, when and why to use it.&amp;#160; &lt;/p&gt;  &lt;p&gt;I am still putting the presentation together, so if you will be in the area and would like me to cover something specific, leave a comment.&amp;#160; Even if you won't be attending, let me know if you think there are points which would be helpful for the people there.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-8825830422733945138?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=YPCEskJWAMg:sd0uIEojfts:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=YPCEskJWAMg:sd0uIEojfts:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=YPCEskJWAMg:sd0uIEojfts:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/YPCEskJWAMg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/8825830422733945138/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=8825830422733945138" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/8825830422733945138?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/8825830422733945138?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/YPCEskJWAMg/speaking-at-gang.html" title="Speaking At GANG" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2008/09/speaking-at-gang.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkYCQXYzcSp7ImA9WxdVFko.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-1061424650299196422</id><published>2008-07-21T18:06:00.002-04:00</published><updated>2008-07-21T18:09:20.889-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-07-21T18:09:20.889-04:00</app:edited><title>Why I Am Sick Of Hearing About Deferred Execution</title><content type="html">&lt;p&gt;Since the announcement of LINQ we've heard plenty about &amp;quot;deferred execution&amp;quot;, this term that has appeared like its some sort of LINQ magic feature.&amp;#160; Personally, I think I need to come up with my own term and claim it's something awesome too.&amp;#160; I'm really tired from hearing about it.&lt;/p&gt;  &lt;p&gt;On Wednesday, July 15th I went to a &lt;a href="http://www.migang.org/"&gt;Great Lakes Area .NET Users Group&lt;/a&gt; talk by &lt;a href="http://srtsolutions.com/blogs/billwagner/"&gt;Bill Wagner&lt;/a&gt; where he was talking about Extension Methods and how to make proper use of them.&amp;#160; Now, don't get me wrong, I have a lot of respect for Bill.&amp;#160; I don't mean to criticizing Bill in any way.&amp;#160; So Bill, if you read this, I really don't mean any disrespect by this.&amp;#160; It was simply your use of the term that made me recall my feelings on this topic.&lt;/p&gt;  &lt;p&gt;Bill was doing a demo where he showed various LINQ extension methods and showed that by making use of these extension methods we were able to harness the power of DFERRED EXECUTION!&amp;#160; &lt;/p&gt;  &lt;p&gt;The first example Bill showed was Enumerable.Range(Int32, Int32) where it returns an IEnumerable&amp;lt;Int32&amp;gt;.&amp;#160; Bill then shows that when he calls the Take() extension method it only iterates through the first x of the items in the range, not the full list of items identified by the range.&amp;#160; Ok yes, this is true.&amp;#160; We didn't have to create a new list and populate it with a million items, just to pull the first 5 items.&lt;/p&gt;  &lt;p&gt;Bill later went on to discuss how if you use a LINQ query with variables, you can change those variables after you have defined the query.&amp;#160; His code looked something like the following:&lt;/p&gt;  &lt;pre name="code" class="c-sharp"&gt;&lt;br /&gt;var range = Enumerable.Range(0, 1000000);&lt;br /&gt;&lt;br /&gt;var maxValue = 40;&lt;br /&gt;&lt;br /&gt;var items = from r in range&lt;br /&gt;            where r &lt; maxValue&lt;br /&gt;            select r;&lt;br /&gt;&lt;br /&gt;var takenItems = items.Take(30);&lt;br /&gt;&lt;br /&gt;maxValue = 20;&lt;br /&gt;&lt;br /&gt;foreach (var i in takenItems)&lt;br /&gt;{&lt;br /&gt;  Console.WriteLine(i);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Output:&lt;br /&gt;&lt;br /&gt;0&lt;br /&gt;1&lt;br /&gt;2&lt;br /&gt;3&lt;br /&gt;4&lt;br /&gt;5&lt;br /&gt;6&lt;br /&gt;7&lt;br /&gt;8&lt;br /&gt;9&lt;br /&gt;10&lt;br /&gt;11&lt;br /&gt;12&lt;br /&gt;13&lt;br /&gt;14&lt;br /&gt;15&lt;br /&gt;16&lt;br /&gt;17&lt;br /&gt;18&lt;br /&gt;19&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Now yes, you define your LINQ query, change your variable after the fact and then consume that class.&amp;#160; Yes, it takes into account the change in your variable.&amp;#160; Yes, this occurs after you defined your query, so deferred execution is a term that makes sense.&lt;/p&gt;&lt;p&gt;Ok, I'll give in a bit, I'm ok with the term, but not the way its talked about.&amp;#160; The magic isn't LINQ, and understanding what is going on is not just about understanding LINQ.&amp;#160; It's the fundamentals of how LINQ works which people should really understand.&lt;/p&gt;&lt;p&gt;I'm going to say this one more time before I move on &amp;quot;Deferred Execution is not a LINQ feature&amp;quot;.&amp;#160; It's a closure feature/implementation pattern.&lt;/p&gt;&lt;p&gt;First let me try to explain the implementation pattern piece by creating my own &amp;quot;Deferred Execution&amp;quot; code which works exactly the same way as as the Range method Bill demonstrated. (Note that this is not necessarily built with production quality in mind).&lt;/p&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp"&gt;&lt;br /&gt;public class MyRange : IEnumerable&lt;int&gt;&lt;br /&gt;{&lt;br /&gt;    private class RangeEnumerator : IEnumerator&lt;int&gt;&lt;br /&gt;    {&lt;br /&gt;        private int? _current;&lt;br /&gt;        private bool _complete = false;&lt;br /&gt;        private readonly int _minValue;&lt;br /&gt;        private readonly int _maxValue;&lt;br /&gt;        &lt;br /&gt;        public void Dispose()&lt;br /&gt;        {&lt;br /&gt;            &lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public bool MoveNext()&lt;br /&gt;        {&lt;br /&gt;            if (_current == null)&lt;br /&gt;            {&lt;br /&gt;                _current = _minValue;&lt;br /&gt;                return true;&lt;br /&gt;            }&lt;br /&gt;            &lt;br /&gt;            if (_current &lt; _maxValue)&lt;br /&gt;            {&lt;br /&gt;                _current += 1;&lt;br /&gt;                return true;&lt;br /&gt;            }&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;                _complete = true;&lt;br /&gt;                return false;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void Reset()&lt;br /&gt;        {&lt;br /&gt;            _current = null;&lt;br /&gt;            _complete = false;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public int Current&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                if (_current == null || _complete)&lt;br /&gt;                {&lt;br /&gt;                    throw new InvalidOperationException();&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                return _current.Value;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        object IEnumerator.Current&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                return Current;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public RangeEnumerator(int minValue, int maxValue)&lt;br /&gt;        {&lt;br /&gt;            _minValue = minValue;&lt;br /&gt;            _maxValue = maxValue;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private readonly int _from;&lt;br /&gt;    private readonly int _to;&lt;br /&gt;&lt;br /&gt;    public IEnumerator&lt;int&gt; GetEnumerator()&lt;br /&gt;    {&lt;br /&gt;        return new RangeEnumerator(_from, _to);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    IEnumerator IEnumerable.GetEnumerator()&lt;br /&gt;    {&lt;br /&gt;        return GetEnumerator();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public MyRange(int from, int to)&lt;br /&gt;    {&lt;br /&gt;        _from = from;&lt;br /&gt;        _to = to;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;That's actually really simple code isn't it?&amp;#160; There is nothing revolutionary in that code.&amp;#160; Any one of us could have implemented that in C# 1.0.&amp;#160; &lt;/p&gt;&lt;p&gt;Now, let's look at a case with closures.&amp;#160; LINQ internally is using closures (via lambda expressions) to perform its queries.&amp;#160; So lets say I write my own closure.&amp;#160;&lt;/p&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp"&gt;&lt;br /&gt;var range = new MyRange(0, 1000000);&lt;br /&gt;&lt;br /&gt;var maxValue = 40;&lt;br /&gt;&lt;br /&gt;Func&lt;int, bool&gt; expression = i =&gt; i &lt; maxValue;&lt;br /&gt;&lt;br /&gt;maxValue = 20;&lt;br /&gt;&lt;br /&gt;foreach (var i in range)&lt;br /&gt;{&lt;br /&gt;    if (!expression(i))&lt;br /&gt;    {&lt;br /&gt;        break;&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;        Console.WriteLine(i);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Output:&lt;br /&gt;&lt;br /&gt;0&lt;br /&gt;1&lt;br /&gt;2&lt;br /&gt;3&lt;br /&gt;4&lt;br /&gt;5&lt;br /&gt;6&lt;br /&gt;7&lt;br /&gt;8&lt;br /&gt;9&lt;br /&gt;10&lt;br /&gt;11&lt;br /&gt;12&lt;br /&gt;13&lt;br /&gt;14&lt;br /&gt;15&lt;br /&gt;16&lt;br /&gt;17&lt;br /&gt;18&lt;br /&gt;19&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt; Huh, wouldn't you guess it, it also shows this magical LINQ &amp;quot;deferred execution&amp;quot; behavior.&lt;/p&gt;&lt;p&gt;So what's the point of all this?&amp;#160; One, I'm probably too easily set off on topics like this.&amp;#160; Second, we shouldn't look at &amp;quot;deferred execution&amp;quot; as some sort of LINQ magic but rather a pattern that can provide us many benefits with our own code.&amp;#160; Deferred execution allows us to enhance performance and flexibility of our applications.&amp;#160; This is something we can all make use of in our algorithms, even if we aren't utilizing LINQ.&lt;/p&gt;&lt;p&gt;And in regards to the Extension method talk by Bill, I really enjoyed it.&amp;#160; It was simple enough for people to learn about new C# 3.0 features.&amp;#160; You talked about it well and gave good examples.&amp;#160; I'm just frustrated that people seem to write this stuff off as magic even though they are simple concepts.&amp;#160; Plus, this term seemingly just appeared with LINQ even though the concept has been around for a long time.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-1061424650299196422?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=k8jq9s5aXe0:P7CFSA4UPpM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=k8jq9s5aXe0:P7CFSA4UPpM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=k8jq9s5aXe0:P7CFSA4UPpM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/k8jq9s5aXe0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/1061424650299196422/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=1061424650299196422" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/1061424650299196422?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/1061424650299196422?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/k8jq9s5aXe0/why-i-am-sick-of-hearing-about-deferred.html" title="Why I Am Sick Of Hearing About Deferred Execution" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2008/07/why-i-am-sick-of-hearing-about-deferred.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0IGRXozfyp7ImA9WxdWGEo.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-8570036988540915180</id><published>2008-07-12T10:05:00.001-04:00</published><updated>2008-07-12T10:05:24.487-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-07-12T10:05:24.487-04:00</app:edited><title>Subtle Bugs When Dealing With Threads</title><content type="html">&lt;p&gt;Pop quiz, what's wrong with the following code?&lt;/p&gt;  &lt;pre name="code" class="c-sharp"&gt;&lt;br /&gt;public void Unsubscribe()&lt;br /&gt;{&lt;br /&gt;	if (_request != null)&lt;br /&gt;	{&lt;br /&gt;		ThreadPool.Enqueue(() =&amp;gt; _service.Unsubscribe(_request));&lt;br /&gt;	}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void Subscribe(string key)&lt;br /&gt;{&lt;br /&gt;	Unsubscribe();&lt;br /&gt;&lt;br /&gt;	if (!String.IsNullOrEmpty(key))&lt;br /&gt;	{&lt;br /&gt;		_request = new Request(key, handler);&lt;br /&gt;		ThreadPool.Enqueue(() =&amp;gt; _service.Subscribe(_request));&lt;br /&gt;	}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Does everyone see the issue?  There is a critical bug in the above code which isn't always readily apparent.  &lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Try to find it...&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;I actually wrote code like this today (same concept, different implementation) and immediately saw some serious defects.  Honestly, I'm lucky the issues popped up right away, these sorts of things tend to not appear right away, but jump up to bite you at a later point.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;In this case the issue is the use of closures.  When using a closure it copies the fields from outside the lambda expression into the expression meaning that my use of _request from within the lambda is actually the same reference that exists outside the lambda expression.  So in the above case the Unsubscribe lambda gets executed on a new thread (from the pool) but by the time it actually executes the _request has already been changed.  &lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;In this case, you're actually unsubscribing from a request that most likely hasn't even been subscribed yet.  And to top it off you haven't unsubscribed from the old request yet either.  Obviously the above is a race condition where the exact output isn't guaranteed.  There is a chance it works perfectly (though doubtful with a true thread pool).  There is a chance the new request is subscribed first and then immediately unsubscribed as well.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;The simplest way to resolve this issue is by changing the variable which is captured from one which is shared between both closures to one that is unique to each closure.  As shown here:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp"&gt;public void Unsubscribe()&lt;br /&gt;{&lt;br /&gt;	if (_request != null)&lt;br /&gt;	{&lt;br /&gt;		var localRequest = _request;&lt;br /&gt;		ThreadPool.Enqueue(() =&amp;gt; _service.Unsubscribe(localRequest));&lt;br /&gt;	}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void Subscribe(string key)&lt;br /&gt;{&lt;br /&gt;	Unsubscribe();&lt;br /&gt;&lt;br /&gt;	if (!String.IsNullOrEmpty(key))&lt;br /&gt;	{&lt;br /&gt;		_request = new Request(key, handler);&lt;br /&gt;		var localRequest =_request;&lt;br /&gt;		ThreadPool.Enqueue(() =&amp;gt; _service.Subscribe(localRequest));&lt;br /&gt;	}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;However, what I really want to solve this type of problem going forward is to develop something which is process aware, much like the Saga in &lt;a href="http://www.nservicebus.com/"&gt;NServiceBus&lt;/a&gt;.  Of course my goal is not to be a long running, persistable process like the Saga in &lt;a href="http://www.nservicebus.com/"&gt;NServiceBus&lt;/a&gt;, but the process portion is what I'm looking at.&lt;br /&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-8570036988540915180?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=guc2GmmYpVQ:N1YB73Ueuxs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=guc2GmmYpVQ:N1YB73Ueuxs:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=guc2GmmYpVQ:N1YB73Ueuxs:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/guc2GmmYpVQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/8570036988540915180/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=8570036988540915180" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/8570036988540915180?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/8570036988540915180?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/guc2GmmYpVQ/subtle-bugs-when-dealing-with-threads.html" title="Subtle Bugs When Dealing With Threads" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2008/07/subtle-bugs-when-dealing-with-threads.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUEBRXc_fCp7ImA9WxdQGE4.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-1276917647406184282</id><published>2008-06-18T21:07:00.001-04:00</published><updated>2008-06-18T21:07:34.944-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-06-18T21:07:34.944-04:00</app:edited><title>StackOverflow.com, Uh oh?</title><content type="html">&lt;p&gt;So I mentioned in my last post that I have began listening to podcasts.&amp;#160; I have a lot of respect for both Jeff Atwood (&lt;a href="http://www.codinghorror.com/blog/"&gt;Coding Horror&lt;/a&gt;) and &lt;a href="http://www.joelonsoftware.com/"&gt;Joel Spoelsky&lt;/a&gt;.&amp;#160; So when I saw they were working together on a new project and publishing their conversations regarding their new product, I figured I had to listen.&amp;#160; Now, they've posted around 9 episodes now, but I've only had a chance to listen to the first couple so far.&lt;/p&gt;  &lt;p&gt;Honestly, I'm a bit concerned by what I heard.&amp;#160; In their first episode I felt like they gave Microsoft technology based developers a really bad name.&amp;#160; Now it may well be largely true (which is probably part of my concern), but I wish there were more resources to correct this bad name, rather than encouraging it.&lt;/p&gt;  &lt;p&gt;Basically, during the podcast you will hear something along the lines that Microsoft technology developers basically resort to the Google-Copy &amp;amp; Paste programming development.&amp;#160; Microsoft technology developers are called pragmatic in that they don't care what the right solution is, or how clean it is, or well it works so long as it does work.&amp;#160; &lt;/p&gt;  &lt;p&gt;Now, I'm not saying that using google to find answers to interesting problems is a bad thing.&amp;#160; I'm not even saying that if you ever copy and paste code you're a bad developer, but ideally the developer is learning from the blog post instead of just finding something which seems to work and moves about their business.&amp;#160; Honestly, typically these samples you find in blog posts are not thorough enough for a true production deployment.&amp;#160; The point of these postings should be to educate people about new concepts, not try to do their job for them.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://stackoverflow.com/"&gt;Stackoverflow.com&lt;/a&gt; from what I gathered wants to be the place to replace google as the first place where you search for doing your job.&amp;#160; Now they stated their goal is to be the first hit on google for all of your searches, but really I think they would be happier if you went straight there instead of google.&lt;/p&gt;  &lt;p&gt;Now Stackoverflow is not Microsoft specific, it is meant to appeal to developers on all platforms.&amp;#160; However, they seem to be looking at the Microsoft centric market as their main target.&amp;#160; Honestly, I think these guys will be successful.&amp;#160; They both have large followings, and I think there is huge demand for systems that can essentially do their jobs for them.&amp;#160; I just wish it appeared to be a more helpful resource that helped developers grow, instead of just allowing them to get by.&lt;/p&gt;  &lt;p&gt;This all being said, the podcast is worth checking out.&amp;#160; These are two extremely intelligent people, and by listening to these podcasts you essentially get a look inside their heads and how they think.&amp;#160; I don't have to agree with Stackoverflow.com, or the topic which they discuss, I'm still able to learn from it while I listen.&amp;#160; To both Joel and Jeff, thank you for posting your phone conversations as podcasts, it has been a great learning experience for me.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-1276917647406184282?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=Hqb_j3_5yEI:oqlAt7NtEt4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=Hqb_j3_5yEI:oqlAt7NtEt4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=Hqb_j3_5yEI:oqlAt7NtEt4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/Hqb_j3_5yEI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/1276917647406184282/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=1276917647406184282" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/1276917647406184282?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/1276917647406184282?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/Hqb_j3_5yEI/stackoverflowcom-uh-oh.html" title="StackOverflow.com, Uh oh?" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2008/06/stackoverflowcom-uh-oh.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUUBRHkzcCp7ImA9WxdQGE4.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-2522404133266602005</id><published>2008-06-18T21:00:00.001-04:00</published><updated>2008-06-18T21:00:55.788-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-06-18T21:00:55.788-04:00</app:edited><title>Deep Fried Goodness</title><content type="html">&lt;p&gt;So I realize I'm going to look like a bit of a sellout based on my procrastinating, but I really meant to write this earlier.&amp;#160; With my newly purchased iPhone and my increased amount of travel, I've recently started listening to Podcasts.&amp;#160; I honestly never saw the point before.&amp;#160; I rarely get an hour where I can really listen to a podcast.&amp;#160; I have always thought of reading as being a simpler and more effective mechanism for learning.&amp;#160; However, while traveling (especially on a plane) I find that a properly timed podcast can provide a lot of information that otherwise I wouldn't be able to consume.&lt;/p&gt;  &lt;p&gt;I saw that &lt;a href="http://keithelder.net/blog/"&gt;Keith Elder&lt;/a&gt; (and &lt;a href="http://blog.cloudsocket.com/"&gt;Chris Woodruff&lt;/a&gt;) had a new podcast called &lt;a href="http://deepfriedbytes.com/"&gt;Deep Fried Bytes&lt;/a&gt;, and I figured I may as well see what it is.&amp;#160; I'm actually one of those people that first met Keith because I recognized his picture from his blog.&amp;#160; Not knowing really what was good for pocasts (besides the obligatory &lt;a href="http://www.hanselminutes.com/"&gt;Hanselminutes&lt;/a&gt; and &lt;a href="http://www.dotnetrocks.com/"&gt;DNR&lt;/a&gt;) I figured it was worth a shot.&lt;/p&gt;  &lt;p&gt;After listening to their episode on interview war stories I was really impressed.&amp;#160; They had some really intelligent people talking about interviewing.&amp;#160; This was a topic, which I have to admit, was not something that immediately peaked my interest.&amp;#160; But what you find is that when many smart people sit down to have a talk, something good will result.&amp;#160; Now, after I picked myself up off the floor from hearing a C# MVP call the using keyword &amp;quot;Obsolete&amp;quot;, I realized that they have a winning format.&lt;/p&gt;  &lt;p&gt;Plus honestly, Keith Elder is the kind of guy where he doesn't need to have anything good to say.&amp;#160; The way he talks and presents himself can be entertaining almost regardless of the topic.&amp;#160; If you listen to podcasts I recommend you go try these guys out.&amp;#160; If you don't listen to podcasts, I recommend giving them a shot anyway.&lt;/p&gt;  &lt;p&gt;As for my contribution to the topic at hand, I suppose I had a little bit of a war story.&amp;#160; From an interviewing side I do remember talking to one guy who's resume really looked great.&amp;#160; He had all sorts of great items written down from projects he had worked on in the past.&amp;#160; While inquiring about these items it became more and more clear that this person really didn't understand the concepts which he had written he had previously implemented.&amp;#160; After a few questions trying to get this candidate to talk about items on his blog he eventually answered that he had nothing to do with those tasks.&amp;#160; They were all completed by other people and he didn't understand how they worked.&amp;#160; He then apologized for writing misleading (or factually incorrect) items on his resume, and we ended the interview.&lt;/p&gt;  &lt;p&gt;As an interviewee.&amp;#160; I just remember the Microsoft interview I had.&amp;#160; When I was graduating from Case Western Reserve University I had an on-campus interview with a representative from Microsoft.&amp;#160; I wanted to be a programmer since I was a small child (maybe 12 or 13 years old) and working for Microsoft was always a dream for me.&amp;#160; I had seen their campus (my family lived in Portland, OR at the time, and we saw their campus while visiting the Seattle area), and everything seemed like the perfect opportunity for a young geek in love with software.&amp;#160; From my interview, I really only remember a single technical question which I was asked.&amp;#160; Now keep in mind I wasn't claiming to be an expert at C or any other language at the time.&amp;#160; I had some professional experience working in VB.NET Beta, as well as some experience in developing relatively simple applications in C, C++, Java, PHP, Basic, Perl and the early versions of C#.&lt;/p&gt;  &lt;p&gt;Anyways, he asked me &amp;quot;What is the fastest way to reverse a string in C?&amp;quot;.&amp;#160; Ok, well I am familiar with C, and I'm familiar with how strings work in C.&amp;#160; I understand pointers, and pointer arithmetic, and immediately I think this must be pointer arithmetic.&amp;#160; Well, before I could even start talking about my response he says &amp;quot;Ohh, and it doesn't use pointer arithmetic.&amp;quot;.&amp;#160; Uh ohh, at that point I pretty much froze.&amp;#160; I didn't know what to do.&amp;#160; I'm not a C expert.&amp;#160; I haven't written any C code in a while, let alone overly complex C code, and I need to know what the fastest way to reverse a string is in that language?&amp;#160; Well, lets just say the rest of that apparently didn't go over so well, and I wasn't asked any other technical questions.&amp;#160; I probably didn't handle the curve ball so well, but that was that.&lt;/p&gt;  &lt;p&gt;I still remember how dumb I felt when I later learned just how many people from one of my classes landed jobs at Microsoft.&amp;#160; While in a class my senior year I remember the professor asking who was going to work for Microsoft, and there must have been at least 30 hands in the room that went up.&amp;#160; The said part of it to me too was I WAS the curve buster in that class.&amp;#160; I remember taking a test where the curve was so bad that a 68 became an A, yet I had scored a 98.&amp;#160; I was trying to figure out where I went wrong at that point.&amp;#160; Oh well, that's just how it goes.&lt;/p&gt;  &lt;p&gt;Well, enough about me and my interviewing war stories, you need to go have a listen to Deep Fried Bytes.&lt;/p&gt;  &lt;p&gt;--John Chapman&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-2522404133266602005?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=H9KrO1Ej9B4:Ji0JWK_juKU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=H9KrO1Ej9B4:Ji0JWK_juKU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=H9KrO1Ej9B4:Ji0JWK_juKU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/H9KrO1Ej9B4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/2522404133266602005/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=2522404133266602005" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/2522404133266602005?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/2522404133266602005?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/H9KrO1Ej9B4/deep-fried-goodness.html" title="Deep Fried Goodness" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2008/06/deep-fried-goodness.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUMESH89fyp7ImA9WxdREUg.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-8147784209090884858</id><published>2008-05-30T09:16:00.001-04:00</published><updated>2008-05-30T09:16:49.167-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-30T09:16:49.167-04:00</app:edited><title>Been Gone</title><content type="html">&lt;p&gt;I just wanted to make a post so people knew I was still alive.&amp;#160; I've been extremely busy over the past two months.&amp;#160; I haven't forgotten about this blog, and I really want to get back to writing.&amp;#160; I really want to get further on the Sudoku series.&lt;/p&gt;  &lt;p&gt;Lately I've been focusing on architecture of a Model-View-Presenter based WPF application.&amp;#160; The current complexities which are being analyzed is that users will have many duplicate views open at the same time, each working on a different item.&amp;#160; So picture 40 or more edit windows open on the same time, some for different items, some for the same items.&amp;#160; Some have similar child widgets, some have different child widgets.&amp;#160; Screens still need to talk to each other, but they have to talk to the appropriate screen.&amp;#160; Oh, and btw, performance is absolutely crucial on this app.&amp;#160; &lt;/p&gt;  &lt;p&gt;The standard Model-View-Presenter samples you see really don't address these issues.&amp;#160; Typically there is one main form which acts as a shell, and there is one region where a given view can live.&amp;#160; Not here, that view can be in any number of places, and there can be any number of them.&amp;#160; It makes the problem a bit more complex.&amp;#160; We have some solutions, but I can't really discuss them here.&lt;/p&gt;  &lt;p&gt;But after looking at the standard Model-View-Presenter samples, it make me feel more strongly that I really need to find the time to get back to the sudoku series, and hopefully I can produce a well documented series about why each choice is made.&lt;/p&gt;  &lt;p&gt;Sorry for the delay.&amp;#160; I will be back.&lt;/p&gt;  &lt;p&gt;--John Chapman&amp;#160; &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-8147784209090884858?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=bSV2S0Lu47M:McK7CRKp_V4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=bSV2S0Lu47M:McK7CRKp_V4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=bSV2S0Lu47M:McK7CRKp_V4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/bSV2S0Lu47M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/8147784209090884858/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=8147784209090884858" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/8147784209090884858?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/8147784209090884858?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/bSV2S0Lu47M/been-gone.html" title="Been Gone" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2008/05/been-gone.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU4ESXs5fyp7ImA9WxZUEk8.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-509287290696466459</id><published>2008-04-03T07:58:00.001-04:00</published><updated>2008-04-03T07:58:28.527-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-04-03T07:58:28.527-04:00</app:edited><title>New Adventures</title><content type="html">&lt;p&gt;I was originally going to write this on Tuesday, but I realized that with it being April 1st, people may have thought I was joking.&amp;#160; I have decided to leave Ryder.&amp;#160; Tomorrow, Friday April 4th will be my last day.&lt;/p&gt;  &lt;p&gt;I have found an opportunity to work as an independent contractor building an application dealing with a domain that I am very passionate about.&amp;#160; I can honestly say that the application I'll be working on is one that I would love to use myself.&amp;#160; How often do we get to say things like that as developers?&amp;#160; I figured this was an opportunity I had to take.&lt;/p&gt;  &lt;p&gt;Ryder has served me very well.&amp;#160; I first started at Ryder at the end of 2004.&amp;#160; I've had the chance to work with some great people.&amp;#160; I've also had the chance to interact with people of all levels in the company.&amp;#160; There were people at Ryder that took good care of me, helping obtain 24&amp;quot; monitors (to replace 17&amp;quot; CRTs for most people) to increase productivity as well as state of the art development machines.&amp;#160; I'll miss working with them.&lt;/p&gt;  &lt;p&gt;I worked on the LMS team at Ryder, which is probably the largest externally facing application at Ryder (don't quote me on that).&amp;#160; I do know that they are backfilling my position, so if you are looking for a new adventure yourself, send them your resume.&lt;/p&gt;  &lt;p&gt;--John Chapman&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-509287290696466459?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=igrQ96KMfyQ:rZ-rtEXCxlc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=igrQ96KMfyQ:rZ-rtEXCxlc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=igrQ96KMfyQ:rZ-rtEXCxlc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/igrQ96KMfyQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/509287290696466459/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=509287290696466459" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/509287290696466459?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/509287290696466459?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/igrQ96KMfyQ/new-adventures.html" title="New Adventures" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2008/04/new-adventures.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU4AR3k-fyp7ImA9WxZVEkw.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-7354005427593022485</id><published>2008-03-15T18:15:00.002-04:00</published><updated>2008-03-22T16:32:26.757-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-22T16:32:26.757-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="WPF" /><category scheme="http://www.blogger.com/atom/ns#" term="Sudoku" /><category scheme="http://www.blogger.com/atom/ns#" term="Castle Project" /><category scheme="http://www.blogger.com/atom/ns#" term="Behavior-Driven Development" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><title>Sudoku Part 5: A Look At The UI Architecture</title><content type="html">&lt;p&gt;Part 5 has been a long time coming.&amp;#160; Originally, the plan was to present an entire UI in this post, which I've come to realize is simply not feasible.&amp;#160; &lt;/p&gt;  &lt;p&gt;I have been attempting to learn WPF as part of this exercise.&amp;#160; Learning an entirely new UI framework while putting together this piece has proven a little bit difficult, and as a result the progress of the application has slowed significantly.&amp;#160; So for the rest of these pieces, I'll try to break down the UI further to show the choices I make while it's being developed and why.&lt;/p&gt;  &lt;p&gt;Today, we're going to take a look at the architecture I plan to use for the WPF sudoku game and why.&amp;#160; We're going to take a look at my simple implementation of MVP (&lt;a href="http://martinfowler.com/eaaDev/ModelViewPresenter.html"&gt;Model-View-Presenter&lt;/a&gt;).&amp;#160; We're going to take a look at the advantages of a MVP architecture and how that fits with our goal of utilizing Behavior Driven Development to build our application.&lt;/p&gt;  &lt;h2&gt;Architecture Description&lt;/h2&gt;  &lt;p&gt;In Part 1 (&lt;a href="http://jaychapman.blogspot.com/2008/01/sudoku-part-1-defining-solver-behavior.html"&gt;Defining The Solver Behavior&lt;/a&gt;) I mentioned that we would be using &lt;a href="http://www.castleproject.org/container/index.html"&gt;Castle Windsor&lt;/a&gt; in this project.&amp;#160; One of the great things about Windsor, and really any good &lt;a href="http://martinfowler.com/articles/injection.html"&gt;inversion of control&lt;/a&gt; framework, is that you can minimize the invasion of container logic in your code via nested dependency injection.&amp;#160; What I mean by this, is that you can use the container to resolve a single service and it will automatically populate all dependencies for all children.&amp;#160; From our perspective, this will mean that the container logic can be restricted to just the UI, resulting in one less dependency throughout the application.&lt;/p&gt;  &lt;p&gt;From previous parts we never made explicit use of Windsor, but rather we defined our inner dependencies via our available constructors.&amp;#160; For example, our RecursiveGenerator that we built in &lt;a href="http://jaychapman.blogspot.com/2008/02/sudoku-part-4-implementing-generator.html"&gt;Part 4&lt;/a&gt; took an ISolver in the constructor which will instruct Windsor to automatically populate the appropriate implementation for our generator.&amp;#160; This process is known as &lt;a href="http://martinfowler.com/articles/injection.html#ConstructorInjectionWithPicocontainer"&gt;Constructor Injection&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;I mentioned that we'll be using a Model-View-Presenter based architecture for our Sudoku game.&amp;#160; The Model-View-Presenter obviously breaks down to three pieces.&amp;#160; There are many variations of the MVP pattern (See Jeremy Miller's &lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2007/07/25/the-build-your-own-cab-series-table-of-contents.aspx"&gt;Build your own CAB series&lt;/a&gt; for some awesome overviews of various techniques), but the way we will use it for our purposes can be described as follows:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;strong&gt;View&lt;/strong&gt; - The portion of the application that actually displays data to the user as well as listens for user input.&amp;#160; Such as watching for button presses or mouse movement.&amp;#160; For this application we will be using WPF for the view. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Presenter&lt;/strong&gt; - Handles the UI behavior logic.&amp;#160; For example the view will show the data to the user, but the presenter will determine what data should be shown to the user and how it should be formatted.&amp;#160; Also, while the view listens to see if a mouse moves, or a button is clicked, how that action is handled belongs to the presenter.&amp;#160; So it would be possible for our game to have many &amp;quot;New Game&amp;quot; buttons on the view, but it would defer the appropriate actions to the presenter to determine what should happen when any of those buttons are pressed. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Model&lt;/strong&gt; - Handles the data which the presenter operates on.&amp;#160; This would typically represent the description of the business domain which is being solved by our application.&amp;#160; In our case this will represent the data needed to track the game which is being played, such as the puzzle which is being worked on, the current status of the solution which the user is building as well as supporting information such as the game clock or at least the time when the game was started. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;So, why go through all of this?&amp;#160; Especially for an application which seems as simple as a sudoku game?&amp;#160; Well, first of all, we are doing this as an exercise, not necessarily the exact application.&amp;#160; Secondly, and far more importantly, this separation of concerns allows us to keep logic more closely aligned to a purpose, and allows us to have fully testable behavior.&amp;#160; By moving our presentation behavior from the XAML &amp;quot;code-behind&amp;quot; to a separate presenter object, we can test our presentation without the need for an actual UI.&amp;#160; This is a major advantage over the old fashioned applications.&amp;#160; We can now have a lot more faith that our application behaves as expected via our automated testing.&lt;/p&gt;  &lt;p&gt;Additionally, MVP does not force us to be tied to the WPF view.&amp;#160; It would be possible for us to re-use the same model and presenter in a WinForms application (or potentially silverlight and other web-based frameworks) with no change, only a different view.&amp;#160; This will be considered out of scope for the time being.&amp;#160; &lt;/p&gt;  &lt;h2&gt;WPF Implementation&lt;/h2&gt;  &lt;p&gt;First off, I want to make a disclaimer. I am not a WPF expert.&amp;#160; If there is a better way to implement this in WPF, I would love to hear about it.&amp;#160; I'm learning WPF as I go with this sample application.&lt;/p&gt;  &lt;p&gt;My first idea was to create a base class which would initialize the appropriate presenter for that view.&amp;#160; I quickly ran into a bit of a problem with WPF.&amp;#160; It's valid to create your own base class instead of Window, but it adds a lot of complexity to the XAML, and Visual Studio didn't seem to appreciate it too much.&amp;#160; &lt;/p&gt;  &lt;p&gt;Since I only needed the base class to resolve the appropriate presenter via my container, I figured it would be ok to just have the convention of every view calling a static Initialize method.&amp;#160; This keeps the XAML simple, and only adds one extra line of code to all views.&lt;/p&gt;  &lt;h3&gt;Application Implementation&lt;/h3&gt;  &lt;p&gt;I chose to initialize Windsor in the Application class, which is where the static Initialize also lives.&amp;#160; The Application class looks like the following:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span class="keyword"&gt;public partial class&lt;/span&gt; &lt;span class="type"&gt;App&lt;/span&gt; : &lt;span class="type"&gt;Application&lt;/span&gt;, &lt;span class="type"&gt;IContainerAccessor&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt; &lt;span class="keyword"&gt;public static&lt;/span&gt; &lt;span class="type"&gt;IWindsorContainer&lt;/span&gt; Container { &lt;span class="keyword"&gt;get&lt;/span&gt;; &lt;span class="keyword"&gt;private set&lt;/span&gt;; }&lt;br /&gt; &lt;br /&gt; &lt;span class="type"&gt;IWindsorContainer IContainerAccessor&lt;/span&gt;.Container&lt;br /&gt; {&lt;br /&gt;  &lt;span class="keyword"&gt;get&lt;/span&gt;&lt;br /&gt;  {&lt;br /&gt;   return Container;&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;&lt;br /&gt; &lt;span class="keyword"&gt;protected override void&lt;/span&gt; OnStartup(&lt;span class="type"&gt;StartupEventArgs&lt;/span&gt; e)&lt;br /&gt; {&lt;br /&gt;  InitializeContainer();&lt;br /&gt;  &lt;span class="keyword"&gt;base&lt;/span&gt;.OnStartup(e);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; &lt;span class="keyword"&gt;private void&lt;/span&gt; InitializeContainer()&lt;br /&gt; {&lt;br /&gt;  Container = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;WindsorContainer&lt;/span&gt;(&lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;XmlInterpreter&lt;/span&gt;());&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; &lt;span class="keyword"&gt;public static void&lt;/span&gt; InitializePresenter&amp;lt;T&amp;gt;(T view)&lt;br /&gt; {&lt;br /&gt;  &lt;span class="type"&gt;Presenter&lt;/span&gt;&amp;lt;T&amp;gt; presenter = Container.Resolve&amp;lt;&lt;span class="type"&gt;Presenter&lt;/span&gt;&amp;lt;T&amp;gt;&amp;gt;();&lt;br /&gt;  presenter.Wireup(view);&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Note that this is as far as our container needs to go into our sudoku application.&amp;#160; When the application first starts we need to initialize our container based on the application configuration file.&amp;#160; The InitializePresenter method is what we expect every view to call when the view is initialized.&amp;#160; The type paramter (T) is the interface type which the view itself implements.&amp;#160; That is the view that the appropriate presenter will use in order to interact with the view.&amp;#160; The Presenter&amp;lt;T&amp;gt; will server as the abstract base class for all presenters.&amp;#160; So in this case we're asking Windsor to locate and instantiate the appropriate presentation logic for our particular view.&amp;#160; Once the presenter is located we call the base class method Wireup which tells the presenter to begin observing any events exposed by the view.&amp;#160; This would also be the time that the presenter could perform any initialization logic.&amp;#160; The Presenter base class looks like the following:&lt;/p&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span class="keyword"&gt;public abstract class&lt;/span&gt; &lt;span class="type"&gt;Presenter&lt;/span&gt;&amp;lt;T&amp;gt;&lt;br /&gt;{&lt;br /&gt; &lt;span class="keyword"&gt;public&lt;/span&gt; T View { &lt;span class="keyword"&gt;get&lt;/span&gt;; &lt;span class="keyword"&gt;private set&lt;/span&gt;; }&lt;br /&gt;&lt;br /&gt; &lt;span class="keyword"&gt;public void&lt;/span&gt; Wireup(T view)&lt;br /&gt; {&lt;br /&gt;  View = view;&lt;br /&gt;  Initialize();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; &lt;span class="keyword"&gt;protected abstract void&lt;/span&gt; Initialize();&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The View implementation would then contain the following:&lt;/p&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span class="keyword"&gt;protected override void&lt;/span&gt; OnInitialized(&lt;span class="type"&gt;EventArgs&lt;/span&gt; e)&lt;br /&gt;{&lt;br /&gt; &lt;span class="keyword"&gt;base&lt;/span&gt;.OnInitialized(e);&lt;br /&gt; &lt;span class="type"&gt;App&lt;/span&gt;.InitializePresenter&amp;lt;&lt;span class="type"&gt;IBoardView&lt;/span&gt;&amp;gt;(&lt;span class="keyword"&gt;this&lt;/span&gt;);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Where obviously in this case the view implements the IBoardView interface.&amp;#160; Our appropriate presenter implementation would be defined as:&lt;/p&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span class="keyword"&gt;public class&lt;/span&gt; &lt;span class="type"&gt;BoardPresenter&lt;/span&gt; : &lt;span class="type"&gt;Presenter&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;IBoardView&lt;/span&gt;&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;To wrap up our initial implementation we would need to configure our Windsor Container in our configuration file as follows:&lt;/p&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;configuration&amp;gt;&lt;br /&gt;  &amp;lt;configSections&amp;gt;&lt;br /&gt;    &amp;lt;section name=&amp;quot;castle&amp;quot;&lt;br /&gt;        type=&amp;quot;Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor&amp;quot; /&amp;gt;&lt;br /&gt;  &amp;lt;/configSections&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;castle&amp;gt;&lt;br /&gt;    &amp;lt;components&amp;gt;&lt;br /&gt;      &amp;lt;component &lt;br /&gt;        id=&amp;quot;generator&amp;quot; &lt;br /&gt;        service=&amp;quot;Sudoku.Bll.Generator.IGenerator, Sudoku.Bll&amp;quot; &lt;br /&gt;        type=&amp;quot;Sudoku.Bll.Generator.RecursiveGenerator, Sudoku.Bll&amp;quot; /&amp;gt;&lt;br /&gt;      &amp;lt;component &lt;br /&gt;        id=&amp;quot;solver&amp;quot; &lt;br /&gt;        service=&amp;quot;Sudoku.Bll.Solver.ISolver, Sudoku.Bll&amp;quot; &lt;br /&gt;        type=&amp;quot;Sudoku.Bll.Solver.RecursiveSolver, Sudoku.Bll&amp;quot; /&amp;gt;&lt;br /&gt;      &amp;lt;component &lt;br /&gt;        id=&amp;quot;boardpresenter&amp;quot;&lt;br /&gt;        lifestyle=&amp;quot;transient&amp;quot; &lt;br /&gt;        service=&amp;quot;Sudoku.UI.Presenter`1[[Sudoku.UI.Views.IBoardView, Sudoku.UI]], Sudoku.UI&amp;quot; &lt;br /&gt;        type=&amp;quot;Sudoku.UI.Presenters.BoardPresenter, Sudoku.UI&amp;quot; /&amp;gt;&lt;br /&gt;    &amp;lt;/components&amp;gt;&lt;br /&gt;  &amp;lt;/castle&amp;gt;&lt;br /&gt;&amp;lt;/configuration&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;In this case our presenter would have an IGenerator parameter in its constructor which would tell Windsor to construct the defined generator, which we've already seen requires a solver implementation.&amp;#160; Therefore these three specific components are necessary to fully configure our Windsor container for this example.&amp;#160; One item to note is that we have specified a lifestyle of transient for our presenter.&amp;#160; This is to signify that every presenter should have its own containing class (since the state of the associated model will matter), whereas our generator and solver services have no defined state and can safely be use the default lifestyle of singleton.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;At this point we have the basics defined for a Model-View-Presenter application in WPF.&amp;#160; We are using Castle Windsor to manage our dependencies.&amp;#160; Our View has no knowledge of our presenter implementation, and the presenter has no knowledge of our view implementation.&amp;#160; All aspects are configurable and easily changeable.&amp;#160; Plus, since our presenter does not know our view implementation it has opened the door to potential porting to an alternative UI framework.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;In the next iteration I hope to examine the needed behavior of our presenter and potentially the implementations which satisfy that behavior.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;--John Chapman&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-7354005427593022485?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=pHXimqq8HN4:vIqg7j-JV1g:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=pHXimqq8HN4:vIqg7j-JV1g:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=pHXimqq8HN4:vIqg7j-JV1g:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/pHXimqq8HN4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/7354005427593022485/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=7354005427593022485" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/7354005427593022485?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/7354005427593022485?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/pHXimqq8HN4/sudoku-part-5-look-at-ui-architecture.html" title="Sudoku Part 5: A Look At The UI Architecture" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2008/03/sudoku-part-5-look-at-ui-architecture.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUDQXcyeip7ImA9WxRaEUk.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-2628755046464497627</id><published>2008-02-03T08:08:00.000-05:00</published><updated>2008-12-12T22:51:10.992-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-12T22:51:10.992-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Sudoku" /><category scheme="http://www.blogger.com/atom/ns#" term="Behavior-Driven Development" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><title>Sudoku Part 4: Implementing A Generator</title><content type="html">&lt;div style="border: 1px dashed rgb(51, 51, 51); background: rgb(221, 221, 221) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;&lt;ul style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2007/12/sudoku-part-0-introduction.html"&gt;Sudoku Part 0&lt;/a&gt;: Introduction&lt;/li&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2008/01/sudoku-part-1-defining-solver-behavior.html"&gt;Sudoku Part 1&lt;/a&gt;: Defining The Solver Behavior&lt;/li&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2008/01/sudoku-part-2-implementing-solver.html"&gt;Sudoku Part 2&lt;/a&gt;: Implementing A Solver&lt;/li&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2008/01/sudoku-part-3-defining-generator.html"&gt;Sudoku Part 3&lt;/a&gt;: Defining The Generator Behavior&lt;/li&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2008/02/sudoku-part-4-implementing-generator.html"&gt;Sudoku Part 4&lt;/a&gt;: Implementing A Generator&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;br /&gt;In our last segment (&lt;a href="http://jaychapman.blogspot.com/2008/01/sudoku-part-3-defining-generator.html"&gt;Defining The Generator Behavior&lt;/a&gt;) we looked at the specifications required to  generate new Sudoku puzzles.  It turned out that from a specification standpoint, there were not many expectations that we placed on the generator.  We basically just want a solvable sudoku puzzle.  We didn't much care how it worked, or what the puzzle looked like, so long as the result was uniquely solvable.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Algorithm&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Today, we're going to create our very first sudoku solver using a similar technique as the one we used to actually solve the puzzle.  We're going to develop what I call the  &lt;span style="font-weight: bold;"&gt;RecursiveGenerator&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;In order to generate our puzzle, we'll first fill all board pieces with a valid sudoku value.  While we're filling in each piece we'll ensure that we never create an invalid board.  Meaning that at no time will we have a board with duplicate row values, column values or region values.  We'll utilize a recursive algorithm very similar to the &lt;span style="font-weight: bold;"&gt;RecurisveSolver&lt;/span&gt; we developed previously.&lt;br /&gt;&lt;br /&gt;Now that we have a fully populated sudoku board with no duplicate row, column or region values, we'll start removing values from random pieces.  In order to do this we'll create a list of all pieces on the board and then assign a random double value to them and sort the list.  We'll iterate over the list removing that piece's value from our board until our &lt;span style="font-weight: bold;"&gt;ISolver&lt;/span&gt; implementation reports that our board is an invalid puzzle.  At this time we'll put back the last piece we removed and consider the puzzle generated.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Test Class Implementation&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Our test class to test our generator implementation is only minimally more complex than the solver implementation we used in an earlier section.  Because this generator we built has a dependency on an &lt;span style="font-weight: bold;"&gt;ISolver&lt;/span&gt; we need to provide an implementation which we have already tested so that our generator can operate successfully.  For this we're obviously going to use our already tested &lt;span style="font-weight: bold;"&gt;RecursiveSolver&lt;/span&gt; implementation.  Note that while it would be possible to use a different type of solver (or notably a mock solver), doing this would most likely require significant changes to the tests which we are running, and this is not an exercise we're yet willing to go through.&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;[&lt;span class="type"&gt;TestClass&lt;/span&gt;]&lt;br /&gt;&lt;span class="keyword"&gt;public class&lt;/span&gt; &lt;span class="type"&gt;When_RecursiveGenerator_Generates_A_Puzzle&lt;/span&gt; : &lt;span class="type"&gt;When_A_New_Puzzle_Is_Generated&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;  &lt;span class="keyword"&gt;public&lt;/span&gt; &lt;span class="type"&gt;When_RecursiveGenerator_Generates_A_Puzzle&lt;/span&gt;()&lt;br /&gt;    : &lt;span class="keyword"&gt;base&lt;/span&gt;(&lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;RecusiveGenerator&lt;/span&gt;(&lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;RecursiveSolver&lt;/span&gt;()))&lt;br /&gt;  {&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Notice that the only new twist to this code is that our constructor for &lt;span style="font-weight: bold;"&gt;RecursiveGenerator&lt;/span&gt; must now takes an implementation of &lt;span style="font-weight: bold;"&gt;ISolver&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;RecursiveGenerator Source&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;&lt;span class="keyword"&gt;public class&lt;/span&gt; &lt;span class="type"&gt;RecusiveGenerator&lt;/span&gt; : &lt;span class="type"&gt;IGenerator&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;  &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="type"&gt;Random&lt;/span&gt; rand;&lt;br /&gt;  &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="type"&gt;ISolver&lt;/span&gt; solver;&lt;br /&gt;&lt;br /&gt;  &lt;span class="keyword"&gt;public&lt;/span&gt; RecusiveGenerator(&lt;span class="type"&gt;ISolver&lt;/span&gt; solver)&lt;br /&gt;  {&lt;br /&gt;    rand = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;Random&lt;/span&gt;();&lt;br /&gt;    &lt;span class="keyword"&gt;this&lt;/span&gt;.solver = solver;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span class="keyword"&gt;public&lt;/span&gt; &lt;span class="type"&gt;Puzzle&lt;/span&gt; Generate()&lt;br /&gt;  {&lt;br /&gt;    &lt;span class="type"&gt;Puzzle&lt;/span&gt; puzzle = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;Puzzle&lt;/span&gt;();&lt;br /&gt;    &lt;br /&gt;    &lt;span class="comment"&gt;//fully fill a puzzle with valid pieces&lt;/span&gt;&lt;br /&gt;    GeneratePiece(GetMinimumPosibilityPiece(puzzle), puzzle);&lt;br /&gt;&lt;br /&gt;    &lt;span class="comment"&gt;//now remove random values until the puzzle is no longer&lt;br /&gt;    //uniquely solvable.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="type"&gt;SortedList&lt;/span&gt;&amp;lt;&lt;span class="keyword"&gt;double&lt;/span&gt;, &lt;span class="type"&gt;Piece&lt;/span&gt;&amp;gt; sortedPieces = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;SortedList&lt;/span&gt;&amp;lt;&lt;span class="keyword"&gt;double&lt;/span&gt;, &lt;span class="type"&gt;Piece&lt;/span&gt;&amp;gt;();&lt;br /&gt;    &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="type"&gt;Piece&lt;/span&gt; piece &lt;span class="keyword"&gt;in&lt;/span&gt; puzzle.Pieces)&lt;br /&gt;    {&lt;br /&gt;      sortedPieces.Add(rand.NextDouble(), piece);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="type"&gt;Piece&lt;/span&gt; lastPiece = &lt;span class="keyword"&gt;null&lt;/span&gt;;&lt;br /&gt;    &lt;span class="type"&gt;Value&lt;/span&gt;? lastValue = &lt;span class="keyword"&gt;null&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;    &lt;span class="keyword"&gt;try&lt;/span&gt;&lt;br /&gt;    {&lt;br /&gt;      &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="keyword"&gt;double&lt;/span&gt; key &lt;span class="keyword"&gt;in&lt;/span&gt; sortedPieces.Keys)&lt;br /&gt;      {&lt;br /&gt;        lastPiece = sortedPieces[key];&lt;br /&gt;        lastValue = lastPiece.AssignedValue;&lt;br /&gt;        lastPiece.AssignedValue = &lt;span class="keyword"&gt;null&lt;/span&gt;;&lt;br /&gt;        solver.Solve(puzzle);&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;    &lt;span class="keyword"&gt;catch&lt;/span&gt; (&lt;span class="type"&gt;DuplicateSolutionFoundException&lt;/span&gt;)&lt;br /&gt;    {&lt;br /&gt;      &lt;span class="comment"&gt;//when we reach the point of a duplicate solution&lt;br /&gt;      //we need to put the last value we stripped off back.&lt;/span&gt;&lt;br /&gt;      lastPiece.AssignedValue = lastValue;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    &lt;span class="keyword"&gt;return&lt;/span&gt; puzzle;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span class="keyword"&gt;private bool&lt;/span&gt; GeneratePiece(&lt;span class="type"&gt;Piece&lt;/span&gt; piece, &lt;span class="type"&gt;Puzzle&lt;/span&gt; puzzle)&lt;br /&gt;  {&lt;br /&gt;    &lt;span class="keyword"&gt;if&lt;/span&gt; (piece == &lt;span class="keyword"&gt;null&lt;/span&gt;)&lt;br /&gt;    {&lt;br /&gt;      &lt;span class="keyword"&gt;return true&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="type"&gt;HashSet&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt; potentials = CalculatePotentials(piece);&lt;br /&gt;&lt;br /&gt;    &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br /&gt;    {&lt;br /&gt;      piece.AssignedValue = &lt;span class="keyword"&gt;null&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;      &lt;span class="comment"&gt;// if there are no potential values for this piece then&lt;br /&gt;      // we have reached the end of the line.&lt;/span&gt;&lt;br /&gt;      &lt;span class="keyword"&gt;if&lt;/span&gt; (potentials.Count == 0)&lt;br /&gt;      {&lt;br /&gt;        &lt;span class="keyword"&gt;return false&lt;/span&gt;;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      piece.AssignedValue = potentials.PopRandomItem();&lt;br /&gt;    } &lt;span class="keyword"&gt;while&lt;/span&gt; (!GeneratePiece(GetMinimumPosibilityPiece(puzzle), puzzle));&lt;br /&gt;&lt;br /&gt;    &lt;span class="keyword"&gt;return true&lt;/span&gt;;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span class="keyword"&gt;private Piece&lt;/span&gt; GetMinimumPosibilityPiece(&lt;span class="type"&gt;Puzzle&lt;/span&gt; puzzle)&lt;br /&gt;  {&lt;br /&gt;    &lt;span class="type"&gt;Piece&lt;/span&gt; minimumPiece = &lt;span class="keyword"&gt;null&lt;/span&gt;;&lt;br /&gt;    &lt;span class="keyword"&gt;int&lt;/span&gt; minimumPossiblities = &lt;span class="type"&gt;Enum&lt;/span&gt;.GetValues(&lt;span class="keyword"&gt;typeof&lt;/span&gt;(&lt;span class="type"&gt;Value&lt;/span&gt;)).Length + 1;&lt;br /&gt;&lt;br /&gt;    &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="type"&gt;Piece&lt;/span&gt; piece &lt;span class="keyword"&gt;in&lt;/span&gt; puzzle.Pieces)&lt;br /&gt;    {&lt;br /&gt;      &lt;span class="keyword"&gt;int&lt;/span&gt; possibilities = CalculatePotentials(piece).Count;&lt;br /&gt;      &lt;span class="keyword"&gt;if&lt;/span&gt; (!piece.AssignedValue.HasValue &amp;&amp; possibilities &amp;lt; minimumPossiblities)&lt;br /&gt;      {&lt;br /&gt;        minimumPossiblities = possibilities;&lt;br /&gt;        minimumPiece = piece;&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="keyword"&gt;return&lt;/span&gt; minimumPiece;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="type"&gt;HashSet&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt; CalculatePotentials(&lt;span class="type"&gt;Piece&lt;/span&gt; piece)&lt;br /&gt;  {&lt;br /&gt;    &lt;span class="type"&gt;HashSet&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt; potentials = GetPossibleValues();&lt;br /&gt;&lt;br /&gt;    potentials.IntersectWith(GetSolutionValues(piece.Column));&lt;br /&gt;    potentials.IntersectWith(GetSolutionValues(piece.Row));&lt;br /&gt;    potentials.IntersectWith(GetSolutionValues(piece.Region));&lt;br /&gt;&lt;br /&gt;    &lt;span class="keyword"&gt;return&lt;/span&gt; potentials;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="type"&gt;HashSet&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt; GetSolutionValues(&lt;span class="type"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Piece&lt;/span&gt;&amp;gt; pieces)&lt;br /&gt;  {&lt;br /&gt;    &lt;span class="type"&gt;HashSet&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt; values = GetPossibleValues();&lt;br /&gt;    &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="type"&gt;Piece&lt;/span&gt; piece &lt;span class="keyword"&gt;in&lt;/span&gt; pieces)&lt;br /&gt;    {&lt;br /&gt;      &lt;span class="keyword"&gt;if&lt;/span&gt; (piece.AssignedValue != &lt;span class="keyword"&gt;null&lt;/span&gt;)&lt;br /&gt;      {&lt;br /&gt;        values.Remove(piece.AssignedValue.Value);&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="keyword"&gt;return&lt;/span&gt; values;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="type"&gt;HashSet&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt; GetPossibleValues()&lt;br /&gt;  {&lt;br /&gt;    &lt;span class="type"&gt;HashSet&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt; values = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;HashSet&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt;();&lt;br /&gt;    &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="type"&gt;Value&lt;/span&gt; val &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="type"&gt;Enum&lt;/span&gt;.GetValues(&lt;span class="keyword"&gt;typeof&lt;/span&gt;(&lt;span class="type"&gt;Value&lt;/span&gt;)))&lt;br /&gt;    {&lt;br /&gt;      values.Add(val);&lt;br /&gt;    }&lt;br /&gt;    &lt;span class="keyword"&gt;return&lt;/span&gt; values;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Notice that a lot of this code is very similar to that of the solver.  This could probably be refactored, but for now we'll leave as is.&lt;br /&gt;&lt;br /&gt;Again, what do we have to show for our hard word? Our green lights of course!&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_NwVxkBFPJG8/R6XOPSwmo5I/AAAAAAAAABc/n7x0XZniAUg/s1600-h/RecursiveGeneratorResults.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_NwVxkBFPJG8/R6XOPSwmo5I/AAAAAAAAABc/n7x0XZniAUg/s400/RecursiveGeneratorResults.jpg" alt="" id="BLOGGER_PHOTO_ID_5162759309979198354" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Notes&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For those readers with a keen eye, something may seem less than optimal regarding the approaches we took here in this section.  We'll get in to what those may be and what we can do about them in future segments after we have built a UI to be able to show these generated Sudoku puzzles.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-2628755046464497627?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=nMfdJQhZC1M:mEwghJ3m7yM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=nMfdJQhZC1M:mEwghJ3m7yM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=nMfdJQhZC1M:mEwghJ3m7yM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/nMfdJQhZC1M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/2628755046464497627/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=2628755046464497627" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/2628755046464497627?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/2628755046464497627?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/nMfdJQhZC1M/sudoku-part-4-implementing-generator.html" title="Sudoku Part 4: Implementing A Generator" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_NwVxkBFPJG8/R6XOPSwmo5I/AAAAAAAAABc/n7x0XZniAUg/s72-c/RecursiveGeneratorResults.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2008/02/sudoku-part-4-implementing-generator.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0cCRHs7eip7ImA9WxZREEk.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-7598622634680259296</id><published>2008-01-27T17:18:00.000-05:00</published><updated>2008-02-03T09:31:05.502-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-02-03T09:31:05.502-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Sudoku" /><category scheme="http://www.blogger.com/atom/ns#" term="Behavior-Driven Development" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><title>Sudoku Part 3: Defining The Generator Behavior</title><content type="html">&lt;div style="border: 1px dashed rgb(51, 51, 51); background: rgb(221, 221, 221) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;&lt;ul style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2007/12/sudoku-part-0-introduction.html"&gt;Sudoku Part 0&lt;/a&gt;: Introduction&lt;/li&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2008/01/sudoku-part-1-defining-solver-behavior.html"&gt;Sudoku Part 1&lt;/a&gt;: Defining The Solver Behavior&lt;/li&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2008/01/sudoku-part-2-implementing-solver.html"&gt;Sudoku Part 2&lt;/a&gt;: Implementing A Solver&lt;/li&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2008/01/sudoku-part-3-defining-generator.html"&gt;Sudoku Part 3&lt;/a&gt;: Defining The Generator Behavior&lt;/li&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2008/02/sudoku-part-4-implementing-generator.html"&gt;Sudoku Part 4&lt;/a&gt;: Implementing A Generator&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;br /&gt;In part 1 (&lt;a href="http://jaychapman.blogspot.com/2008/01/sudoku-part-1-defining-solver-behavior.html"&gt;Defining The Solver Behavior&lt;/a&gt;) we examined how Behavior Driven Development could assist us in defining the specifications of a small portion of our application.  Today we're going to take the same approach, but instead we're going to tackle the Generation portion of a Sudoku puzzle instead of the solving of the puzzle.&lt;br /&gt;&lt;br /&gt;We're going to resume our conversations with our domain expert, and see what types of behaviors this new piece of functionality should include.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Needed Behavior&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Just like last time, we'll have simple questions and simple answers which will later drive how we create and define our behavior based unit tests.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;What is the result when a new puzzle is generated?&lt;/li&gt;&lt;ul&gt;&lt;li&gt;No column should have duplicate values&lt;/li&gt;&lt;li&gt;No row should have duplicate values&lt;/li&gt;&lt;li&gt;No region should have duplicate values&lt;/li&gt;&lt;li&gt;The puzzle should be uniquely solvable.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;Really, that's it.  We don't care too much about how the puzzle is generated, or what it looks like (at least at this point), so long as the puzzle itself can be solved.&lt;br /&gt;&lt;br /&gt;Notice, that making the puzzle solvable would actually be quite a tricky requirement if we had not already built a Sudoku solver in part 2 (&lt;a href="http://jaychapman.blogspot.com/2008/01/sudoku-part-2-implementing-solver.html"&gt;Implementing A Solver&lt;/a&gt;).  Lucky for us, since we have a fully tested solver which we have proven works we can plug that implementation in to our behavior tests for the generator in order to verify the output.  Note that really any implementation of an ISolver will suffice for our purposes, since our behavior tests are actually written against the interface and not any particular implementation.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;The BDD Style Specifications&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We're going to write our test class (or specification) in much the same way we did before.  We try to match the discussion with the domain expert as close as we can, and then write relatively simple tests which we can use to ensure our implementations provide the correct behavior.&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;[&lt;span class="type"&gt;TestClass&lt;/span&gt;]&lt;br /&gt;&lt;span class="keyword"&gt;public abstract class&lt;/span&gt; &lt;span class="type"&gt;When_A_New_Puzzle_Is_Generated&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt; &lt;span class="keyword"&gt;protected&lt;/span&gt; &lt;span class="type"&gt;Puzzle&lt;/span&gt; puzzle;&lt;br /&gt; &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="type"&gt;IGenerator&lt;/span&gt; generator;&lt;br /&gt; &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="type"&gt;ISolver&lt;/span&gt; solver;&lt;br /&gt;&lt;br /&gt; &lt;span class="keyword"&gt;protected&lt;/span&gt; When_A_New_Puzzle_Is_Generated(&lt;span class="type"&gt;IGenerator&lt;/span&gt; generator)&lt;br /&gt; {&lt;br /&gt;   this.generator = generator;&lt;br /&gt;   this.solver = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;RecursiveSolver&lt;/span&gt;();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; [&lt;span class="type"&gt;TestInitialize&lt;/span&gt;]&lt;br /&gt; &lt;span class="keyword"&gt;public void&lt;/span&gt; Initialize()&lt;br /&gt; {&lt;br /&gt;   puzzle = generator.Generate();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; [&lt;span class="type"&gt;TestMethod&lt;/span&gt;]&lt;br /&gt; &lt;span class="keyword"&gt;public void&lt;/span&gt; No_Column_Should_Have_Duplicate_Values()&lt;br /&gt; {&lt;br /&gt;   &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="type"&gt;Column&lt;/span&gt; col &lt;span class="keyword"&gt;in&lt;/span&gt; puzzle.Columns)&lt;br /&gt;   {&lt;br /&gt;     &lt;span class="type"&gt;List&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt; foundValues = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;List&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt;();&lt;br /&gt;     &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="type"&gt;Piece&lt;/span&gt; piece &lt;span class="keyword"&gt;in&lt;/span&gt; col)&lt;br /&gt;     {&lt;br /&gt;       &lt;span class="keyword"&gt;if&lt;/span&gt; (piece.AssignedValue.HasValue)&lt;br /&gt;       {&lt;br /&gt;         &lt;span class="type"&gt;Assert&lt;/span&gt;.IsFalse(foundValues.Contains(piece.AssignedValue.Value));&lt;br /&gt;         foundValues.Add(piece.AssignedValue.Value);&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; [&lt;span class="type"&gt;TestMethod&lt;/span&gt;]&lt;br /&gt; &lt;span class="keyword"&gt;public void&lt;/span&gt; No_Row_Should_Have_Duplicate_Values()&lt;br /&gt; {&lt;br /&gt;   &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="type"&gt;Row&lt;/span&gt; row &lt;span class="keyword"&gt;in&lt;/span&gt; puzzle.Rows)&lt;br /&gt;   {&lt;br /&gt;     &lt;span class="type"&gt;List&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt; foundValues = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;List&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt;();&lt;br /&gt;     &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="type"&gt;Piece&lt;/span&gt; piece &lt;span class="keyword"&gt;in&lt;/span&gt; row)&lt;br /&gt;     {&lt;br /&gt;       &lt;span class="keyword"&gt;if&lt;/span&gt; (piece.AssignedValue.HasValue)&lt;br /&gt;       {&lt;br /&gt;         &lt;span class="type"&gt;Assert&lt;/span&gt;.IsFalse(foundValues.Contains(piece.AssignedValue.Value));&lt;br /&gt;         foundValues.Add(piece.AssignedValue.Value);&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; [&lt;span class="type"&gt;TestMethod&lt;/span&gt;]&lt;br /&gt; &lt;span class="keyword"&gt;public void&lt;/span&gt; No_Region_Should_Have_Duplicate_Values()&lt;br /&gt; {&lt;br /&gt;   &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="type"&gt;Region&lt;/span&gt; region in puzzle.Regions)&lt;br /&gt;   {&lt;br /&gt;     &lt;span class="type"&gt;List&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt; foundValues = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;List&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt;();&lt;br /&gt;     &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="type"&gt;Piece&lt;/span&gt; piece &lt;span class="keyword"&gt;in&lt;/span&gt; region)&lt;br /&gt;     {&lt;br /&gt;       &lt;span class="keyword"&gt;if&lt;/span&gt; (piece.AssignedValue.HasValue)&lt;br /&gt;       {&lt;br /&gt;         &lt;span class="type"&gt;Assert&lt;/span&gt;.IsFalse(foundValues.Contains(piece.AssignedValue.Value));&lt;br /&gt;         foundValues.Add(piece.AssignedValue.Value);&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; [&lt;span class="type"&gt;TestMethod&lt;/span&gt;]&lt;br /&gt; &lt;span class="keyword"&gt;public void&lt;/span&gt; The_Puzzle_Should_Be_Uniquely_Solvable()&lt;br /&gt; {&lt;br /&gt;   &lt;span class="type"&gt;Assert&lt;/span&gt;.IsNotNull(solver.Solve(puzzle));&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/4292687466688891558-7598622634680259296?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=WuYRNaFkPa8:FDV2FleY-MA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=WuYRNaFkPa8:FDV2FleY-MA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=WuYRNaFkPa8:FDV2FleY-MA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/WuYRNaFkPa8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/7598622634680259296/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=7598622634680259296" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/7598622634680259296?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/7598622634680259296?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/WuYRNaFkPa8/sudoku-part-3-defining-generator.html" title="Sudoku Part 3: Defining The Generator Behavior" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2008/01/sudoku-part-3-defining-generator.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUDQH4ycCp7ImA9WxRaEUk.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-8466887243373176387</id><published>2008-01-15T20:01:00.000-05:00</published><updated>2008-12-12T22:51:11.098-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-12T22:51:11.098-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Sudoku" /><category scheme="http://www.blogger.com/atom/ns#" term="Behavior-Driven Development" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><title>Sudoku Part 2: Implementing A Solver</title><content type="html">&lt;div style="border: 1px dashed rgb(51, 51, 51); background: rgb(221, 221, 221) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;&lt;ul style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2007/12/sudoku-part-0-introduction.html"&gt;Sudoku Part 0&lt;/a&gt;: Introduction&lt;/li&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2008/01/sudoku-part-1-defining-solver-behavior.html"&gt;Sudoku Part 1&lt;/a&gt;: Defining The Solver Behavior&lt;/li&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2008/01/sudoku-part-2-implementing-solver.html"&gt;Sudoku Part 2&lt;/a&gt;: Implementing A Solver&lt;/li&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2008/01/sudoku-part-3-defining-generator.html"&gt;Sudoku Part 3&lt;/a&gt;: Defining The Generator Behavior&lt;/li&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2008/02/sudoku-part-4-implementing-generator.html"&gt;Sudoku Part 4&lt;/a&gt;: Implementing A Generator&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;br /&gt;In the previous posting (&lt;a href="http://jaychapman.blogspot.com/2008/01/sudoku-part-1-defining-solver-behavior.html"&gt;Defining The Solver Behavior&lt;/a&gt;) we discussed the needed behavior in order to build a working Sudoku solver.  Today we're going to build our first implementation of a solver which exhibits the previously described behaviors.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Algorithm&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For the first solver I took a relatively simple approach.  It's not quite a brute-force solver, but it is close.  I call the first implementation the &lt;span style="font-weight: bold;"&gt;RecursiveSolver&lt;/span&gt;, since it solves the puzzle using a recursive algorithm.&lt;br /&gt;&lt;br /&gt;In order to solve the puzzle we'll first analyze the board position to determine the number of candidate values for each puzzle piece.  The set of candiate values will be the full list of values minus the set of values in the piece's row, minus the set of values in the piece's column and then minus the set of values in the piece's region.&lt;br /&gt;&lt;br /&gt;Once we have computed the candidate values for each piece, we'll record the piece with the fewest candidate values.  We'll then loop over the candidate values in a random order calculating the piece with the minimum candidates given that move and continuing the process.&lt;br /&gt;&lt;br /&gt;If we find a board position where there are no longer any pieces without an assigned value we know we have found a solution.  If we have already recorded a value solution and we find a second board position we know we have found an invalid position.&lt;br /&gt;&lt;br /&gt;If we found a board position where there is a piece with 0 potential values, we know we have traversed a path which will not lead to a solution.&lt;br /&gt;&lt;br /&gt;If we traverse all possible paths of the puzzle and can not find a solution, then we know we have an unsolvable puzzle as our algorithm would have examined every possible choice a solver could make.&lt;br /&gt;&lt;br /&gt;Broken into steps our algorithm looks like the following:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Find The Piece With The Minimum Number Of Candidate Values&lt;/li&gt;&lt;li&gt;If A Piece Is Found With No Candidate Values, Return Without Solution&lt;/li&gt;&lt;li&gt;If No Pieces exist with Candidate Values Return the Solution We Are Done&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Loop Over Each Candidate Value&lt;/li&gt;&lt;li&gt;Assign the Value to the Solution&lt;/li&gt;&lt;li&gt;Return To Step 1 Given The New State&lt;/li&gt;&lt;li&gt;If We Found A Solution, Verify That We Have Not Previously Found A Solution&lt;/li&gt;&lt;li&gt;Loop To Step 4 Until No Other Candidates Are Available&lt;/li&gt;&lt;li&gt;Return The Solution If It Was Found&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Test Class Implementations&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In the last installment we created abstract behavior tests since we did not have a specific implementation of a solver.  We had a set of behaviors we wanted all potential solver implementations to exhibit.   So first we need to create concrete test classes which inherit from our abstract ones.&lt;br /&gt;&lt;br /&gt;First, let's look at what we need to do for the case when a puzzle is solved:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;[&lt;span class="type"&gt;TestClass&lt;/span&gt;]&lt;br /&gt;&lt;span class="keyword"&gt;public class&lt;/span&gt; &lt;span class="type"&gt;When_RecursiveSolver_Solves_A_Puzzle&lt;/span&gt; : &lt;span class="type"&gt;When_A_Puzzle_Is_Solved&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt; &lt;span class="keyword"&gt;public&lt;/span&gt; When_RecursiveSolver_Solves_A_Puzzle()&lt;br /&gt;   : &lt;span class="keyword"&gt;base&lt;/span&gt;(&lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;RecursiveSolver&lt;/span&gt;())&lt;br /&gt; {&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That's pretty simple isn't it?  Now, this works fine with the MSTest tool, I have not actually verified that this technique works in other .NET unit testing frameworks, but I believe it does.  We rely on inheritance to pull all of our expectations from our base test class.&lt;br /&gt;&lt;br /&gt;We can continue this pattern for all other behavior cases as well.  Take special note to the fact that we are constructing the instance of the solver we want to test in the constructor of the test class.  This is needed since our base class takes an ISolver to use for its test cases.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Solver Source&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now let's look at the good stuff.  What does the solver code look like?&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;&lt;span class="keyword"&gt;public class&lt;/span&gt; &lt;span class="type"&gt;RecursiveSolver&lt;/span&gt; : &lt;span class="type"&gt;ISolver&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt; &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="type"&gt;Random&lt;/span&gt; rand;&lt;br /&gt;&lt;br /&gt; &lt;span class="keyword"&gt;public&lt;/span&gt; RecursiveSolver()&lt;br /&gt; {&lt;br /&gt;   &lt;span class="keyword"&gt;this&lt;/span&gt;.rand = new &lt;span class="type"&gt;Random&lt;/span&gt;();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; &lt;span class="keyword"&gt;#region&lt;/span&gt; ISolver Members&lt;br /&gt;&lt;br /&gt; &lt;span class="keyword"&gt;public&lt;/span&gt; Solution Solve(&lt;span class="type"&gt;Puzzle&lt;/span&gt; puzzle)&lt;br /&gt; {&lt;br /&gt;   &lt;span class="type"&gt;Solution&lt;/span&gt; solution = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;Solution&lt;/span&gt;(puzzle);&lt;br /&gt;&lt;br /&gt;   solution = SolvePiece(FindMinimumCandidatePiece(solution), solution);&lt;br /&gt;&lt;br /&gt;   &lt;span class="keyword"&gt;return&lt;/span&gt; solution;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; &lt;span class="keyword"&gt;#endregion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="type"&gt;Solution&lt;/span&gt; SolvePiece(&lt;span class="type"&gt;Piece&lt;/span&gt; piece, &lt;span class="type"&gt;Solution&lt;/span&gt; solution)&lt;br /&gt; {&lt;br /&gt;   &lt;span class="comments"&gt;//when the provided piece is null we know there are no remaining&lt;br /&gt;   //pieces to be filled in indicating that the puzzle is solved.&lt;/span&gt;&lt;br /&gt;   &lt;span class="keyword"&gt;if&lt;/span&gt; (piece == &lt;span class="keyword"&gt;null&lt;/span&gt;)&lt;br /&gt;   {&lt;br /&gt;     &lt;span class="keyword"&gt;return&lt;/span&gt; solution;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   &lt;span class="comments"&gt;//we clone the current solution to ensure that we always provide&lt;br /&gt;   //later steps with the same configuration.  Otherwise once the item&lt;br /&gt;   //recursed the values within the soultion reference would have changed.&lt;/span&gt;&lt;br /&gt;   solution = (&lt;span class="type"&gt;Solution&lt;/span&gt;)solution.Clone();&lt;br /&gt;   &lt;span class="type"&gt;Solution&lt;/span&gt; returnSolution = &lt;span class="keyword"&gt;null&lt;/span&gt;;&lt;br /&gt;   &lt;span class="type"&gt;Solution&lt;/span&gt; foundSolution = &lt;span class="keyword"&gt;null&lt;/span&gt;;&lt;br /&gt;   &lt;span class="type"&gt;HashSet&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;amp;*gt; candidates = CalculateCandidates(piece, solution);&lt;br /&gt;&lt;br /&gt;   &lt;span class="comments"&gt;//loop over all possible choices for this piece.  If we finish&lt;br /&gt;   //looping and no slution was found the earlier steps will have&lt;br /&gt;   //a null solution indicating the path was incorrect.&lt;/span&gt;&lt;br /&gt;   &lt;span class="keyword"&gt;while&lt;/span&gt; (candidates.Count &gt; 0)&lt;br /&gt;   {&lt;br /&gt;     solution.Values[piece] = candidates.PopRandomItem();&lt;br /&gt;     returnSolution = SolvePiece(FindMinimumCandidatePiece(solution), solution);&lt;br /&gt;&lt;br /&gt;     &lt;span class="keyword"&gt;if&lt;/span&gt; (returnSolution != &lt;span class="keyword"&gt;null&lt;/span&gt;)&lt;br /&gt;     {&lt;br /&gt;       &lt;span class="keyword"&gt;if&lt;/span&gt; (foundSolution != &lt;span class="keyword"&gt;null&lt;/span&gt;)&lt;br /&gt;       {&lt;br /&gt;         &lt;span class="keyword"&gt;throw new&lt;/span&gt; &lt;span class="type"&gt;DuplicateSolutionFoundException&lt;/span&gt;("Provided puzzle is invalid.");&lt;br /&gt;       }&lt;br /&gt;       foundSolution = returnSolution;&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   &lt;span class="keyword"&gt;return&lt;/span&gt; foundSolution;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="type"&gt;Piece&lt;/span&gt; FindMinimumCandidatePiece(&lt;span class="type"&gt;Solution&lt;/span&gt; solution)&lt;br /&gt; {&lt;br /&gt;   &lt;span class="type"&gt;Piece&lt;/span&gt; foundPiece = &lt;span class="keyword"&gt;null&lt;/span&gt;;&lt;br /&gt;   &lt;span class="type"&gt;int&lt;/span&gt; minimumCandidates = 10;&lt;br /&gt;&lt;br /&gt;   &lt;span class="type"&gt;foreach&lt;/span&gt; (&lt;span class="type"&gt;Piece&lt;/span&gt; piece &lt;span class="keyword"&gt;in&lt;/span&gt; solution.Puzzle.Pieces)&lt;br /&gt;   {&lt;br /&gt;     &lt;span class="keyword"&gt;if&lt;/span&gt; (!solution.Values.ContainsKey(piece))&lt;br /&gt;     {&lt;br /&gt;       &lt;span class="type"&gt;HashSet&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt; candidates = CalculateCandidates(piece, solution);&lt;br /&gt;       &lt;span class="keyword"&gt;if&lt;/span&gt; (candidates.Count &lt; minimumcandidates)&lt;br /&gt;        { &lt;br /&gt;          minimumCandidates = candidates.Count;&lt;br /&gt;          foundpiece = piece; &lt;br /&gt;          &lt;br /&gt;         &lt;span class="comments"&gt;//If we found a piece with only 1 candidate we can stop looking&lt;br /&gt;         //since 1 is the minimum possible candidates for a valid piece.&lt;/span&gt;&lt;br /&gt;         &lt;span class="keyword"&gt;if&lt;/span&gt; (minimumCandidates == 1)&lt;br /&gt;         {&lt;br /&gt;           &lt;span class="keyword"&gt;break&lt;/span&gt;;&lt;br /&gt;         }&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   &lt;span class="keyword"&gt;return&lt;/span&gt; foundPiece;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="type"&gt;HashSet&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt; CalculateCandidates(&lt;span class="type"&gt;Piece&lt;/span&gt; piece, &lt;span class="type"&gt;Solution&lt;/span&gt; solution)&lt;br /&gt; {&lt;br /&gt;   &lt;span class="type"&gt;HashSet&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt; candidates = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;HashSet&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt;((&lt;span class="type"&gt;Value&lt;/span&gt;[])&lt;span class="type"&gt;Enum&lt;/span&gt;.GetValues(&lt;span class="keyword"&gt;typeof&lt;/span&gt;(&lt;span class="type"&gt;Value&lt;/span&gt;)));&lt;br /&gt; &lt;br /&gt;   candidates.ExceptWith(GetAssignedValues(piece.Column, solution));&lt;br /&gt;   candidates.ExceptWith(GetAssignedValues(piece.Row, solution));&lt;br /&gt;   candidates.ExceptWith(GetAssignedValues(piece.Region, solution));&lt;br /&gt;&lt;br /&gt;   &lt;span class="keyword"&gt;return&lt;/span&gt; candidates;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="type"&gt;HashSet&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt; GetAssignedValues(&lt;span class="type"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Piece&lt;/span&gt;&amp;gt; pieces, &lt;span class="type"&gt;Solution&lt;/span&gt; solution)&lt;br /&gt; {&lt;br /&gt;   &lt;span class="type"&gt;HashSet&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt; values = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;HashSet&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt;();&lt;br /&gt;&lt;br /&gt;   &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="type"&gt;Piece&lt;/span&gt; piece &lt;span class="keyword"&gt;in&lt;/span&gt; pieces)&lt;br /&gt;   {&lt;br /&gt;     &lt;span class="keyword"&gt;if&lt;/span&gt; (solution.Values.ContainsKey(piece))&lt;br /&gt;     {&lt;br /&gt;       values.Add(solution.Values[piece]);&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   &lt;span class="keyword"&gt;return&lt;/span&gt; values;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Notice that there is actually a lot of logic within this solver.  While it could be argued that some of this logic deserves its own behavior class, at this time I'm going to consider it premature optimization, and leave it for future refactoring.&lt;br /&gt;&lt;br /&gt;For example the ability to calculate potential values isn't something which is specific to a solver, or at least this solver.  This could be usable elsewhere.  If/When it becomes valuable to break it out we'll do it.&lt;br /&gt;&lt;br /&gt;Also of note is the PopRandomValue method on the HashSet&lt;&gt;.  PopRandomValue is obviously an extension method here, just don't tell anyone!  This method randomly selects an item from the Set and then removes it from the set so it won't be selected next time.  The implementation is as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;&lt;span class="keyword"&gt;public static class&lt;/span&gt; &lt;span class="type"&gt;HashSetExtension&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt; &lt;span class="keyword"&gt;private static&lt;/span&gt; &lt;span class="type"&gt;Random&lt;/span&gt; rand;&lt;br /&gt;&lt;br /&gt; &lt;span class="keyword"&gt;static&lt;/span&gt; HashSetExtension()&lt;br /&gt; {&lt;br /&gt;   rand = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;Random&lt;/span&gt;();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; &lt;span class="keyword"&gt;public static&lt;/span&gt; T PopRandomItem&lt;t&gt;(&lt;span class="keyword"&gt;this&lt;/span&gt; &lt;span class="type"&gt;HashSet&lt;/span&gt;&amp;lt;T&amp;gt; set)&lt;br /&gt; {&lt;br /&gt;   &lt;span class="type"&gt;List&lt;/span&gt;&amp;lt;T&amp;gt; list = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;List&lt;/span&gt;&amp;lt;T&amp;gt;(set);&lt;br /&gt;   T item = list[rand.Next(0, list.Count - 1)];&lt;br /&gt;   set.Remove(item);&lt;br /&gt;   &lt;span class="keyword"&gt;return&lt;/span&gt; item;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/t&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;What do we have to show for all of our effort?  Well a pretty screen with lots of green of course!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_NwVxkBFPJG8/R41qkUfzuZI/AAAAAAAAABU/RQkvd6eNaPw/s1600-h/RecursiveSolverTestResults.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_NwVxkBFPJG8/R41qkUfzuZI/AAAAAAAAABU/RQkvd6eNaPw/s400/RecursiveSolverTestResults.jpg" alt="" id="BLOGGER_PHOTO_ID_5155894320619043218" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Notes&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Note that we could have included additional behavior tests regarding how this particular solver should behave.  At this time I don't deem it necessary since our only real requirements is that the solver gives valid solutions when one is available, and reports when no solution is available.&lt;br /&gt;&lt;br /&gt;As previously mentioned we could break apart some items of this solver into multiple solvers.  We'll investigate those possibilities at a later point.&lt;br /&gt;&lt;br /&gt;Look for the next section where we'll discuss our Sudoku puzzle generator!&lt;br /&gt;&lt;br /&gt;-- John Chapman&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-8466887243373176387?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=ZF0l-BgVRh8:y-el93EJUlo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=ZF0l-BgVRh8:y-el93EJUlo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=ZF0l-BgVRh8:y-el93EJUlo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/ZF0l-BgVRh8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/8466887243373176387/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=8466887243373176387" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/8466887243373176387?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/8466887243373176387?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/ZF0l-BgVRh8/sudoku-part-2-implementing-solver.html" title="Sudoku Part 2: Implementing A Solver" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_NwVxkBFPJG8/R41qkUfzuZI/AAAAAAAAABU/RQkvd6eNaPw/s72-c/RecursiveSolverTestResults.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2008/01/sudoku-part-2-implementing-solver.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUDQHw9eyp7ImA9WxRaEUk.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-3266352553612946685</id><published>2008-01-05T09:34:00.000-05:00</published><updated>2008-12-12T22:51:11.263-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-12T22:51:11.263-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Sudoku" /><category scheme="http://www.blogger.com/atom/ns#" term="Behavior-Driven Development" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><title>Sudoku Part 1: Defining The Solver Behavior</title><content type="html">&lt;div style="border: 1px dashed rgb(51, 51, 51); background: rgb(221, 221, 221) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;&lt;ul style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2007/12/sudoku-part-0-introduction.html"&gt;Sudoku Part 0&lt;/a&gt;: Introduction&lt;/li&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2008/01/sudoku-part-1-defining-solver-behavior.html"&gt;Sudoku Part 1&lt;/a&gt;: Defining The Solver Behavior&lt;/li&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2008/01/sudoku-part-2-implementing-solver.html"&gt;Sudoku Part 2&lt;/a&gt;: Implementing A Solver&lt;/li&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2008/01/sudoku-part-3-defining-generator.html"&gt;Sudoku Part 3&lt;/a&gt;: Defining The Generator Behavior&lt;/li&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2008/02/sudoku-part-4-implementing-generator.html"&gt;Sudoku Part 4&lt;/a&gt;: Implementing A Generator&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;br /&gt;In the introduction I talked briefly about my goals for this series.  I wanted to create both a Sudoku generator which could generate puzzles for both myself and a theoretical automatic solver.  There are many places to find such tools on the internet, but my goal was to use this as an exercise to show how someone could use various techniques and tools such as Behavior-Driven Development and the Castle Windsor Project.  Today, we'll start with Behavior-Driven Development.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Needed Behavior&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What are we trying to accomplish Here?  Let's start with the Sudoku Solver first.  Let's pretend that I am having a conversation with a customer who is asking me to write this Sudoku solver for them.  Let's also say that I am not familiar with sudoku puzzles.  First the customer explains to me that a Sudoku puzzle is a 9x9 grid with 9 3x3 sub-regions within the grid where each cell can hold a value from 1-9.  He also explains that the puzzle begins with some of the cells (or pieces) already filled in for us, and the rest is for the solver to fill in.&lt;br /&gt;&lt;br /&gt;So we have the following dialog:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;What happens when the puzzle is solved?&lt;/li&gt;&lt;/ul&gt;&lt;ol&gt;&lt;ul&gt;&lt;li&gt;All cells should be assigned a value.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;No column should have duplicate values.&lt;/li&gt;&lt;li&gt;No row should have duplicate values.&lt;/li&gt;&lt;li&gt;No region should have duplicate values.&lt;/li&gt;&lt;/ul&gt;&lt;/ol&gt;The customer explains to me that if the solution meets the provided criteria we are guaranteed of a valid solution for the given puzzle.  But then I start thinking.  Is it possible to be given a Sudoku puzzle which has many possible solutions?  I think that if I don't place any pieces, clearly there would be many possible solutions.   So this leads to the following:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;What happens when a puzzle has multiple solutions?&lt;/li&gt;&lt;ul&gt;&lt;li&gt;The puzzle should be reported as invalid.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;Ok, so now I know what happens if a puzzle has many solutions, but what if the puzzle has no solution.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;What happens when a puzzle has no solution?&lt;/li&gt;&lt;ul&gt;&lt;li&gt;There is no solution for the puzzle.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;Ok, so my customer gave me a pretty weird look on that one, but there is nothing wrong with asking right?&lt;br /&gt;&lt;br /&gt;Note that my customer has not told me any specifics about how he or she would like the puzzle to be solved, only that the puzzle should be solved and what the result of a valid solved puzzle would be.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Letting The Behavior Drive Our Development&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Ok, so now I'm back in the office, ready to begin work on the Sudoku solver for my customer.  Where do I begin?  This is where the Behavior-Driven Development (BDD) comes in to play.  Behavior-Driven Development is basically a Test-Driven Development (TDD)  technique where your tests are designed around the needed behaviors of your software.  This should result in tests which are far easier to refactor, since most changes results in complete removal or replacement of tests instead of removing pieces of a method based test.&lt;br /&gt;&lt;br /&gt;Additionally by wording your tests in such a way that it portrays the resulting behavior of the software, the results of the tests become easy for our customers to read to understand how the software is working.&lt;br /&gt;&lt;br /&gt;Let's look at the resulting unit tests to show what I'm talking about.  First lets look at solving a valid puzzle. (*Warning* These tests are currently written in MSTest, I will most likely change to NUnit or mbUnit before releasing the entire source code.)&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;[&lt;span class="type"&gt;TestClass&lt;/span&gt;]&lt;br /&gt;&lt;span class="keyword"&gt;public abstract class&lt;/span&gt; &lt;span class="type"&gt;When_A_Puzzle_Is_Solved&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;  private Sudoku.Solver.&lt;span class="type"&gt;ISolver&lt;/span&gt; solver;&lt;br /&gt;  private &lt;span class="type"&gt;Puzzle&lt;/span&gt; puzzle;&lt;br /&gt;  private &lt;span class="type"&gt;Solution&lt;/span&gt; solution;&lt;br /&gt;&lt;br /&gt;  &lt;span class="keyword"&gt;public&lt;/span&gt; When_A_Puzzle_Is_Solved(Sudoku.Solver.&lt;span class="type"&gt;ISolver&lt;/span&gt; solver)&lt;br /&gt;  {&lt;br /&gt;    this.solver = solver;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  [TestInitialize]&lt;br /&gt;  &lt;span class="keyword"&gt;public&lt;/span&gt; &lt;span class="keyword"&gt;void&lt;/span&gt; Initialize()&lt;br /&gt;  {&lt;br /&gt;    CreateSolvablePuzzle();&lt;br /&gt;    solution = solver.Solve(puzzle);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span class="keyword"&gt;private void&lt;/span&gt; CreateSolvablePuzzle()&lt;br /&gt;  {&lt;br /&gt;    puzzle = new &lt;span class="type"&gt;Puzzle&lt;/span&gt;();&lt;br /&gt;&lt;br /&gt;    puzzle.Rows[0][1].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Five;&lt;br /&gt;    puzzle.Rows[0][2].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Four;&lt;br /&gt;    puzzle.Rows[0][7].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Two;&lt;br /&gt;    puzzle.Rows[1][0].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Three;&lt;br /&gt;    puzzle.Rows[1][3].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Four;&lt;br /&gt;    puzzle.Rows[2][0].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Seven;&lt;br /&gt;    puzzle.Rows[2][3].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Eight;&lt;br /&gt;    puzzle.Rows[2][6].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Three;&lt;br /&gt;    puzzle.Rows[2][7].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Five;&lt;br /&gt;    puzzle.Rows[3][1].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Seven;&lt;br /&gt;    puzzle.Rows[3][2].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.One;&lt;br /&gt;    puzzle.Rows[3][5].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Five;&lt;br /&gt;    puzzle.Rows[3][8].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Three;&lt;br /&gt;    puzzle.Rows[4][0].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Six;&lt;br /&gt;    puzzle.Rows[4][3].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Three;&lt;br /&gt;    puzzle.Rows[4][5].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Eight;&lt;br /&gt;    puzzle.Rows[4][8].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Nine;&lt;br /&gt;    puzzle.Rows[5][0].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Five;&lt;br /&gt;    puzzle.Rows[5][3].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Nine;&lt;br /&gt;    puzzle.Rows[5][6].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Four;&lt;br /&gt;    puzzle.Rows[5][7].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Seven;&lt;br /&gt;    puzzle.Rows[6][1].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Eight;&lt;br /&gt;    puzzle.Rows[6][2].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Five;&lt;br /&gt;    puzzle.Rows[6][5].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Four;&lt;br /&gt;    puzzle.Rows[6][8].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.One;&lt;br /&gt;    puzzle.Rows[7][5].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Three;&lt;br /&gt;    puzzle.Rows[7][8].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Six;&lt;br /&gt;    puzzle.Rows[8][1].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Six;&lt;br /&gt;    puzzle.Rows[8][6].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Eight;&lt;br /&gt;    puzzle.Rows[8][7].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Nine;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  [&lt;span class="type"&gt;TestMethod&lt;/span&gt;]&lt;br /&gt;  &lt;span class="keyword"&gt;public void&lt;/span&gt; All_Pieces_Should_Have_A_Value()&lt;br /&gt;  {&lt;br /&gt;    &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="type"&gt;Piece&lt;/span&gt; piece in puzzle.Pieces)&lt;br /&gt;    {&lt;br /&gt;      &lt;span class="type"&gt;Assert&lt;/span&gt;.IsTrue(solution.Values.ContainsKey(piece));&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  [&lt;span class="type"&gt;TestMethod&lt;/span&gt;]&lt;br /&gt;  &lt;span class="keyword"&gt;public void&lt;/span&gt; No_Column_Should_Have_Duplicate_Values()&lt;br /&gt;  {&lt;br /&gt;    &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="type"&gt;Column&lt;/span&gt; col in puzzle.Columns)&lt;br /&gt;    {&lt;br /&gt;      &lt;span class="type"&gt;List&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt; foundValues = new &lt;span class="type"&gt;List&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt;();&lt;br /&gt;      &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="type"&gt;Piece&lt;/span&gt; piece in col)&lt;br /&gt;      {&lt;br /&gt;        &lt;span class="type"&gt;Assert&lt;/span&gt;.IsFalse(foundValues.Contains(solution.Values[piece]));&lt;br /&gt;        foundValues.Add(solution.Values[piece]);&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  [&lt;span class="type"&gt;TestMethod&lt;/span&gt;]&lt;br /&gt;  &lt;span class="keyword"&gt;public void&lt;/span&gt; No_Row_Should_Have_Duplicate_Values()&lt;br /&gt;  {&lt;br /&gt;    &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="type"&gt;Row&lt;/span&gt; row in puzzle.Rows)&lt;br /&gt;    {&lt;br /&gt;      &lt;span class="type"&gt;List&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt; foundValues = new &lt;span class="type"&gt;List&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt;();&lt;br /&gt;      &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="type"&gt;Piece&lt;/span&gt; piece in row)&lt;br /&gt;      {&lt;br /&gt;        &lt;span class="type"&gt;Assert&lt;/span&gt;.IsFalse(foundValues.Contains(solution.Values[piece]));&lt;br /&gt;        foundValues.Add(solution.Values[piece]);&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  [&lt;span class="type"&gt;TestMethod&lt;/span&gt;]&lt;br /&gt;  &lt;span class="keyword"&gt;public void&lt;/span&gt; No_Region_Should_Have_Duplicate_Values()&lt;br /&gt;  {&lt;br /&gt;    &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="type"&gt;Region&lt;/span&gt; region in puzzle.Regions)&lt;br /&gt;    {&lt;br /&gt;      &lt;span class="type"&gt;List&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt; foundValues = new &lt;span class="type"&gt;List&lt;/span&gt;&amp;lt;&lt;span class="type"&gt;Value&lt;/span&gt;&amp;gt;();&lt;br /&gt;      &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="type"&gt;Piece&lt;/span&gt; piece in region)&lt;br /&gt;      {&lt;br /&gt;        &lt;span class="type"&gt;Assert&lt;/span&gt;.IsFalse(foundValues.Contains(solution.Values[piece]));&lt;br /&gt;        foundValues.Add(solution.Values[piece]);&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;Notice how closely these tests match the above dialog I had with the fictional customer.  Anyone, including the customer should be able to read that test fixture (especially how it formatted in a proper runner) and verify that the behavior is correct.  Plus, the test methods themselves are very short, easy to read and verify.&lt;br /&gt;&lt;br /&gt;Behavior-Driven Development works by you first defining the scenario.  The scenario becomes the test class itself with the test initialization being the place where we place our objects in to the appropriate state for our scenario.  Each method then becomes a validation of what happens in a given scenario.  The methods and class names are then written out as words so it easy to tell what behaviors are being tested.&lt;br /&gt;&lt;br /&gt;Note that the initialization logic of this test builds a valid Sudoku puzzle and then asks the solver to solve it.  As proof of a valid solution I have provided the puzzle and the associated solution in red below.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_NwVxkBFPJG8/R3-6BUfzuYI/AAAAAAAAABM/LWhRHC1kXX4/s1600-h/ValidSolvedPuzzle.gif"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_NwVxkBFPJG8/R3-6BUfzuYI/AAAAAAAAABM/LWhRHC1kXX4/s400/ValidSolvedPuzzle.gif" alt="" id="BLOGGER_PHOTO_ID_5152041030579894658" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;There are a few things which need to be explained in this code.&lt;br /&gt;&lt;br /&gt;First, I chose to use an enumeration for puzzle values as a way to limit the values of the puzzle.  This actually looks very lame when I read it, having the names of numbers represent the numbers themselves, and it may be refactored at a later point, but for now it helped me ensure no 0s or 10s showed up (although I have learned that enumerations are pretty lame and nothing stops you from assigning an invalid integer value to the enumeration, but that's a post for another day).&lt;br /&gt;&lt;br /&gt;Second, notice that I used an interface for my solver, not a specific solver.  The reason for this is really simple.  I don't know at this point how the puzzle will be solved, only what the result of a solver should be.  It doesn't matter how the internal solver works at this point, provided it sticks to the interface and this root behavior.&lt;br /&gt;&lt;br /&gt;I also made the choice to make the Puzzle class and a separate Solution class.  Basically this just allows a puzzle to remain free of solution information and would theoretically allow someone to make Puzzle classes persistable and not have to worry about updating a puzzle while creating a solution for it.&lt;br /&gt;&lt;br /&gt;Now that we have our behaviors defined for what happens with a valid puzzle, lets move on to the other cases which were discussed in the dialog with the customer.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;[&lt;span class="type"&gt;TestClass&lt;/span&gt;]&lt;br /&gt;&lt;span class="keyword"&gt;public abstract class&lt;/span&gt; &lt;span class="type"&gt;When_A_Puzzle_Has_Multiple_Solutions&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;  &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="type"&gt;ISolver&lt;/span&gt; solver;&lt;br /&gt;  &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="type"&gt;Puzzle&lt;/span&gt; puzzle;&lt;br /&gt;&lt;br /&gt;  &lt;span class="keyword"&gt;public&lt;/span&gt; When_A_Puzzle_Has_Multiple_Solutions(&lt;span class="type"&gt;ISolver&lt;/span&gt; solver)&lt;br /&gt;  {&lt;br /&gt;    this.solver = solver;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  [&lt;span class="type"&gt;TestInitialize&lt;/span&gt;]&lt;br /&gt;  &lt;span class="keyword"&gt;public void&lt;/span&gt; Initialize()&lt;br /&gt;  {&lt;br /&gt;    CreateInvalidPuzzle();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span class="keyword"&gt;private void&lt;/span&gt; CreateInvalidPuzzle()&lt;br /&gt;  {&lt;br /&gt;    puzzle = new &lt;span class="type"&gt;Puzzle&lt;/span&gt;();&lt;br /&gt;&lt;br /&gt;    puzzle.Rows[4][4].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Five;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  [&lt;span class="type"&gt;TestMethod&lt;/span&gt;]&lt;br /&gt;  [&lt;span class="type"&gt;ExpectedException&lt;/span&gt;(&lt;span class="keyword"&gt;typeof&lt;/span&gt;(&lt;span class="type"&gt;DuplicateSolutionFoundException&lt;/span&gt;))]&lt;br /&gt;  &lt;span class="keyword"&gt;public void&lt;/span&gt; The_Solver_Should_Report_An_Invalid_Puzzle()&lt;br /&gt;  {&lt;br /&gt;    solver.Solve(puzzle);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;Note that in this scenario, many valid sudoku boards could be created when only one piece is filled in.  As such we are saying that whenever a puzzle with many solutions is provided we expect any solver to throw an exception.&lt;br /&gt;&lt;br /&gt;I'm not actually a big fan of this approach, but I did it anyways here.  Basically checking for duplicate solutions is something which I think would actually be useful for business logic.  Therefore I for see cases where I could wind up using this exception for flow control, which I am opposed to.  However, since at this point I just need a failure it works fine, and I can always refactor it later.&lt;br /&gt;&lt;br /&gt;There is still one case remaining from the solver discussion:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;[&lt;span class="type"&gt;TestClass&lt;/span&gt;]&lt;br /&gt;&lt;span class="keyword"&gt;public abstract class&lt;/span&gt; &lt;span class="type"&gt;When_A_Puzzle_Has_No_Solution&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;  &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="type"&gt;Puzzle&lt;/span&gt; puzzle;&lt;br /&gt;  &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="type"&gt;ISolver&lt;/span&gt; solver;&lt;br /&gt;&lt;br /&gt;  &lt;span class="keyword"&gt;public&lt;/span&gt; When_A_Puzzle_Has_No_Solution(&lt;span class="type"&gt;ISolver&lt;/span&gt; solver)&lt;br /&gt;  {&lt;br /&gt;    this.solver = solver;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  [&lt;span class="type"&gt;TestInitialize&lt;/span&gt;]&lt;br /&gt;  &lt;span class="keyword"&gt;public void&lt;/span&gt; Initialize()&lt;br /&gt;  {&lt;br /&gt;    puzzle = new &lt;span class="type"&gt;Puzzle&lt;/span&gt;();&lt;br /&gt;&lt;br /&gt;    puzzle.Rows[0][0].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Five;&lt;br /&gt;    puzzle.Rows[0][1].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.One;&lt;br /&gt;    puzzle.Rows[0][2].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Three;&lt;br /&gt;    puzzle.Rows[0][3].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Two;&lt;br /&gt;    puzzle.Rows[0][4].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Nine;&lt;br /&gt;    puzzle.Rows[0][5].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Four;&lt;br /&gt;    puzzle.Rows[0][6].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Eight;&lt;br /&gt;    puzzle.Rows[0][7].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Seven;&lt;br /&gt;    puzzle.Rows[0][8].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Six;&lt;br /&gt;    puzzle.Rows[1][0].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Eight;&lt;br /&gt;    puzzle.Rows[1][1].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Two;&lt;br /&gt;    puzzle.Rows[1][2].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Seven;&lt;br /&gt;    puzzle.Rows[1][3].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Five;&lt;br /&gt;    puzzle.Rows[1][4].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Six;&lt;br /&gt;    puzzle.Rows[1][5].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.One;&lt;br /&gt;    puzzle.Rows[1][6].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Three;&lt;br /&gt;    puzzle.Rows[1][7].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Four;&lt;br /&gt;    puzzle.Rows[1][8].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Nine;&lt;br /&gt;    puzzle.Rows[2][0].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Nine;&lt;br /&gt;    puzzle.Rows[2][1].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Six;&lt;br /&gt;    puzzle.Rows[2][2].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Four;&lt;br /&gt;    puzzle.Rows[2][3].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Seven;&lt;br /&gt;    puzzle.Rows[2][4].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Eight;&lt;br /&gt;    puzzle.Rows[2][5].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Three;&lt;br /&gt;    puzzle.Rows[2][6].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.One;&lt;br /&gt;    puzzle.Rows[2][7].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Two;&lt;br /&gt;    puzzle.Rows[2][8].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Five;&lt;br /&gt;    puzzle.Rows[3][0].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Six;&lt;br /&gt;    puzzle.Rows[3][1].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Five;&lt;br /&gt;    puzzle.Rows[3][2].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.One;&lt;br /&gt;    puzzle.Rows[3][3].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Three;&lt;br /&gt;    puzzle.Rows[3][4].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Seven;&lt;br /&gt;    puzzle.Rows[3][5].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Nine;&lt;br /&gt;    puzzle.Rows[3][6].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Two;&lt;br /&gt;    puzzle.Rows[3][7].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Eight;&lt;br /&gt;    puzzle.Rows[3][8].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Four;&lt;br /&gt;    puzzle.Rows[4][0].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Two;&lt;br /&gt;    puzzle.Rows[4][1].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Eight;&lt;br /&gt;    puzzle.Rows[4][2].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Nine;&lt;br /&gt;    puzzle.Rows[4][3].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.One;&lt;br /&gt;    puzzle.Rows[4][4].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Five;&lt;br /&gt;    puzzle.Rows[4][5].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Six;&lt;br /&gt;    puzzle.Rows[4][6].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Seven;&lt;br /&gt;    puzzle.Rows[4][7].AssignedValue = &lt;span class="type"&gt;Value&lt;/span&gt;.Three;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  [&lt;span class="type"&gt;TestMethod&lt;/span&gt;]&lt;br /&gt;  &lt;span class="keyword"&gt;public void&lt;/span&gt; No_Solution_Should_Be_Provided()&lt;br /&gt;  {&lt;br /&gt;    &lt;span class="type"&gt;Assert&lt;/span&gt;.IsNull(solver.Solve(puzzle));&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;Note that for this scenario I took the puzzle from &lt;a href="http://jaychapman.blogspot.com/2007/12/sudoku-part-0-introduction.html"&gt;Part 0&lt;/a&gt; which proved to be unsolvable and used it as my test puzzle.&lt;br /&gt;&lt;br /&gt;Hopefully this gives you a good idea of how to define your behaviors.  In the next post we'll look at creating concrete tests for an actual implementation of a solver that exhibits the behaviors we discussed here.  Note that we discussed the behavior unit tests first since when developing with Behavior-Driven Development, the behavior tests come first!&lt;br /&gt;&lt;br /&gt;--John Chapman&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-3266352553612946685?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=t8f3Ra2UOEk:pEhsSQkvCdE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=t8f3Ra2UOEk:pEhsSQkvCdE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=t8f3Ra2UOEk:pEhsSQkvCdE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/t8f3Ra2UOEk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/3266352553612946685/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=3266352553612946685" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/3266352553612946685?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/3266352553612946685?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/t8f3Ra2UOEk/sudoku-part-1-defining-solver-behavior.html" title="Sudoku Part 1: Defining The Solver Behavior" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_NwVxkBFPJG8/R3-6BUfzuYI/AAAAAAAAABM/LWhRHC1kXX4/s72-c/ValidSolvedPuzzle.gif" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2008/01/sudoku-part-1-defining-solver-behavior.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0MMQXcyeip7ImA9WB9aE08.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-4655082707993760155</id><published>2008-01-02T20:36:00.000-05:00</published><updated>2008-01-02T20:58:00.992-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-01-02T20:58:00.992-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="CodeMash" /><title>CodeMash 2008 Here I Come!</title><content type="html">&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;a href="http://www.codemash.org/"&gt; &lt;img src="http://www.codemash.org/images/bloggerbadge2008.gif" alt="CodeMash – I'll be there!" /&gt;&lt;/a&gt;&lt;a href="http://www.codemash.org/" rel="tag"&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Well, it's official I've gone and registered for CodeMash 2008!  I'm really looking forward to this conference.  If anyone who reads this is going to attend let me know, maybe we can meet up at some point.&lt;br /&gt;&lt;br /&gt;These are just some of the interesting topics I'm looking forward to.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;LinqTo&lt;t&gt;: Implementing IQueryProvider (Bill Wagner)&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Has anyone out there taken a look at what it takes to implement your own Linq provider?  It's a major pain in the rear!  Now, I don't know to what depths Bill will go, but any good overview would really be helpful.  For this session I'm not really looking for a good how to implement guide, since I doubt I'll ever work on my own custom Linq provider, but really it's more to help me get a better grasp of how Linq is working under the covers to help myself in consuming it!&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Putting the Fun into Functional with F# (Dustin Campbell)&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Ok, so I've kind of been watching the boat sail on all of the popular dynamic languages.  I've dabbled in the past with python, but only very slightly.  I've written a modest amount of javascript to get the hang of the ideas behind it, but I think a good solid introduction to the up and coming dynamic first class citizen of .NET is in order.  Let's get a good introduction to all of the fuss.  I should have enough of python to follow along with the presentation.  Again, this isn't something I plan to use on a day to day basis, but rather just help me understand how the other half lives, and help me to understand why I make the choices that I do.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Introduction To Behavior Driven Development (Andrew Glober)&lt;/li&gt;&lt;ul&gt;&lt;li&gt;This one concerns me a little bit with the introduction tag, but I'm starting to become a big fan of Behavior Driven Development or (BDD).  Any additional insight in to the thought processes which it takes to implement it properly would be beneficial to me.  Plus the fact that it is being shown for a Java implementation might help me to think a little bit out of the box while implementing BDD myself in the C# world.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Story-Driven Testing (Jim Holmes)&lt;/li&gt;&lt;ul&gt;&lt;li&gt;This one basically belongs with the prior item.  It's just an area which I want to learn more about.  I believe this one should have a .NET focus (not that it is even necessarily for the topic).&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Introducing Castle (Jay R. Wren)&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Castle is one of those projects I've grown to enjoy.  I still won't use some parts of the project (like ActiveRecord), but that is also the beauty of Castle.  You don't have to.  You take the pieces you want.  I've grown to enjoy Microkernel/Windsor and while I've never actually used MonoRail, it actually makes a lot of sense to me.  The Microsoft MVC framework actually helped me realize just how good of an MVC framework already existed for the .NET platform.  So, while the term Introducing may be a slight put off, there is still a chance to see some items in a different light.  Plus, I've met Jay in the past, and he's a sharp guy.  I would like to see a full presentation on what he has to say about the subject.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Introduction To Workflow Foundation (Keith Elder)&lt;/li&gt;&lt;ul&gt;&lt;li&gt;On this one I don't really mind the Introduction part.  I really don't know much about implementing WF.  I understand you need to run the engine yourself, and I've seen the GUI used to create workflows, but really I don't know much beyond that.  It's something which has seemed like it would provide benefits to me and my projects in the past, but I haven't ever gotten enough expertise to know for sure if it was something to invest in or not.  Hopefully this will help me down that path.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Rails: A Peek Under The Covers (Brian Sam-Bodden)&lt;/li&gt;&lt;ul&gt;&lt;li&gt;I'm going a bit in to the deep end on this one.  I understand only the absolute minimum of Ruby, yet who hasn't heard of Ruby on Rails?  This may give a better oversight regarding why it has become such a popular framework.  I'm familiar with the ideas behind what the Rail framework offers, but seeing how it works with Ruby should be interesting.&lt;/li&gt;&lt;/ul&gt;&lt;/ol&gt;And this is just a short list.  I haven't actually checked to see what the times are for these sessions, lets just hope I am able to get to all of them.&lt;br /&gt;&lt;br /&gt;Hopefully I'll see you all at CodeMash!&lt;br /&gt;&lt;br /&gt;--John Chapman&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-4655082707993760155?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=0_qnaA3KhgQ:YM3oAbKcPDA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=0_qnaA3KhgQ:YM3oAbKcPDA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=0_qnaA3KhgQ:YM3oAbKcPDA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/0_qnaA3KhgQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/4655082707993760155/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=4655082707993760155" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/4655082707993760155?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/4655082707993760155?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/0_qnaA3KhgQ/codemash-2008-here-i-come.html" title="CodeMash 2008 Here I Come!" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2008/01/codemash-2008-here-i-come.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUDQHs8fyp7ImA9WxRaEUk.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-6662416085115871194</id><published>2007-12-30T09:44:00.000-05:00</published><updated>2008-12-12T22:51:11.577-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-12T22:51:11.577-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Dependency Injection" /><category scheme="http://www.blogger.com/atom/ns#" term="Sudoku" /><category scheme="http://www.blogger.com/atom/ns#" term="Behavior-Driven Development" /><title>Sudoku Part 0: Introduction</title><content type="html">&lt;div style="border: 1px dashed rgb(51, 51, 51); background: rgb(221, 221, 221) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;&lt;ul style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2007/12/sudoku-part-0-introduction.html"&gt;Sudoku Part 0&lt;/a&gt;: Introduction&lt;/li&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2008/01/sudoku-part-1-defining-solver-behavior.html"&gt;Sudoku Part 1&lt;/a&gt;: Defining The Solver Behavior&lt;/li&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2008/01/sudoku-part-2-implementing-solver.html"&gt;Sudoku Part 2&lt;/a&gt;: Implementing A Solver&lt;/li&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2008/01/sudoku-part-3-defining-generator.html"&gt;Sudoku Part 3&lt;/a&gt;: Defining The Generator Behavior&lt;/li&gt;&lt;li style="margin-top: 0.5em; margin-bottom: 0.5em;"&gt;&lt;a href="http://jaychapman.blogspot.com/2008/02/sudoku-part-4-implementing-generator.html"&gt;Sudoku Part 4&lt;/a&gt;: Implementing A Generator&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;br /&gt;It's been a while since my last post here.  Part of the reason it has been so long is the fact that I traveled for the holidays, making it more difficult to make time to update this blog.&lt;br /&gt;&lt;br /&gt;While traveling I break out sudoku (and other similar puzzle games) to help the time go by on the way to my destination.  As a programmer I tend to take any problem I'm solving and analyze it as if I was developing a program to solve the problem for me.  This isn't generally something I follow through on, but rather just a mental exercise where I wonder about the what ifs.&lt;br /&gt;&lt;br /&gt;While working on a Sudoku puzzle I thought, as fun as solving this puzzle is, writing an algorithm that solved it in the same manner that I do would be even more enjoyable.  Better yet, there may be many ways to build a sudoku solving algorithm.  I also thought that in order to make an enjoyable sudoku solving algorithm I would also need to create a sudoku generating algorithm.  Again, I thought there may be potential for many algorithms.&lt;br /&gt;&lt;br /&gt;This time it got me thinking.  Sudoku is fun, maybe this would be a good platform to introduce some topics.  I have spent some time reading about Behavior-Driven Development (BDD), and would like to introduce an example of it on my blog.  This seems like a good candidate.  Most people are familiar with the puzzles.  Secondly, I would also like to use this as an example for how to use a Dependency Injection framework.  The fact that I hope to be able to generate multiple algorithms would seem to enforce the use of such a tool here.&lt;br /&gt;&lt;br /&gt;I plan to make this a multi-part series as there are too many topics to cover to justify a single blog post.  I am currently investigating this program now, so don't blame me if it takes a while to write the entire series.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Initial Thoughts&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When I was first thinking about these problems on the Plane I thought a sudoku generator would be relatively simple.  Well I can now say with confidence that it is not.  The algorithm I formed in my head went something like the following:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Divide the board in to rows, columns and regions, matching the general rules for the game.&lt;/li&gt;&lt;li&gt;For each row, column and region create a set of Sudoku values (1-9) which are valid to be used for that grouping.&lt;/li&gt;&lt;li&gt;Loop over all pieces of the board&lt;/li&gt;&lt;li&gt;For each piece take the intersection of the valid values from this pieces row, column and region&lt;/li&gt;&lt;li&gt;Randomly select a value from the remaining values, assign it's value to the piece and then remove it from the list of valid values for the pieces row, column and region.&lt;/li&gt;&lt;li&gt;Once a valid board is created, randomly select a piece on the board to clear the value from&lt;/li&gt;&lt;li&gt;Continue randomly removing values until the puzzle is no longer uniquely solvable, and re-add the last removed value.&lt;/li&gt;&lt;/ol&gt;This seemed like a reasonable algorithm to me.  It seemed that there would always be a choice for valid values seeing as all previous pieces used valid values.  I guess I just assumed that while placing pieces there would always be remaining valid pieces until you finished the puzzle.  To my initial surprise, this algorithm failed on step 5 every time.  The generator kept kitting situations where there were no valid values which could be placed on the current piece.&lt;br /&gt;&lt;br /&gt;See the below example of the result of my algorithm.  Note that there is no valid value which can be placed in the next box, even though all previous entries were entirely valid.  According to the row of the piece the value should be 4.  Yet 4 is invalid for that piece's column and region.  So clearly 4 will not work there.  Any value besides 4 will cause an issue for the row.  This algorithm clearly doesn't work.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_NwVxkBFPJG8/R3e1IEfzuXI/AAAAAAAAABE/2Aa66JhT9oI/s1600-h/FailedSudoku.gif"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_NwVxkBFPJG8/R3e1IEfzuXI/AAAAAAAAABE/2Aa66JhT9oI/s400/FailedSudoku.gif" alt="" id="BLOGGER_PHOTO_ID_5149783849172187506" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;With that experiment I'm pretty much back to the drawing board.  I do have a few ideas on algorithms that should work, but my goal with this is to have at least two working sudoku generation algorithms.  So far I'm at least enjoying the hunt for a working algorithm.  I would like to create at least one solution on my own, but at some point I may have to break down and look for some assistance.&lt;br /&gt;&lt;br /&gt;--John Chapman&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-6662416085115871194?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=8k9KGZgI2mg:dGX0v3gMs00:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=8k9KGZgI2mg:dGX0v3gMs00:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=8k9KGZgI2mg:dGX0v3gMs00:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/8k9KGZgI2mg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/6662416085115871194/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=6662416085115871194" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/6662416085115871194?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/6662416085115871194?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/8k9KGZgI2mg/sudoku-part-0-introduction.html" title="Sudoku Part 0: Introduction" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_NwVxkBFPJG8/R3e1IEfzuXI/AAAAAAAAABE/2Aa66JhT9oI/s72-c/FailedSudoku.gif" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2007/12/sudoku-part-0-introduction.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU8FQH44cSp7ImA9WB9UGE4.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-6721292253966782995</id><published>2007-12-16T12:59:00.001-05:00</published><updated>2007-12-16T14:36:51.039-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-12-16T14:36:51.039-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio 2008" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><title>UI: Good Use For Extension Methods</title><content type="html">Ok, this is a little weird for me, but I think I just had my epiphany.  I think I have finally converted in to an Extnsions Methods believer!  I know, first there was &lt;a href="http://jaychapman.blogspot.com/2007/10/c-30-extension-methods-good-idea.html"&gt;C# 3.0 Extension Methods? A Good Idea?&lt;/a&gt; and then there was &lt;a href="http://jaychapman.blogspot.com/2007/12/reserving-judgment.html"&gt;Reserving Judgement&lt;/a&gt;, but now I have found where I really, really like them.&lt;br /&gt;&lt;br /&gt;How many of you have written a class like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span class="keyword"&gt;public class&lt;/span&gt; &lt;span class="type"&gt;Person&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;   &lt;span class="keyword"&gt;private string&lt;/span&gt; firstName;&lt;br /&gt;   &lt;span class="keyword"&gt;private string&lt;/span&gt; lastName;&lt;br /&gt;&lt;br /&gt;   &lt;span class="keyword"&gt;public string&lt;/span&gt; FirstName&lt;br /&gt;   {&lt;br /&gt;       &lt;span class="keyword"&gt;get&lt;/span&gt; { &lt;span class="keyword"&gt;return&lt;/span&gt; firstName; }&lt;br /&gt;       &lt;span class="keyword"&gt;set&lt;/span&gt; { firstName = &lt;span class="keyword"&gt;value&lt;/span&gt;; }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   &lt;span class="keyword"&gt;public string&lt;/span&gt; LastName&lt;br /&gt;   {&lt;br /&gt;       &lt;span class="keyword"&gt;get&lt;/span&gt; { &lt;span class="keyword"&gt;return&lt;/span&gt; lastName; }&lt;br /&gt;       &lt;span class="keyword"&gt;set&lt;/span&gt; { lastName = &lt;span class="keyword"&gt;value&lt;/span&gt;; }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   &lt;span class="keyword"&gt;public string&lt;/span&gt; GetFullName()&lt;br /&gt;   {&lt;br /&gt;       &lt;span class="keyword"&gt;return&lt;/span&gt; LastName + ", " + FirstName;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I don't know about you, but I feel dirty every time I write something like that.  To me this is display logic, and now it's polluting my business objects!  This really smells to me.  This smells so bad that I prefer to put a method on my page which does the formatting for me.  But the problem is that people are used to this sort of syntax.  They expect this to be how they format that class.&lt;br /&gt;&lt;br /&gt;How do we satisfy both sides?  Keep the presentation logic out of the business layer, yet keep the interfaces clean?  Enter Extension Methods!&lt;br /&gt;&lt;br /&gt;In order to solve this problem I would now create a new static class in my web assembly (UIHelper possibly, or another name that fits).  This new class would look like the following:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span class="keyword"&gt;public static class&lt;/span&gt; &lt;span class="type"&gt;UIHelper&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;   &lt;span class="keyword"&gt;public static string&lt;/span&gt; GetFullName(&lt;span class="keyword"&gt;this&lt;/span&gt; &lt;span class="type"&gt;Person&lt;/span&gt; person)&lt;br /&gt;   {&lt;br /&gt;       &lt;span class="keyword"&gt;return&lt;/span&gt; person.LastName + ", " + person.FirstName;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now you can take the GetFullName method out of the Person class and use the extension method in your UI layer instead.  The class will still work exactly the same way from a UI perspective, except when working within the Person there will no longer be a GetFullName method.&lt;br /&gt;&lt;br /&gt;The Person class now looks like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span class="keyword"&gt;public class&lt;/span&gt; &lt;span class="type"&gt;Person&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;   &lt;span class="keyword"&gt;private string&lt;/span&gt; firstName;&lt;br /&gt;   &lt;span class="keyword"&gt;private string&lt;/span&gt; lastName;&lt;br /&gt;&lt;br /&gt;   &lt;span class="keyword"&gt;public string&lt;/span&gt; FirstName&lt;br /&gt;   {&lt;br /&gt;       &lt;span class="keyword"&gt;get&lt;/span&gt; { &lt;span class="keyword"&gt;return&lt;/span&gt; firstName; }&lt;br /&gt;       &lt;span class="keyword"&gt;set&lt;/span&gt; { firstName = &lt;span class="keyword"&gt;value&lt;/span&gt;; }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   &lt;span class="keyword"&gt;public string&lt;/span&gt; LastName&lt;br /&gt;   {&lt;br /&gt;       &lt;span class="keyword"&gt;get&lt;/span&gt; { &lt;span class="keyword"&gt;return&lt;/span&gt; lastName; }&lt;br /&gt;       &lt;span class="keyword"&gt;set&lt;/span&gt; { lastName = &lt;span class="keyword"&gt;value&lt;/span&gt;; }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Just make sure you add the using directive to the namespace which contains the UIHelper class on your page (or add an Import directive to your aspx file).  Your code on the page now looks like the following:&lt;br /&gt;&lt;br /&gt;This is actually the happiest I've been with any use of extension methods when you control the class which is being extended.&lt;br /&gt;&lt;br /&gt;--John Chapman&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-6721292253966782995?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=GHWdUL7epQY:fj6-BXBduOk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=GHWdUL7epQY:fj6-BXBduOk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=GHWdUL7epQY:fj6-BXBduOk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/GHWdUL7epQY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/6721292253966782995/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=6721292253966782995" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/6721292253966782995?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/6721292253966782995?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/GHWdUL7epQY/ui-good-use-for-extension-methods.html" title="UI: Good Use For Extension Methods" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2007/12/ui-good-use-for-extension-methods.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0MARHw9eip7ImA9WB9UGE0.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-2424088115307321477</id><published>2007-12-16T06:27:00.000-05:00</published><updated>2007-12-16T06:44:05.262-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-12-16T06:44:05.262-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="mvc" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><title>Are Developers Lazy?</title><content type="html">I have been watching the ASP.NET 3.5 Extensions with great interest.  Of special note is the MVC framework that Microsoft is adding to ASP.NET.  If you haven't heard anything about this framework I recommend you go take a look at the posts Scott Guthrie has made starting with this &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=A9C6BC06-B894-4B11-8300-35BD2F8FC908&amp;amp;displaylang=en"&gt;one&lt;/a&gt;.  I'm really excited about the potential enhancements which are offered with this new framework.  Yes, I know Monorail is nothing new, but something has always kept me from adopting it. &lt;br /&gt;&lt;br /&gt;Of particular interest with the Mvc framework is the ability to easily test the majority of your UI code.  This is something which today is near impossible.  Plus, who hasn't been frustrated with the quality of the HTML which are generated by the ASP.NET WebForms?  Finally a way to take real control of your web pages while still using the ASP.NET pipelines (or at least what is remaining of it).&lt;br /&gt;&lt;br /&gt;What has really caught me by surprise though is the amount of complaining people are doing regarding the ControllerActionAttribute.  Basically with the Mvc framework in order to expose an action from a controller (an action basically equates to the way a given URL interacts with the controller) you need to mark it with the ControllerActionAttribute.  This is the default policy which Microsoft provides, and you can change it if you want to go through the many steps involved in re-working some of their components.&lt;br /&gt;&lt;br /&gt;Developers have been seemingly outraged by this.  Instead most developers (at least the ones who speak the loudest) seem to say that any public method on the Controller should automatically be considered a controller action meaning all public methods of a controller should be publicly accessible via a URL.   Now, I may be in the minority here, but  having public methods exposed from a URL is actually pretty scary, and I actually like explicitly specifying which methods are exposed to a URL and which are not.  Not because I wouldn't be able to tell with just public methods, and not that I wouldn't be able to use it properly, but just from a sense that many developers mistakenly write public methods when they should not be public.  A developer may not realize what the "magic" is which is taking place.  By making it specific it takes very little time, and then there is far less chance of mistakenly exposing parts of the application that have no business being exposed.&lt;br /&gt;&lt;br /&gt;Is it really that much work to mark a property as [ControllerAction].  I don't get it.  It takes half a millisecond, and then everything is clear.  After all, we do this same sort of thin with all of our unit testing frameworks don't we?  Why not just automatically treat every public method of a test fixture as a test unless otherwise marked?  The argument seems to hold there as well.  I understand other Mvc frameworks have worked in this way where an attribute wasn't needed, but so what?  Is it that we're lazy, or is it that we are resistant to change?  If we're resistant to change, then it seems like this whole argument is moot since this Mvc framework is a big change already.&lt;br /&gt;&lt;br /&gt;Maybe instead we're resistant to change so complaining ensues for a couple of months before we realize that there are actually benefits on the other side and then we quiet down for a while?&lt;br /&gt;&lt;br /&gt;The really interesting part to all of this is that the people complaining about the attribute are the same people who complain about the designer and drag &amp;amp; drop "programming".  Admittedly, I am also one of those people who hates the designer.  This means that when it comes to writing their pages they aren't being lazy.  They are taking great care of the final output and look of their application. &lt;br /&gt;&lt;br /&gt;So if being lazy is not a problem while writing the HTML for your web pages (or views as I should say with Mvc), then why is assigning an attribute such a big deal?&lt;br /&gt;&lt;br /&gt;--John Chapman&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-2424088115307321477?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=DsY19UDDbYI:OAIzJo_wYDU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=DsY19UDDbYI:OAIzJo_wYDU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=DsY19UDDbYI:OAIzJo_wYDU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/DsY19UDDbYI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/2424088115307321477/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=2424088115307321477" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/2424088115307321477?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/2424088115307321477?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/DsY19UDDbYI/are-developers-lazy.html" title="Are Developers Lazy?" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2007/12/are-developers-lazy.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkYFRHc9fSp7ImA9WB9UFU0.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-2200329041592734858</id><published>2007-12-12T19:59:00.000-05:00</published><updated>2007-12-12T20:08:35.965-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-12-12T20:08:35.965-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Testing" /><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio 2008" /><title>Visual Studio 2008 Test Result Cleanup!</title><content type="html">I don't know how many other people used the MSTest (Unit Testing capabilities of Visual Studio 2005 Team Edition) but those test results really pile up after a while. &lt;br /&gt;&lt;br /&gt;We currently have 525 unit tests on our current project.  At one point in time I noticed that my disk space was running low on my development machine.  I had no clue how so much space could evaporate so quickly.  I started doing quick checks on different folders that I thought could be problematic.  I eventually found my way to our solution folders.  We typically have multiple branches loaded on our local machine, but I never thought we wrote enough code to justify a 20+ Gig project folder.  Further investigation led me to a folder known as TestResults. I found out that Visual Studio was keeping the results of every unit test run I ever did.&lt;br /&gt;&lt;br /&gt;Don't get me wrong, I love the ability to review past test runs to see where one failed.  I really enjoy the ability to create bugs directly from the results of the test where the associated result is attached to the bug for the assigned developer to review (assuming it wasn't the assigned developer that noticed the failing test).  But keeping a history of these files was really adding up!&lt;br /&gt;&lt;br /&gt;I found myself deleting the old test runs from this folder every so often.  Then something really interesting happened today.  I tried running my full suite of tests after loading the solution in Visual Studio 2008.  A message box appeared stating that my old test runs will be deleted since I will be over the maximum of 25 historical test runs.  It made me agree to the deletion of these items and also told me that the number was configurable in the Tools &gt; Options menu! &lt;br /&gt;&lt;br /&gt;Now, maybe this feature existed in 2005, but I could never find it.  This turns out to be one of those features that isn't really advertised, isn't major but just made me happy.  For some reason it's the little things that seem to get me excited.  It seems like this would have been so simple to leave out, yet they took care of it anyway. &lt;br /&gt;&lt;br /&gt;Good job on that one Microsoft!  You just made my life a little easier.&lt;br /&gt;&lt;br /&gt;--John Chapman&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-2200329041592734858?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=dnap9t6xT8g:1huQlTsJNXg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=dnap9t6xT8g:1huQlTsJNXg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=dnap9t6xT8g:1huQlTsJNXg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/dnap9t6xT8g" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/2200329041592734858/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=2200329041592734858" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/2200329041592734858?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/2200329041592734858?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/dnap9t6xT8g/visual-studio-2008-test-result-cleanup.html" title="Visual Studio 2008 Test Result Cleanup!" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2007/12/visual-studio-2008-test-result-cleanup.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMMSHo9fip7ImA9WB9UE0k.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-396775297282585498</id><published>2007-12-10T20:17:00.000-05:00</published><updated>2007-12-10T21:34:49.466-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-12-10T21:34:49.466-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Rhino Mocks" /><category scheme="http://www.blogger.com/atom/ns#" term="Open Source Software" /><title>Open Source Rocks!</title><content type="html">I've recently began seriously investigating mocking frameworks (See &lt;a href="http://nmock.org/"&gt;NMock&lt;/a&gt; and &lt;a href="http://www.ayende.com/projects/rhino-mocks.aspx"&gt;Rhino Mocks&lt;/a&gt; specifically).  I've looked at mock frameworks before, but I was quick to dismiss them.  I never really saw the benefit.  I honestly don't think I really understood what they were used for.&lt;br /&gt;&lt;br /&gt;At first I thought maybe it was used to automatically create my business objects so that I would have full object graphs in memory.  This is something we use a lot to perform mapping file tests, it turned out the tools didn't really fit for this purpose, and I pushed them aside.&lt;br /&gt;&lt;br /&gt;Now, I spent some time again wondering if I missed the big picture when I looked before.  After all this was years ago that I last researched mock frameworks.  While the NMock interface seemed pretty clean to me I didn't like the use of strings.  Rhino Mock's ability to use strongly typed method calls was a deal sealer.  How could I use a weakly typed mock framework when a popular strongly typed variety exists?&lt;br /&gt;&lt;br /&gt;I've decided that mock frameworks come in handy while performing unit tests which would otherwise use external resources.  Previously I always skipped testing these methods and moved as much of the business logic to methods which had no outside dependencies.  I've finally seen the light and embraced the mock frameworks for what they were truly intended.&lt;br /&gt;&lt;br /&gt;If you haven't looked at Rhino Mocks, I strongly recommend you do!  Let's take a very simple example to see the power of this tool!  This is a totally contrived example, so don't blame me if it is unrealistic.  Let's say you have a dependency on an external pricing service which finds the best available price for a given product in your companies purchasing department.  Let's define the needed interface as IPricingService&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;public interface&lt;/span&gt; &lt;span style="color:#99cccc;"&gt;IPricingService&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;  &lt;span style="color:blue;"&gt;decimal&lt;/span&gt; GetPrice(&lt;span style="color:#99cccc;"&gt;Product&lt;/span&gt; p);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A very simple service for sure.  Given any product it will return the current price which we can pay for that product.  We'll use this service in our AddDetail Method of our Order class.  See the Order, OrderDetail and Product implementations below.  Note I use public fields for brevity only.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;public class&lt;/span&gt; &lt;span style="color:#99cccc;"&gt;Product&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;  &lt;span style=""&gt;public int&lt;/span&gt; Id;&lt;br /&gt;  &lt;span style="color:blue;"&gt;public string&lt;/span&gt; Name;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;public class&lt;/span&gt; &lt;span style=""&gt;Order&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;  &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:#99cccc;"&gt;IPricingService&lt;/span&gt; pricingService;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:#99cccc;"&gt;IList&lt;/span&gt;&amp;lt;&lt;span style="color:#99cccc;"&gt;OrderDetail&lt;/span&gt;&amp;gt; Details&lt;br /&gt;      = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#99cccc;"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color:#99cccc;"&gt;OrderDetail&lt;/span&gt;&amp;gt;();&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:blue;"&gt;public&lt;/span&gt; Order(&lt;span style="color:blue;"&gt;IPricingService &lt;/span&gt; pricingService)&lt;br /&gt;  {&lt;br /&gt;      this.pricingService = pricingService;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:#99cccc;"&gt;OrderDetail&lt;/span&gt; AddDetail(&lt;span style="color:#99cccc;"&gt;Product&lt;/span&gt; product, &lt;span style="color:blue;"&gt;int&lt;/span&gt; quantity)&lt;br /&gt;  {&lt;br /&gt;      &lt;span style="color:#99cccc;"&gt;OrderDetail&lt;/span&gt; detail&lt;br /&gt;          = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#99cccc;"&gt;OrderDetail&lt;/span&gt;(&lt;br /&gt;              product,&lt;br /&gt;              quantity,&lt;br /&gt;              pricingService.GetPrice(product));&lt;br /&gt;&lt;br /&gt;      Details.Add(detail);&lt;br /&gt;      &lt;span style="color:blue;"&gt;return&lt;/span&gt; detail;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;public class&lt;/span&gt; &lt;span style="color:#99cccc;"&gt;OrderDetail&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;  &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:#99cccc;"&gt;Product&lt;/span&gt; Product;&lt;br /&gt;  &lt;span style="color:blue;"&gt;public int&lt;/span&gt; Quantity;&lt;br /&gt;  &lt;span style="color:blue;"&gt;public decimal&lt;/span&gt; Price;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:blue;"&gt;public&lt;/span&gt; OrderDetail(&lt;span style="color:#99cccc;"&gt;Product&lt;/span&gt; product, &lt;span style="color:blue;"&gt;&lt;br /&gt;      int&lt;/span&gt; quantity, &lt;span style="color:blue;"&gt;&lt;br /&gt;      decimal&lt;/span&gt; price)&lt;br /&gt;  {&lt;br /&gt;      &lt;span style="color:blue;"&gt;this&lt;/span&gt;.Product = product;&lt;br /&gt;      &lt;span style="color:blue;"&gt;this&lt;/span&gt;.Quantity = quantity;&lt;br /&gt;      &lt;span style="color:blue;"&gt;this&lt;/span&gt;.Price = price;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now our job is to test the AddDetail method which we see above.  Well we don't want to rely on an actual pricing service which would use in production, so instead we will resort to our trusty Rhino Mocks framework to fill in a fake implementation.  Now we can test 100% of the code in our Order without worrying about external dependencies.  This helps keep our unit tests focussed as well as allows us to improve our code coverage.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[&lt;span style="color:#99cccc;"&gt;TestMethod&lt;/span&gt;]&lt;br /&gt;&lt;span style="color:blue;"&gt;public void&lt;/span&gt; AddDetail()&lt;br /&gt;{&lt;br /&gt;  &lt;span style="color:#99cccc;"&gt;MockRepository&lt;/span&gt; mocks = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#99cccc;"&gt;MockRepository&lt;/span&gt;();&lt;br /&gt;  &lt;span style="color:#99cccc;"&gt;Product&lt;/span&gt; p = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#99cccc;"&gt;Product&lt;/span&gt;();&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:#99cccc;"&gt;IPricingService&lt;/span&gt; pricingService&lt;br /&gt;      = mocks.CreateMock&amp;lt;&lt;span style="color:#99cccc;"&gt;IPricingService&lt;/span&gt;&amp;gt;();&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:#99cccc;"&gt;Expect&lt;/span&gt;.Call(pricingService.GetPrice(p)).Return(15.50M);&lt;br /&gt;&lt;br /&gt;  mocks.ReplayAll();&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:#99cccc;"&gt;Order&lt;/span&gt; order = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#99cccc;"&gt;Order&lt;/span&gt;(pricingService);&lt;br /&gt;  &lt;span style="color:#99cccc;"&gt;OrderDetail&lt;/span&gt; newDetail = order.AddDetail(p, 20);&lt;br /&gt;  &lt;span style="color:#99cccc;"&gt;Assert&lt;/span&gt;.AreEqual&amp;lt;&lt;span style="color:blue;"&gt;decimal&lt;/span&gt;&amp;gt;(15.50M, newDetail.Price);&lt;br /&gt;  &lt;span style="color:#99cccc;"&gt;Assert&lt;/span&gt;.AreEqual&amp;lt;&lt;span style="color:blue;"&gt;int&lt;/span&gt;&amp;gt;(20, newDetail.Quantity);&lt;br /&gt;&lt;br /&gt;  mocks.VerifyAll();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Take special note of the MockRepository, the CreateMock method and the Expect builder.  Expect basically tells the framework that it should expect a call to the method provided in the Call() and to expect it for the specified parameter.  When the mock receives that call that the provided parameter it should return the value 15.5 as the price.&lt;br /&gt;&lt;br /&gt;ReplayAll is a bit confusing, but basically this tells Rhino Mocks to stop using the method calls for recording instead use it to return the results we configured and to track the calls which are made.&lt;br /&gt;&lt;br /&gt;After we have called ReplayAll we make our method calls and assert that the new order detail was created correctly and added with the appropriate price which was returned by the pricing service.  VerifyAll tells us that our expectations we created before replaying were met (such as expecting a call to the GetPrice method with a parameter of p.&lt;br /&gt;&lt;br /&gt;If I didn't want to set expectations for method calls I could have opted for the SetupResults class instead of Expect class.&lt;br /&gt;&lt;br /&gt;This is just the tip of the ice berg regarding the framework.  If this peeked your interest, you owe it to yourself to take a deeper look.&lt;br /&gt;&lt;br /&gt;If you're like me and you saw the Expect.Call() taking an execution of the method you expect a call for you asked yourself "How the heck did he do that?"  When I first tried it I was blown away that it worked.  I tried to come up with ideas of how it worked.&lt;br /&gt;&lt;br /&gt;This is one of the true beauties of open source software.  I can satisfy my own curiosity!  After playing with the framework I downloaded the source code to check it out.  The final implementation wasn't actually that complex.  Basically the proxy object which the mock framework creates tracks what the last method call was and what parameters were provided to the method call.  So the Call() method doesn't really do anything except return the options for the last method call which was made.  The fact that it is provided as an argument to Call() is complete ignored!  I view this as genius.  It's really thinking out of the box in a way that I'm not so sure I would have come up with.  Being exposed to code that works in different ways that I think allows me to expand my mind and come up with solutions to my own problems I may not have previously come up with.&lt;br /&gt;&lt;br /&gt;I've also spent a considerable amount of time reviewing some of the NHibernate code.  This is after all how I was able to write such a specific performance test regarding the &lt;a href="http://jaychapman.blogspot.com/2007/11/nhibernate-access-performance.html"&gt;performance of NHibernate accessors&lt;/a&gt; after all.  I used just the specific NHibernate pieces I needed.&lt;br /&gt;&lt;br /&gt;As software developers we are unbelievable lucky to be living in such a day and age where such great software code is available for free for us to learn from.  I recommend to everyone interested in really improving their skills find an open source project which revolves around something you are interested in and take a look.  There is tons of great stuff out there!  We should all take advantage.&lt;br /&gt;&lt;br /&gt;Lastly, I just want to thank Oren Eini (aka &lt;a href="http://www.ayende.com/"&gt;Ayende Rahien&lt;/a&gt;), this Rhino Mocks framework he created is truly awesome.&lt;br /&gt;&lt;br /&gt;--John Chapman&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-396775297282585498?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=_gt8wXjq99w:fiVYOFsbrbY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=_gt8wXjq99w:fiVYOFsbrbY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=_gt8wXjq99w:fiVYOFsbrbY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/_gt8wXjq99w" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/396775297282585498/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=396775297282585498" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/396775297282585498?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/396775297282585498?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/_gt8wXjq99w/open-source-rocks.html" title="Open Source Rocks!" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2007/12/open-source-rocks.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEAFSXc7eSp7ImA9WB9UEkg.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-1955972676096207276</id><published>2007-12-09T20:07:00.000-05:00</published><updated>2007-12-09T21:11:58.901-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-12-09T21:11:58.901-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio 2008" /><category scheme="http://www.blogger.com/atom/ns#" term="LINQ" /><title>Linq to Sql: The Good, The Bad &amp; The Bottom Line</title><content type="html">I promised my take on Linq to Sql a few days ago.  I have spent some time over the past couple days playing with Linq to Sql connected to the AdventureWorks SQL Server sample database.&lt;br /&gt;&lt;br /&gt;I have a lot of experience working with NHibernate so you may see some comparisons throughout the post.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Overview&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Most everyone who is likely to read this post probably knows what Linq to Sql is.  For those that don't, Linq to Sql (and really Linq in general) has been one of the most talked about (Once we found out Linq to Entities wasn't going to ship with Visual Studio 2008) and hyped features of Visual Studio 2008 and the .NET 3.5 framework.&lt;br /&gt;&lt;br /&gt;Linq to Sql is actually a big shift for Microsoft.  Linq to Sql is Microsoft's first production quality &lt;a href="http://en.wikipedia.org/wiki/Object_Relational_Mapping"&gt;Object Relational Mapper&lt;/a&gt; or O/RM for short.  They may have tried in the past with products such as ObjectSpaces, but this is the first tool to be released as a completed tool.  O/RM tools exist to try and solve the &lt;a href="http://en.wikipedia.org/wiki/Object-Relational_impedance_mismatch"&gt;Object-relational impedance mismatch&lt;/a&gt; which basically says that most applications are developed in object oriented programming languages these days yet the data which they operate on is typically stored in a relational database.  This process of moving data between the objects and relations and vice versa is described as the impedance mismatch.  There are obviously many fundamental differences between data stored in a relation and data stored in our objects.&lt;br /&gt;&lt;br /&gt;Traditionally Microsoft has endorsed using DataSets to solve this problem.  DataSets are essentially a relation based object in your object oriented programming language.  Essentially it would allow you to work with your data in your application as relational data.  The problem with this?  You fail to take advantage of object oriented application design and the advantages it brings to you.  Typically these programs have little testability and a significant amount of duplication.  As such many O/RM tools became popular (although far less so than if Microsoft had endorsed them) such as &lt;a href="http://www.hibernate.org/343.html"&gt;NHibernate&lt;/a&gt;, &lt;a href="http://www.llblgen.com/defaultgeneric.aspx"&gt;LLBLGen Pro&lt;/a&gt;, &lt;a href="http://www.vanatec.com/en/product-information"&gt;Vanatec OpenAccess&lt;/a&gt;, &lt;a href="http://www.ormapper.net/"&gt;Wilson ORMapper&lt;/a&gt;, &lt;a href="http://www.entityspaces.net/Portal/Default.aspx"&gt;EntitySpaces&lt;/a&gt;, &lt;a href="http://www.devexpress.com/Products/NET/Libraries/XPO/"&gt;eXpress Persistent Objects&lt;/a&gt; and many others (apologies to any I didn't list).&lt;br /&gt;&lt;br /&gt;Note that Linq to Sql isn't necessarily a direct competitor to NHibernate or the other above listed O/RM tools for the .NET framework, that is &lt;a href="http://msdn2.microsoft.com/en-us/library/aa697427%28VS.80%29.aspx"&gt;Linq to Entities&lt;/a&gt; (AKA ADO.NET Entity Framework).  Linq to Sql is more of an introduction to the O/RM world.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;The Good&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;ul style="font-weight: bold;"&gt;&lt;li&gt;The Linq query language itself&lt;/li&gt;&lt;/ul&gt;The Linq query language is just awesome.  It really is a joy when you start to work with it.  It can quickly become a pain because it is complex, but then it makes you realize just how powerful it is.  I have never seen a query language that is quite so rich.  Basic queries are very simple to write and understand, yet it also provides functionality for very complex queries.&lt;br /&gt;&lt;br /&gt;Plus, the queries are strongly typed so now there is much less to worry about when refactoring your business objects as compile-time checks are now available for your queries.  Note that even with stored procedures, if you change a column in a table referenced by a stored procedure, it won't inform you that you just broke a stored procedure.  Likewise stored queries in your applications will not inform you if you change a property name or column either.&lt;br /&gt;&lt;br /&gt;For fun see the following blog post: &lt;a href="http://blogs.msdn.com/lukeh/archive/2007/10/01/taking-linq-to-objects-to-extremes-a-fully-linqified-raytracer.aspx"&gt;Taking LINQ to Objects to Extremes: A fully LINQified RayTracer&lt;/a&gt;.  This is not something you woudl actually do, but it does help reinforce just how powerful Linq really is.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Better Naming Conventions Than NHibernate&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;While working with Linq to Sql I felt that the methods on the context were easy to understand and more intuitive than the NHibernate equivalents.  For example, when you want to save your changes to your database NHibernate says &lt;span style="font-style: italic;"&gt;Flush&lt;/span&gt; whereas Linq to Sql uses &lt;span style="font-style: italic;"&gt;SubmitChanges&lt;/span&gt;.  But the big advantages are Linq to Sql's &lt;span style="font-style: italic;"&gt;InsertOnSubmit&lt;/span&gt; vs NHibernate's &lt;span style="font-style: italic;"&gt;Save&lt;/span&gt; as well as &lt;span style="font-style: italic;"&gt;Attach&lt;/span&gt; versus NHibernate's &lt;span style="font-style: italic;"&gt;Update&lt;/span&gt; or &lt;span style="font-style: italic;"&gt;Lock&lt;/span&gt; methods.&lt;br /&gt;&lt;br /&gt;I can't tell you how many times I've explained how the Save, Update and Lock functionality for NHibernate works.  Most people seem to think that they need to call these methods to cause a database operation to take place.  They assume Save = Execute Insert NOW, and Update means execute an update NOW!  Then they use Flush for good measure because someone told them too.  The Linq to Sql naming convention seems to imply that that is not quite what is going on.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Simple to Get Started&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;It didn't take me very long to get up and going with Linq to Sql.  While I'm not the biggest fan of the Object Relational Designer, it sure is easy to use and fast to build basic object graphs.  Someone who is not familiar with O/RM tools should be able to have objects mapped to database tables in a matter of minutes.  This could work very well for simple RAD applications.  This process really couldn't be much simpler.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Superior Optimistic Concurrency Support&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;My apologies to any O/RM tools out there that have as good concurrency support as Linq to Sql, I just know I prefer the flexibilty offered by Linq to Sql over NHibernate's.  Now, that being said NHibernate's concurrency has always worked fine for me, it's just nice to have additional options.&lt;br /&gt;&lt;br /&gt;First, when a &lt;a href="http://msdn2.microsoft.com/en-us/library/system.data.linq.changeconflictexception%28VS.90%29.aspx"&gt;ChangeConflictException&lt;/a&gt; is thrown it includes a ton of information such as the entity involved, the columns involved and allows your code to recover from it.  Linq to Sql will also let you configure if you want to catch all change conflicts or fail as soon as the first conflict is found.  These are features, which to my knowledge, NHibernate does not support.&lt;br /&gt;&lt;br /&gt;Plus, this is basic but Linq to Sql has native support for SQL Server timestamp columns.  This allows you to ensure that you know of all updates even if it occurs outside the scope of Linq to Sql.  For some reason NHibernate still does not support this type of column.  Instead it rolls its own version column.&lt;br /&gt;&lt;br /&gt;Resolving stale data with &lt;a href="http://msdn2.microsoft.com/en-us/library/system.data.linq.refreshmode%28VS.90%29.aspx"&gt;RefreshMode &lt;/a&gt;allows for many options when re-syncing your objects with the database.  Again, I just like the options.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Superior Stored Procedure Support&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;If you have a wealth of stored procedures, rest assured they are easy to use from Linq to Sql.  Just &lt;span style="font-style: italic;"&gt;drag&lt;/span&gt; (I do feel dirty using that word) the stored procedure from the server explorer to the methods list in the object relational designer and you will see a new method on your associated context which directly calls that stored procedure.  To your code it looks the same as any other method.&lt;br /&gt;&lt;br /&gt;Note it is also possible to write your Linq to Sql CRUD through stored procedures.  This is also a relatively simple process.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;The Bad&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Very Basic Object Support&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;This is actually the killer here.  Linq to Sql is a &lt;span style="font-style: italic;"&gt;very&lt;/span&gt; basic O/RM and does not support many of the object oriented concepts sophisticated applications are likely to use. Just a few of the missing features are:&lt;br /&gt;&lt;ul&gt;&lt;ul&gt;&lt;li&gt;No Inheritance&lt;/li&gt;&lt;li&gt;No Value based objects (IE NHibernate Components)&lt;/li&gt;&lt;li&gt;No Timespan support (A huge problem for the Logistics field I work in)&lt;/li&gt;&lt;li&gt;Collections limited to EntitySet (which isn't even a real Set)&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Where is the Dictionary support at least?&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li style="font-weight: bold;"&gt;No SaveOrUpdate Equivalent&lt;/li&gt;&lt;/ul&gt;This forces more persistence knowledge to a lower level requiring that all code which associates an object with a context must know if it already exists in the database or not.  This basically just adds extra checks in your code which should not be necessary.  Sometimes it can seem a bit dirty to check if an object already has a primary key or not yourself, it seems like logic which doesn't belong within the application itself.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;GUI based Drag &amp;amp; Drop&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;Yes, I know you can use a seperate mapping file, much like you can with NHibernate, but this isn't realistic.  If you don't use the designer, you don't get the code generation.  If you don't get the code generation you are responsible for writing all of the many Hooks in your objects that Linq to Sql needs.  Folks, these objects are quite dirty.  At least with NHibernate your objects are complete persistence ignorant (aka POCO aka Plain Old CLR Object) meaning they look clean and usable for more than just NHibernate.  Therefore using anything besides the designer isn't very feasible.&lt;br /&gt;&lt;br /&gt;The big problem here though is that your entire object graph needs to live in one diagram and the code behind these objects winds up in a single code file by default.  This just isn't acceptable for applications of any size.  Diagrams which contain 20-30 objects would be a major pain here, let alone applications that have hundreds.  For large applications this just wouldn't fly.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Relationships Aren't Interface Based&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;All of the associations to related objects are handled with EntitySet&lt;t&gt; and EntityRef&lt;t&gt;.  Whereas with NHibernate you have the ISet&lt;t&gt; and just the object type you expect.  This basically forces the Linq to Sql references on your object, decreasing the ability for unit testing your objects in my opinion.  I also don't like the persistence based decencies on my objects.&lt;br /&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Transaction API is Goofy&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;For whatever reason you need to handle all explicit transactions outside of the Linq to Sql context.  You have to create and the commit it outside the context while supplying the transaction to the context while it is in use.  Linq to Sql implicitly uses transactions for all calls to SubmitChanges, but you would think it would be possible to begin new transactions via the context, and then commit or roll them back through the context as well.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;The Bottom Line&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;Really, I have only touched on a brief overview of Linq to Sql here.  The important question I ask myself is, "Would I use this framework?".  Well, it's a bit of a difficult question.  If I was writing a small application which I knew would not grow in to a large one and my object model would be simple enough for the limited object support, yes I would use it.  I could get up and going very fast, and I enjoy working with the context interfaces.&lt;br /&gt;&lt;br /&gt;However, if I was working on a larger application (really doesn't take much to be too large for what I would do with Linq to Sql), or one which I thought had potential to adjust and grow over time, I would skip Linq to Sql and look for my trusty NHibernate.&lt;br /&gt;&lt;br /&gt;So really, it would only be used for a very small subset of problems out there that I would try to solve.&lt;br /&gt;&lt;br /&gt;All of that being said, I think Linq to Sql is very important to the .NET development community.  Microsoft has historically tried to pretend that O/RM tools didn't exist and to do any development except their DataSets or repetitive patterns was crazy.  Now that Microsoft has a framework to endorse it should greatly expand the exposure to such technologies in the .NET development community.  I think overall this is a good thing, and will result in overall superior developers.&lt;br /&gt;&lt;br /&gt;My only concern with this introduction is that people may get the idea that O/RM tools are nice, and get you up and going fast but fall flat on their face once you try to do anything advanced and then you need to resort to the same tools you used all along.  This was actually a very common opinion by people I talked to about NHibernate a few years ago.  They had heard of others using O/RM tools (not NHibernate specifically) and how they just don't handle advanced things, they are only good for simple things.&lt;br /&gt;&lt;br /&gt;With Linq to Sql I hope developers become exposed to O/RM and become curious about other tools such as NHibernate when Linq to Sql is too simple for what they need instead of grouping all O/RM tools together as being too simple and idealistic.&lt;br /&gt;&lt;br /&gt;I'm actually excited about the potential of the .NET development community now that more people will be exposed to O/RM.  Long live O/RM tools, you have been lifesavers for me!&lt;br /&gt;&lt;br /&gt;--John Chapman&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-1955972676096207276?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=C3gnQhR67TQ:6pX1aqwzcRA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=C3gnQhR67TQ:6pX1aqwzcRA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=C3gnQhR67TQ:6pX1aqwzcRA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/C3gnQhR67TQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/1955972676096207276/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=1955972676096207276" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/1955972676096207276?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/1955972676096207276?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/C3gnQhR67TQ/linq-to-sql-good-bad-bottom-line.html" title="Linq to Sql: The Good, The Bad &amp; The Bottom Line" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2007/12/linq-to-sql-good-bad-bottom-line.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUMGRX07eyp7ImA9WB9UEkw.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-4993737259385444372</id><published>2007-12-09T11:19:00.000-05:00</published><updated>2007-12-09T11:23:44.303-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-12-09T11:23:44.303-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio 2008" /><title>More on Extension Method Judgment</title><content type="html">Just another tidbit from my last post Reserving Judgment.  I was reading &lt;a href="http://weblogs.asp.net/scottgu/default.aspx"&gt;Scott Guthrie&lt;/a&gt;'s latest post on the ASP.NET MVC framework (&lt;a href="http://weblogs.asp.net/scottgu/archive/2007/12/09/asp-net-mvc-framework-part-4-handling-form-edit-and-post-scenarios.aspx"&gt;ASP.NET MVC Framework (Part 4): Handling Form Edit and Post Scenarios&lt;/a&gt;), and noticed that he showed a tool which was using extension methods in much the same way Greg Young was describing.  See Scott's use of the ASP.NET MVC HTML Helpers.&lt;br /&gt;&lt;br /&gt;What can I say, I actually kind of like how they work in that scenario.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-4993737259385444372?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=6BBzMupMB50:asNbRn_ZSpA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=6BBzMupMB50:asNbRn_ZSpA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=6BBzMupMB50:asNbRn_ZSpA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/6BBzMupMB50" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/4993737259385444372/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=4993737259385444372" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/4993737259385444372?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/4993737259385444372?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/6BBzMupMB50/more-on-extension-method-judgment.html" title="More on Extension Method Judgment" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2007/12/more-on-extension-method-judgment.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkYMSHY4eyp7ImA9WB9UEkw.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-2204655470574065066</id><published>2007-12-09T10:06:00.000-05:00</published><updated>2007-12-09T10:29:49.833-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-12-09T10:29:49.833-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio 2008" /><title>Reserving Judgment</title><content type="html">I have been very quick to put down certain pieces of the .NET 3.5 framework (reference prior post on &lt;a href="http://jaychapman.blogspot.com/2007/10/c-30-extension-methods-good-idea.html"&gt;extension methods&lt;/a&gt; and &lt;a href="http://jaychapman.blogspot.com/2007/10/partial-methods-what.html"&gt;partial methods&lt;/a&gt;), most specifically extension methods and partial methods.  I'm not quite ready to give in on partial methods yet, they still just seem like a tool used to make code generators slightly easier, but I think I'm ready to reserve judgment on extension methods now.&lt;br /&gt;&lt;br /&gt;I still think extension methods are dangerous and are going to be subject to blatant misuse.  That being said, I think I need to keep an open mind regarding the potential uses for extension methods.  Note that I'm referring to the use of extension methods entirely within code that you control.&lt;br /&gt;&lt;br /&gt;I recently read a blog post by &lt;a href="http://codebetter.com/blogs/gregyoung/default.aspx"&gt;Greg Young&lt;/a&gt; titled &lt;a href="http://codebetter.com/blogs/gregyoung/archive/2007/12/05/a-use-for-extension-methods.aspx"&gt;A Use For Extension Methods&lt;/a&gt; where he basically stated that there are a lot of people out there that share my kind of viewpoint.  He also wanted to show one possible way where extension methods could be used.  He basically showed that extension methods were useful in controlling the context of intellisense when using a &lt;a href="http://martinfowler.com/bliki/FluentInterface.html"&gt;fluent interface&lt;/a&gt; for a pseudo-&lt;a href="http://en.wikipedia.org/wiki/Builder_pattern"&gt;builder pattern&lt;/a&gt;.  I call it pseudo since really there is only one type of available builder.&lt;br /&gt;&lt;br /&gt;Basically his extension method looks like the following:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;div style="background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"&gt;           &lt;div style="background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"&gt;              &lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span&gt;Builder&lt;/span&gt;&lt;/p&gt;                &lt;p style="margin: 0px;"&gt;{&lt;/p&gt;                &lt;p style="margin: 0px;"&gt;}&lt;/p&gt;                &lt;p style="margin: 0px;"&gt; &lt;/p&gt;            &lt;/div&gt;             &lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span&gt;Create&lt;/span&gt;&lt;/p&gt;              &lt;p style="margin: 0px;"&gt;{&lt;/p&gt;              &lt;p style="margin: 0px;"&gt;    &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span&gt;Builder &lt;/span&gt;New = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span&gt;Builder&lt;/span&gt;();&lt;/p&gt;              &lt;p style="margin: 0px;"&gt;}&lt;/p&gt;          &lt;/div&gt;&lt;br /&gt;&lt;div style="background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"&gt;            &lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span&gt;CostBuilder&lt;/span&gt; Cost(&lt;span style="color: blue;"&gt;this&lt;/span&gt; &lt;span&gt;Builder&lt;/span&gt; s)&lt;/p&gt;              &lt;p style="margin: 0px;"&gt;{&lt;/p&gt;              &lt;p style="margin: 0px;"&gt;    &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span&gt;CostBuilder&lt;/span&gt;();&lt;/p&gt;              &lt;p style="margin: 0px;"&gt;}&lt;/p&gt;          &lt;/div&gt;&lt;/pre&gt;&lt;br /&gt;So now when you call the Create.New you'll only see the builders which are in the namespaces which you referenced in your using directives.&lt;br /&gt;&lt;br /&gt;Fair enough, upon seeing this I thought it seemed interesting, but went in to my pessimistic anti-extension method mode and came up with my usual answer, why not just do this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span&gt;Create&lt;/span&gt;&lt;/p&gt;              &lt;p style="margin: 0px;"&gt;{&lt;/p&gt;              &lt;p style="margin: 0px;"&gt;    &lt;span style="color: blue;"&gt;public&lt;/span&gt; T New&lt;t&gt;()  &lt;span style="color: blue;"&gt;where&lt;/span&gt; T : &lt;span style="color: blue;"&gt;new&lt;/span&gt;()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;    {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;        &lt;span style="color: blue;"&gt;return new&lt;/span&gt; T();&lt;br /&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;    }&lt;/p&gt;              &lt;p style="margin: 0px;"&gt;}&lt;/p&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;But upon reading this, it's pretty lame isn't it?  It's basically a generic factory that doesn't new anything, why not just call new CostBuilder().DoStuff().DoMoreStuff()? &lt;br /&gt;&lt;br /&gt;But Greg's interface is a bit cleaner than what I am offering.  It's not that extension methods are really needed here, it's just that it can actually make your code a little cleaner and slightly easier to read (when working on large projects), which is something I didn't expect to say regarding extension methods.&lt;br /&gt;&lt;br /&gt;Maybe I need to wait this one out for a year to see what kinds of things developers come up with while using extension methods.&lt;br /&gt;&lt;br /&gt;--John Chapman&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-2204655470574065066?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=HNxM_gPBhOU:KFHIvKSBfMU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=HNxM_gPBhOU:KFHIvKSBfMU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=HNxM_gPBhOU:KFHIvKSBfMU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/HNxM_gPBhOU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/2204655470574065066/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=2204655470574065066" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/2204655470574065066?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/2204655470574065066?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/HNxM_gPBhOU/reserving-judgment.html" title="Reserving Judgment" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2007/12/reserving-judgment.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkAFQH0yeCp7ImA9WB9UEUs.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-8274295987233962011</id><published>2007-12-08T19:15:00.000-05:00</published><updated>2007-12-08T19:38:31.390-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-12-08T19:38:31.390-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio 2008" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><category scheme="http://www.blogger.com/atom/ns#" term="LINQ" /><title>C# Type Inference But Still Strongly Typed</title><content type="html">I have spent considerable time today reviewing Linq and more specifically Linq to Sql.  I'm currently working on a blog post where I'll go in to the details of what I think the pros and cons of Linq to Sql are as well as my overall opinion.  In case you couldn't guess it I'll be using NHibernate for my comparisons, after all it is what I'm familiar with.&lt;br /&gt;&lt;br /&gt;While reviewing some things I ran in to the following compile time check.  It was very simple for me to resolve, but I wonder if it will cause developers to fall in to traps.  Especially those developers who have some experience with weakly typed languages such as Javascript.&lt;br /&gt;&lt;br /&gt;Take a look at the following code I wrote:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color:lightblue;"&gt;AdventureWorksDataContext&lt;/span&gt; context = &lt;br /&gt;    &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:lightblue;"&gt;AdventureWorksDataContext&lt;/span&gt;();&lt;br /&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;var&lt;/span&gt; orders = &lt;span style="color:blue;"&gt;from&lt;/span&gt; po &lt;span  style="color:blue;"&gt;in&lt;/span&gt; context.PurchaseOrderHeaders&lt;br /&gt;           &lt;span style="color:blue;"&gt;select&lt;/span&gt; po;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt; (chkUseDate.Checked)&lt;br /&gt;{&lt;br /&gt;  orders = &lt;span style="color:blue;"&gt;from&lt;/span&gt; po &lt;span style="color:blue;"&gt;in&lt;/span&gt; orders&lt;br /&gt;           &lt;span style="color:blue;"&gt;where&lt;/span&gt; po.OrderDate &gt; dtOrderFrom.Value&lt;br /&gt;           &lt;span style="color:blue;"&gt;select&lt;/span&gt; po;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;orders = &lt;span style="color:blue;"&gt;from&lt;/span&gt; po &lt;span style="color:blue;"&gt;in&lt;/span&gt; orders&lt;br /&gt;       &lt;span style="color:blue;"&gt;orderby&lt;/span&gt; po.OrderDate &lt;span style="color:blue;"&gt;ascending&lt;/span&gt;&lt;br /&gt;       &lt;span style="color:blue;"&gt;select new&lt;/span&gt;&lt;br /&gt;       {&lt;br /&gt;           po.PurchaseOrderID,&lt;br /&gt;           po.RevisionNumber,&lt;br /&gt;           po.OrderDate,&lt;br /&gt;           po.ShipDate&lt;br /&gt;       };&lt;br /&gt;&lt;/spnan&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Does anyone see what is wrong with the code above and why it failed to compile?&lt;br /&gt;&lt;br /&gt;The compile-time error was:&lt;br /&gt;&lt;blockquote&gt;Cannot implicitly convert type 'System.Linq.IQueryable&amp;lt;AnonymousType#1&amp;gt;' to 'System.Linq.IQueryable&amp;lt;BLL.PurchaseOrderHeader&amp;gt;'. An explicit conversion exists (are you missing a cast?)&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;After seeing that I immediately realized that I tried to use an object which type inferred to return PurchaseOrderHeader objects to return anonymous type objects instead.  You can't just change a reference to be of another type in C# 3.0, hence the strong typing, I should know better.&lt;br /&gt;&lt;br /&gt;But honestly, with the whole var keyword, I wasn't really thinking about it.  It was a minor slip up, but I wonder how many developers will fall in to that trap.  I think some developers may have seen the var keyword before in Javascript and they may have used it in the fashion I just did.&lt;br /&gt;&lt;br /&gt;That being said, I have been enjoying my time with Linq today.  I should have a post up within the next few days with more details.&lt;br /&gt;&lt;br /&gt;P.S. If you're wondering what is going on with the 3 step linq ueries above, that's how you write dynamic queries in Linq.  Simply reference the previously defined query in your new linq query in order to further restrict the query which you are building.  Keep in mind that writing a linq query doesn't perform any operations.  You have to either enumerate over the values of the query or call a method on the query like ToArray(), ToDictionary(), Select() etc...&lt;br /&gt;&lt;br /&gt;If you're curious how to resolve the issue above you just need to declare a new variable for the last query to store the new type.  var results = &amp;lt;Linq expression&amp;gt; would work just fine.&lt;br /&gt;&lt;br /&gt;--John Chapman&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-8274295987233962011?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=OYEdmHgpBSE:dGciU8lna-Y:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=OYEdmHgpBSE:dGciU8lna-Y:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=OYEdmHgpBSE:dGciU8lna-Y:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/OYEdmHgpBSE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/8274295987233962011/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=8274295987233962011" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/8274295987233962011?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/8274295987233962011?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/OYEdmHgpBSE/c-type-inference-but-still-strongly.html" title="C# Type Inference But Still Strongly Typed" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2007/12/c-type-inference-but-still-strongly.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4MSHs4eCp7ImA9WB9UEUg.&quot;"><id>tag:blogger.com,1999:blog-4292687466688891558.post-4309544684447130910</id><published>2007-12-08T16:49:00.000-05:00</published><updated>2007-12-08T16:56:29.530-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-12-08T16:56:29.530-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio 2005" /><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio 2008" /><title>Solution Folders To Group Projects</title><content type="html">While reading &lt;a href="http://weblogs.asp.net/scottgu/"&gt;Scott Guthrie's blog&lt;/a&gt; today I stumbled upon one of his links of the day for december 8th entitled &lt;a href="http://dotnettipoftheday.org/tips/visual-studio-solution-folders.aspx"&gt;Big Solutions Can Be Organized Using Solution Folders&lt;/a&gt; which is at the &lt;a href="http://dotnettipoftheday.org/"&gt;.NET Tip of the Day&lt;/a&gt; web site.&lt;br /&gt;&lt;br /&gt;Actually, this is really cool.  Am I the only schmuck who didn't realize this was possible?  I have used Solution Folders in the past, but it was always to group files which were not part of the actual build process.  For example we always had a Libraries folder which contained the third party dlls which need to be referenced to build the project.  This way all a developer needs to do to build the project is to download the latest source code, and the solution will automatically download the needed referenced assemblies.  Plus any upgrade we do to a third party dll automatically propagates when someone gets latest.&lt;br /&gt;&lt;br /&gt;But the ability to place projects within the folders to group them together?  This will actually be very handy for us.  At work our current solution has 33 projects, and truthfully it is growing!  Being able to group the projects which are similar or somehow related will really come in handy for us.&lt;br /&gt;&lt;br /&gt;Why didn't I realize this sooner?&lt;br /&gt;&lt;br /&gt;--John Chapman&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4292687466688891558-4309544684447130910?l=jaychapman.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=fzCA-uheygU:Z39zAbRttJs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?a=fzCA-uheygU:Z39zAbRttJs:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ChapmansCodingCorridor?i=fzCA-uheygU:Z39zAbRttJs:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ChapmansCodingCorridor/~4/fzCA-uheygU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jaychapman.blogspot.com/feeds/4309544684447130910/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4292687466688891558&amp;postID=4309544684447130910" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/4309544684447130910?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4292687466688891558/posts/default/4309544684447130910?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChapmansCodingCorridor/~3/fzCA-uheygU/solution-folders-to-group-projects.html" title="Solution Folders To Group Projects" /><author><name>John Chapman</name><uri>http://www.blogger.com/profile/06903416900062029948</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10925840624621688322" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://jaychapman.blogspot.com/2007/12/solution-folders-to-group-projects.html</feedburner:origLink></entry></feed>
