<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5933717644607161038</id><updated>2012-01-31T13:58:04.267-08:00</updated><category term='c#'/><category term='code snippets'/><category term='c++'/><category term='vb'/><category term='extension methods'/><category term='macros'/><title type='text'>Genne's Blog</title><subtitle type='html'>Programming, photo, music and other random thoughts!</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>23</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-1062120152976614342</id><published>2009-12-13T02:43:00.002-08:00</published><updated>2009-12-14T12:00:14.233-08:00</updated><title type='text'>Python and doctest</title><content type='html'>I've just recently got to learn &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt;, and after a bit of struggling with the new syntax, I found the language to be very appealing. It's well structured, and has been around for a long time so if you can't find the library you are looking for in pythons standard libraries (which is very unlikely), there are a bunch of other libraries to install (for example &lt;a href="http://codespeak.net/lxml/"&gt;lxml&lt;/a&gt;, which is a great xml/xpath wrapper for libxml2). The only issue I've had so far is with some libraries not being compatible with python 3.1 (which differs a lot from 2.x), but this is probably a transition period soon being over.&lt;br /&gt;&lt;br /&gt;And as with all languages, sooner or later you would like to know how to setup your tests. And when googling "python test framework", I stumbled upon &lt;a href="http://docs.python.org/library/doctest.html"&gt;doctest&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;The doctest module searches for pieces of text that look like interactive Python sessions, and then executes those sessions to verify that they work exactly as shown.&lt;/blockquote&gt;This is something I've never seen before, but yet strikes me as very powerful. To write your tests, you simply include an example execution of the function you want to test in the comment, i.e.:&lt;br /&gt;&lt;pre class="python" name="code"&gt;&lt;br /&gt;'''&lt;br /&gt;This function prints the string "Hello World!".&lt;br /&gt;&lt;br /&gt;For example:&lt;br /&gt;&gt;&gt;&gt; say_hello_world()&lt;br /&gt;Hello World!&lt;br /&gt;'''&lt;br /&gt;def say_hello_world():&lt;br /&gt;print("Hello World!")&lt;br /&gt;&lt;/pre&gt;To run the tests, you can either include the test execution in the main method of the script file, which to me is wrong if you would like to have another default main method. Another way to do it (if you have python 2.6 or later) is to execute like this:&lt;br /&gt;&lt;pre&gt;python -m doctest -v helloworld.py&lt;/pre&gt;This will load the doctest module, and then execute the tests in helloworld.py, which will call the function say_hello_world(), and make sure it's output equals "Hello World!", as written in the comment. You then extend the tests by simply including more examples in your comment.&lt;br /&gt;&lt;br /&gt;IMO, the real power of this is that you don't need to write separate test functions, plus you get the documentation for free. I.e., with xunit the same test would look something like this:&lt;br /&gt;&lt;pre class="python" name="code"&gt;&lt;br /&gt;def test_say_hello_world():&lt;br /&gt;mocked_print = create_print_mock_function()&lt;br /&gt;say_hello_world()&lt;br /&gt;xunit.assert_equal("Hello World!", mocked_print.get())&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And I'm not even sure if create_print_mock_function is possible to do. Even if it would, the tests becomes much larger, and harder to maintain.&lt;br /&gt;&lt;br /&gt;The main downside I see to using doctest is that it depends on the expected output being formatted exactly as python would have formatted it. For example, the following function will fail, just because python will include extra spaces in the array:&lt;br /&gt;&lt;pre class="python" name="code"&gt;&lt;br /&gt;'''&lt;br /&gt;&gt;&gt;&gt; get_array()&lt;br /&gt;[1,2]&lt;br /&gt;'''&lt;br /&gt;def get_array():&lt;br /&gt;return [1,2]&lt;br /&gt;&lt;/pre&gt;will fail with&lt;br /&gt;&lt;pre&gt;Failed example:&lt;br /&gt;get_array()&lt;br /&gt;Expected:&lt;br /&gt;[1,2]&lt;br /&gt;Got:&lt;br /&gt;[1, 2]&lt;br /&gt;&lt;/pre&gt;In this case it's easy to fix, but how will it scale when you have hundreds of tests? What happens when you update your tostring methods? Instead of inspecting the returned data, you inspect the data formatted to a string, which can very well mean something quite different if you are writing your own tostring methods.&lt;br /&gt;&lt;br /&gt;Anyway, at the latest coding dojo (Majorna Coding Dojo!), we decided to give python and doctest a try, and it worked very well. Even though most of us didn't know Python from before, we didn't have any problems using doctest.&lt;br /&gt;&lt;br /&gt;I will definitely use doctest more in the future, and will even see if I can find similar testing frameworks (Document Driven Development, DDD) for other languages such as Ruby, C# and C++. So if you are into Python programming, I definitely recommend you trying this out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-1062120152976614342?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/1062120152976614342/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=1062120152976614342' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/1062120152976614342'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/1062120152976614342'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2009/12/python-and-doctest.html' title='Python and doctest'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-2927362403300628092</id><published>2009-08-27T10:57:00.001-07:00</published><updated>2009-08-27T11:20:00.508-07:00</updated><title type='text'>My first piano sheet successfully created!</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_F5z3mmdTM8I/SpbOGBIbCbI/AAAAAAAADrI/5l92i21afE0/s1600-h/DinnerTimeSampleSheet.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 234px;" src="http://4.bp.blogspot.com/_F5z3mmdTM8I/SpbOGBIbCbI/AAAAAAAADrI/5l92i21afE0/s400/DinnerTimeSampleSheet.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5374709808091564466" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Just recently finished my first piano sheet based on an improvisation I made some years ago. Not that I was planning to do anything serious with it, just to learn and to some day be able to say: "I've produced my own piano sheet". Well, now I can :) There are some things I know I could make better, but it takes too much time figuring out how to do it in Cubase (which I used to produce the sheet), so I'll just let it be as it is now. It was really fun producing it, so I'll definitely continue doing so. And hopefully it won't take so much time in the future!&lt;br /&gt;&lt;br /&gt;Have a look if you want, or download the .mp3:&lt;br /&gt;&lt;br /&gt;Sheet: &lt;a href="http://www.christiangenne.com/music/DinnerTime.pdf"&gt;DinnerTimer.pdf&lt;/a&gt;&lt;br /&gt;MP3: &lt;a href="http://www.christiangenne.com/music/DinnerTime.mp3"&gt;DinnerTimer.mp3&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-2927362403300628092?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/2927362403300628092/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=2927362403300628092' title='4 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/2927362403300628092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/2927362403300628092'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2009/08/my-first-piano-sheet-successfully.html' title='My first piano sheet successfully created!'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_F5z3mmdTM8I/SpbOGBIbCbI/AAAAAAAADrI/5l92i21afE0/s72-c/DinnerTimeSampleSheet.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-2702002507386036013</id><published>2009-08-18T12:55:00.000-07:00</published><updated>2009-08-18T15:15:35.627-07:00</updated><title type='text'>Podcasts at 2x speed</title><content type='html'>On a morning walk to work for a few days ago, when I, as usual, listened to a podcast on my iPhone, I happened to accidentally click on an icon I've never noticed earlier - "2x". Suddenly my podcast started playing at two times the speed (at least what it felt like), but without making it difficult listening. It was actually quite easy to keep up with the podcast-dialogue, and after 15 minutes I had completed half an hour long podcast. It feels a bit like skimming through a book, you may miss the details, but get the big picture. And when they suddenly start talking about something that is very interesting you can always return to the "standard speed".&lt;br /&gt;&lt;br /&gt;So if you have an iPhone or iPod Touch with OS 3.0, start a podcast and click the 2x-icon in the upper right corner, and you may be able to start optimizing your time!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-2702002507386036013?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/2702002507386036013/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=2702002507386036013' title='1 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/2702002507386036013'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/2702002507386036013'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2009/08/podcasts-at-2x-speed.html' title='Podcasts at 2x speed'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-1546476380849452049</id><published>2009-06-02T13:48:00.000-07:00</published><updated>2009-09-03T11:40:19.292-07:00</updated><title type='text'>Objective-C... yet another programming language?</title><content type='html'>Just recently installed XCode on my mac in order to develop applications for my iPhone. The first thing I realized was that I needed to learn yet another programming language. Just another syntax, or does Objective-C actually bring something new?&lt;br /&gt;&lt;br /&gt;It turns out Objective-C (which is a language derived from C, similar to C++, but still very different) has one feature I haven't seen before. First of, instead of calling a method on an object, your send a message to it. It's almost the same, but also requires you to pass along named parameters (which means more code to write, but easier to read). The new and cool feature appears when you want to send a message to an object, which should return a value, when the object turns out to be nil.&lt;br /&gt;&lt;pre class="c#" name="code"&gt;&lt;br /&gt;MyClass* myObject = nil;&lt;br /&gt;if ([myObject getValue] == 0.0) {&lt;br /&gt;  // myObject getValue retuned 0, OR myObject is nil&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So when executing this code, as opposed to how normal programming languages handles it, it doesn't crash. It simply returns 0.0 if the expected return type is a number, or nil if the expected return type is a pointer to an object. This also works for functions returning nothing (i.e. void), sending a void returning message to a nil object will simpy do nothing.&lt;br /&gt;&lt;br /&gt;In for example C# you always have to do null checks all over the code, in order to verify your object isn't nil.&lt;br /&gt;&lt;br /&gt;I'm not sure I like it or not, but if you learn to think "pure Objective-C" then perhaps this can be used as an advantage! I'm looking forward to learning Objective-C further, and to adapt these new concepts!&lt;br /&gt;&lt;br /&gt;I'll let you know when I've published my first iPhone app :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-1546476380849452049?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/1546476380849452049/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=1546476380849452049' title='1 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/1546476380849452049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/1546476380849452049'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2009/06/objective-c-yet-another-programming.html' title='Objective-C... yet another programming language?'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-8102568234053351215</id><published>2009-03-04T12:00:00.000-08:00</published><updated>2009-09-03T11:40:19.292-07:00</updated><title type='text'>Why you love and hate Ruby</title><content type='html'>What strikes me when programming Ruby is how simple everything is! You've got utility functions for almost everything, and writing an application doesn't take more then a few lines of code. No need to setup a project, no need to think about types. You just write code!&lt;br /&gt;&lt;br /&gt;The downside of this, of course, is that the code easily becomes bad written, and as there are very few rules in Ruby, it isn't very easy reading others' code. This is why Ruby sometimes is classified as a "hard to lean language". There are simply too many ways of writing the same code.&lt;br /&gt;&lt;br /&gt;I don't agree that this makes the language more hard to learn, but perhaps makes it take longer to learn the language fully. For instance, I just recently learned you can write code in the following way:&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;&lt;br /&gt;puts "Hello my friend" if userIsFriendly&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I've never seen code like that before, but it really opens up for some nice syntax! &lt;br /&gt;&lt;br /&gt;Another feature of Ruby is that Classes are open, and &lt;span style="font-weight:bold;"&gt;everything&lt;/span&gt; is an object, meaning you can extend/modify classes on the fly. Even classes are objects! For example:&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;&lt;br /&gt;class Fixnum&lt;br /&gt;  def minutes&lt;br /&gt;    return Timespan.new(self)&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;class Timespan&lt;br /&gt;  def ago&lt;br /&gt;    return Time.now - self&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;5.minutes.ago&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The syntax is almost perfect! How would you otherwise say "5 minutes ago"? That's what people often talk about when they describe Ruby. "The only truly object oriented language".&lt;br /&gt;&lt;br /&gt;Why Ruby isn't the perfect language, IMO, is because it's too "open". There are too many ways of writing code. Writing smaller applications, or better scripts, won't take you more than a few minutes, but when you need to work on a larger project, I would definitely go with a strictly typed language, such as C#, where you have better control over your code. Also, not surprisingly, no IDE can help you writing your code, as the code is dynamically typed, and you really can't say what functions are available on an object until you actually run the code.&lt;br /&gt;&lt;br /&gt;So, thumb up for this language when working on smaller applications. But for larger projects, I would recommend going for another one.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-8102568234053351215?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/8102568234053351215/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=8102568234053351215' title='2 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/8102568234053351215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/8102568234053351215'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2009/03/why-you-love-and-hate-ruby.html' title='Why you love and hate Ruby'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-1487374734587615806</id><published>2009-02-06T07:38:00.000-08:00</published><updated>2009-09-03T11:40:19.292-07:00</updated><title type='text'>Trying out ruby for the very first time</title><content type='html'>So, I've made up my mind. The language of this year is going to be &lt;a href="http://www.ruby-lang.org/en/"&gt;Ruby&lt;/a&gt;! The reasons are many, but mostly I feel I can use this language more in my daily work, and on a podcast over at &lt;a href="http://altnetpodcast.com/episodes/13-ruby-on-rails"&gt;AltDotNet about Ruby&lt;/a&gt;, they mentioned something like "learning ruby will make you a better C# developer". Languages like lisp and python will have to wait for at least one year!&lt;br /&gt;&lt;br /&gt;About two weeks ago, I was out skiing with Gustaf and some friends of him. We ended up playing a lot of &lt;a href="http://en.wikipedia.org/wiki/Four_in_a_row"&gt;four in a row&lt;/a&gt;, a really funny and simple game. This game made me think about how to develop a &lt;a href="http://ai-depot.com/articles/minimax-explained/"&gt;min max AI&lt;/a&gt;, and suddenly I had written down the pseudo code for such an AI in my notebook. Here is a picture of the game is supposed to be played (from wikipedia):&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://upload.wikimedia.org/wikipedia/en/thumb/a/a4/Connect_four_game.svg/250px-Connect_four_game.svg.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 250px; height: 214px;" src="http://upload.wikimedia.org/wikipedia/en/thumb/a/a4/Connect_four_game.svg/250px-Connect_four_game.svg.png" alt="" border="0" /&gt;&lt;/a&gt;Now, back home at my computer, I started digging into the ruby documentations, and after not more than a few hours I had finished the first version of the AI! Turns out Ruby isn't that hard to learn, at least not if you just want to get some basic things done. It's like writing c#, except you skip the types, and instead of writing void foo(int x) { ... } you write def foo(x) ... end, and so on...&lt;br /&gt;&lt;br /&gt;Here is how my final version of the game looks when you run it:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;C:\Documents and Settings\Christian\Desktop&gt;ruby 4irad.rb&lt;br /&gt;Run against ai (A), another player (P) or let two AIs play against eachother (X)&lt;br /&gt;A&lt;br /&gt;Enter AI 1 level (1 to 5):&lt;br /&gt;3&lt;br /&gt;Enter name of human player (default Human 1):&lt;br /&gt;&lt;br /&gt;---------------&lt;br /&gt;|0 1 2 3 4 5 6|&lt;br /&gt;---------------&lt;br /&gt;| | | | | | | |&lt;br /&gt;| | | | | | | |&lt;br /&gt;| | | | | | | |&lt;br /&gt;| | | | | | | |&lt;br /&gt;| | | | | | | |&lt;br /&gt;| | | | | | | |&lt;br /&gt;---------------&lt;br /&gt;AI 1 (3) played: 3&lt;br /&gt;---------------&lt;br /&gt;|0 1 2 3 4 5 6|&lt;br /&gt;---------------&lt;br /&gt;| | | | | | | |&lt;br /&gt;| | | | | | | |&lt;br /&gt;| | | | | | | |&lt;br /&gt;| | | | | | | |&lt;br /&gt;| | | | | | | |&lt;br /&gt;| | | |O| | | |&lt;br /&gt;---------------&lt;br /&gt;Human 1, make your move:&lt;br /&gt;2&lt;br /&gt;Human 1 played: 2&lt;br /&gt;---------------&lt;br /&gt;|0 1 2 3 4 5 6|&lt;br /&gt;---------------&lt;br /&gt;| | | | | | | |&lt;br /&gt;| | | | | | | |&lt;br /&gt;| | | | | | | |&lt;br /&gt;| | | | | | | |&lt;br /&gt;| | | | | | | |&lt;br /&gt;| | |X|O| | | |&lt;br /&gt;---------------&lt;br /&gt;AI 1 (3) played: 3&lt;br /&gt;---------------&lt;br /&gt;|0 1 2 3 4 5 6|&lt;br /&gt;---------------&lt;br /&gt;| | | | | | | |&lt;br /&gt;| | | | | | | |&lt;br /&gt;| | | | | | | |&lt;br /&gt;| | | | | | | |&lt;br /&gt;| | | |O| | | |&lt;br /&gt;| | |X|O| | | |&lt;br /&gt;---------------&lt;br /&gt;Human 1, make your move:&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;and so on...&lt;br /&gt;&lt;br /&gt;I wonder how much code can you post in a blog, without the post becoming too long? I would like to post the code as an attachment, but I'm not sure you can do that in blogger, so I'll simply put it here. To try it out, copy the code to a file, i.e. 4inarow.rb, then run it using &lt;i&gt;ruby 4inarow.rb&lt;/i&gt;. Enjoy ;)&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;&lt;br /&gt;$debugEnabled = false&lt;br /&gt;def debug(text)&lt;br /&gt; if $debugEnabled then&lt;br /&gt;  puts &amp;quot;&amp;gt;&amp;gt;&amp;gt; &amp;quot; + text&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class State&lt;br /&gt;&lt;br /&gt; attr_reader :cols, :rows, :player, :winner, :lastPlayed, :isFull&lt;br /&gt; &lt;br /&gt; Player1 = &amp;quot;Player 1&amp;quot;&lt;br /&gt; Player2 = &amp;quot;Player 2&amp;quot;&lt;br /&gt;&lt;br /&gt; def initialize&lt;br /&gt;  @cols = []&lt;br /&gt;  (0..6).each { @cols &amp;lt;&amp;lt; [] }&lt;br /&gt;  @rows = []&lt;br /&gt;  (0..5).each { @rows &amp;lt;&amp;lt; Array.new(7, nil) }&lt;br /&gt;  @player = Player1&lt;br /&gt;  @winner = nil&lt;br /&gt;  @isFull = false&lt;br /&gt; end&lt;br /&gt; &lt;br /&gt; def deep_copy&lt;br /&gt;  return Marshal.load( Marshal.dump( self ) )&lt;br /&gt; end&lt;br /&gt; &lt;br /&gt; def to_s&lt;br /&gt;  return &amp;quot;---------------\n&amp;quot; + &lt;br /&gt;   &amp;quot;|&amp;quot; + (0..6).to_a.join(&amp;quot; &amp;quot;) + &amp;quot;|\n&amp;quot; +&lt;br /&gt;   &amp;quot;---------------\n&amp;quot; +&lt;br /&gt;   @rows.reverse.collect{|row| &amp;quot;|&amp;quot; + row.collect{|r| if !r then &amp;quot; &amp;quot; elsif r == Player2 then &amp;quot;X&amp;quot; else &amp;quot;O&amp;quot; end}.join(&amp;quot;|&amp;quot;) + &amp;quot;|&amp;quot;}.join(&amp;quot;\n&amp;quot;) + &amp;quot;\n&amp;quot; +&lt;br /&gt;   &amp;quot;---------------&amp;quot;&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def canPlay( i )&lt;br /&gt;  return @winner == nil &amp;amp;&amp;amp; @cols[i].length &amp;lt; 6&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def play( i )&lt;br /&gt;  if canPlay i then&lt;br /&gt;   rowIndex = @cols[i].length&lt;br /&gt;   @cols[i] &amp;lt;&amp;lt; @player&lt;br /&gt;   @rows[rowIndex][i] = @player&lt;br /&gt;   @lastPlayed = i&lt;br /&gt;&lt;br /&gt;   switchPlayer&lt;br /&gt;   updateWinner&lt;br /&gt;   updateIsFull&lt;br /&gt;  end&lt;br /&gt; end&lt;br /&gt; &lt;br /&gt; def updateIsFull&lt;br /&gt;  for p in @rows[5]&lt;br /&gt;   if !p then return end&lt;br /&gt;  end&lt;br /&gt;  @isFull = true&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def findWinner( row )&lt;br /&gt;  for i in 0..(row.length-4)&lt;br /&gt;   p = nil&lt;br /&gt;   n = 0&lt;br /&gt;   for j in 0..3&lt;br /&gt;    rp = getPlayed(row[i+j])&lt;br /&gt;    if rp.class != Fixnum then&lt;br /&gt;     if !p then&lt;br /&gt;      p = rp&lt;br /&gt;     elsif p != rp&lt;br /&gt;      p = 0&lt;br /&gt;      break&lt;br /&gt;     end&lt;br /&gt;     if rp != 0 then&lt;br /&gt;      n += 1&lt;br /&gt;     end&lt;br /&gt;    end&lt;br /&gt;   end&lt;br /&gt;   if p != 0 and n == 4 then&lt;br /&gt;    return p&lt;br /&gt;   end&lt;br /&gt;  end&lt;br /&gt;  return nil&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def updateWinner&lt;br /&gt;  for row in getAllRanges&lt;br /&gt;   p = findWinner row&lt;br /&gt;   if p then&lt;br /&gt;    @winner = p&lt;br /&gt;   end&lt;br /&gt;  end&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def switchPlayer&lt;br /&gt;  if @player == Player1 then&lt;br /&gt;   @player = Player2&lt;br /&gt;  else&lt;br /&gt;   @player = Player1&lt;br /&gt;  end&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def getPlayed(cell)&lt;br /&gt;  c = cell[0]&lt;br /&gt;  r = cell[1]&lt;br /&gt;  col = @cols[c]&lt;br /&gt;  if r &amp;gt;= col.length then&lt;br /&gt;   return r - col.length + 1&lt;br /&gt;  end&lt;br /&gt;  return @cols[c][r]&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def posValid( c, r )&lt;br /&gt;  return c &amp;gt;= 0 &amp;amp;&amp;amp; c &amp;lt;= 6 &amp;amp;&amp;amp; r &amp;gt;= 0 &amp;amp;&amp;amp; r &amp;lt;= 5&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def getDiagonal( c, r, dc )&lt;br /&gt;  d = []&lt;br /&gt;  while posValid( c, r )&lt;br /&gt;   d &amp;lt;&amp;lt; [c, r] &lt;br /&gt;   c += dc&lt;br /&gt;   r += 1&lt;br /&gt;  end&lt;br /&gt;  return d&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def getAllDiagonalsRanges&lt;br /&gt;  diags = []&lt;br /&gt;  for r in 0..5&lt;br /&gt;   diags &amp;lt;&amp;lt; getDiagonal( 0, r, 1 )&lt;br /&gt;  end&lt;br /&gt;  for c in 1..6&lt;br /&gt;   diags &amp;lt;&amp;lt; getDiagonal( c, 0, 1 )&lt;br /&gt;  end&lt;br /&gt;  for r in 0..5&lt;br /&gt;   diags &amp;lt;&amp;lt; getDiagonal( 6, r, -1 )&lt;br /&gt;  end&lt;br /&gt;  for c in 0..5&lt;br /&gt;   diags &amp;lt;&amp;lt; getDiagonal( c, 0, -1 )&lt;br /&gt;  end&lt;br /&gt;  return diags&lt;br /&gt; end&lt;br /&gt; &lt;br /&gt; def getAllColsRanges&lt;br /&gt;  return (0..6).collect{|c| (0..5).collect{|r| [c, r]}}&lt;br /&gt; end&lt;br /&gt; def getAllRowsRanges&lt;br /&gt;  return (0..5).collect{|r| (0..6).collect{|c| [c, r]}}&lt;br /&gt; end&lt;br /&gt; &lt;br /&gt; def getAllRanges&lt;br /&gt;  return  getAllColsRanges + &lt;br /&gt;    getAllRowsRanges + &lt;br /&gt;    getAllDiagonalsRanges&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class Node&lt;br /&gt;&lt;br /&gt; attr_reader :state, :children, :isLeaf&lt;br /&gt;&lt;br /&gt; def initialize( state, player )&lt;br /&gt;  if !player then&lt;br /&gt;   raise &amp;quot;player is nil&amp;quot;&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  @state = state&lt;br /&gt;  @isLeaf = true&lt;br /&gt;  @children = {}&lt;br /&gt;  @player = player&lt;br /&gt; end&lt;br /&gt; &lt;br /&gt; def getPoints( row )&lt;br /&gt;  points = 0.0&lt;br /&gt;  for i in 0..(row.length-4)&lt;br /&gt;   p = nil&lt;br /&gt;   n = 0&lt;br /&gt;   divider = 1&lt;br /&gt;   for j in 0..3&lt;br /&gt;    rp = @state.getPlayed(row[i+j])&lt;br /&gt;    if rp.class == Fixnum then&lt;br /&gt;     divider *= rp&lt;br /&gt;    else&lt;br /&gt;     if !p then&lt;br /&gt;      p = rp&lt;br /&gt;     elsif !rp then&lt;br /&gt;     &lt;br /&gt;     elsif p != rp&lt;br /&gt;      p = nil&lt;br /&gt;      break&lt;br /&gt;     end&lt;br /&gt;     if rp then&lt;br /&gt;      n += 1&lt;br /&gt;     end&lt;br /&gt;    end&lt;br /&gt;   end&lt;br /&gt;   if p then&lt;br /&gt;    blockPoints = calculatePoints n / divider&lt;br /&gt;    if p == @player then&lt;br /&gt;     points += blockPoints&lt;br /&gt;    else&lt;br /&gt;     points = points - blockPoints&lt;br /&gt;    end&lt;br /&gt;   end&lt;br /&gt;  end&lt;br /&gt;  if points.infinite? then&lt;br /&gt;   debug &amp;quot;Found winner: &amp;quot; + points.to_s + &amp;quot;: &amp;quot; + row.join(&amp;quot;|&amp;quot;)&lt;br /&gt;  end&lt;br /&gt;  return points&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def calculatePoints( n )&lt;br /&gt;  return n.to_f**3 / (4 - [n,4].min)&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def nodePoints&lt;br /&gt;  points = 0.0&lt;br /&gt;  for row in state.getAllRanges&lt;br /&gt;   p = getPoints(row)&lt;br /&gt;   if p != 0 then&lt;br /&gt;    #debug row.collect{|r| if r then r else &amp;quot; &amp;quot; end}.join(&amp;quot;|&amp;quot;) + &amp;quot; &amp;quot; + p.to_s&lt;br /&gt;   end&lt;br /&gt;   &lt;br /&gt;   newPoints = points + p&lt;br /&gt;   if newPoints.nan? then&lt;br /&gt;    raise &amp;quot;points + p == NaN: points=&amp;quot; + points.to_s + &amp;quot; p=&amp;quot; + p.to_s&lt;br /&gt;   end&lt;br /&gt;   points = newPoints&lt;br /&gt;  end&lt;br /&gt;  #puts state&lt;br /&gt;  #puts &amp;quot;Points: &amp;quot; + points.to_s&lt;br /&gt;  return points&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def allChildPoints&lt;br /&gt;  return children.values.collect {|child| child.totalPoints}&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def isMyTurn&lt;br /&gt;  return state.player == @player&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def totalPoints&lt;br /&gt;  if @totalPoints then&lt;br /&gt;   return @totalPoints&lt;br /&gt;  end&lt;br /&gt;  p = nil&lt;br /&gt;  if @isLeaf then&lt;br /&gt;   p = nodePoints&lt;br /&gt;  else&lt;br /&gt;   if isMyTurn then&lt;br /&gt;    p = allChildPoints.max&lt;br /&gt;   else&lt;br /&gt;    p = allChildPoints.min&lt;br /&gt;   end&lt;br /&gt;  end&lt;br /&gt;  if !p then&lt;br /&gt;   raise &amp;quot;nil points returned&amp;quot;&lt;br /&gt;  end&lt;br /&gt;  @totalPoints = p&lt;br /&gt;  return p&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def grow&lt;br /&gt;  if @totalPoints then&lt;br /&gt;   #puts &amp;quot;Gah, totalPoints is set&amp;quot;&lt;br /&gt;   @totalPoints = nil&lt;br /&gt;  end&lt;br /&gt;  if @isLeaf &amp;amp;&amp;amp; !@state.winner&lt;br /&gt;   #debug &amp;quot;Growing leaf: &amp;quot; + self.to_s&lt;br /&gt;   for i in 0..6&lt;br /&gt;    if @state.canPlay i then&lt;br /&gt;     childState = @state.deep_copy&lt;br /&gt;     childState.play i&lt;br /&gt;     child = Node.new(childState, @player)&lt;br /&gt;     children[i] = child&lt;br /&gt;    end&lt;br /&gt;   end&lt;br /&gt;   @isLeaf = false&lt;br /&gt;  else&lt;br /&gt;   for child in @children.values&lt;br /&gt;    child.grow&lt;br /&gt;   end&lt;br /&gt;  end&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def findNodeWithState( state )&lt;br /&gt;  if state.lastPlayed then&lt;br /&gt;   return @children[state.lastPlayed]&lt;br /&gt;  else&lt;br /&gt;   return nil&lt;br /&gt;  end&lt;br /&gt; end&lt;br /&gt; &lt;br /&gt; def to_s&lt;br /&gt;  return &amp;quot;Played: &amp;quot; + @state.lastPlayed.to_s + &amp;quot; Points: &amp;quot; + totalPoints.to_s&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class AIPlayer&lt;br /&gt;&lt;br /&gt; def initialize( level, name )&lt;br /&gt;  @level = level&lt;br /&gt;  @name = name&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def to_s&lt;br /&gt;  return @name + &amp;quot; (&amp;quot; + @level.to_s + &amp;quot;)&amp;quot;&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def selectBestNode&lt;br /&gt;  # Add some randomness&lt;br /&gt;  bestChild = nil&lt;br /&gt;  bestChildCount = nil&lt;br /&gt;  for child in @node.children.values&lt;br /&gt;   #puts child.state&lt;br /&gt;   #puts child.totalPoints&lt;br /&gt;   if !bestChild then&lt;br /&gt;    bestChild = child&lt;br /&gt;    bestChildCount = 1&lt;br /&gt;   else&lt;br /&gt;    if child.totalPoints &amp;gt; bestChild.totalPoints then&lt;br /&gt;     bestChild = child&lt;br /&gt;     bestChildCount = 1&lt;br /&gt;    elsif child.totalPoints == bestChild.totalPoints then&lt;br /&gt;     bestChildCount = bestChildCount + 1&lt;br /&gt;     if rand(bestChildCount) == 0 then&lt;br /&gt;      bestChild = child&lt;br /&gt;     end&lt;br /&gt;    end&lt;br /&gt;   end&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  #Just to make sure&lt;br /&gt;  if !bestChild then&lt;br /&gt;   raise &amp;quot;bestChild is nil&amp;quot;&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  debug &amp;quot;Best points: &amp;quot; + bestChild.totalPoints.to_s&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;  @node = bestChild&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def play(state)&lt;br /&gt;  if state.lastPlayed then&lt;br /&gt;   debug &amp;quot;Finding last played node&amp;quot;&lt;br /&gt;   @node = @node.findNodeWithState(state)&lt;br /&gt;   @node.grow&lt;br /&gt;  end&lt;br /&gt;  debug &amp;quot;Finding the best node&amp;quot;&lt;br /&gt;  selectBestNode&lt;br /&gt;  @node.grow&lt;br /&gt;  state.play @node.state.lastPlayed&lt;br /&gt; end&lt;br /&gt; &lt;br /&gt; def setupGame(state, player)&lt;br /&gt;  @node = Node.new(state, player)&lt;br /&gt;  debug &amp;quot;Creating min max tree (&amp;quot; + (7**@level).to_s + &amp;quot; nodes)...&amp;quot;&lt;br /&gt;  (1..@level).each{ @node.grow } &lt;br /&gt; end&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class HumanPlayer&lt;br /&gt;&lt;br /&gt; def initialize(name)&lt;br /&gt;  @name = name&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def to_s&lt;br /&gt;  return @name&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def play(state)&lt;br /&gt;  puts @name + &amp;quot;, make your move:&amp;quot;&lt;br /&gt;  &lt;br /&gt;  begin&lt;br /&gt;   toPlay = gets&lt;br /&gt;   if toPlay == &amp;quot;q\n&amp;quot; then&lt;br /&gt;    exit&lt;br /&gt;   end&lt;br /&gt;   toPlay = toPlay.to_i&lt;br /&gt;   if !state.canPlay toPlay&lt;br /&gt;    puts &amp;quot;Can't play &amp;quot; + toPlay.to_s + &amp;quot;. Select another:&amp;quot;&lt;br /&gt;    selectOther = true&lt;br /&gt;   else&lt;br /&gt;    state.play toPlay&lt;br /&gt;   end&lt;br /&gt;  end while selectOther&lt;br /&gt; end&lt;br /&gt; &lt;br /&gt; def setupGame(state, player)&lt;br /&gt;  &lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def runGame&lt;br /&gt;&lt;br /&gt; puts &amp;quot;Run against ai (A), another player (P) or let two AIs play against eachother (X)?&amp;quot;&lt;br /&gt; gameType = readline.strip&lt;br /&gt; case gameType&lt;br /&gt;  when &amp;quot;A&amp;quot;, &amp;quot;a&amp;quot;&lt;br /&gt;   player1 = createAIPlayer&lt;br /&gt;   player2 = createHumanPlayer&lt;br /&gt;   &lt;br /&gt;  when &amp;quot;P&amp;quot;, &amp;quot;p&amp;quot;&lt;br /&gt;   player1 = createHumanPlayer&lt;br /&gt;   player2 = createHumanPlayer&lt;br /&gt;   &lt;br /&gt;  when &amp;quot;X&amp;quot;, &amp;quot;x&amp;quot;&lt;br /&gt;   player1 = createAIPlayer&lt;br /&gt;   player2 = createAIPlayer&lt;br /&gt;   &lt;br /&gt;  else&lt;br /&gt;   puts &amp;quot;Invalid input: #{gameType}&amp;quot;&lt;br /&gt;   exit&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; players = [player1, player2]&lt;br /&gt; state = State.new&lt;br /&gt; &lt;br /&gt; player1.setupGame(state, State::Player1)&lt;br /&gt; player2.setupGame(state, State::Player2)&lt;br /&gt;&lt;br /&gt; while (!state.winner &amp;amp;&amp;amp; !state.isFull)&lt;br /&gt;  for player in players&lt;br /&gt;   puts state&lt;br /&gt;   player.play(state)&lt;br /&gt;   puts player.to_s + &amp;quot; played: &amp;quot; + state.lastPlayed.to_s&lt;br /&gt;   if state.winner then break end&lt;br /&gt;  end&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; if state.winner&lt;br /&gt;  puts state&lt;br /&gt;  puts &amp;quot;Winner: &amp;quot; + state.winner.to_s&lt;br /&gt; elsif state.isFull&lt;br /&gt;  puts state&lt;br /&gt;  puts &amp;quot;Draw!&amp;quot;&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;$aiCounter = 0&lt;br /&gt;def createAIPlayer&lt;br /&gt; $aiCounter = $aiCounter + 1&lt;br /&gt; name = &amp;quot;AI &amp;quot; + $aiCounter.to_s&lt;br /&gt; puts &amp;quot;Enter &amp;quot; + name + &amp;quot; level (1 to 5):&amp;quot;&lt;br /&gt; level = readline.to_i&lt;br /&gt; return AIPlayer.new(level, name)&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;$humanCounter = 0&lt;br /&gt;def createHumanPlayer&lt;br /&gt; $humanCounter = $humanCounter + 1&lt;br /&gt; defaultName = &amp;quot;Human &amp;quot; + $humanCounter.to_s&lt;br /&gt; puts &amp;quot;Enter name of human player (default &amp;quot; + defaultName + &amp;quot;):&amp;quot;&lt;br /&gt; name = readline.strip&lt;br /&gt; if !name || name == &amp;quot;&amp;quot; then&lt;br /&gt;  name = defaultName&lt;br /&gt; end&lt;br /&gt; return HumanPlayer.new(name)&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def runTests&lt;br /&gt;&lt;br /&gt; state = State.new&lt;br /&gt; &lt;br /&gt; state.play(3)&lt;br /&gt; state.play(3)&lt;br /&gt; state.play(4)&lt;br /&gt; state.play(4)&lt;br /&gt; state.play(5)&lt;br /&gt; state.play(5)&lt;br /&gt; state.play(6)&lt;br /&gt;&lt;br /&gt; #test getPlayed&lt;br /&gt; if state.getPlayed([3, 0]) != State::Player1 then raise &amp;quot;getPlayed doesn't work&amp;quot; end&lt;br /&gt; if state.getPlayed([3, 1]) != State::Player2 then raise &amp;quot;getPlayed doesn't work&amp;quot; end&lt;br /&gt; if state.getPlayed([3, 2]) != 1 then raise &amp;quot;getPlayed doesn't work&amp;quot; end&lt;br /&gt; if state.getPlayed([3, 2]).class != Fixnum then raise &amp;quot;getPlayed doesn't work&amp;quot; end&lt;br /&gt;&lt;br /&gt; #test findWinner&lt;br /&gt; winningRow = (3..6).collect{|c| [c, 0]}&lt;br /&gt; if !state.findWinner(winningRow) then raise &amp;quot;findWinner doesn't work. winningRow=&amp;quot; + winningRow.to_s end&lt;br /&gt; &lt;br /&gt; #test state.winner&lt;br /&gt; if state.winner == nil then raise &amp;quot;winner should be set&amp;quot; end&lt;br /&gt;  &lt;br /&gt; puts &amp;quot;All tests ok&amp;quot;&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;runGame&lt;br /&gt;#runTests&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/5933717644607161038-1487374734587615806?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/1487374734587615806/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=1487374734587615806' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/1487374734587615806'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/1487374734587615806'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2009/02/trying-out-ruby-for-very-first-time.html' title='Trying out ruby for the very first time'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-8984850066674789484</id><published>2008-10-16T00:33:00.000-07:00</published><updated>2009-09-03T11:40:19.293-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='extension methods'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>The ForEach extension method (C#)</title><content type='html'>Everyone knows about the foreach keyword, but have you ever noticed there are no equivalent extension method for IEnumerables? I.e. execute "this action" on each element. Perhaps the most simple extension method of them all, which is the reason I'll share it with you :)&lt;br /&gt;&lt;pre name="code" class="c#"&gt;&lt;br /&gt;public static class MyExtensionMethods&lt;br /&gt;{&lt;br /&gt;  public static void ForEach&amp;LT;T&amp;GT;(this IEnumerable&amp;LT;T&amp;GT; list, Action&amp;LT;T&amp;GT; action)&lt;br /&gt;  {&lt;br /&gt;    foreach(var item in list) action(item);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;For you who aren't familiar with extension methods, what it really says is that, ForEach is a member method of IEnumerable&amp;LT;T&amp;GT;, and can be called by simply writing &lt;br /&gt;&lt;pre name="code" class="c#"&gt;myList.ForEach(myAction)&lt;/pre&gt;&lt;br /&gt;For example, to output each item of a list to the console, you could write:&lt;br /&gt;&lt;pre name="code" class="c#"&gt;myList.ForEach(x =&gt; Console.Write(x));&lt;/pre&gt;&lt;br /&gt;instead of&lt;br /&gt;&lt;pre name="code" class="c#"&gt;foreach(var x in in myList) Console.Write(x);&lt;/pre&gt;&lt;br /&gt;In this case you might not gain so much in terms of code size, but I think it makes the code more readable. You are reading text from left to right, so it makes sense having the for each statement to the right, right? :)&lt;br /&gt;&lt;pre name="code" class="c#"&gt;myList.WhereThis().SelectThat().DoThis();&lt;/pre&gt;&lt;br /&gt;(There is probably some kind of cool name for this pattern, like "The opposite of law of demeter"... Gustaf probably has more knowledge in this!)&lt;br /&gt;&lt;br /&gt;Here is a more complex example of a combination of extension methods:&lt;br /&gt;&lt;pre name="code" class="c#"&gt;myList.Where(x =&gt; x.IsValid()).Select(x =&gt; x.ComputeValue()).Where(x =&gt; x &gt; 0).ForEach(x =&gt; Console.Write(x));&lt;/pre&gt;&lt;br /&gt;Where and Select are also extension methods of IEnumerable&lt;T&gt;. Without these you would have to write:&lt;br /&gt;&lt;pre name="code" class="c#"&gt;&lt;br /&gt;foreach(var x in myList) &lt;br /&gt;{&lt;br /&gt;  if (x.IsValid()) &lt;br /&gt;  {&lt;br /&gt;    var value = x.ComputeValue();&lt;br /&gt;    if (value &gt; 0) Console.Write(value);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;8 lines instead of 1! Impressed? :)&lt;br /&gt;&lt;br /&gt;So, extension methods! Learn them, use them, and write your own!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-8984850066674789484?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/8984850066674789484/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=8984850066674789484' title='9 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/8984850066674789484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/8984850066674789484'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2008/10/foreach-extension-method-c.html' title='The ForEach extension method (C#)'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-614782586190473687</id><published>2008-09-06T03:56:00.000-07:00</published><updated>2009-09-03T11:40:19.293-07:00</updated><title type='text'>ClickOnce deployment or not?</title><content type='html'>Some weeks ago, I developed a small program in C# called P4 Explorer. To distribute it, i used a technique called &lt;a href="http://msdn.microsoft.com/en-us/library/t71a733d%28VS.80%29.aspx"&gt;ClickOnce deployment&lt;/a&gt;, which is a part of Visual Studio C# Express 2008. This blog post will be about what ClickOnce deployments are, how they can be used, and why you in the end shouldn't use them...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;ClickOnce&lt;/span&gt;&lt;br /&gt;ClickOnce deployments will simplify your deployment a lot. To deploy your application, all you need to do is:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;specify the location to publish the application (i.e. a network drive, web site or ftp),&lt;/li&gt;&lt;li&gt;specify from what location the users will install it from (propably the same as 1), and&lt;br /&gt;&lt;/li&gt;&lt;li&gt;decide whether the application should be installed at the start menu, or always must be started from the install path (2).&lt;/li&gt;&lt;/ol&gt;Furhermore you can specify if the application automatically should check for updates, which is really great if you plan to update your application frequently. You then specify how often the it should check for updates, and when an update is found, the user will be notified and can download the latest version. All by only selecting "The application should check for updates". Very nice!&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_F5z3mmdTM8I/SMJyks0BXsI/AAAAAAAAB_Y/uovBNC4xwJE/s1600-h/ClickOnce_Updates.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_F5z3mmdTM8I/SMJyks0BXsI/AAAAAAAAB_Y/uovBNC4xwJE/s320/ClickOnce_Updates.jpg" alt="" id="BLOGGER_PHOTO_ID_5242878891042889410" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Now, for you to deploy a new version, all you do is click "Publish". When the user then starts the program, the update will be found and installed (if permitted by the user). Very easy!&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style="font-size:180%;"&gt;Limitations&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Application Path&lt;/span&gt;&lt;br /&gt;ClickOnce deployment doesn't come for free though. First of, the application won't be installed under "C:\Program Files\MyCompany\MySoftware" as you might expect, but at some secret place (hidden from the user and developer). If you decide to let the installer add a shortcut to your start menu, there is no way to find out where this shortcut points, as it's not a normal shortcut. Right clicking on it and selecting properties will not give you the information you expect, i.e. the path to the executable.&lt;br /&gt;Now, there is a simple way of finding out the path of the executable. When starting the installed application, the property Application.ExecutablePath will be correctly set and you can thus be used to, for example, add to the PATH environment variable:&lt;br /&gt;&lt;pre name="code" class="c#"&gt;void UpgradePathVariable()&lt;br /&gt;{&lt;br /&gt;    string l_ApplicationFolder = Path.GetDirectoryName(Application.ExecutablePath);&lt;br /&gt;    string l_PathVariable = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine);&lt;br /&gt;    if (!l_PathVariable.Contains(l_ApplicationFolder))&lt;br /&gt;    {&lt;br /&gt;        l_PathVariable = l_OldPathVariable + ";" + l_ApplicationFolder;&lt;br /&gt;    }&lt;br /&gt;    Environment.SetEnvironmentVariable("PATH", l_PathVariable, EnvironmentVariableTarget.Machine);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Parameters&lt;/span&gt;&lt;br /&gt;Also, because the program doesn't have a fixed installation path, there is no support for sending parameters to the program. I.e. args in static void Main(string[] args) will always be empty. The documentation at MSDN states that the only way to send parameters to a click once application is to deploy it at a web page, and let the user send html-parameters to it, i.e.:&lt;br /&gt;http://www.yourdomain.com/yourapplication.exe?parameter1=val1&amp;amp;parameter2=val2&lt;br /&gt;But&lt;br /&gt;&lt;ol&gt;&lt;li&gt;this requires your application to be deployed using a web page, and&lt;/li&gt;&lt;li&gt;you must always download the installer every time you need to sent parameters to the program.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Say for example you want to let the user start the program by right clicking on a file in explorer and selecting "Open in my program". You would need to add a line in your registry pointing to the executable file:&lt;br /&gt;&lt;br /&gt;pathtoyourexe "%1"&lt;br /&gt;&lt;br /&gt;This would be both slow and hacky if using the recommended http-style mentioned above. Instead, by using the Application.ExecutablePath property, you can actually access the physical path to the installed executable, and thus add this path to the registry. With this setup correctly, right clicking on a file and selecting your program to open it with, will open the program and send the parameter correctly to it!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Settings&lt;/span&gt;&lt;br /&gt;But, even though everything might seem to work out fine, you will soon notice that the Settings object defined in your application will be different if starting the program using the shortcut from your start menu, or right clicking on a file. They are not sharing the same application settings. And if you upgrade the program, all settings in your "right clicked version" will be gone, because the new version will be installed in a new folder.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;In the end&lt;/span&gt;&lt;br /&gt;Even though click once applications are really easy to deploy, and give you a lot for free, the limitations just makes them really hard to work with. Making simple applications might work, but as soon as you want the user to interact with it through the explorer shell, you are better off making your own installer (or using a free one such as &lt;a href="http://nsis.sourceforge.net/"&gt;NSIS&lt;/a&gt;). So in the end I decided to deploy my program manually using a source control, which made all my problems go away. Sending parameters worked, settings worked, and the application had a fixed folder!&lt;br /&gt;&lt;br /&gt;The only thing I was really missing from ClickOnce was the ability for the program to automatically check for updates, which was something I really needed to make sure everyone using my application had the latest version (hopefully having less bugs in it). But it turned out this wasn't so hard to make on my own! The pseudo code for it, printed here, is divided in two programs - your main application, yourapp.exe, and the upgrade application, upgrade.exe.&lt;br /&gt;&lt;br /&gt;yourapp.exe:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Is there a new version available (i.e. check using source control)&lt;/li&gt;&lt;li&gt;Copy upgrade.exe (and dependencies) to a new folder "temp"&lt;/li&gt;&lt;li&gt;Start new process temp\upgrade.exe&lt;/li&gt;&lt;li&gt;Close program&lt;/li&gt;&lt;/ol&gt;upgrade.exe:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Make sure all instances of yourapp.exe are closed&lt;/li&gt;&lt;li&gt;Download the latest version (i.e. using source control)&lt;/li&gt;&lt;li&gt;Start new process ..\&lt;yourapplication&gt;yourapp.exe&lt;/yourapplication&gt;&lt;/li&gt;&lt;li&gt;Close program&lt;/li&gt;&lt;/ol&gt;You can always make it faster by running the check for new version in it's own thread, and only checking every x hour, but the main thing is that I get the same features as if running with ClickOnce, but don't need to limit my application as much as you do with ClickOnce applications!&lt;br /&gt;&lt;br /&gt;So, ClickOnce, good for small application, not good for more advanced applications.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-614782586190473687?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/614782586190473687/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=614782586190473687' title='2 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/614782586190473687'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/614782586190473687'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2008/09/clickonce-deployment-or-not.html' title='ClickOnce deployment or not?'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_F5z3mmdTM8I/SMJyks0BXsI/AAAAAAAAB_Y/uovBNC4xwJE/s72-c/ClickOnce_Updates.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-4080974539911375038</id><published>2008-08-08T01:55:00.000-07:00</published><updated>2009-09-03T11:40:19.293-07:00</updated><title type='text'>Google Calendar</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_F5z3mmdTM8I/SJw3dcJjqFI/AAAAAAAAByU/LVdTb_rV5is/s1600-h/google+calendar.bmp"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_F5z3mmdTM8I/SJw3dcJjqFI/AAAAAAAAByU/LVdTb_rV5is/s320/google+calendar.bmp" alt="" id="BLOGGER_PHOTO_ID_5232117846009686098" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;img src="file:///C:/DOCUME%7E1/chrgen/LOCALS%7E1/Temp/moz-screenshot.jpg" alt="" /&gt;&lt;br /&gt;I love &lt;a href="http://www.google.com/calendar"&gt;Google Calendar&lt;/a&gt;, mostly because of the free sms service, sending you an sms x minutes before an event. What's the point of otherwise having a calendar if you only get notifications from it when sitting in front of a computer, such as how ms exchange and similar works. "You need to be at the dentist in 30 minutes", well hopefully I'm sitting in front of the computer when this message pops up. Of course you can always install a mail service in your mobile, and receive a mail when an appointment is about to happened, and you can buy an expensive mobile phone having it's own calendar which you then can sync with the computer from time to time. But for me, I just want to say "at that time, I need to be there, and wherever I am 30 minutes before that, notify me". That's why I love google calendar, because you can be anywhere and still get a notification!&lt;br /&gt;&lt;br /&gt;Now, that's all glorious and so, but as always there are some problems - I want to be able to sync it with other calendars, so that I don't need to open up a browser, enter the adress, and log in every time I need to add an event. For &lt;a href="http://www.mozilla.com/en-US/thunderbird/"&gt;Mozilla Thunderbird&lt;/a&gt; there is an add on to support calendars called &lt;a href="http://www.mozilla.org/projects/calendar/lightning/"&gt;Lighting&lt;/a&gt;, and for this add on there is another one called &lt;a href="https://addons.mozilla.org/en-US/thunderbird/addon/4631"&gt;Provider for Google Calendar&lt;/a&gt;, which makes it possible to view and update the google calendar from the calendar within Thunderbird. Niiice!&lt;br /&gt;&lt;br /&gt;But hey, wait a minute, the reason I wanted to support google calendar in the first place was because of it's sms service, but as it turns out, the google calendar provider for thunderbird doesn't support this :( So in the end I still need to access google calendar from within a web-browser, and change the settings of all my events manually.&lt;br /&gt;&lt;br /&gt;So that's where I'm now, still looking for the perfect solution. Google calendar is still the best option for me, but if you know about a better one then please let me know...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-4080974539911375038?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/4080974539911375038/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=4080974539911375038' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/4080974539911375038'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/4080974539911375038'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2008/08/google-calendar.html' title='Google Calendar'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_F5z3mmdTM8I/SJw3dcJjqFI/AAAAAAAAByU/LVdTb_rV5is/s72-c/google+calendar.bmp' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-207304897786467433</id><published>2008-06-02T05:15:00.000-07:00</published><updated>2009-09-03T11:40:19.293-07:00</updated><title type='text'>Hacking VS C# 2008 Express</title><content type='html'>&lt;a href="http://www.microsoft.com/express/vcsharp/"&gt;VS C# 2008 Express&lt;/a&gt; is a really nice product in many ways - you've got most of the stuff you need, but most of all, it's free!&lt;br /&gt;&lt;br /&gt;Though, I was playing around for it a bit, and needed to support compiling against a specific platform (x86 instead of Any CPU which is default). The reason for this was that, in my project, I was refering to a dll written in managed c++ - compiled for x86! Mixing x64 and x86 is never a good solution, and as C# projects per default compiles against Any CPU they will run in 64-bits mode on a 64-bit computer. When the application tries to load the 32-bit dll, the application crashes...&lt;br /&gt;&lt;br /&gt;Now, in VS C# 2008 &lt;span style="font-weight: bold;"&gt;Express&lt;/span&gt;, you &lt;span style="font-weight: bold;"&gt;cannot&lt;/span&gt; specify another target platform but the Any CPU platform. Guess they think that "if you need support for specific platforms, you should be able to pay for a commercial version".&lt;br /&gt;&lt;br /&gt;I was reading through MSDN, and found this note:&lt;br /&gt;&lt;blockquote&gt;Note   /platform is not available in the development environment in Visual C# Express.&lt;/blockquote&gt;&lt;br /&gt;"Damn", I thought, "this is the end. But what does &lt;span style="font-style: italic;"&gt;development environment&lt;/span&gt; mean?". I had to try it out manually using the command prompt, so I compiled the project in VS and copied the command line output from the output window, being something like:&lt;br /&gt;&lt;pre&gt;C:\WINDOWS\Microsoft.NET\Framework\v3.5\Csc.exe /noconfig /nowarn:1701,1702 ...&lt;br /&gt;&lt;/pre&gt;I put the line in a batch file, and added the /target:x86 flag, compiled it and... it worked! The project got compiled using x86 as a target platform.&lt;br /&gt;&lt;br /&gt;As it turns out, VS C# 2008 Express &lt;span style="font-weight: bold;"&gt;does&lt;/span&gt; support the /target option, and probably others as well. They only lack the support for the option in the IDE, which is kinda a hacky way of disabling a feature, IMO.&lt;br /&gt;&lt;br /&gt;Now, I don't want to build the project using a batch file every time, I would like to build it inside VS IDE so that others can easily build it. As the VS project files are nothing but XML, you can easily open them up in any editor you like to see their contents. I did this to find out if there was some way to add a target flag to the compiler, but unfortunately I couldn't find anything interesting (of course that would be &lt;span style="font-style: italic;"&gt;too&lt;/span&gt; easy!). I continued with searching the web, and found this strange property:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-weight: bold;"&gt;CSharpProjectConfigurationProperties3.PlatformTarget Property&lt;/span&gt;&lt;br /&gt;This member provides internal-only access to C# project configuration properties.&lt;br /&gt;...&lt;br /&gt;External components can access these properties through the Properties collection for the appropriate Visual Studio automation object.&lt;br /&gt;&lt;/blockquote&gt;"Well", I said to my self, "the &lt;span style="font-style: italic;"&gt;Properties collection&lt;/span&gt; would probably refer to the XML properties found in the project file, so once again I opened up the project file, and browsed to two property groups being:&lt;br /&gt;&lt;pre&gt;&amp;lt;PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' "&amp;gt;&lt;/pre&gt;and&lt;br /&gt;&lt;pre&gt;&amp;lt;PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "&amp;gt;&lt;/pre&gt;In these groups, I added the PlatformTarget property:&lt;br /&gt;&lt;pre&gt;&amp;lt;PlatformTarget&amp;gt;x86&amp;lt;/PlatformTarget&amp;gt;&lt;/pre&gt; I saved the file, reloaded it in VS, recompiled the project... and viola, it worked! All you needed to do was to find out the magic property to add to the project file! :)&lt;br /&gt;&lt;br /&gt;This proves that C# Express contains more under the hood than what's visible to the eye. With a simple editor, and some knowledge on how to search MSDN, you can get a lot out of this product!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-207304897786467433?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/207304897786467433/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=207304897786467433' title='7 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/207304897786467433'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/207304897786467433'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2008/06/hacking-vs-c-2008-express.html' title='Hacking VS C# 2008 Express'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-2054843124378054644</id><published>2008-05-12T08:47:00.000-07:00</published><updated>2009-09-03T11:40:19.293-07:00</updated><title type='text'>What is your favorite language?</title><content type='html'>We all have our favorite language, but for most people it's almost religious to discuss which language is the best. I realized I don't know what language people &lt;span style="font-weight:bold;"&gt;really&lt;/span&gt; prefer, simply because I've never discussed it!&lt;br /&gt;&lt;br /&gt;Having a look at &lt;a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html"&gt;TIOBE Programming Community Index for May 2008&lt;/a&gt; got me thinking. You will see Java in top, followed by C and then (Visual) Basic. I couldn't get this, until I read the following:&lt;br /&gt;&lt;blockquote&gt;Observe that the TIOBE index is not about the best programming language or the language in which most lines of code have been written.&lt;/blockquote&gt;&lt;br /&gt;Of course, Java produces a lots of lines of code, and C has been around for a long long time. Visual Basic I can't say why is rated third, but I guess every newbie programmer develops in VB, and also, you have all those macros! I guess those makes up for a few lines?! :)&lt;br /&gt;&lt;br /&gt;C# is only at 8'th place, but I hope that's because you don't need to write as much code in it as you do with other languages... which probably isn't true because you DO write a lots of code in it. With C# 3.0 you can use synthetic sugar to write less code, but not &lt;span style="font-weight:bold;"&gt;that much&lt;/span&gt; ;) I really think the reason C# is not being that highly ranked is because it hasn't been around for that long. People are still experimenting with it, and those companies that &lt;span style="font-style:italic;"&gt;has&lt;/span&gt; been around for a while can't see the reason for replacing Java with C#. But, in the future, when everyone is &lt;a href="http://www.michaelnygard.com/blog/2008/05/when_should_you_jump_jsr_308_t.html"&gt;jumping off Java&lt;/a&gt;, C# will grow in popularity!&lt;br /&gt;&lt;br /&gt;Anyway, I added a vote to this blog (in the left sidebar), so go ahead and vote on your favorite language. And, if you want, post a comment on this post, arguing for why you think your language is the best!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-2054843124378054644?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/2054843124378054644/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=2054843124378054644' title='6 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/2054843124378054644'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/2054843124378054644'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2008/05/what-is-your-favorite-language.html' title='What is your favorite language?'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-5894795845142646422</id><published>2008-05-10T06:16:00.000-07:00</published><updated>2009-09-03T11:40:19.294-07:00</updated><title type='text'>C# Lambda Lazy List FizzBuzz :)</title><content type='html'>Ok, so here is my next example of an implementation of the FizzBuzz problem. I'm going to use a combination of C# 3.0's lambda expressions, lazy lists and extension methods!&lt;br /&gt;&lt;br /&gt;First, I create a function returning a lazy list over all numbers starting from 1:&lt;br /&gt;&lt;pre name="code" class="c#"&gt;static IEnumerable&amp;lt;int&amp;gt; AllNumbers()&lt;br /&gt;{&lt;br /&gt;    int i = 1;&lt;br /&gt;    while (true) yield return i++;&lt;br /&gt;}&lt;/pre&gt;Second, I create a function returning a lazy list of strings, being pText every pCount time. I.e. null, null, Fizz, null, null, Fizz.&lt;br /&gt;&lt;pre name="code" class="c#"&gt;static IEnumerable&amp;lt;string&amp;gt; FizzBuzz(int pCount, string pText)&lt;br /&gt;{&lt;br /&gt;    while (true)&lt;br /&gt;    {&lt;br /&gt;        for (int i = 0; i &lt; pCount-1; i++)&lt;br /&gt;        {&lt;br /&gt;            yield return null;&lt;br /&gt;        }&lt;br /&gt;        yield return pText;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Now, I need a way of combining the values two lists, so I create an extension method for this. It takes another list and a combinator function:&lt;br /&gt;&lt;pre name="code" class="c#"&gt;static IEnumerable&amp;lt;T&amp;gt Combine&amp;lt;T, TA, TB&amp;gt;(this IEnumerable&amp;lt;TA&amp;gt pA, IEnumerable&amp;lt;TB&amp;gt pB, Func&amp;lt;TA, TB, T&amp;gt; pCombineFunc)&lt;br /&gt;{&lt;br /&gt;    var i = pA.GetEnumerator();&lt;br /&gt;    var j = pB.GetEnumerator();&lt;br /&gt;    while(i.MoveNext() &amp;&amp; j.MoveNext())&lt;br /&gt;    {&lt;br /&gt;        yield return pCombineFunc(i.Current, j.Current);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;And here is the whole FizzBuzz program, returning a list of strings being 1, 2, Fizz, 4, Buzz...:&lt;br /&gt;&lt;pre name="code" class="c#"&gt;static IEnumerable&amp;lt;string&amp;gt; FizzBuzz()&lt;br /&gt;{&lt;br /&gt;    return AllNumbers().Combine(&lt;br /&gt;        FizzBuzz(3, "Fizz").Combine(FizzBuzz(5, "Buzz"), (x, y) =&gt; x + y),&lt;br /&gt;        (x, y) =&gt; (y != "") ? y : x.ToString());&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;To write the result to the console, I use this main function:&lt;br /&gt;&lt;pre name="code" class="c#"&gt;static void Main(string[] args)&lt;br /&gt;{&lt;br /&gt;    foreach (string fizzBuzz in FizzBuzz().Take(100))&lt;br /&gt;    {&lt;br /&gt;        Console.WriteLine(fizzBuzz);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Thats it! Nice and easy eh? :) Hope you liked it and perhaps makes you look into C# 3.0, if you haven't already? You can always &lt;a href="http://www.microsoft.com/express/"&gt;download Visual Studio 2008 C# Express for free&lt;/a&gt; if you want to try it out!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Edit: Changed generic parameters &amp;lt;T&amp;gt; to html-characters. Changed C# 3.5 to 3.0 (thank u Gustaf :))&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-5894795845142646422?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/5894795845142646422/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=5894795845142646422' title='2 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/5894795845142646422'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/5894795845142646422'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2008/05/c-lambda-lazy-list-fizzbuzz.html' title='C# Lambda Lazy List FizzBuzz :)'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-9212630053604826954</id><published>2008-05-08T22:10:00.000-07:00</published><updated>2009-09-03T11:40:19.294-07:00</updated><title type='text'>C# FizzBuzz :)</title><content type='html'>Here is my thoughts and solution to Gustafs &lt;a href="http://coffeedrivendevelopment.blogspot.com/2008/04/ok-so-heres-my-first-real-post-its-spin.html"&gt;Functional FizzBuzz&lt;/a&gt; problem! It's more or less a copy from what I wrote as a &lt;a href="http://gustafnilssonkotte.blogspot.com/2008/04/functional-fizzbuzz.html"&gt;comment in his old blog&lt;/a&gt;, except for some modifications in the code snippet below.&lt;br /&gt;&lt;br /&gt;I believe that in almost all cases, where you should write a solution for a given problem, you have two solutions to choose from. The first one focuses on writing well looking, readable, code (which is always good), the second focuses on writing fast code (which is required in some projects).&lt;br /&gt;&lt;br /&gt;My solution for a bit faster code (I guess), would be this (c# style):&lt;br /&gt;&lt;pre name="code" class="c#"&gt;&lt;br /&gt;for (int i = 1, j = 1, k = 1; i &lt;= 100; i++, j++, k++)&lt;br /&gt;{&lt;br /&gt;    string t = "";&lt;br /&gt;    if (j == 3)&lt;br /&gt;    {&lt;br /&gt;        t = "Fizz";&lt;br /&gt;        j = 0;&lt;br /&gt;    }&lt;br /&gt;    if (k == 5)&lt;br /&gt;    {&lt;br /&gt;        t += "Buzz";&lt;br /&gt;        k = 0;&lt;br /&gt;    }&lt;br /&gt;    if (t == "")&lt;br /&gt;    {&lt;br /&gt;        t = i.ToString();&lt;br /&gt;    }&lt;br /&gt;    Console.WriteLine(t);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The difference is that you don't need to call "x `mod` m == 0" to find out if you should print Fizz or Buzz, instead two extra counters are used to keep track on when to write Fizz and when to write Buzz. I guess you could write this in functional style as well, but my haskell skills are a bit out of date so I wouldn't dare to try that ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-9212630053604826954?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/9212630053604826954/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=9212630053604826954' title='1 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/9212630053604826954'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/9212630053604826954'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2008/05/c-fizzbuzz.html' title='C# FizzBuzz :)'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-2292844344491716908</id><published>2008-04-27T09:54:00.003-07:00</published><updated>2008-04-27T10:24:20.523-07:00</updated><title type='text'>New blog at CoffeeDrivenDevelopment.blogspot.com</title><content type='html'>And so, finally, me and &lt;a href="http://gustafnilssonkotte.blogspot.com/"&gt;Gustaf&lt;/a&gt; decided to put our writing skills together to form a new blog. Inspired (drugged) by coffee and cool technical terms such as TDD (Test Driven Development) and BDD (Behaviour Driven Development), we decided to call it Coffee Driven Development...&lt;br /&gt;&lt;br /&gt;Please visit (and possibly subscribe to) the blog at:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://CoffeeDrivenDevelopment.blogspot.com"&gt;http://CoffeeDrivenDevelopment.blogspot.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;That also means that this probably will be my last post here, unless me and Gustaf starts disagreeing on some odd topic and war is uppon us. Then I might come back here to write about why Gustaf is wrong. :)&lt;br /&gt;&lt;br /&gt;But until then, see you at coffedrivendevelopment.blogspot.com!&lt;br /&gt;&lt;br /&gt;Christian&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-2292844344491716908?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/2292844344491716908/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=2292844344491716908' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/2292844344491716908'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/2292844344491716908'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2008/04/new-blog-at-coffeedrivendevelopmentblog.html' title='New blog at CoffeeDrivenDevelopment.blogspot.com'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-8957052531056343814</id><published>2008-04-16T22:13:00.000-07:00</published><updated>2009-08-27T11:28:50.572-07:00</updated><title type='text'>Retained or Immediate?</title><content type='html'>This topic is based on a discussion with a friend, Johannes, so many creds to him for sharing his experience and knowledge! Here you are Johannes, a can of coke! :)&lt;br /&gt;&lt;br /&gt;&lt;img src="http://lh6.ggpht.com/christian.genne/SAqAwS0mz0I/AAAAAAAAA3Y/DT0PEq1eshI/IMG_2885.JPG?imgmax=1152"   width=400 align=center&gt;&lt;br /&gt;&lt;br /&gt;Now, with that taken care of, let's get started :)&lt;br /&gt;&lt;br /&gt;There are nowadays two ways of visualizing data, either using retained or immediate mode. In retained mode you have no control over the rendering your self, but put all your rendering setup in an internal data structure, which then is used by the renderer to know what to render. You don't tell the renderer directly how to render it, but "hey, here is my stuff, can you cache it for me and then render it when you want to". In immediate mode you render your data directly, by explicitly telling the rendering framework (OpenGl/DirectX) what you want to render.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Retained Mode&lt;/span&gt;&lt;br /&gt;In games, retained rendering would typically be represented by a scene graph, looking something like this:&lt;br /&gt;&lt;pre name="code" class="c#"&gt;void SetupRenderer()&lt;br /&gt;{&lt;br /&gt;  SceneNode node = new SceneNode();&lt;br /&gt;  node.Mesh = myMesh;&lt;br /&gt;  node.Transform = Matrix.Create(...);&lt;br /&gt;  renderer.SceneGraph.AddNode(node);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In gui rendering, this is often represented by gui controls holding their own states. For example a checkbox having an internal state "checked", which typically represents some logical value you store elsewhere in your application.&lt;br /&gt;&lt;pre name="code" class="c#"&gt;void SetupGui()&lt;br /&gt;{&lt;br /&gt;  CheckBox b = new CheckBox();&lt;br /&gt;  b.Checked = myCheckedState;&lt;br /&gt;  b.OnCheckedChanged += OnCheckBoxCheckedChanged;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void OnCheckBoxCheckedChanged(object o, EventArgs e)&lt;br /&gt;{&lt;br /&gt;  myCheckedState = (o as CheckBox).Checked;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As you see, because the gui caches the value for you, you need to make sure to update your own internal state "myCheckedState" when the gui control chances state. And of course, if you change the value of myCheckedState you probably want to update the gui as well.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Immediate Mode&lt;/span&gt;&lt;br /&gt;In the opposite method, immediate mode, you instead render all objects your self in an explicit rendering call. Instead of caching your state, and then letting an external renderer handle the rendering, you collect all your rendering into your own function, which when called renders your current state to the screen.&lt;br /&gt;&lt;pre name="code" class="c#"&gt;void Render(State myState)&lt;br /&gt;{&lt;br /&gt;  Mesh playerMesh = getPlayerMesh();&lt;br /&gt;  foreach( Player p in myState )&lt;br /&gt;  {&lt;br /&gt;    renderer.RenderMesh(playerMesh, p.Position, p.Orientation);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This is good because you don't need to cache your values anywhere, and have better control over the rendering. Instead of adding new nodes to your scene graph, which would probably be represented as new instances of a scene node class, you just add your function calls directly in your rendering method.&lt;br /&gt;&lt;br /&gt;For window applications, this type of rendering hasn't been quite as accepted as in game rendering. In Java, though, I think most of their gui controls are represented as a view and a model (the so called model view controlled (mvc) approach). This is a good way of defining guis, as a view of some model. The gui should not store any values it self, but only reflect a model you define and maintain elsewhere. Unfortunately this is not possible in many other gui-platforms, such as in .Net.&lt;br /&gt;&lt;br /&gt;There is another technique for gui rendering which, as far as I know, is relatively new. It is called IMGUI, or immediate gui. For a nice video explaining imgui, see:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.mollyrocket.com/video/imgui.avi"&gt;http://www.mollyrocket.com/video/imgui.avi&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;IMGUI basically means that the gui has no state at all, and even no callbacks. The gui is only responsible for drawing the current state, which is drawn &lt;span style="font-style: italic;"&gt;every frame&lt;/span&gt;, and &lt;span style="font-style: italic;"&gt;at the same time&lt;/span&gt; returning any state. For example, to find out if a button is pressed, you make a rendering call such as:&lt;br /&gt;&lt;pre name="code" class="c#"&gt;if (gui.DoButton(x, y, "Press me!"))&lt;br /&gt;{&lt;br /&gt;  // Button was pressed&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This code will both render the button at position x, y, &lt;span style="font-style: italic;"&gt;and&lt;/span&gt; return true if the button is being pressed. Because of this you need to render the gui ever frame (several times each second), but with todays graphic cards this shouldn't be a problem.&lt;br /&gt;&lt;br /&gt;I won't go into detail about how to use IMGUI, but for another more complex example of how to use it, see &lt;a href="http://www.spellofplay.com/forum/viewtopic.php?t=478"&gt;Johannes post on www.spellofplay&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Which One is Best?&lt;/span&gt;&lt;br /&gt;Now, the big difference between immediate and retained rendering is that in immediate rendering you specify, in your rendering loop, &lt;span style="font-style: italic;"&gt;exactly&lt;/span&gt; what you want to render. This makes it more coupled, as the rendering must know of all the different types of models, instead of, as when using a scene graph, only telling the renderer that you want to render something that has "these properties". But in this case&lt;span style="font-style: italic;"&gt; the renderer doesn't know what it is rendering&lt;/span&gt;. This is the reason immediate rendering is so much better. You know for sure what you are rendering, and can, based on this knowledge have more control over the rendering. You never get to a situation where you need to question yourself "am I rendering a can of coke?".&lt;br /&gt;&lt;br /&gt;And that is where I want to get to in this post, that you always should strive for writing code so that you always know what data you are working on. Avoid using a generic base class for everything where you put a lots of virtual methods doing all your magic stuff, because&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Reading such code is a hell because you never know what will happen when you call that function, until you actually run it&lt;/li&gt;&lt;li&gt;The code will get very coupled as you need to put all your specific implementations at the same place, unless you:&lt;/li&gt;&lt;ol&gt;&lt;li&gt;Use the visitor pattern (requires a lots of code, and a new class for each new type of action to perform on the types).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Use reflection (non-portable solution, what if you change an entity type to another?).&lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt;So, instead of writing:&lt;br /&gt;&lt;pre name="code" class="c#"&gt;void Render()&lt;br /&gt;{&lt;br /&gt;  foreach(Entity e in entities)&lt;br /&gt;  {&lt;br /&gt;    e.Render();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;you should write:&lt;br /&gt;&lt;pre name="code" class="c#"&gt;void Render()&lt;br /&gt;{&lt;br /&gt;  foreach(Player p in players)&lt;br /&gt;  {&lt;br /&gt;    RenderPlayer(p);&lt;br /&gt;  }&lt;br /&gt;  foreach(Enemy e in enemies)&lt;br /&gt;  {&lt;br /&gt;    RenderEnemy(p);&lt;br /&gt;  }&lt;br /&gt;  foreach(CanOfCoke c in canOfCokes)&lt;br /&gt;  {&lt;br /&gt;    RenderCanOfCoke(c);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;You move the render specific stuff out from the entity you are trying to render and into the rendering code, where it should belong. You also know for sure exactly what types of entities you have in your world, and can thus perform different tasks depending on the type directly, instead of first trying to resolve the type using different techniques.&lt;br /&gt;&lt;br /&gt;In school you learn to use scene graphs, to structure your code into a big hierarchy of classes, and to always prepare for the case when you "need to expand". Don't do that! Make it simple, don't prepare for the worst, don't make your classes super generic. Write code that does exactly what it should, no more, no less, and always try to make it as readable as possible. That is my tip to you today!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-8957052531056343814?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/8957052531056343814/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=8957052531056343814' title='1 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/8957052531056343814'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/8957052531056343814'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2008/04/retained-or-immediate.html' title='Retained or Immediate?'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/christian.genne/SAqAwS0mz0I/AAAAAAAAA3Y/DT0PEq1eshI/s72-c/IMG_2885.JPG?imgmax=1152' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-7509343255350379309</id><published>2008-04-06T14:01:00.000-07:00</published><updated>2008-04-06T14:38:37.877-07:00</updated><title type='text'>Experimenting with syntax highlighting</title><content type='html'>Every code blogger need syntax highlighting, so no exception for me! After struggling some with different scripts, I finally got it to work! Doesn't it look good?! :)&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="c++"&gt;&lt;br /&gt;// Example comment&lt;br /&gt;class X&lt;br /&gt;{&lt;br /&gt;  int p;&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/5933717644607161038-7509343255350379309?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/7509343255350379309/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=7509343255350379309' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/7509343255350379309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/7509343255350379309'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2008/04/experimenting-with-syntax-highlighting.html' title='Experimenting with syntax highlighting'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-5183368711836998281</id><published>2008-03-30T06:40:00.000-07:00</published><updated>2008-04-06T14:40:19.862-07:00</updated><title type='text'>Dedefending my case: Stop documenting your code!</title><content type='html'>Here is my response to &lt;a href="http://pethol.wordpress.com/2008/03/25/do-comment-code/"&gt;Peters post - Do comment code!&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;First off, I think it's okey to be critical, you should not take anything for granted, and of course we all have our own ways of programming. My post was more of a tip based on my own experience from working in a larger team with no/little code documentation.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;blockquote&gt;Commenting code isn’t as much about pinning down knowledge, as it is communication. And when it comes to communication, redundancy is almost never a problem :)&lt;/blockquote&gt;&lt;/span&gt;Commenting code is communication, but you are communicating knowledge. The same knowledge is always communicated through the code. If you find it hard to "read" the code, then, in my own experience, the code is not well written and/or formatted. Make sure you have a coding policy stating how you should write code so that all code looks the same and can be easily "parsed by your brain". It's amazing how much easier it is to read code that is well written and formatted.&lt;br /&gt;&lt;br /&gt;I'm not saying you should avoid all documentation, but documenting every class and function is always redundant if the documentation doesn't state anything new. You should always strive for having code that is easy to read, before putting comments around everything you do.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;blockquote&gt;And another thing, without documentation, I might misunderstand the code I’m reading and think that I find defects or suboptimal solutions.&lt;/blockquote&gt;&lt;/span&gt;That's true. Of course you can have comments here saying "don't use this function this or that way", but perhaps there is another way of writing the function so that it can't be used incorrectly? If you write a method and document in the header that this function should only be used if some requirements are met, then I guarantee you that this function sooner or less will be misused. Make sure you add requirement checks (for example assertions) in the beginning of the function breaking the program, so that you crash early if someone make such misstates. But always strive for writing code that is impossible to use incorrectly.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;blockquote&gt; And then there’s the case with APIs that you don’t have the code to… Ok ok, thats another story.&lt;/blockquote&gt;&lt;/span&gt;If you are shipping your code to another company, or group of programmers, then you always need to communicate what the code does, because the code you shipped is persistent and will not change. Thus, the comments you write will always be correct (if being correct when shipped). And if you don't ship along your implementation, then of course you need to document your code, but more importantly, document your project as a whole. Do this by describing how it should be used and what the subparts of the project does and how they communicate with each other. Focus on the big picture.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;blockquote&gt; But hey, you can’t possibly mean that I shouldn’t document my Assembly code, do you? Super haxxor might read and understand ASM as I understand English, but the vast majority don’t.&lt;/blockquote&gt;&lt;/span&gt;Well, if the super haxxor wrote the code then he or she will in most cases be the only one reading it and than you don't need documentation. If the assembly code is only a small part of the project which is written in another language (say C++), extract the assembly code and put it in it's own function describing what it does. By doing so, you will also make the code more easy to test and validate! A better question might be, do you really need assembly code?&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;blockquote&gt; Saying that documenting/commenting code is wrong, is saying ‘I don’t care if other people are able to read my code, and if they don’t understand their lazy and dumb’. And thats lazy and dumb :-)&lt;/blockquote&gt;&lt;/span&gt;I'm saying that if you write your code so that a follows a well written coding policy, you will not have any problems with reading the code. If you feel that some code you have written needs to be documented, stop a second and think about it. Is there another way of formatting the code so that it's easier to read? What if I extract a part of this function as a new function, giving that function a good name, would that help? What about using coding policies for variable naming conventions? Adding prefixes such as m_ for member, p_ for parameter and l_ for local will for example quickly let you identify the scope of a variable.&lt;br /&gt;&lt;br /&gt;Here are some final notes from me:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;If you are working on a larger project, then your comments &lt;span style="font-weight: bold;"&gt;will&lt;/span&gt; become deprecated sooner or less. You must alway be aware of the fact that any code you write now will probably be changed in the future (no code is perfect).&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Always strive for as little code as possible. The more code you have, the more code you need to maintain. The same goes for comments.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Write comments in unclear situations, but don't write trivial comments. Instead, define a good coding policy and start writing "easy to read" code!&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-5183368711836998281?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/5183368711836998281/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=5183368711836998281' title='2 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/5183368711836998281'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/5183368711836998281'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2008/03/dedefending-my-case-stop-documenting.html' title='Dedefending my case: Stop documenting your code!'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-4551464120092917385</id><published>2008-03-27T14:57:00.000-07:00</published><updated>2008-03-28T12:27:12.376-07:00</updated><title type='text'>Twitter and Counter Posts</title><content type='html'>Gustaf recommended me this site called &lt;a href="https://twitter.com/home"&gt;twitter&lt;/a&gt;, which seems to be a great way of finding out what your friends are doing right now. Like a mini-blog where you write max 140 lines of text. &lt;a href="http://www.twitter.com/genne"&gt;I have just tried it out&lt;/a&gt;, but recommend you all to test it and to find out if you like it. Hanselman wrote a nice blog on this twitter-thing - read it at:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.hanselman.com/blog/TwitterTheUselessfulnessOfMicroblogging.aspx"&gt;http://www.hanselman.com/blog/TwitterTheUselessfulnessOfMicroblogging.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And also, if you haven't read the comments on my last post, Peter posted a comment, which he also posted as a "counter-post" on &lt;a href="http://pethol.wordpress.com/"&gt;his own blog&lt;/a&gt;, describing why you &lt;span style="font-weight: bold;"&gt;should&lt;/span&gt; comment code. There are some nice arguments, so please read it. Of course I'm planning a "counter-counter-post" on my blog, put you have to wait some more days before I will release it into the public :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-4551464120092917385?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/4551464120092917385/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=4551464120092917385' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/4551464120092917385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/4551464120092917385'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2008/03/twitter-and-counter-posts.html' title='Twitter and Counter Posts'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-5054479643413554659</id><published>2008-03-18T13:48:00.000-07:00</published><updated>2008-04-06T14:45:12.249-07:00</updated><title type='text'>Stop documenting your code!</title><content type='html'>I've been reading this interesting book for a while now, The Pragmatic Programmer by Andrew Hunt and David Thomas. I was actually planning to blog about it first when being finished, but my mind is just going crazy about some stuff I've read recently, and thus I feel the need to blog about it now!&lt;br /&gt;&lt;br /&gt;The book is based on "tips" that can easily be memorized and used again later when you put your programming hat on. One of these tips, which especially caught my attention, and which is going to form this post, describes the following principle:&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;DRY - Don't Repeat Yourself&lt;/blockquote&gt;This basically means that you should not repeat knowlegde. Further the book states that:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-style: italic;"&gt;Every peace of knowledge must have a single, unambiguous, authoritative representation within a system.&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;Well, you say, this is trivial, you should not write two peaces of code that does the same type of work. If you for example have two functions being very similar, then you use refactoring and extract the common code into a new function. If you have two classes representing two different branches of some common structure, then you extract what is common, put it in a new base class, and let the two classes inherit from this new base class. But this you probably already know, so I will not bore you with this anymore.&lt;br /&gt;&lt;br /&gt;Instead, think about the following for a second: being a programmer, does repeated knowledge only apply to code? What about &lt;span style="font-style: italic;"&gt;comments&lt;/span&gt;? What if you comment a function, doesn't this mean you &lt;span style="font-style: italic;"&gt;repeat knowledge&lt;/span&gt;? For example, look at the following code:&lt;br /&gt;&lt;pre name="code" class="c#"&gt;&lt;br /&gt;// Sets the name of the player&lt;br /&gt;// @param name The new name of the player to set&lt;br /&gt;void SetPlayerName(string name)&lt;br /&gt;{&lt;br /&gt;    mPlayerName = name;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This is obviously repeated knowledge, right? Both the name of the function and the implementation perfectly describes what it does. Is there really a need for documentation here? I know from experience that in many cases you write comments like this, just because you &lt;span style="font-style: italic;"&gt;should&lt;/span&gt; &lt;span style="font-style: italic;"&gt;write something. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So what about a more difficult case:&lt;br /&gt;&lt;pre name="code" class="c#"&gt;&lt;br /&gt;// Returns the name of the currently loaded level&lt;br /&gt;// or "" if none is loaded.&lt;br /&gt;string GetCurrentLevelName();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If the comment didn't state that "" is returned when no level is loaded, then you could actually think it should throw an exception when no level is loaded, or that you would get the name of the previously loaded level (or if you are using C# or Java that &lt;span style="font-style: italic;"&gt;null&lt;/span&gt; should be returned). But once again, knowledge is repeated. Just look up the implementation and it will state exactly what it does.&lt;br /&gt;&lt;pre name="code" class="c#"&gt;&lt;br /&gt;string GetCurrentLevelName()&lt;br /&gt;{&lt;br /&gt;    if (mCurrentLevel != null)&lt;br /&gt;        return mCurrentLevel-&gt;mName;&lt;br /&gt;    else&lt;br /&gt;        return "";&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Fact is, the implementation is the &lt;span style="font-weight: bold;"&gt;only&lt;/span&gt; "valid" documentation, because it's the only one you will know for sure is true. How many times haven't you written a function, documented it, then later in the development process realized that this function needs to be changed. You change the code but are a bit too lazy to update the documentation. Suddenly you have invalid knowledge! Isn't it better then just to remove the comment and let anyone who wants to know what it does open up the implementation and actually read the code?&lt;br /&gt;&lt;br /&gt;If you find it too hard to find out what a function does, you probably need to refactor the function by giving it a more descriptive name, extracting larger independent blocks of statements, rename your variables (members, parameters and local) to something more descriptive (i.e. don't use "temp"!) and so on. If this doesn't work, then you are either bad at reading others code (which is a good practice in order to become a better programmer!) (I hope you know how to read your own code!? :) ) or the code you are looking at is really bad and should be removed as quickly as possible. You don't want to maintain such code.&lt;br /&gt;&lt;br /&gt;Reading code should be like reading a book! You don't want the author of a book to add a lots of comments everywhere describing everything a second time in other words. The same goes for writing code, you should not add comments repeating what you have already written in another language.&lt;br /&gt;&lt;br /&gt;So, my tips to you is this: &lt;span style="font-weight: bold;"&gt;refactor your code, and remove those comments&lt;/span&gt;!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-5054479643413554659?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/5054479643413554659/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=5054479643413554659' title='2 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/5054479643413554659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/5054479643413554659'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2008/03/stop-documenting-your-code.html' title='Stop documenting your code!'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-4084021065923019550</id><published>2008-03-12T15:11:00.000-07:00</published><updated>2008-03-12T15:12:19.080-07:00</updated><title type='text'>Gimpel Software Bug of the Month</title><content type='html'>Finally someone made games for us programmers ;) Check it out!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.gimpel.com/html/bugs.htm"&gt;Gimpel Software Bug of the Month&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And if you find them to be a bit too trivial, here is a harder case (actually the post where I first found out about this "Bug of the Month" site):&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blogs.msdn.com/vcblog/archive/2007/05/17/diagnosing-hidden-odr-violations-in-visual-c-and-fixing-lnk2022.aspx"&gt;Visual C++   Team Blog : Diagnosing Hidden ODR Violations in Visual C  ++ (and fixing LNK2022)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;That one was really tricky (I couldn't solve it), but was fun reading!&lt;br /&gt;&lt;br /&gt;Have fun :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-4084021065923019550?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/4084021065923019550/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=4084021065923019550' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/4084021065923019550'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/4084021065923019550'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2008/03/gimpel-software-bug-of-month.html' title='Gimpel Software Bug of the Month'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-7336826438406439393</id><published>2008-03-08T08:33:00.000-08:00</published><updated>2008-03-08T19:13:55.425-08:00</updated><title type='text'>C++ vs. C#</title><content type='html'>For you who think that C# is the master language, why really is it? C++ has been around for soon 30 years, and is still considered to be the one language for many developers. You might say that those developers are a bit out of date or conservative, only sticking to the one language they learned several years ago, but the thing is I really think C++ has some interesting stuff not supported by other languages such as C#.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Memory Control&lt;/span&gt;&lt;br /&gt;For one think, C++ has total memory control. You can allocate memory when every you want to and then use it any way you like. Then, when you don't need the memory you release the memory manually. This means of course that it's easy to shoot your self in the foot and forget to release the allocated memory, but also that you aren't required to have a garbage collector running in background thread taking up important cpu power (if the cpu power is important). Also, garbage collectors can only release an instance when there are exactly no references left to it left, so if there are circular references then those can never be released (except when exiting the application).&lt;br /&gt;&lt;br /&gt;The garbage collector can thus not remove something on demand. For example, at some point in your program you might know for sure that "this instance is not going to be used any more, if it is then there is a bug", but you don't know for sure that there are no references left to it (perhaps you put it in a list somewhere and forgot to remove it?) and thus the garbage collector might not remove it and your memory consumption will grow larger and larger. After running your program for some time you will notice that the memory usage becomes large, and because you have no control over memory you cannot simply search in the code for a missing "delete" statement (which you can in C++, or actually search for new with a missing delete). And because the garbage collector can clean up the memory when ever it wants to, you cannot rely on the destructor being called at an appropriate time. C# (or Microsoft) thus doesn't recommend you to use destructors, but rather to implement a method such as void Dispose() which you must call manually to dispose any unmanaged resources being held by that object (you can actually use destructors, but what if you in that destructor adds a reference to the object somewhere? Suddenly the object is alive and shouldn't be destructed...). But if you forget to call Dispose in your code, you could easily lock up resources and get unpredictable behaviors.&lt;br /&gt;&lt;br /&gt;In C++ you have better control to whether put something on the heap or the stack. If on the stack, you know that the destructor will be automatically called when leaving the scope, something not possible to do using C#. In C# you instead need to implement the Dispose method, and then create an instance of that class in a using-block, which will automatically call Dispose when the instance leaves the scope. There is no other way to do this in C#. If you for example have a lock helper class that automatically locks a given object when constructed and releases the object when being destructed, you could write code like this in C++:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;void doDangerousStuff(Object &amp;amp;a, Object &amp;amp;b)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  LockScope lockScopeA(a);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  LockScope lockScopeB(b);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // Do dangerous stuff on a and b&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;In C# you could write this:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;void doDangerousStuff(Object &amp;amp;a, Object &amp;amp;b)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  LockScope lockScopeA(a);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  LockScope lockScopeB(b);    &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  // Do dangerous stuff on a and b&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  lockScopeA.Dispose()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  lockScopeB.Dispose()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;But what if you got an exception in the middle of the code? Then the Dispose() method would not be called, so instead you should use the using keyword:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;  void doDangerousStuff(Object &amp;amp;a, Object &amp;amp;b)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  using( LockScope lockScopeA(a) )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    using( LockScope lockScopeB(b) )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      // Do dangerous stuff on a and b&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;But this doesn't look good, and what if you need to add more locks on other variables, the code would just grow more and more to the right, and at least to my opinion that's something you should avoid to the max. C# thus doesn't give you a good solution to this problem.&lt;br /&gt;&lt;br /&gt;Actually, in C#, you can control whether to put something on the heap or on the stack. Classes are automatically put on the heap when allocated, and structs are stored on the stack. This means that it theoretical should be possible to call the destructor when the instance of a struct leaves the scope, but unfortunately C# doesn't allow you to add destructors to structs, so no good luck there :(&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Headers and Linkage Errors&lt;/span&gt;&lt;br /&gt;Another positive thing of C++, which some of you might find confusing, is the possibility to declare a function in a header, but then never implement it. This lets you design a class without actually giving an implementation. If you then try to compile the program you will not get any compiler errors but instead linkage errors. This means that "the code looks good, but I couldn't find the definition of these functions". You cannot do this in C#. Instead you need to add a method with an empty body, and in that body you throw an exception or assert false. Thus, instead of getting linkage errors, you get runtime errors.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;The Const Keyword&lt;/span&gt;&lt;br /&gt;I just can't figure out why languages such as Java and C# doesn't support the use of a const modifier. In C++ you can state a class method to be const, meaning it can't modify the state of the object. This is very useful if you for example want to pass an object by reference to a function, but want to make sure it isn't modified. You then mark is as const, and the function can only call the methods declared on that object that are marked as const. The state of that object will thus remain unchanged.&lt;br /&gt;&lt;br /&gt;In Java and C# this is not possible. In Java you can at most (at least to my experience) send primitive types such as int, byte and float which will be passed as values (copies) and thus any change of these values in the function will only affect the copy. In C# you can do something similar, but even structs will be passed by value, enforcing the state of that object not being changed. This though would require you to rewrite every class you want to be able to pass to a function without it being modified, which of course isn't a very pleasing solution. Quite the opposite actually, as it also enforces you to make copies of the object every time you want to use it in another function.&lt;br /&gt;&lt;br /&gt;To get around this (at least what I think) Java and C# have implemented some classes that are &lt;span style="font-style: italic;"&gt;immutable&lt;/span&gt;. One such class is the String class. If you have ever examined this class you might realize that there is no way to modify it, it is fixed. To change it you actually have to instantiate a new string which holds the changed value. So, functions taking strings as parameters cannot modify them, even though they are passed by reference. But is this the solution you want for your big universal state that you want to pass a function which should not modify it?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Macros&lt;/span&gt;&lt;br /&gt;One last thing to mention about C++, and which is also not supported by C#, is macros. A macro can totally destroy your code, but also let you write complicated beautiful code in only a few lines. If you for example have a lots of classes that you want to register to a factory, instead of writing:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;factory.RegisterClass("MyClassA", &amp;amp;MyClassA::Constructor);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;factory.RegisterClass("MyClassB", &amp;amp;MyClassB::Constructor);&lt;/span&gt;&lt;/blockquote&gt;you can define a macro and simply write&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;#define REGISTER(class) factory.RegisterClass(#class, &amp;amp;class::Constructor)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;REGISTER(MyClassA);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;REGISTER(MyClassB);&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;Isn't that cool? You can actually do a lot more complicated stuff if you want to, and even generate default class implementations this way. With macros you can do anything! The closest thing to macros you have in C# is reflection. With reflection you can for example extract the name of a class dynamically, and get a function from a class based on a string (the name of that function), but if that class hasn't implemented that function you will instead get a runtime error. In C++ this error will appear when compiling!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Why C# Still is Cool :)&lt;/span&gt;&lt;br /&gt;But to turn to the other side of the street, C# isn't that bad after all. Compiling C++ code will give you a headache if compared to compiling C# code, which will only take a few seconds. Also, running C# code isn't actually that much slower than you might think. In some cases you will actually find out that your code is equally fast in C# as in C++! And C# has a lots of cool features not supported at all by C++ (and many other languages) such as properties, attributes, partial classes, yield and lock statements, coalesce operator ??, just to mention a few. And with C# 3.5 you have support for even more nice stuff, such as lambda expressions, LINQ and extension methods.&lt;br /&gt;&lt;br /&gt;Actually, the reason to why I'm not writing a post on why C# is better then C++ is that it's so trivial :) C# have so many things C++ misses out on, but I just felt I had to write this article so that people don't think that C++ is nonsense. Because it isn't! At least in the gaming industry, C++ is still the leading language, with the reason probably being "you have more control" and "it's fast"! And around 2009, the next version of C++ is planned to be shipped, called C++0x, which hopefully will give the language a boost to survive the future!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-7336826438406439393?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/7336826438406439393/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=7336826438406439393' title='3 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/7336826438406439393'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/7336826438406439393'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2008/03/c-vs-c.html' title='C++ vs. C#'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-6937314264462417321</id><published>2008-02-25T23:02:00.000-08:00</published><updated>2008-02-26T12:23:07.167-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='vb'/><category scheme='http://www.blogger.com/atom/ns#' term='code snippets'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='macros'/><title type='text'>Visual Studio Code Snippets and Macros</title><content type='html'>In this first real post I'll try to explain something called &lt;span style="font-weight: bold;"&gt;macros&lt;/span&gt; in Visual Studio, and how they can make your work (programming) easier. I just recently found out about them, and realized that they resemble something I've been missing in the C++ environment of VS for a long time; &lt;span style="font-weight: bold;"&gt;code snippets&lt;/span&gt;! If you don't know what code snippets are, then here is a short description:&lt;br /&gt;&lt;br /&gt;Code snippets are short keywords in your C# document, which when you double-press tab will be converted into C# code! If the code is parameterized, over for example different names or types, then these parameters will be selected first so that you can easily change them. If you for example write &lt;span style="font-style: italic;"&gt;prop&lt;/span&gt; and double-press the tab key, a new property will be added to the class you are in.&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;prop &amp;lt;tab&amp;gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;tab&amp;gt;&lt;/span&gt;&lt;/blockquote&gt;becomes&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;private int myVar;&lt;br /&gt;&lt;br /&gt;public int MyProperty&lt;br /&gt;{&lt;br /&gt;get { return myVar; }&lt;br /&gt;set { myVar = value; }&lt;br /&gt;}&lt;/blockquote&gt;where int, myVar and MyProperty are parameters which can easily be changed. There are a lot of nice code snippets to use in the C# environment, making coding easier. Just goto &lt;span style="font-style: italic;"&gt;Tools -&gt; Code Snippet Manager...&lt;/span&gt; or press &lt;span style="font-style: italic;"&gt;Ctrl+K&lt;/span&gt; followed by &lt;span style="font-style: italic;"&gt;Ctrl+B&lt;/span&gt; for a list of possible snippets.&lt;br /&gt;&lt;br /&gt;But for C++ this doesn't seem to exist. I read something about code snippets being available for C++ in VS 2003, but somehow they where removed in VS 2005.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_F5z3mmdTM8I/R8Rs2uzPXBI/AAAAAAAAAAQ/4nvHe1W3ssI/s1600-h/Macro+Explorer.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://4.bp.blogspot.com/_F5z3mmdTM8I/R8Rs2uzPXBI/AAAAAAAAAAQ/4nvHe1W3ssI/s320/Macro+Explorer.png" alt="" id="BLOGGER_PHOTO_ID_5171377959659854866" border="0" /&gt;&lt;/a&gt;So this is where macros comes into play! With a macro you can more or less do what ever you want to do. You just create a macro, write the code for it (in VB) and then use it from the macro explorer within VS. To make it even more powerful you can bind keyboard shortcuts to these macros (&lt;span style="font-style: italic;"&gt;Tools -&gt; Options... -&gt; Environment -&gt; Keyboard&lt;/span&gt;). To show the currently available macros, activate the &lt;span style="font-style: italic;"&gt;macro explorer&lt;/span&gt; using either&lt;span style="font-style: italic;"&gt; Tools -&gt; Macros -&gt; Macro Explorer &lt;/span&gt;or by pressing &lt;span style="font-style: italic;"&gt;Alt+F8&lt;/span&gt;. By default you will have a list of sample macros installed, which are great for playing around with and to get familiar with macros.&lt;br /&gt;&lt;br /&gt;So, what then can you do with macros, you ask yourself. Well, for example you can write macros that automatically adds new classes, with a default header and cpp-file, based on a class name. You just tell VS to add two files to your current project, and then put some the class definition in the header, and some default implementations of perhaps constructors and destructors in your cpp-file. Or you can create a macro that cleans up headers and cpp-files, by searching in the code using regular expressions for #include "ClassName.h", and then comment this include if ClassName can't be found in the code. The possibilities are really endless!&lt;br /&gt;&lt;br /&gt;So if you are developing in VS using C++, or actually any language supported by VS, and haven't used macros, then go ahead and try it out. It's amazing what you can do! Or if you are developing in C# and haven't tried code snippets then I really encourage you to learn about them. As have been said before: to be a good programmer, you must know your tools!&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;b&gt;&lt;/b&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-6937314264462417321?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/6937314264462417321/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=6937314264462417321' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/6937314264462417321'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/6937314264462417321'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2008/02/visual-studio-code-snippets-and-macros.html' title='Visual Studio Code Snippets and Macros'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_F5z3mmdTM8I/R8Rs2uzPXBI/AAAAAAAAAAQ/4nvHe1W3ssI/s72-c/Macro+Explorer.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5933717644607161038.post-7067060476612762775</id><published>2008-02-24T09:07:00.000-08:00</published><updated>2008-02-24T22:54:22.366-08:00</updated><title type='text'>Free coffee with Gustaf and ideas of sharing knowledge</title><content type='html'>So, the idea of this blog is to try to share the knowledge I'm gaining when reading other blogs, listening to podcasts, discussing with friends over coffees, reading books or what ever. As mentioned in an episode of Hanselminutes: to become a better programmer you should try to write the knowledge down and share it with other people. So that's what I will try to do in this blog!&lt;br /&gt;&lt;br /&gt;But not now, because it's too late :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5933717644607161038-7067060476612762775?l=christiangenne.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiangenne.blogspot.com/feeds/7067060476612762775/comments/default' title='Kommentarer till inlägget'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5933717644607161038&amp;postID=7067060476612762775' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/7067060476612762775'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5933717644607161038/posts/default/7067060476612762775'/><link rel='alternate' type='text/html' href='http://christiangenne.blogspot.com/2008/02/free-coffee-with-gustaf-and-ideas-of.html' title='Free coffee with Gustaf and ideas of sharing knowledge'/><author><name>Christian Genne</name><uri>http://www.blogger.com/profile/05183435846100768676</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='18' height='32' src='http://bp2.blogger.com/_F5z3mmdTM8I/R8lEzI2TnAI/AAAAAAAAAAc/Rhe8x9Nk7Uw/S220/070505+183.jpg'/></author><thr:total>0</thr:total></entry></feed>
