<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://www.lostechies.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title type="html">Louis Salin&amp;#39;s Blog</title><subtitle type="html" /><id>http://www.lostechies.com/blogs/louissalin/atom.aspx</id><link rel="alternate" type="text/html" href="http://www.lostechies.com/blogs/louissalin/default.aspx" /><link rel="self" type="application/atom+xml" href="http://www.lostechies.com/blogs/louissalin/atom.aspx" /><generator uri="http://communityserver.org" version="4.1.30929.2835">Community Server</generator><updated>2009-02-19T15:35:18Z</updated><entry><title>I don't just code</title><link rel="alternate" type="text/html" href="/blogs/louissalin/archive/2010/03/07/i-don-t-just-code.aspx" /><id>/blogs/louissalin/archive/2010/03/07/i-don-t-just-code.aspx</id><published>2010-03-07T16:16:00Z</published><updated>2010-03-07T16:16:00Z</updated><content type="html">&lt;p&gt;I have an obscure, personal blog to which I fled back to recently. I posted the following entry:&lt;/p&gt;
&lt;p&gt;
&lt;p style="padding-left: 30px;"&gt;Well whadaya know? I'm having existential doubts these days. There's a battle that rages inside of me every time I get a little bit of free time: what should I spend my precious little time on? Until recently, I had been trying to get an enterprise-y application going, but it filled me with dread. Every line of code had to be extracted from my body with forceps, put into place and tested. It was a fine equilibrium, a delicate balance that I maintained by making myself believe that this is what I wanted to do. It was more that just something to do on a rainy day; it was more than just a reason to go out and hang out in a coffee shop all afternoon on Sundays. It was what I wanted to do. But I hated it. Well, most of it.&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;Anyway, that balance tipped over when I lost control of the app. Slowly, I stopped unit testing features. Then I simply started hacking it without too much thought or process. I started drifting. Thoughts would come and distract me. What is the next big thing? How can I become hugely successful and never have to worry about money again? Should I remain a Windows developer, forever branded as a .Net guy, or should I venture to the free ecosystem that is Linux? What about Mono? Oh, I could write server apps with Mono! But what about Lisp? I've always wanted to learn Lisp! I could write a Command &amp;amp;amp; Query type application and start with the Login system and write it in Lisp. Or even better yet, I should write a .Net version of Common Lisp, just like that dude that wrote Clojure on top of the JVM. And of course, it would have to be done entirely by using the command line and VIM... Is there a book on Amazon for VIM?..&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;And on, and on, and on it would go. Every Sunday. Torture. I would power on my laptop and sit transfixed in front of the monitor, my hands calmly positioned over the keyboard. There would be a shell prompt and a VIM window open, waiting. Oh, the possibilities! And yet, I couldn't come up with anything to do. Eventually, I'd give up and log on to twitter, facebook, news.ycombinator, arstechica, slashdot, news.google, nytime, programmer-looking-for-a-problem-to-solve-that-wont-bore-him-to-death.com... I'd then slam shut the laptop lid and be in a funky mood all day. Hell, that's exactly what happened today. Again!&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;Except that today I decided it was all over. I would stop wasting the rest of my life pursuing something I'm starting to feel weak at. Focus on my strength. That's what I need to do! But then I read a blog post about using object databases and cracked open my Common Lisp book. Damn it! I feel excited about programming again. It makes me feel like getting my laptop down from the shelf where it's quietly sitting and hack on something.&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;Why?&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;I'm clearly passionate about something! I just can't put my finger on it. So here's what I'm going to do. I'm gonna blog about that until I figure out what it is. Yeah. Blogging. That's so 2005! It's so not the next big thing.... oh... here I go again!&lt;/p&gt;
&lt;/p&gt;
&lt;p&gt;It's only been a month, and already my mind is on something else. You guys have read my posts, or if you haven't, go check my post history. I'm all over the place! Why the hell did I want to learn Lisp? Why go away from what I know best? I think we all want to do something significant in life. We all want to get better. But in my case, I clearly need some focus. Instead of learning something new and obscure (and hard!), why not get better at what I already do?&amp;nbsp;I'll admit it: I'm not a spare time or weekend coder. I can't do it. I don't pull the all nighters. I don't stay up until 2am at night. I actually try to get between 8 and 9 hours of sleep every night because that's what makes me feel great during the day. This sort of balance is what I need. When I try to focus too much on code, I end up developing this allergic reaction that causes the kind of posts I just showed you. It's not fun. Yet, I envy all of you who do code all the time. I feel that not doing it slows me down on my journey to become a better programmer.&lt;/p&gt;
&lt;p&gt;I suppose the journey is what's important. The important thing is that we go forward. The pace doesn't matter. As for me, I'm not forcing myself to code anymore. I'm enjoying my time with my family and feel I'm a better developer at work because of it.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=I+don%27t+just+code&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2010%2f03%2f07%2fi-don-t-just-code.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2010%2f03%2f07%2fi-don-t-just-code.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=74270" width="1" height="1"&gt;</content><author><name>louissalin</name><uri>http://www.lostechies.com/members/louissalin/default.aspx</uri></author></entry><entry><title>Fun with Mono.Cecil</title><link rel="alternate" type="text/html" href="/blogs/louissalin/archive/2009/11/25/fun-with-mono-cecil.aspx" /><id>/blogs/louissalin/archive/2009/11/25/fun-with-mono-cecil.aspx</id><published>2009-11-25T22:35:00Z</published><updated>2009-11-25T22:35:00Z</updated><content type="html">&lt;p&gt;During the past couple of days, I took it upon myself to automatically generate documentation about our "Scriptable" methods. These methods are used to provide an entry point into our Silverlight application for our automated acceptance test suite. Since we do not run our tests from the browser, which is currently the only way to go with an out-of-box tool, we decided to write our tests with RSpec, in Ruby, by using Watir to start up a web browser and connect to our application. Since Silverlight is inaccessible through the DOM, our scriptable methods are the only way we have access to our controls. I've talked about &lt;a href="http://www.lostechies.com/blogs/louissalin/archive/2009/04/15/poll-don-t-wait-for-your-silverlight-applications.aspx"&gt;this whole process&lt;/a&gt; in the past.&lt;/p&gt;
&lt;p&gt;Basically, a scriptable method is a method that has a ScriptableMemberAttribute on it. The Silverlight plugin takes those methods and makes them accessible through Javascript, which is how we can call them from our Ruby test suite. Most of our views and controls have a bunch of of those and things have gotten a bit out of hand. One of the things that really slows us down while writing tests is just figuring out how to get access to a certain control. For example, starting from the main view, what is the path of scriptable methods that you must take to get to the latest error message? It might be: Main View -&amp;gt; Sidebar Control -&amp;gt; Menu Item #6 -&amp;gt; Error Message Panel. If you don't know your way, you have to set breakpoints in your code and manually, through trial and error, figure out how to get to where you want to go.&lt;/p&gt;
&lt;p&gt;Enough! Now, we have a crude, basic, version 1 Html Scriptable Method Generator 3000 (tm)!&lt;/p&gt;
&lt;p&gt;First thing that had to be done was load up our web client assembly and reflect on it. I quickly hit a wall when the Microsoft reflection utilities would refuse to load it up. I realized that it was a Silverlight library that I was trying to load and that I would have to create a Silverlight solution instead of a regular, normal CLR solution. You see, there is a difference between the two .Net runtimes. A normal CLR application cannot reflect upon a Silverlight library, which is compiled using the Core CLR. (I also wrote &lt;a href="http://www.lostechies.com/blogs/louissalin/archive/2009/03/09/net-libraries-in-silverlight.aspx"&gt;about this&lt;/a&gt; in the past)&lt;/p&gt;
&lt;p&gt;Darn!&lt;/p&gt;
&lt;p&gt;Thankfully, however, somebody suggested on stackoverflow.com to use Mono.Cecil instead.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.mono-project.com/Cecil"&gt;Mono.Cecil&lt;/a&gt; is a library that allows you to reflect on assemblies, basically. But it can do much more. As my colleague Gabriel &lt;a href="http://www.lostechies.com/blogs/gabrielschenker/archive/2009/11/26/writing-a-profiler-for-silverlight-applications-part-1.aspx"&gt;has blogged&lt;/a&gt; about, it can allow you to inject CIL code into a compile library. It will even let you inspect all you anonymous methods in your code. Is it hard to use? Nope! Just download the dll, add it to your project references and you're good to go. Windows or Linux, Monodevelop or Visual Studio; it just works (tm).&lt;/p&gt;
&lt;p&gt;Documentation is spread out a bit everywhere, but I found this to be really helpful to start with: the &lt;a href="http://mono-project.com/Cecil:FAQ"&gt;Mono.Cecil FAQ&lt;/a&gt;. Additionally, Google will help you find a bunch of usage examples. I would post some code, except that I didn't do anything that you can't find in the FAQ that I linked to above. The scriptable doc generator loops over all the methods that have a ScriptableMemberAttribute on them, using the main view as a starting point, and generates a tree where each node is a scriptable method, it's return type and a sub-tree of child scriptable methods. Using that tree, the generator creates an Html file for each class that has scriptable methods and lists all of those methods in an unordered list.&lt;/p&gt;
&lt;p&gt;I plan on making this better in the future by adding links and collapsible tree views. It'll also be very cool to add it to our continuous integration system to update a wiki site whenever a build is finished. And ultimately, I hope this makes us much, much faster in writing our tests. Eliminating waste is always the ultimate goal.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Fun+with+Mono.Cecil&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f11%2f25%2ffun-with-mono-cecil.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f11%2f25%2ffun-with-mono-cecil.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=34959" width="1" height="1"&gt;</content><author><name>louissalin</name><uri>http://www.lostechies.com/members/louissalin/default.aspx</uri></author></entry><entry><title>The Passionate Programmer Book Review</title><link rel="alternate" type="text/html" href="/blogs/louissalin/archive/2009/11/15/the-passionate-programmer-review.aspx" /><id>/blogs/louissalin/archive/2009/11/15/the-passionate-programmer-review.aspx</id><published>2009-11-15T22:19:00Z</published><updated>2009-11-15T22:19:00Z</updated><content type="html">&lt;p&gt;Earlier this year, I've been given the chance to read any book of my choice from the Pragmatic Programmer bookshelf and write a quick review. Being so focused right now on figuring out where I want to go with my career, I thought I'd give &lt;a href="http://www.pragprog.com/titles/cfcar2/the-passionate-programmer"&gt;The Passionate Programmer&lt;/a&gt; a try. I mean, who doesn't want to be passionate about their job? Loving what you do makes it fun and this is the key to a very successful career! I don't think I can do it justice until I've tried to put into practice most of what the author is preaching in the book, so here is a quick and dirty review of the book. (spoiler: I liked the book!)&lt;/p&gt;
&lt;p&gt;The author, &lt;a href="http://chadfowler.com/"&gt;Chad Fowler&lt;/a&gt;, didn't get his start by getting a degree in computer science. Yet, he has accomplished more in his career than most software developers will ever do in their lifespan. So he must be doing something right, no? Well, the book might not teach you how to be passionate about anything. However, it will give you great pointers to make a great career out of software programming, which might make you passionate about the whole thing, I guess.&lt;/p&gt;
&lt;p&gt;The book is divided into five independent parts, each of which you need to give serious thought to if you're ever going to become great at what you do, and remain great. In each part are multiple, small chapters of about two to three pages long, that will give you some hopefully valuable insight about growing you skills, finding mentors, pleasing your managers, how not to panic in dire situations and being careful about market changes, among many, various others topics. All in all, there are 53 "tips" in the book and I must say that most of them are very useful.&lt;/p&gt;
&lt;p&gt;I would've wished that not all of those tips be written as if it was a recipe for success. Every single one ends with a "Act on it" section with exercises that are bound to put some of us out of our comfort zone. But maybe that's a good thing! Any day, I can open up the book and re-read one of the tips that I know I should be working on. There is no doubt in my mind that I can become a remarkable programmer by working on my weaknesses, and Chad covers most of them in his book.&lt;/p&gt;
&lt;p&gt;This isn't a book that you'll read cover to cover. The optimal way to get through it, in my opinion, is to read it one chapter or two at a time and quickly put into practice what was read before progressing any further. Incidentally, this makes the book a very easy read; you could be spending only 15 minutes every night reading this book. But to make it effective, you'll need to actively put it into practice. I know I will. And I know I'll probably end up re-reading it a couple of times.&lt;/p&gt;
&lt;p&gt;I have read the 7 Habits of Highly Successful People and Who Moved My Cheese and Chad's book reminded me of them. Because of that, I can only recommend this book to all my peers, unless you are already at the top of your game. Then maybe you should write your own book too! Oh wait, that's one of the tips in The Passionate Programmer!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=The+Passionate+Programmer+Book+Review&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f11%2f15%2fthe-passionate-programmer-review.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f11%2f15%2fthe-passionate-programmer-review.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=31453" width="1" height="1"&gt;</content><author><name>louissalin</name><uri>http://www.lostechies.com/members/louissalin/default.aspx</uri></author></entry><entry><title>Gtk# for .Net Developers, part II</title><link rel="alternate" type="text/html" href="/blogs/louissalin/archive/2009/10/15/gtk-for-windows-developers-part-ii.aspx" /><id>/blogs/louissalin/archive/2009/10/15/gtk-for-windows-developers-part-ii.aspx</id><published>2009-10-16T02:41:00Z</published><updated>2009-10-16T02:41:00Z</updated><content type="html">&lt;p&gt;In the &lt;a href="http://www.lostechies.com/blogs/louissalin/archive/2009/09/29/gtk-for-net-developers.aspx"&gt;first post&lt;/a&gt; in this series we went over the details of creating a new desktop application using
Gtk# using MonoDevelop. The main reason for doing that was to get
acquainted with the IDE and the way it creates and manages the Gtk# code for us, behind the scene.
This time, we'll stay strictly on the front side, using MonoDevelop's tools to create a simple UI with a simple layout and place buttons and
labels on the screen. Nothing too complicated, really.&lt;br /&gt;&lt;br /&gt;I'd like to point out that there are some excellent tutorials out there that you can check out, including:&lt;br /&gt;-
&lt;a href="http://zetcode.com/tutorials/gtksharptutorial/"&gt;a tutorial&lt;/a&gt; that is very similar to what this series is about, except
without using MonoDevelop&lt;br /&gt;- the tutorials on the mono project's own &lt;a href="http://www.mono-project.com/GtkSharpTutorials"&gt;website&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;What
is written here is not novel (if you'll pardon the pun!) I'm just
taking a shot at it from a different perspective. If you've written desktop applications on Windows, most of what you'll read here will be very familiar. Just reading the tutorials above will teach you what you need to know. I hope, however, to save you the few minutes or hours that you will spend figuring out the few features that are not as well documented.&lt;/p&gt;
&lt;p&gt;That being said,
let's get started!&lt;br /&gt;&lt;br /&gt;I'd like to add two buttons to
our application. One that will close the main window, and the other one
that will change the text on a label that sits somewhere around the center of the window. For this, we will use Gtk's
excellent abilities at layering and positioning controls (or widgets,
remember?) on the screen. We'll stack the buttons on the right hand
side of the window and center the label in the remaining empty space.
Open up the project that we created in the last post and open up the
MainWindow.cs file. At the bottom, you'll see that you can view this
file in two ways: view the source code, of view the designer. Select
the designer view.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Components.UserFiles/00.00.00.21.36.layout/designer.png" width="842" height="526" /&gt;&lt;/p&gt;
&lt;p&gt;The first thing we need to do is add a container, which is a type control that is used by Gtk# to define your UI layout. There are a few that
are available to us right out of the box and what we want is something
that will allow us to have the buttons on the left and an empty space
on the right. Open up the toolbox tab on the right and take a look at
was is in the containers list:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Components.UserFiles/00.00.00.21.36.layout/containers.png" width="842" height="526" /&gt;&lt;/p&gt;
&lt;p&gt;Drag an HBox onto the main window:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Components.UserFiles/00.00.00.21.36.layout/hbox.png" width="842" height="526" /&gt;&lt;/p&gt;
&lt;p&gt;An HBox is a container that is used to layout your UI in any number of
vertical columns. As you can see, the default amount of columns is
three. However, we only need two but fortunately, adding and removing
columns is easy enough. Right click on any columns and select the
delete option in the context menu.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Components.UserFiles/00.00.00.21.36.layout/two_5F00_panes.png" width="842" height="526" /&gt;&lt;/p&gt;
&lt;p&gt;You can edit the properties of any widget or container from the
properties tab on the right. Select and rename the HBox by using the
combo box right above the UI builder window, then open up that
properties tab:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Components.UserFiles/00.00.00.21.36.layout/hbox-properties.png" width="842" height="526" /&gt;&lt;/p&gt;
&lt;p&gt;We are now ready to stack our buttons. Go back to the toolbox and drag a VBox to the leftmost column:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Components.UserFiles/00.00.00.21.36.layout/button_5F00_stack.png" width="842" height="526" /&gt;&lt;/p&gt;
&lt;p&gt;As you can see, VBoxes and HBoxes are exactly the same, differing only
in their alignement. Just like with the HBox, we have one too many rows
in our VBox so go ahead and remove one. Then, drag a button from the
toolbox into each of the remaining rows:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Components.UserFiles/00.00.00.21.36.layout/two_5F00_buttons.png" width="842" height="526" /&gt;&lt;/p&gt;
&lt;p&gt;It's interesting to see how the buttons are automatically stacked at
the top of the window. The reason why is that you can specify how
widgets are packed inside a container. Select a button and go take a
look at its properties. Expand the Box Child Layout category. In there,
you can adjust the pack type and the position of the widget. The pack
type tells Gtk# to put that button either at the start or at the end of
a container. By selecting end, the selected button would be put at the
bottom of the screen. You can also change the position of the button.
Gtk# will then put it at position x, starting from the top or bottom,
depending on the selected pack type. Note that the position is 0 based.
Go ahead and play with those and see what happens. You can also play
with the pack type and positioning of the VBox itself!&lt;br /&gt;&lt;br /&gt;Alright, let's rename those buttons.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Components.UserFiles/00.00.00.21.36.layout/button-properties.png" width="842" height="526" /&gt;&lt;/p&gt;
&lt;p&gt;I'd like to quickly mention that in the Common Widget Properties
categories, you'll surely use the Sensitive property. In .Net talk, it
means Enabled. Yes, Sensitive == Enabled. It took me a while to find
that one!&lt;br /&gt;&lt;br /&gt;Open up the Button Properties category and change the
name and label of the buttons. Name one "Quit" and the other "Change
Text". Did you happen to notice the Button Type property? I've never
played with it, but having the ability to put images and text on a
button right out of the box is pretty sweet!&lt;br /&gt;&lt;br /&gt;Now, go and drag a
Label widget from the toolbox into the empty remaining space in the
window. Great, it's centered vertically, but not horizontally. Open up
its properties and in the Box Child Layout section, unselect Auto Size
and then check the Expand and Fill check boxes. There, it's centered
now. Go ahead, compile and run the app and bask in the glory of having
done something with Gtk#!&lt;br /&gt;&lt;br /&gt;Have you basked in the glory? Good.
Now we really should think about making those buttons do something. You
might have noticed the Signals tab when looking at a widget's
properties. This is where we hook up a method in our class to an event,
called signals.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Components.UserFiles/00.00.00.21.36.layout/signals.png" width="842" height="526" /&gt;&lt;/p&gt;
&lt;p&gt;The screenshot above shows the signals that are available for a button
widget. Go to the Clicked signals and enter in "OnClicked" in the
textbox next to it. Then, go back to the source code for our MainWindow
class. You should see a new OnClicked method that has been created for
you. Edit the method and add the following code:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;

&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnClicked (&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, System.EventArgs e)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;{&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    centerLabel.Text = &lt;span class="str"&gt;"Clicked!"&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This will simply change the text on the label that we put in the center
of the screen. If you didn't name your label widget "centerLabel", just
use whatever name you chose in the code. Run the app, click on the
button, and the text will change! A small step for man, a giant step
for humanity... or something like that!&lt;br /&gt;&lt;br /&gt;Finally, go back to the signals panel of the Quit button and add a Clicked signal. In your method, enter the following line:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;

&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;Application.Quit();&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
which will close the app.&lt;br /&gt;
&lt;br /&gt;
That's it for this post. Nothing special was presented, really. The
main thing I wanted to showcase is the the layout capabilities of Gtk#,
which is what I found to be highly refreshing, coming from a Windows
Forms world. In the next post, we'll check out the code that was
generated for us in the background while we were draging and dropping
widgets on the screen.&lt;br /&gt;
&lt;br /&gt;
Thanks for reading!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Gtk%23+for+.Net+Developers%2c+part+II&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f10%2f15%2fgtk-for-windows-developers-part-ii.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f10%2f15%2fgtk-for-windows-developers-part-ii.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=26580" width="1" height="1"&gt;</content><author><name>louissalin</name><uri>http://www.lostechies.com/members/louissalin/default.aspx</uri></author></entry><entry><title>Mono, open source and Azure</title><link rel="alternate" type="text/html" href="/blogs/louissalin/archive/2009/10/10/mono-open-source-and-azure.aspx" /><id>/blogs/louissalin/archive/2009/10/10/mono-open-source-and-azure.aspx</id><published>2009-10-10T16:16:00Z</published><updated>2009-10-10T16:16:00Z</updated><content type="html">&lt;p&gt;I've got this theory and it seems like all the pieces kinda fit together: Microsoft building an open standard CLR, Novell building Mono so that .Net apps can run on multiple platforms, Microsoft slowly warming up to open source and dynamic languages with Iron Ruby and the CodePlex foundation, and Microsoft's new Azure cloud services. Now, how could Microsoft think it can compete in the cloud services arena when so many big players are already entrenched and actively building up their technologies?&amp;nbsp;
&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;p&gt;There's only one way. They need leverage. They need us, .Net developers. Microsoft has known for a long time that the future of computing involved the Internet but has failed to develop a technology that would make them leaders in the same way Bill Gates recognized that micro-processors were going to be the next big thing back in the, er... what, early 80s?&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;p&gt;With cloud services popping up left and right, Microsoft probably thinks that this is it! It might be too late, but they have no choice. The threat of the Internet browser being the OS of the future is looming over them and they can't ignore it, lest they become one of those old dinosaurs that die with their obsolete technologies. So Azure is coming and Microsoft will try to stay young and hip and hang out with the young ones.&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;p&gt;But it's got one advantage that the others don't. There are a lot of .Net developers in the world and finding a way to get them to develop on Azure, along with the monthly bills, might very well make Microsoft relevant again. But can it do more than that? Well, what if Linux developers could write .Net applications? What if Ruby enthusiasts could write .Net applications? What if Python developers could write .Net applications? With Mono, the DLR, IronRuby and IronPython, Microsoft can very well convert a lot of developers to its new platform.&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;p&gt;And that is why I think Mono developers are safe from litigation from Microsoft. It benefits the behemoth not to turn those people away. Everyone that is somehow linked to .Net is a potential for extra monthly revenue, and who would purposefully slash away at their potential market? I think Microsoft has come to realize that with the current state of the web, it has lost its monopoly on everything except corporate IT, and even that under threat. IE won't save them, ASP.Net won't save them, SQL Server won't save them. Azure just might, though, if Microsoft plays its cards just right.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Mono%2c+open+source+and+Azure&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f10%2f10%2fmono-open-source-and-azure.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f10%2f10%2fmono-open-source-and-azure.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=26072" width="1" height="1"&gt;</content><author><name>louissalin</name><uri>http://www.lostechies.com/members/louissalin/default.aspx</uri></author></entry><entry><title>Gtk# for .Net developers</title><link rel="alternate" type="text/html" href="/blogs/louissalin/archive/2009/09/29/gtk-for-net-developers.aspx" /><id>/blogs/louissalin/archive/2009/09/29/gtk-for-net-developers.aspx</id><published>2009-09-30T01:18:00Z</published><updated>2009-09-30T01:18:00Z</updated><content type="html">&lt;p&gt;This is going to be my first post in a series about my experience using Gtk#, a choice I made a few months ago when I decided to build my next .Net app on Linux and Mono. I've always thought that Mono was worth exploring and as I've mentioned &lt;a href="http://www.lostechies.com/blogs/louissalin/archive/2009/05/25/learning-how-to-walk-with-mono.aspx"&gt;before&lt;/a&gt;, the experience has been very easy going so far.&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;The wikipedia entry on &lt;a href="http://en.wikipedia.org/wiki/Gtk_Sharp"&gt;Gtk#&lt;/a&gt; says that it&lt;span&gt;&amp;nbsp;is basically a set of .Net bindings for the GTK+ GUI toolkit, which stands for GIMP ToolKit. GTK+ was created specifically for the UI of the GIMP, the most popular open source raster graphics editor. Since then, GNOME, a widely used window manager that runs on top of X11, also started using this library for its UI and by extension all software written for GNOME also uses GTK+.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;If you would like to follow along and try out the code examples in this series, it would be easier to install Mono on your Linux distribution of choice, or install Gtk# and Mono on your Windows machine, which you can download from &lt;a href="http://mono.wikia.com/wiki/GTKSharp"&gt;here&lt;/a&gt;. All of my examples have been created with &lt;a href="http://monodevelop.com/"&gt;MonoDevelop&lt;/a&gt;&amp;nbsp;and I encourage you to try it out, simply because of its UI builder. Using Visual Studio will work, but to take advantage of having all your UI Gtk# code generated for you, MonoDevelop is a must.&amp;gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;h3&gt;Differences between WinForms and Gtk#&lt;/h3&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;I&amp;nbsp;assume that most of you, just like myself, come from a .Net background with a lot of experience building Win Forms or (gasp!) Web Forms. As I learn more and more about Gtk#, I discover new tricks and tools that I suddenly wish I'd have know about in the past. As WinForms developers, or even web developers in a Windows world, we are very much isolated from different technologies that exist outside of Microsoft's ecosystem. So for me, discovering and using Gtk# seemed like a bit of fresh air sprinkled with some wonderment!&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;So let's see what is different between WinForms and Gtk#.&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;The main difference is that WinForms use a static layout scheme, whereas Gtk# layouts grow and shrink automatically as you re-size the window, which has technically always been a pain to do on a WinForm application. I mean, how many of you have used SQL Server in the past and just stood there in puzzlement over why the dialog boxes were not resizable, forcing you to scroll down or to read a 100 pixel wide textbox with at least 200 characters in it?. How much time have you also spent trying to make your apps resize gracefully?&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Gtk# controls, which are called widgets, must be part of a container and will either fill up the container's space or make the container shrink to fit the widget. Containers can be embedded within other containers too, which allows you to layout your UI before adding the widgets in. All of this will be demonstrated in further articles, but my point right now is that all of this is baked into Gtk#. You don't have to worry about it. And the best thing is that it works great and is really intuitive.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;h3&gt;Simple example (click me button and text box)&lt;/h3&gt;
&lt;p&gt;Let's start by creating an empty Gtk# application which, once compiled and lauched, will result in the typical empty window:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Components.UserFiles/00.00.00.21.36/EmptyWindow.png" /&gt;&lt;/p&gt;
&lt;p&gt;Now let's take a peek at the code that was generated to make this happen:&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Gtk;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; Gtk&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;{&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    &lt;span class="kwrd"&gt;class&lt;/span&gt; MainClass&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main (&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;            Application.Init ();&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;            MainWindow win = &lt;span class="kwrd"&gt;new&lt;/span&gt; MainWindow ();&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;            win.Show ();&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;            Application.Run ();&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;    }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;First, a quick work on the Gtk namespace. I named my project "Gtk", which doesn't seem to cause any namespace name clashes. However, it might confuse you into thinking that you have to use the same namespace for things to "just work". You don't. So please disregard it.&lt;br /&gt;&lt;br /&gt;Pretty standard stuff, except maybe that the Application class doesn't seem to be connected to the main window. The main window needs to be shown *and* the application needs to be ran. Application.Init is first called with no arguments. You could pass in the program name and the program arguments if you'd like, but the default "empty" application doesn't seem to need to. Then, the main window is instanciated and shown on the screen. Finally, Application.Run starts the main event loop. You will see later that when closing the main window, a call is made to Application.Quit. That is how the main event loop exits and you app is freed from memory.&lt;br /&gt;&lt;br /&gt;Now let's take a look at the MainWindow class:&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Gtk;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MainWindow: Gtk.Window&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;{    &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; MainWindow (): &lt;span class="kwrd"&gt;base&lt;/span&gt; (Gtk.WindowType.Toplevel)&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;        Build ();&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;    }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;    &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnDeleteEvent (&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, DeleteEventArgs a)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;    {&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;        Application.Quit ();&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;        a.RetVal = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;    }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;MainWindow is defined as a TopLevel window, which is almost always going to be the case, unless you want a popup. Specifying the TopLevel type make Gtk# connect the window to the OS or window manager. The Build method takes care of visually creating the UI. It has been defined elsewhere, thanks to the fact that MainWindow is a partial class. This just smell like code generation! We'll take a look very soon. But first, I want to mention that the OnDeleteEvent method is responsible for terminating the Application's main event loop.&lt;br /&gt;&lt;br /&gt;Alright, let's look at the other part of MainWindow. To see it right click on the project in the solution explorer, go to display options and check "Show all files". A gtk-gui folder will appear in the solution explorer. Once expanded, it will reveal three files: MainWindow.cs, generated.cs and gui.stetic. Open up MainWindow.cs:&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MainWindow {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;    &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Build() {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;        Stetic.Gui.Initialize(&lt;span class="kwrd"&gt;this&lt;/span&gt;);&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;        &lt;span class="rem"&gt;// Widget MainWindow&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;        &lt;span class="kwrd"&gt;this&lt;/span&gt;.Name = &lt;span class="str"&gt;"MainWindow"&lt;/span&gt;;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;        &lt;span class="kwrd"&gt;this&lt;/span&gt;.Title = Mono.Unix.Catalog.GetString(&lt;span class="str"&gt;"MainWindow"&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;        &lt;span class="kwrd"&gt;this&lt;/span&gt;.WindowPosition = ((Gtk.WindowPosition)(4));&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; ((&lt;span class="kwrd"&gt;this&lt;/span&gt;.Child != &lt;span class="kwrd"&gt;null&lt;/span&gt;)) {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.Child.ShowAll();&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;        &lt;span class="kwrd"&gt;this&lt;/span&gt;.DefaultWidth = 400;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;        &lt;span class="kwrd"&gt;this&lt;/span&gt;.DefaultHeight = 300;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;        &lt;span class="kwrd"&gt;this&lt;/span&gt;.Show();&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;        &lt;span class="kwrd"&gt;this&lt;/span&gt;.DeleteEvent += &lt;span class="kwrd"&gt;new&lt;/span&gt; Gtk.DeleteEventHandler(&lt;span class="kwrd"&gt;this&lt;/span&gt;.OnDeleteEvent);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;    }&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Yuck, ugly code! Obviously, this code has been generated (you might have to compile the solution first.) Here is where the Build method is defined. It is a virtual method that can be overriden in subclasses, which I have found to be very useful when creating different views that can be displayed in an application I'm building. Here, the title, position and default size of the window are specified and the DeleteEvent is set to call the OnDeleteEvent method we say earlier.&lt;br /&gt;&lt;br /&gt;What about the Stetic.Gui.Initialize call? Well, by default, MonoDevelop utilizes Stetic as the Gui designer for your applications. As you lay out your widgets and containers, the gui.stetic file that was mentioned earlier is built. It is simply an xml file (oh, noes!) that holds every possible detail about your UI. Let's take a quick look:&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="html"&gt;xml&lt;/span&gt; &lt;span class="attr"&gt;version&lt;/span&gt;&lt;span class="kwrd"&gt;="1.0"&lt;/span&gt; &lt;span class="attr"&gt;encoding&lt;/span&gt;&lt;span class="kwrd"&gt;="utf-8"&lt;/span&gt;?&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;stetic-interface&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;target-gtk-version&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;2.12&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;target-gtk-version&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;import&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;widget-library&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="glade-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;widget-library&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="../bin/Debug/Gtk.exe"&lt;/span&gt; &lt;span class="attr"&gt;internal&lt;/span&gt;&lt;span class="kwrd"&gt;="true"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;import&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;widget&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;="Gtk.Window"&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="MainWindow"&lt;/span&gt; &lt;span class="attr"&gt;design-size&lt;/span&gt;&lt;span class="kwrd"&gt;="400 300"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;property&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="MemberName"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;property&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="Title"&lt;/span&gt; &lt;span class="attr"&gt;translatable&lt;/span&gt;&lt;span class="kwrd"&gt;="yes"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;MainWindow&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;property&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="WindowPosition"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;CenterOnParent&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;property&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;signal&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="DeleteEvent"&lt;/span&gt; &lt;span class="attr"&gt;handler&lt;/span&gt;&lt;span class="kwrd"&gt;="OnDeleteEvent"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;child&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;placeholder&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;child&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;widget&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;stetic-interface&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Our MainWindow is defined on line 12 and looks awefully like the ugly generated code from above. What happens is that as you build your UI with MonoDevelop, the stetic file is generated. When you compile your application, the ugly partial MainWindow class is automatically re-generated and then compiled.&lt;br /&gt;&lt;br /&gt;So there it is, our first empty window application.&lt;br /&gt;Next time, we'll go in a add... a button! See you then!&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Gtk%23+for+.Net+developers&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f09%2f29%2fgtk-for-net-developers.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f09%2f29%2fgtk-for-net-developers.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=25645" width="1" height="1"&gt;</content><author><name>louissalin</name><uri>http://www.lostechies.com/members/louissalin/default.aspx</uri></author></entry><entry><title>Querying Rally with ruby</title><link rel="alternate" type="text/html" href="/blogs/louissalin/archive/2009/09/25/querying-rally-with-ruby.aspx" /><id>/blogs/louissalin/archive/2009/09/25/querying-rally-with-ruby.aspx</id><published>2009-09-25T22:03:00Z</published><updated>2009-09-25T22:03:00Z</updated><content type="html">&lt;p&gt;I've had the opportunity to play around a bit with the &lt;a href="http://www.rallydev.com/support_extensions.jsp"&gt;Rally REST API&lt;/a&gt; to automatically generate acceptance test stubs at work recently. For those of you who don't know, &lt;a href="http://www.rallydev.com"&gt;Rally&lt;/a&gt;&amp;nbsp;is a bug/feature tracking software that allows you to write stories and test cases, along with tracking hours spent implementing all of these. Usually, a product manager will create stories ahead of time and developers then bring the story to life, after which acceptance tests have to be written and passed.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;So we decided to generate empty test stubs for each and every test case that didn't have a test already, which will save a ton of time to all the developers. Moreover, since Rally is integrated to &lt;a href="http://www.jetbrains.com/teamcity/"&gt;TeamCity&lt;/a&gt;, we would know instantly which tests have been implemented, and which ones haven't, the moment we kick off our acceptance test job.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Should you want to do something similar, or simply query Rally, I hope the following code will help you with that.&lt;/p&gt;
&lt;p&gt;First things first, though. You will need to install the ruby gem rally_rest_api (here's the &lt;a href="http://rally-rest-api.rubyforge.org/rally_rest_api/"&gt;documentation&lt;/a&gt;). In a command prompt, type in:&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;gem install rally_rest_api&lt;/p&gt;
&lt;p&gt;Then, start up your favorite ruby editor and start coding! The first thing we did was to put a wrapper class around the gem's RallyRestAPI class:&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; MyRally&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;  def initialize&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    @rally = RallyRestAPI.&lt;span class="kwrd"&gt;new&lt;/span&gt;(:base_url =&amp;gt; &lt;span class="str"&gt;"https://rally1.rallydev.com/slm"&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;                              :username =&amp;gt; &lt;span class="str"&gt;"your_username"&lt;/span&gt;,&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;                              :password =&amp;gt; &lt;span class="str"&gt;"your_password"&lt;/span&gt;)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;  end&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;  def get_stories(project_name)&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;    query_results = @rally.find(:project) {equal :name, project_name}&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;    project = query_results.results.first&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;    query_results = @rally.find(:hierarchical_requirement, :fetch =&amp;gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;) {equal :project, project}&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;    query_results.map &lt;span class="kwrd"&gt;do&lt;/span&gt; |story_result| &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;      puts &lt;span class="str"&gt;"fetching story #{story_result.formatted_i_d}"&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;      Story.&lt;span class="kwrd"&gt;new&lt;/span&gt;(story_result, self)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;    end&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;  end&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;  def get_test_cases_for_story(story_result)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;    test_case_query_result = @rally.find(:test_case, :fetch =&amp;gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;) {equal :work_product, story_result}&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;    test_case_query_result.map &lt;span class="kwrd"&gt;do&lt;/span&gt; |test_case_result|&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;      puts &lt;span class="str"&gt;"--fetching test case #{test_case_result.formatted_i_d}"&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;      TestCase.&lt;span class="kwrd"&gt;new&lt;/span&gt;(test_case_result)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;    end&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;  end&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;end&lt;/pre&gt;
&lt;pre&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In the initialize method, the RallyRestAPI object is instantiated with your credentials, which will allow it to make the proper service calls to the Rally server. Then, the get_stories method takes a project name as a parameter and will find all the stories belonging to that project in Rally.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Note that the @rally.find call on line 9 takes both parameters and an optional block. If you wanted to, you could yield to the caller inside the block instead of having to pass in the project name to the get_stories method. That would allow you to specify any extra constraints at the moment you call get_stories. For example, instead of writing:&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;my_rally.get_stories(&lt;span class="str"&gt;"Sharks with laser beams"&lt;/span&gt;)&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;you could write:&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;my_rally.get_stories &lt;span class="kwrd"&gt;do&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;  equals :name, &lt;span class="str"&gt;"Sharks with laser beams"&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;  greater_than :priority, &lt;span class="str"&gt;"Fix Immediately"&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;end&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;which allows you to be more specific in your querying without having to create a new method for each and every single combination of constraints you need to query your stories.&lt;/p&gt;
&lt;p&gt;Back up in the code, the first thing the script does is to find the actual project. Then, it uses the project to find all the user stories that have been defined for it. The result set that is returned by the Rally API is mapped to an array of Story object, which have been implemented as a wrapper around the returned data. Finally, the test cases are fetched in the same manner, for each story, and mapped to a TestCase object.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Here is the code for the Story and TestCase classes:&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; Story&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;  attr_reader :formatted_name&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;  def initialize(story_result, rally)&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    @formatted_name = &lt;span class="str"&gt;"#{story_result.formatted_i_d[5..-1]}_#{story_result.name.underscorize}"&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    @test_cases = rally.get_test_cases_for_story(story_result)&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;  end&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;  def to_s&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;    str = @formatted_name + &lt;span class="str"&gt;"\n"&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;    @test_cases.each &lt;span class="kwrd"&gt;do&lt;/span&gt; |test_case|&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;      str += &lt;span class="str"&gt;"  name: #{test_case.name}\n"&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;      str += &lt;span class="str"&gt;"  id: #{test_case.id}\n"&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;      str += &lt;span class="str"&gt;"  pre_conditions: #{test_case.pre_conditions}\n"&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;      &lt;span class="kwrd"&gt;if&lt;/span&gt; test_case.steps != nil&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;        test_case.steps.each { |step| str += &lt;span class="str"&gt;"    - #{step}\n"&lt;/span&gt;}&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;      end&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;      &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;      str += &lt;span class="str"&gt;"\n"&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;    end&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;    str += &lt;span class="str"&gt;"--------------------------------\n"&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;  end&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;end&lt;/pre&gt;
&lt;pre&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; TestCase&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;  attr_reader :name, :id, :pre_conditions, :steps&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;  &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;  def initialize(test_case_result)&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    @name = test_case_result.name.underscorize&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    @id = test_case_result.formatted_i_d[2..-1]&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    pre_conditions = test_case_result.pre_conditions&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;    @pre_conditions = test_case_result.pre_conditions.clean_up unless pre_conditions == nil&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    @steps = test_case_result.validation_input.clean_up unless test_case_result.validation_input == nil&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;  end&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;end&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The astute reader (I've always wanted to say that!) will have noticed that we use obscure methods like &lt;i&gt;underscorize &lt;/i&gt;on the story and test case names. These have been added to the String class for our own particular reasons which, in this case, require all the words in the names to be separated with underscores.&lt;/p&gt;
&lt;p&gt;That's pretty much as far as we went with the API so far, and I hope it'll help any of you who use Rally as well! Have a great weekend!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Querying+Rally+with+ruby&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f09%2f25%2fquerying-rally-with-ruby.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f09%2f25%2fquerying-rally-with-ruby.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=25557" width="1" height="1"&gt;</content><author><name>louissalin</name><uri>http://www.lostechies.com/members/louissalin/default.aspx</uri></author></entry><entry><title>Do you plan your work?</title><link rel="alternate" type="text/html" href="/blogs/louissalin/archive/2009/09/22/do-you-plan-your-work.aspx" /><id>/blogs/louissalin/archive/2009/09/22/do-you-plan-your-work.aspx</id><published>2009-09-22T19:19:00Z</published><updated>2009-09-22T19:19:00Z</updated><content type="html">&lt;p&gt;Just last week, a coworker and I started working on a defect. It was easy enough, really. Fixing the problem involved performing two distinct operations that were *almost* independent of each other. The work was easily divided between the two of us and so, before getting started, we quickly discussed the issue at hand and then we both went back to our cubicle to get started. It was only later that our boss came by and asked us what our plan was. &lt;/p&gt;
&lt;p&gt;I was speechless. A plan? We... er... I... I gave up. We had no plan, whatsoever. He told us to get together and come up with a plan for fixing the defect.&lt;/p&gt;
&lt;p&gt;
&lt;div&gt;Planning what needed to get done and doing some design up front immediately put into light some complications we might run into and allowed us to synchronize our efforts better. Both my co-worker and I knew where and how we'd depend on each other's work and found out how we'd hopefully never have to wait for the other to complete a task.&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;This was an eye opener for me. How many times in the past have I gone straight into coding without doing any sort of planning? Sure, we write stories and scenarios. But what I'm talking about is workflow planning: figuring out what needs to get done, in what order and by whom. And something funny happened: even though this is a small scale example, by planning and doing some design up front, we kind of unknowingly did some risk analysis. We discovered some potentially problematic areas and took that into consideration when giving our boss our time estimates for the defect.&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;Of course, we ended up being completely wrong on a few things... But at least we gained some experience in the process.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;I know that I, for one, will try to do that more often.&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Do+you+plan+your+work%3f&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f09%2f22%2fdo-you-plan-your-work.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f09%2f22%2fdo-you-plan-your-work.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=25464" width="1" height="1"&gt;</content><author><name>louissalin</name><uri>http://www.lostechies.com/members/louissalin/default.aspx</uri></author></entry><entry><title>Learning how to walk with Mono</title><link rel="alternate" type="text/html" href="/blogs/louissalin/archive/2009/05/25/learning-how-to-walk-with-mono.aspx" /><id>/blogs/louissalin/archive/2009/05/25/learning-how-to-walk-with-mono.aspx</id><published>2009-05-26T01:01:00Z</published><updated>2009-05-26T01:01:00Z</updated><content type="html">&lt;p&gt;I started experimenting with Mono this week. The reason is simple enough: somebody wants me to write a small application that will run on their Windows box. The problem is, I own a Mac and a Linux powered laptop (yes, taking the Vista sticker off was a exercise in patience that left a lot of residual glue on the laptop...) Mono is a perfect solution for writing .Net software on Linux that will run on Windows.&lt;/p&gt;
&lt;h2&gt;The Setup&lt;/h2&gt;
&lt;p&gt;I run OpenSuse 11.1 because I figured I might as well go with the distribution that was created by the people who are currently behind Mono: Novell. Also, at the time of this writing, I have Mono 2.4, which is .Net 3.5 compatible, and Monodevelop 2.0 installed. As a bonus, I realized today that NUnit was also installed: version 2.4.8.&lt;/p&gt;
&lt;h2&gt;The Solution&lt;br /&gt;&lt;/h2&gt;
&lt;p&gt;Creating a new solution with Monodevelop is pretty straightforward.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Components.UserFiles/00.00.00.21.36.monodevelop/1.jpg" width="820" height="513" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;As you can see, it&amp;#39;s fairly similar to the Visual Studio experience. I selected the Library type of project and named it MyTest. After clicking the Forward button, Monodevelop asked me if I wanted to add packaging, unix integration or other little nifties to my project. I graciously declined.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Components.UserFiles/00.00.00.21.36.monodevelop/2.jpg" width="820" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;The above image depicts what you get when you create a new, empty library project. Eager to get on my way, I coded one of the simplest class I&amp;#39;ve ever coded:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; MyTest&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;{&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MyClass&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; MyString { get; set; }&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; MyClass()&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;    }&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And I then set out to write a test using Scott Bellware&amp;#39;s SpecUnit. First, I added a NUnit library project to my solution, which I called MyTest_spec.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Components.UserFiles/00.00.00.21.36.monodevelop/3.jpg" width="820" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;This created a simple, empty project with everything you need to use NUnit and write some tests. The interesting thing I discovered is that Monodevelop includes its own Reflector utility. Going to the references of my NUnit project and double-clicking on nunit.framework, I got this:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Components.UserFiles/00.00.00.21.36.monodevelop/4.jpg" width="820" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Which is how I figured out I was using version 2.4.8. You can drill down into the assemblies and click on methods. I guarantee it; you will see code! Anyway, here&amp;#39;s my test code:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; MyTest;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; NUnit.Framework;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; SpecUnit;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; MyTest_spec&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;{    &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    [TestFixture()]&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;    [Concern(&lt;span class="str"&gt;&amp;quot;MyClass&amp;quot;&lt;/span&gt;)]&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; when_changing_the_string_of_my_class : ContextSpecification&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;    {    &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;        [Observation]&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; should_persist_the_new_string()&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;            myClass.MyString.ShouldEqual(&lt;span class="str"&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt;);&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;        &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Because ()&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;            &lt;span class="kwrd"&gt;base&lt;/span&gt;.Because ();&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;            myClass.MyString = &lt;span class="str"&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt;;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;        &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Context ()&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;            &lt;span class="kwrd"&gt;base&lt;/span&gt;.Context ();&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;            myClass = &lt;span class="kwrd"&gt;new&lt;/span&gt; MyClass();&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;        &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; MyClass myClass;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;    }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Please note that Monodevelop default to using the .Net 2.0 framework. You will have to change this to .Net 3.5. Right-click on each one of the projects of your solution, select Options and go to Build/General. Change the runtime version to .Net 3.5, like shown below:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Components.UserFiles/00.00.00.21.36.monodevelop/5.jpg" width="820" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve got my class, I&amp;#39;ve got my spec. Now I need to run the tests and see if this whole thing works on Linux! So I compiled... And BAM! I got an error. The compiler complained that SpecUnit was expecting the 2.4.6 version of NUnit. The problem is, as you&amp;#39;ve seen higher in this post, I was using nunit-2.4.8. I went back online and downloaded the SpecUnit code, thinking I&amp;#39;d recompile it with the 2.4.8 dlls of NUnit. I found the solution file (SpecUnit was created with Visual Studio, so I was looking for a .sln file) double-clicked on it and crossed my fingers... It worked! Monodevelop loaded the entire SpecUnit solution! All I had to do then was to replace the nunit.framework references with the newer ones from the 2.4.8 version, which were conveniently located with all the other regular .Net references. Recompile and voila! A brand new SpecUnit, ready to roll!&lt;/p&gt;
&lt;p&gt;To tell you the truth, I wasn&amp;#39;t expecting Monodevelop to load a .sln file. Later, reading the feature list of Mono and Monodevelop, I saw that Monodevelop fully supports MSBuild and even defaults to it. Nice! Embrace, extend, and... er... isn&amp;#39;t that was Microsoft is supposed to do? Interesting to see somebody else doing it!&lt;/p&gt;
&lt;p&gt;I replaced the old SpecUnit reference with the new one, compiled... And BAM! Another error! This time, the compiler was not too happy with my use of the extension method ShouldEqual, which was otherwise recognized correctly by the editor. However, the compiler kept complaining. After double-checking that all my projects were compiling for the .Net 3.5 framework, I googled the problem and found out that you have to include System.core in your references, which is not automatically done by Monodevelop. And that did the trick, the solution compiled!&lt;/p&gt;
&lt;p&gt;I just had commited a heresy. I had just put a DLL on my pure, pristine Linux system. A DLL! No, even worse: two DLLs! I grapsed for something to hold on to. When the oily feeling that tainted my soul finally subsided, I ran the test:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Components.UserFiles/00.00.00.21.36.monodevelop/6.jpg" width="820" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;It passed!&lt;/p&gt;
&lt;p&gt;Now, this is really cool! I look forward to doing more with Mono. Hopefully, more and more developers will start using it. So far, the experience has been good, but I miss ReSharper and the ability to run tests from within the IDE. Monodevelop allows us to write plugins, so anybody up for a a R# clone on Monodevelop?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Thanks for reading.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Learning+how+to+walk+with+Mono&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f05%2f25%2flearning-how-to-walk-with-mono.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f05%2f25%2flearning-how-to-walk-with-mono.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=21223" width="1" height="1"&gt;</content><author><name>louissalin</name><uri>http://www.lostechies.com/members/louissalin/default.aspx</uri></author></entry><entry><title>Yield, I thought I knew you!</title><link rel="alternate" type="text/html" href="/blogs/louissalin/archive/2009/05/19/yield-i-thought-i-knew-you.aspx" /><id>/blogs/louissalin/archive/2009/05/19/yield-i-thought-i-knew-you.aspx</id><published>2009-05-19T13:30:00Z</published><updated>2009-05-19T13:30:00Z</updated><content type="html">&lt;p&gt;The yield keyword, in whatever language, has a special meaning to me. First introduced in threading, it was used to yield the execution of the current thread and let the next one go. The concept fit in my head very nicely. After all, we have yield signs on the road everywhere, instructing us to give priority to other cars, bikes or pedestrians. Making the switch to a threading environment was pretty straightforward.&lt;/p&gt;
&lt;p&gt;Then came Ruby.&lt;/p&gt;
&lt;p&gt;Ruby&amp;#39;s usage of the yield keyword is to execute a block that was given to a method. For example:&lt;/p&gt;
&lt;div style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:100%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;height:159px;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;" id="codeSnippetWrapper"&gt;
&lt;div style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;" id="codeSnippet"&gt;
&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum1"&gt;   1:&lt;/span&gt; @words = [&lt;span style="color:#006080;"&gt;&amp;#39;hello&amp;#39;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;#39;world&amp;#39;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;#39;how&amp;#39;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;#39;are&amp;#39;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;#39;you&amp;#39;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;#39;doing?&amp;#39;&lt;/span&gt;]&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum2"&gt;   2:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum3"&gt;   3:&lt;/span&gt; def reverse_words&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum4"&gt;   4:&lt;/span&gt;   @words.each &lt;span style="color:#0000ff;"&gt;do&lt;/span&gt; |word|&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;yield&lt;/span&gt; word.reverse&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum6"&gt;   6:&lt;/span&gt;   end&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum7"&gt;   7:&lt;/span&gt; end&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum8"&gt;   8:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum9"&gt;   9:&lt;/span&gt; reverse_words {|reversed_word| puts reversed_word}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;When calling the method reverse_words, you need to supply a block that will be called back from within the method. This is accomplished by using the yield keyword, where reverse_method calls your block and gives it a reversed version of each word in the words array.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Again, the usage of yield here still makes sense to me. The method is yielding to the caller&amp;#39;s block of instructions.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;But C# also has the yield keyword! And I thought I knew what it did until I stumbled upon the following code at work:&lt;/p&gt;
&lt;div style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:150.02%;cursor:text;direction:ltr;max-height:270px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;height:352px;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;" id="codeSnippetWrapper"&gt;
&lt;div style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;" id="codeSnippet"&gt;
&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; IEnumerable&amp;lt;EditModeSpec&amp;gt; PreviewInFormAndEditInAnswer(&lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; ...&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:148.51%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;height:18px;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;yield&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; VisibleWhen(FormMode.Any, FormStatus.Any); &lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:136.78%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;height:18px;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;yield&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; InteractableWhen(FormMode.Create, FormStatus.Any);&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum5"&gt;   5:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:145.18%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;height:15px;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;yield&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; EditableWhen(FormMode.Answer | FORM_MODE_REVIEW_ANY, ...&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:153.28%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;height:17px;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum7"&gt;   7:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;yield&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; EditableWhen(FormMode.Answer, FORM_STATUS_NOT_SUBMITTED, ...&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:149.09%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;height:22px;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;yield&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; EditableWhen(FormMode.Answer, FormStatus.Approved, ...&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum9"&gt;   9:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum10"&gt;  10:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;yield&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; EditableWhen(FormMode.Answer, FormStatus.Scheduled | ...&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum11"&gt;  11:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;yield&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; EditableWhen(FormMode.Answer, FormStatus.Approved, ...&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum12"&gt;  12:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum13"&gt;  13:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;yield&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; EditableWhen(FormMode.Answer, FormStatus.Submitted, ...&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#606060;" id="lnum14"&gt;  14:&lt;/span&gt; }&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Woa! What is going on here?&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The above method returns an IEnumerable type. Because of the yield statement, the values inside that enumerable type will be calculated only when they are accessed the first time. Basically, &amp;quot;yield&amp;quot; delays the execution of the returned values. Whenever I decide to loop over them, all those returned statement would be executed at that point and their result stored inside the returned enumerable type.&lt;/p&gt;
&lt;p&gt;So in C#, yield means something somewhat different. Yield, I thought I knew you!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Yield%2c+I+thought+I+knew+you!&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f05%2f19%2fyield-i-thought-i-knew-you.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f05%2f19%2fyield-i-thought-i-knew-you.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=21103" width="1" height="1"&gt;</content><author><name>louissalin</name><uri>http://www.lostechies.com/members/louissalin/default.aspx</uri></author></entry><entry><title>So, what's up doc?</title><link rel="alternate" type="text/html" href="/blogs/louissalin/archive/2009/05/18/so-what-s-up-doc.aspx" /><id>/blogs/louissalin/archive/2009/05/18/so-what-s-up-doc.aspx</id><published>2009-05-19T00:45:00Z</published><updated>2009-05-19T00:45:00Z</updated><content type="html">&lt;p&gt;I started blogging last July because I felt I had to get out of the rot I was in. Stuck in the middle of nowhere doing Classic ASP forms on top of a database, I knew I was missing the boat. I knew .Net, but my skills dated from the days of C# 1.1. What&amp;#39;s more, their was virtually no developer community where I was.&lt;/p&gt;
&lt;p&gt;Nowadays, my life has morphed into the exact opposite. I live in Austin, TX. The community here is amazingly vast, smart, and varied. My job has me work with IoC containers, unit tests, automated UI acceptance testing. This is a dream come true! Except that I have slowed down on the blogging. &lt;/p&gt;
&lt;p&gt;Of course, I have excuses! I work hard and my work is fullfilling my need for knowledge. Blogging is not the learning medium that it was for me just a few months ago. In this new situation, I find that I have lost my voice. But no worries, I am fully aware of the fact and I spend the bigger part of my days trying to catch up.&lt;/p&gt;
&lt;p&gt;Of course, I could also get up from my ass, dig deep and just do it. &lt;/p&gt;
&lt;p&gt;Thanks for reading, I promise I&amp;#39;ll be back soon.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=So%2c+what%27s+up+doc%3f&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f05%2f18%2fso-what-s-up-doc.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f05%2f18%2fso-what-s-up-doc.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=21070" width="1" height="1"&gt;</content><author><name>louissalin</name><uri>http://www.lostechies.com/members/louissalin/default.aspx</uri></author></entry><entry><title>Poll, Don't Wait for your Silverlight Applications</title><link rel="alternate" type="text/html" href="/blogs/louissalin/archive/2009/04/15/poll-don-t-wait-for-your-silverlight-applications.aspx" /><id>/blogs/louissalin/archive/2009/04/15/poll-don-t-wait-for-your-silverlight-applications.aspx</id><published>2009-04-15T19:52:00Z</published><updated>2009-04-15T19:52:00Z</updated><content type="html">&lt;p&gt;Did you ever write code like the following pseudo-code for your Silverlight acceptance tests? &lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:98.33%;cursor:text;direction:ltr;max-height:160px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;height:198px;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;"&gt;
&lt;div id="codeSnippet" style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;
&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum1" style="color:#606060;"&gt;   1:&lt;/span&gt; browser = Watir::IE.&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum2" style="color:#606060;"&gt;   2:&lt;/span&gt; browser.&lt;span style="color:#0000ff;"&gt;goto&lt;/span&gt;(&lt;span style="color:#006080;"&gt;&amp;quot;http://myserver/page.aspx&amp;quot;&lt;/span&gt;)&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum3" style="color:#606060;"&gt;   3:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum4" style="color:#606060;"&gt;   4:&lt;/span&gt; sleep 10&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum5" style="color:#606060;"&gt;   5:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum6" style="color:#606060;"&gt;   6:&lt;/span&gt; screen = browser.get_screen&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum7" style="color:#606060;"&gt;   7:&lt;/span&gt; screen.enter_user_name(&lt;span style="color:#006080;"&gt;&amp;quot;user&amp;quot;&lt;/span&gt;)&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum8" style="color:#606060;"&gt;   8:&lt;/span&gt; screen.enter_password(&lt;span style="color:#006080;"&gt;&amp;quot;password&amp;quot;&lt;/span&gt;)&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum9" style="color:#606060;"&gt;   9:&lt;/span&gt; screen.click_login&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum10" style="color:#606060;"&gt;  10:&lt;/span&gt; ...&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;(Before diving into the code, please note that most method calls done on the browser object are methods that are defined in our Silverlight application, but made available as scriptable methods. We encapsulated their usage so as to make them easy to read. Normally, they would be called as you call a javascript function.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In the above snippet, we first get a new instance of an Internet Explorer process by using Watir, a ruby library that allows us to connect to a browser and interact with the DOM Then, using that process, we navigate to the page that we want to test and we wait for 10 seconds for the Silverlight app to finish loading. Yes, even though Watir can tell us when the page has finished loading, it unfortunately doesn&amp;#39;t mean that Silverlight is also up and running. So we have to wait a bit. Here, 10 seconds is a wild guess that should cover most scenarios. If we underestimate and start testing too early, the test will fail. Anyway, once we&amp;rsquo;re good to go, we get the current screen using a scriptable method in our main Silverlight class and use the object it returns to enter a user name and password and to simulate a click on the login button, also through scriptable methods.&lt;/p&gt;
&lt;p&gt;Did I mention how useful scriptable methods are? Hmmm, yes. Yes, they are.&lt;/p&gt;
&lt;p&gt;The problem with that code however, is that it will take a minimum of 10 seconds to run. You might want to go ahead and reduce the sleep instruction down to 5 seconds and find out it works anyway. But when you proudly show it to your boss the next day, your email software starts archiving your thousands of deleted email and slows down your computer just enough that the page takes slightly longer than 5 seconds to load, resulting in an exception raised while trying to enter the user name. Then you&amp;rsquo;ll give your boss the usual excuse: &amp;ldquo;It worked yesterday!&amp;rdquo; Yeah, right!&lt;/p&gt;
&lt;p&gt;Pausing your acceptance tests seems to be the norm in the industry as a mean to let your application do its work before you send it the next command. We don&amp;#39;t have a choice; acceptance tests are asynchronous because the test process is separate from the application process. The amount of time you have to wait between instructions will vary from computer to computer, depending on the hardware or other factors, like network latency. You also want your tests to run on all the developers&amp;#39; machines so that they can verify that their piece of code didn&amp;#39;t break a test. So the waiting time needs to be high enough that the slowest machine in your department will be able to run it. Unfortunately, it means that a lot of people with faster boxes will end up wasting their time while waiting for the tests to complete. And who knows, maybe you have, hmmm, 30 tests that they have to go through? That&amp;rsquo;s five minutes, right there!&lt;/p&gt;
&lt;p&gt;So much for green-red-refactor!&lt;/p&gt;
&lt;h2&gt;Polling&lt;/h2&gt;
&lt;p&gt;We haven&amp;#39;t completely solved the problem yet where I work, but we are well on our way to do so. We have introduced a way for the testing process to poll the application in a way that allowed us to re-write the code snippet above like this:&lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:88.67%;cursor:text;direction:ltr;max-height:400px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;height:346px;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;"&gt;
&lt;div id="codeSnippet" style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;
&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum1" style="color:#606060;"&gt;   1:&lt;/span&gt; def app_loaded?&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum2" style="color:#606060;"&gt;   2:&lt;/span&gt;     $browser.run_script(&lt;span style="color:#006080;"&gt;&amp;quot;isAppLoaded&amp;quot;&lt;/span&gt;)&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum3" style="color:#606060;"&gt;   3:&lt;/span&gt; end&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum4" style="color:#606060;"&gt;   4:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum5" style="color:#606060;"&gt;   5:&lt;/span&gt; def wait_for_app&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum6" style="color:#606060;"&gt;   6:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;while&lt;/span&gt; !app_loaded?&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum7" style="color:#606060;"&gt;   7:&lt;/span&gt;         sleep 1&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum8" style="color:#606060;"&gt;   8:&lt;/span&gt;     end&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum9" style="color:#606060;"&gt;   9:&lt;/span&gt; end&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum10" style="color:#606060;"&gt;  10:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum11" style="color:#606060;"&gt;  11:&lt;/span&gt; $browser = Watir::IE.&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum12" style="color:#606060;"&gt;  12:&lt;/span&gt; $browser.&lt;span style="color:#0000ff;"&gt;goto&lt;/span&gt;(&lt;span style="color:#006080;"&gt;&amp;quot;http://myserver/page.aspx&amp;quot;&lt;/span&gt;)&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum13" style="color:#606060;"&gt;  13:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum14" style="color:#606060;"&gt;  14:&lt;/span&gt; wait_for_app&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum15" style="color:#606060;"&gt;  15:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum16" style="color:#606060;"&gt;  16:&lt;/span&gt; screen = $browser.get_screen&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum17" style="color:#606060;"&gt;  17:&lt;/span&gt; screen.enter_user_name(&lt;span style="color:#006080;"&gt;&amp;quot;user&amp;quot;&lt;/span&gt;)&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum18" style="color:#606060;"&gt;  18:&lt;/span&gt; screen.enter_password(&lt;span style="color:#006080;"&gt;&amp;quot;password&amp;quot;&lt;/span&gt;)&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum19" style="color:#606060;"&gt;  19:&lt;/span&gt; screen.click_login&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span id="lnum20" style="color:#606060;"&gt;  20:&lt;/span&gt; ...&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;What&amp;rsquo;s happening here is that when we load the web page and call the wait_for_app method, the test script will pause for a second, then execute the isAppLoaded() javascript function, located in page.aspx or in any javascript file include with the page. Based on a variable that is initialized to false but set to true after Silverlight successfully made a call to a web service, isAppLoaded() returns true only after we are certain the application is fully loaded.&lt;/p&gt;
&lt;p&gt;This was easy part&amp;hellip; We now are faced with the prospect of removing all our pauses that we inserted between all our test instructions and using a polling technique instead. For example, when we click on the login button, we need a way for the application to let page.aspx know that it is done processing that command. This is one of the challenges waiting for us. Polling the app to discover when an operation has completed successfully or not is not obvious.&lt;/p&gt;
&lt;h4&gt;Build polling into the architecture&lt;/h4&gt;
&lt;p&gt;We are lucky. Our codebase was built using SOLID principles. This means that there is one class responsible for executing commands it knows when they are done with their tasks. So it shouldn&amp;#39;t be too hard to implement polling in our case. &lt;/p&gt;
&lt;p&gt;My guess is that someone could use a Message Bus system, or something similar, to centrally deal with all the calls made from the UI to the application layer. This way, polling, and much greatness, would be accessible to the developers. &lt;/p&gt;
&lt;p&gt;Oh yeah, and all your wildest dreams will also come true. Really!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Poll%2c+Don%27t+Wait+for+your+Silverlight+Applications&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f04%2f15%2fpoll-don-t-wait-for-your-silverlight-applications.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f04%2f15%2fpoll-don-t-wait-for-your-silverlight-applications.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=20319" width="1" height="1"&gt;</content><author><name>louissalin</name><uri>http://www.lostechies.com/members/louissalin/default.aspx</uri></author></entry><entry><title>Using SVN's latest revision in your TeamCity build</title><link rel="alternate" type="text/html" href="/blogs/louissalin/archive/2009/03/30/using-svn-s-latest-revision-in-your-teamcity-build.aspx" /><id>/blogs/louissalin/archive/2009/03/30/using-svn-s-latest-revision-in-your-teamcity-build.aspx</id><published>2009-03-30T20:06:00Z</published><updated>2009-03-30T20:06:00Z</updated><content type="html">&lt;p&gt;Continuous integration is a fun beast to deal with. Sometimes irritating to set up but it feels great once it&amp;#39;s running properly, like walking barefoot on the grass!&lt;/p&gt;
&lt;p&gt;My team has recently moved from Cruise Control.Net to TeamCity for our continuous intergration process and I have been put in charge of taking our nAnt scripts and converting them to a rakefile. This was easily done except for one little hick-up... TeamCity checks out the code for you at the beginning of the build process, without all the .svn folders. This means that we don&amp;#39;t have access to the &amp;quot;svn log&amp;quot; command to get the head revision number like we used to when checking out the code manually with nAnt.&lt;/p&gt;
&lt;p&gt;After digging and searching, I found out about a powerful feature of TeamCity: setting and environment variables. It turns out that TeamCity gets the latest revision number from svn when getting the latest and greatest copy of your code and makes it available to you through the system variable &amp;quot;build.vcs.number&amp;quot;:&lt;/p&gt;
&lt;p&gt;&lt;img height="700" width="798" src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Components.UserFiles/00.00.00.21.36/step11.JPG" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;You can then use that variable to label you build number when you edit your general settings:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.lostechies.com/resized-image.ashx/__size/798x700/__key/CommunityServer.Components.UserFiles/00.00.00.21.36/step22.JPG" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Finally, TeamCity makes that build number available to you in you nAnt scripts, or any other scripts by setting a special shell environment variable that you can pick up at your leasure. In my case, using Ruby, all I had to do was:&lt;/p&gt;
&lt;p&gt;build_number = ENV[&amp;#39;BUILD_NUMBER&amp;#39;]&lt;/p&gt;
&lt;p&gt;The environment variable set by TeamCity are accessible just under the system variable ones:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.lostechies.com/resized-image.ashx/__size/798x700/__key/CommunityServer.Components.UserFiles/00.00.00.21.36/step33.JPG" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Now that I know about all of this, I&amp;#39;m wondering what else I can do with this feature. Because you know, you can set your own properties and I really like how TeamCity helps you share them across multiple tools.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Using+SVN%27s+latest+revision+in+your+TeamCity+build&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f03%2f30%2fusing-svn-s-latest-revision-in-your-teamcity-build.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f03%2f30%2fusing-svn-s-latest-revision-in-your-teamcity-build.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=20075" width="1" height="1"&gt;</content><author><name>louissalin</name><uri>http://www.lostechies.com/members/louissalin/default.aspx</uri></author><category term="SVN" scheme="http://www.lostechies.com/blogs/louissalin/archive/tags/SVN/default.aspx" /><category term="TeamCity" scheme="http://www.lostechies.com/blogs/louissalin/archive/tags/TeamCity/default.aspx" /><category term="Continuous Integration" scheme="http://www.lostechies.com/blogs/louissalin/archive/tags/Continuous+Integration/default.aspx" /></entry><entry><title>.Net libraries in Silverlight</title><link rel="alternate" type="text/html" href="/blogs/louissalin/archive/2009/03/09/net-libraries-in-silverlight.aspx" /><id>/blogs/louissalin/archive/2009/03/09/net-libraries-in-silverlight.aspx</id><published>2009-03-09T22:08:00Z</published><updated>2009-03-09T22:08:00Z</updated><content type="html">&lt;p&gt;This past week has brought it&amp;#39;s fair share of action to my life, with my new job in a new city! So far, I like everything about it, even though my appartment is empty and my family hasn&amp;#39;t moved in just yet. At work, the software that my company produces is a full blown Silverlight web application and it looks very, very sleek. My boss didn&amp;#39;t waste time and assigne to me my first task: eliminate the special testing assembly that we were using to run our specs. Let me explain why.&lt;/p&gt;
&lt;p&gt;Silverlight applications, being that they run in the browser, use a subset of the CLR to run, called the Core CLR. There are multiple reasons for that, including a different security paradigm and shorter download time. When you create a Silverlight application, it runs on top of the Core CLR. This is important, because it forces you to use libraries that have been built on top of the Core CLR also. You cannot reference a regular .Net library in your Silverlight application, it won&amp;#39;t let you.&lt;/p&gt;
&lt;p&gt;So then, you need a way to test the silverlight classes that you code. What we had done was to create a separate project using the regular CLR and link in all the silverlight classes. Then, in the code it self, we would use preprecessor directives to ignore the silverlight specific code:&lt;/p&gt;
&lt;pre&gt;#if !SILVERLIGHT_FOR_TEST
    (silverlight only code)
#else
    (non silverlight code)
#endif
&lt;/pre&gt;
&lt;p&gt;Compiling the project with the compilation symbol SILVERLIGHT_FOR_TEST set would make the compiler ignore all our silverlight specific code and allow the rest to be compile against the regular CLR. That allowed us to run tests. But maintaining two seperate projects was a pain.&lt;/p&gt;
&lt;p&gt;The first thing I did was find a version of NUnit that had been compiled against the Core CLR. You can find it &lt;a target="_blank" href="http://www.jeff.wilcox.name/2009/01/nunit-and-silverlight/"&gt;here, at the bottom of the article&lt;/a&gt;. Next, I found out that Rhino Mocks had also been compiled against Silverlight&amp;#39;s Core CLR. You can find the binaries &lt;a target="_blank" href="http://ayende.com/projects/rhino-mocks/downloads.aspx"&gt;here&lt;/a&gt;. Using those libraries, I was able, with a few modifications, to get rid our our test project and run our specs directly against our main Silverlight application.&lt;/p&gt;
&lt;p&gt;Tomorrow, I&amp;#39;ll write a bit more about my current task: develop a way to test the UI with IronRuby from within the app. Woa, there! Now, that is cool stuff!! Thanks for reading, and thank you very much to all the developers that have ported NUnit and Rhino Mocks to Silverlight!&lt;/p&gt;
&lt;p&gt;[To be continued...]&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=.Net+libraries+in+Silverlight&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f03%2f09%2fnet-libraries-in-silverlight.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f03%2f09%2fnet-libraries-in-silverlight.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=19728" width="1" height="1"&gt;</content><author><name>louissalin</name><uri>http://www.lostechies.com/members/louissalin/default.aspx</uri></author><category term="Core CLR" scheme="http://www.lostechies.com/blogs/louissalin/archive/tags/Core+CLR/default.aspx" /><category term="silverlight" scheme="http://www.lostechies.com/blogs/louissalin/archive/tags/silverlight/default.aspx" /></entry><entry><title>Stubs and application scaffolding</title><link rel="alternate" type="text/html" href="/blogs/louissalin/archive/2009/02/19/stubs-and-application-scaffolding.aspx" /><id>/blogs/louissalin/archive/2009/02/19/stubs-and-application-scaffolding.aspx</id><published>2009-02-19T20:35:18Z</published><updated>2009-02-19T20:35:18Z</updated><content type="html">&lt;blockquote&gt;   &lt;p&gt;&lt;b&gt;Stubs&lt;/b&gt; provide canned answers to calls made during the test, usually not responding at all to anything outside what’s programmed in for the test. &lt;/p&gt;    &lt;p&gt;- Martin Fowler&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I had an Ah-ha! moment a couple of days ago. I was using a stub to bypass my repository class, and thus costly database calls, when I realized that I could use that technique during the development of my app itself rather than strictly in the test code. It was one of those magical moments where you suddenly remember certain key elements all at the same time, just like if the planets had aligned. I recalled that one &lt;a href="http://blog.lonestardeveloper.com/2008/11/lean-software-development.html"&gt;lean principle&lt;/a&gt; calls for delaying important decisions for as long as possible. I also remembered that a lot of agile practitioners create their domain model before they create their persistence layer or their database schema.&lt;/p&gt;  &lt;p&gt;Ah, that’s how you do it! I used to start with my database schema since I would need data to test my application. Not so. Just create a stub instead! Stub out a repository class that will give you what you want. So here I am, quietly writing my app, when suddenly I need to authenticate a user! Oh, no. The authentication module hasn’t been written yet and the User class is still a figment of my imagination. Hmm, let’s write something down real quick.&lt;/p&gt;  &lt;div style="font-size:11pt;background:black;color:white;font-family:consolas;"&gt;   &lt;pre style="margin:0px;"&gt;&lt;span style="color:#ff8000;"&gt;public&lt;/span&gt; &lt;span style="color:#ff8000;"&gt;class&lt;/span&gt; &lt;span style="color:yellow;"&gt;User&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160; {&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#ff8000;"&gt;public&lt;/span&gt; &lt;span style="color:#ff8000;"&gt;string&lt;/span&gt; UserId { &lt;span style="color:#ff8000;"&gt;get&lt;/span&gt;; &lt;span style="color:#ff8000;"&gt;set&lt;/span&gt;; }&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#ff8000;"&gt;public&lt;/span&gt; &lt;span style="color:#ff8000;"&gt;string&lt;/span&gt; HashedPassword { &lt;span style="color:#ff8000;"&gt;get&lt;/span&gt;; &lt;span style="color:#ff8000;"&gt;set&lt;/span&gt;; }&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160; }&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now I need a way to load an “existing” user to memory. I like to have a Find() static method in my entity classes to do that. This way, I would simply need to write:&lt;/p&gt;

&lt;div style="font-size:11pt;background:black;color:white;font-family:consolas;"&gt;
  &lt;pre style="margin:0px;"&gt;&lt;span style="color:yellow;"&gt;User&lt;/span&gt; user = &lt;span style="color:yellow;"&gt;User&lt;/span&gt;.Find(&lt;span style="color:lime;"&gt;&amp;quot;louis&amp;quot;&lt;/span&gt;);&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;which I find to be very readable and self-explanatory.&lt;/p&gt;

&lt;p&gt;This Find() method would access a repository class which would return a user object with the user id “louis”, or throw some sort of UserNotFoundException if it couldn’t find it. I know that eventually, the repository will make calls to the data abstraction layer to get the data it needs, but in the mean time I want to concentrate on how the object is used, not how it is persisted. Obviously, the User class cannot know anything about existing users, so it needs to delegate that responsibility to the repository class:&lt;/p&gt;

&lt;div style="font-size:11pt;background:black;color:white;font-family:consolas;"&gt;
  &lt;pre style="margin:0px;"&gt;&lt;span style="color:#ff8000;"&gt;public&lt;/span&gt; &lt;span style="color:#ff8000;"&gt;class&lt;/span&gt; &lt;span style="color:yellow;"&gt;A_UserRepository&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;IUserRepository&lt;/span&gt; &lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160; { &lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#ff8000;"&gt;private&lt;/span&gt; &lt;span style="color:yellow;"&gt;User&lt;/span&gt; _louis = &lt;span style="color:#ff8000;"&gt;new&lt;/span&gt; &lt;span style="color:yellow;"&gt;User&lt;/span&gt;(&lt;span style="color:lime;"&gt;&amp;quot;louis&amp;quot;&lt;/span&gt;) { Name = &lt;span style="color:lime;"&gt;&amp;quot;Louis&amp;quot;&lt;/span&gt; }; &lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#ff8000;"&gt;private&lt;/span&gt; &lt;span style="color:yellow;"&gt;User&lt;/span&gt; _cara = &lt;span style="color:#ff8000;"&gt;new&lt;/span&gt; &lt;span style="color:yellow;"&gt;User&lt;/span&gt;(&lt;span style="color:lime;"&gt;&amp;quot;cara&amp;quot;&lt;/span&gt;) { Name = &lt;span style="color:lime;"&gt;&amp;quot;Cara&amp;quot;&lt;/span&gt; }; &lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#ff8000;"&gt;private&lt;/span&gt; &lt;span style="color:yellow;"&gt;Hashtable&lt;/span&gt; _usersByUserId = &lt;span style="color:#ff8000;"&gt;new&lt;/span&gt; &lt;span style="color:yellow;"&gt;Hashtable&lt;/span&gt;(); &lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#ff8000;"&gt;public&lt;/span&gt; A_UserRepository() &lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; { &lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _usersByUserId[&lt;span style="color:lime;"&gt;&amp;quot;louis&amp;quot;&lt;/span&gt;] = _louis; &lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _usersByUserId[&lt;span style="color:lime;"&gt;&amp;quot;cara&amp;quot;&lt;/span&gt;] = _cara; &lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#ff8000;"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;IList&lt;/span&gt;&amp;lt;&lt;span style="color:yellow;"&gt;User&lt;/span&gt;&amp;gt; FindUserByUserId(&lt;span style="color:#ff8000;"&gt;string&lt;/span&gt; userId) &lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; { &lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#2b91af;"&gt;IList&lt;/span&gt;&amp;lt;&lt;span style="color:yellow;"&gt;User&lt;/span&gt;&amp;gt; rList = &lt;span style="color:#ff8000;"&gt;new&lt;/span&gt; &lt;span style="color:yellow;"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color:yellow;"&gt;User&lt;/span&gt;&amp;gt;(); &lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#ff8000;"&gt;if&lt;/span&gt; (_usersByUserId.ContainsKey(userId))&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; rList.Add(_usersByUserId[userId] &lt;span style="color:#ff8000;"&gt;as&lt;/span&gt; &lt;span style="color:yellow;"&gt;User&lt;/span&gt;); &lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#ff8000;"&gt;return&lt;/span&gt; rList; &lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160; }&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;When I wrote that, I started missing the &lt;a href="http://railshotspot.blogspot.com/2008/07/rspec-fixtures-vs-mocks.html"&gt;fixture&lt;/a&gt; functionality that users &lt;a href="http://rspec.info/"&gt;rSpec&lt;/a&gt; enjoy in the Ruby world. A fixture is simply the data that would be loaded into an object. That data is kept in a separate file and loaded automatically by rSpec to populate test objects. There might be a way to do the same in C#, but since this example is fairly simple, I didn’t take the time to research this.&lt;/p&gt;

&lt;p&gt;Anyway, you’ll notice that my temporary repository implements the IUserRepository interface. This is because I know I’ll eventually need to use a real repository. If all my classes use IUserRepository objects, it will be easy to replace one with the other down the line. But how will my user know which repository to use? The static method Find() sure did not specify how to do that. Let’s see, how does it look when I write:&lt;/p&gt;

&lt;div style="font-size:11pt;background:black;color:white;font-family:consolas;"&gt;
  &lt;pre style="margin:0px;"&gt;&lt;span style="color:yellow;"&gt;User&lt;/span&gt;.FindByUserId(&lt;span style="color:#ff8000;"&gt;new&lt;/span&gt; &lt;span style="color:yellow;"&gt;A_UserRepository&lt;/span&gt;(), &lt;span style="color:lime;"&gt;&amp;quot;louis&amp;quot;&lt;/span&gt;);&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Not too bad. Check out the signature of the method.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/louissalin/repository_5F00_6EA43AB4.jpg"&gt;&lt;img title="repository" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="59" alt="repository" src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/louissalin/repository_5F00_thumb_5F00_74EB1142.jpg" width="462" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;The method signature tells me that it’s going to find a user with a IUserRepository, which I’ll now have to provide. In the future, when I’m ready to plug the User class with a real, manly repository, I’ll simply have to pass it as a parameter to the method instead of my stub, without having to change the User class, like so:&lt;/p&gt;

&lt;div style="font-size:11pt;background:black;color:white;font-family:consolas;"&gt;
  &lt;pre style="margin:0px;"&gt;&lt;span style="color:yellow;"&gt;User&lt;/span&gt;.FindByUserId(&lt;span style="color:#ff8000;"&gt;new&lt;/span&gt; &lt;span style="color:yellow;"&gt;A_Real_Manly_UserRepository&lt;/span&gt;(), &lt;span style="color:lime;"&gt;&amp;quot;louis&amp;quot;&lt;/span&gt;);&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;So there you have it, a way to use scaffolding in order to concentrate on building your domain model first, without having to bother yourself with how to construct your data access layer logic yet.&lt;/p&gt;

&lt;p&gt;I’m also happy to have shared some code for the &lt;a href="http://www.lostechies.com/blogs/louissalin/archive/2009/02/19/the-valley-of-continuous-learning.aspx"&gt;first time&lt;/a&gt; with you guys! &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Stubs+and+application+scaffolding&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f02%2f19%2fstubs-and-application-scaffolding.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2flouissalin%2farchive%2f2009%2f02%2f19%2fstubs-and-application-scaffolding.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=18500" width="1" height="1"&gt;</content><author><name>louissalin</name><uri>http://www.lostechies.com/members/louissalin/default.aspx</uri></author><category term="technique" scheme="http://www.lostechies.com/blogs/louissalin/archive/tags/technique/default.aspx" /></entry></feed>