<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://codebetter.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Rod Paddock</title><link>http://codebetter.com/blogs/rodpaddock/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>Can a Fish Use a Bicycle?</title><link>http://codebetter.com/blogs/rodpaddock/archive/2009/11/28/can-a-fish-use-a-bicycle.aspx</link><pubDate>Sat, 28 Nov 2009 14:15:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:453835</guid><dc:creator>Rod Paddock [MVP]</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/rodpaddock/rsscomments.aspx?PostID=453835</wfw:commentRss><comments>http://codebetter.com/blogs/rodpaddock/archive/2009/11/28/can-a-fish-use-a-bicycle.aspx#comments</comments><description>&lt;h2&gt;&amp;nbsp;Can a Fish Use a Bicycle?&lt;/h2&gt;
&lt;p&gt;This post will appear in the Jan/Dec issue of CODE Magazine&amp;hellip;.&lt;/p&gt;
&lt;p&gt;A few months ago, my friend and CODE Magazine contributor Ted Neward posted a statement on Twitter repeating something said by Billy Hollis: &amp;ldquo;Agile is treating the symptoms, not the disease&amp;rdquo;. This flame bait drew a number of responses that Ted later replied to on his blog (&lt;span style="text-decoration:underline;"&gt;&lt;a href="http://blogs.tedneward.com/"&gt;http://blogs.tedneward.com/&lt;/a&gt;&lt;/span&gt;)&lt;/p&gt;
&lt;p&gt;From Ted&amp;rsquo;s blog we learned the origins of Billy&amp;rsquo;s statement. Billy was lamenting the complexities of the &amp;ldquo;stack&amp;rdquo; of tools we use when developing applications in .NET today. The number of technologies we use is staggering: SQL, MVC, EF, LINQ, WPF, WCF, MEF... and so on. I agree-whole heartedly that the stack of tools is complex and very difficult for developers to keep a handle on. &lt;/p&gt;
&lt;p&gt;The blog post described how Microsoft and other companies moved from selling to &amp;ldquo;long tail&amp;rdquo; i.e., small development shops, into the &amp;ldquo;enterprise&amp;rdquo; space. This shift from small to large has left small shops in a difficult situation. Ted mentions in his blog post that not long ago, it was possible to build software with one or two developers. He asks &amp;ldquo;What chance do these developers have today?&amp;rdquo; Then he throws out the non sequitur (and I paraphrase at a distance here) &amp;ldquo;Agile development does not solve this problem.&amp;rdquo; And you know what? He is right. Agile does not solve this problem because agile has nothing to do with it. This statement in its radical context shift made me think of this statement:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;A woman needs a man like a fish needs a bicycle.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;This is a statement made by Irina Dunn and popularized by Gloria Steinem during the women&amp;rsquo;s movement; basically, it means that women are not dependant on men. Just like women and men, agile development and toolsets are unrelated processes.&lt;/p&gt;
&lt;p&gt;I am going to illustrate this point with the basic values of the Agile Manifesto (&lt;span style="text-decoration:underline;"&gt;&lt;a href="http://agilemanifesto.org/"&gt;http://agilemanifesto.org/&lt;/a&gt;&lt;/span&gt;).&lt;/p&gt;
&lt;p&gt;&amp;middot; Individuals and interactions over processes and tools &lt;/p&gt;
&lt;p&gt;&amp;middot; Working software over comprehensive documentation&lt;/p&gt;
&lt;p&gt;&amp;middot; Customer collaboration over contract negotiation&lt;/p&gt;
&lt;p&gt;&amp;middot; Responding to change over following a plan&lt;/p&gt;
&lt;p&gt;Where do you see any mention of specific tools? In fact, the first line states individuals and interactions OVER processes and tools.&lt;/p&gt;
&lt;p&gt;Agile is all about customer collaboration and building software not toolsets or specific techniques. If you drill down into the principles, you will see things like this:&lt;/p&gt;
&lt;p&gt;&amp;middot; Our highest priority is to satisfy the customer through early and continuous delivery of valuable software.&lt;/p&gt;
&lt;p&gt;&amp;middot; Build projects around motivated individuals. Give them the environment and support they need, and trust them to get the job done. &lt;/p&gt;
&lt;p&gt;&amp;middot; The most efficient and effective method of conveying information to and within a development team is face-to-face conversation. &lt;/p&gt;
&lt;p&gt;&amp;middot; At regular intervals, the team reflects on how to become more effective, then tunes and adjusts its behavior accordingly. &lt;/p&gt;
&lt;p&gt;These are just four of twelve principles. You will not see any details about specific tools or techniques. It is all about philosophy and how development teams interact with customers and each other and how they strive to build quality software. I will continue with some of my own questions to further illustrate my point:&lt;/p&gt;
&lt;p&gt;&amp;middot; Can I do Agile development using Access?&lt;/p&gt;
&lt;p&gt;&amp;middot; Can I do Agile development using FileMaker Pro?&lt;/p&gt;
&lt;p&gt;&amp;middot; Can I do Agile development using SharePoint?&lt;/p&gt;
&lt;p&gt;&amp;middot; Can I do Agile development using Visual FoxPro?&lt;/p&gt;
&lt;p&gt;&amp;middot; Can I do Agile development using an assembly language?&lt;/p&gt;
&lt;p&gt;The answer to all of these questions is YES. You can do agile development in any tool you choose because it does not pre-suppose any specific tool or technique. Another very valid point that Billy makes is that there are a lot of agile zealots that say if you are not doing/using &amp;ldquo;insert nouveau idea here&amp;rdquo; you are not doing &amp;ldquo;it&amp;rdquo; right. Simply put, those zealots need to learn and implement a little pragmatism in their discussions of agile. Are some tools or techniques better suited to the agile style of development? Yes, there are better tools, but your definition of better may be radically different than mine.&lt;/p&gt;
&lt;p&gt;In summary, agile does nothing to address the complexity of today&amp;rsquo;s modern toolset. We will always be faced with an ever-growing list of tools and techniques we use. Agile is a process, plain and simple. In my next editorial, I will illustrate some ideas you can use to make your life simpler in tackling the &amp;ldquo;stack.&amp;rdquo;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=453835" width="1" height="1"&gt;</description></item><item><title>Comments Suspended</title><link>http://codebetter.com/blogs/rodpaddock/archive/2009/07/15/comments-suspended.aspx</link><pubDate>Wed, 15 Jul 2009 16:04:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:251355</guid><dc:creator>Rod Paddock [MVP]</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;Because of spam bot whackness I have turned off comments.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=251355" width="1" height="1"&gt;</description></item><item><title>Move The Chair</title><link>http://codebetter.com/blogs/rodpaddock/archive/2009/07/03/move-the-chair.aspx</link><pubDate>Fri, 03 Jul 2009 14:17:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:249650</guid><dc:creator>Rod Paddock [MVP]</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/rodpaddock/rsscomments.aspx?PostID=249650</wfw:commentRss><comments>http://codebetter.com/blogs/rodpaddock/archive/2009/07/03/move-the-chair.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rodpaddock/IMG_5F00_0133_5F00_3CAC13AC.jpg"&gt;&lt;img border="0" align="left" width="285" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rodpaddock/IMG_5F00_0133_5F00_thumb_5F00_536DEBE6.jpg" alt="IMG_0133" height="379" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;margin:0px 10px 0px 0px;border-right-width:0px;" title="IMG_0133" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Last Sunday I took my family to Red Robin (a family style restaurant) after church. I requested a table with a high chair for my&amp;nbsp; 3.5 yr old son. Upon bringing this high chair the hostess simply moved an adult chair to the side and put the high chair in its place. (See Image)&lt;/p&gt;
&lt;p&gt;This is where the fun began&amp;hellip;&lt;/p&gt;
&lt;p&gt;For the next hour or so I watched countless customers, servers and managers limbo their way between these two chairs. A lot of them did it repeatedly, some even carrying trays full of drinks and/or food. Finally I provided evidence to to my family that I am 100% full on geek. I got excited about the insight that this little experience game me (to the point of taking pictures)&lt;/p&gt;
&lt;p&gt;I was simply amazed that people would allow this &amp;ldquo;friction to continue&amp;rdquo; It was a simple problem in this case. Move the chair!&lt;/p&gt;
&lt;p&gt;I find it interesting that it&amp;rsquo;s built into our DNA incur friction in our lives without really addressing it. In real life its called denial. I know the chair was not that big a deal but it did open my eyes to our basic nature. Our basic nature follows through to software development as well.&lt;/p&gt;
&lt;p&gt;The example of the misplaced chair provides some interesting parallels when it comes to technical debt (which is a cause of software development friction) We all have technical debt in our applications and it&amp;rsquo;s in our nature to shimmy, shuffle, limbo, mambo, and shake around these issues&amp;nbsp; whenever possible. It takes a constant vigilance to address technical debt. We must be active in our quest to remove technical debt. We must take the time to do two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Recognize the debt. In our case: The chair. &lt;/li&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Remove the debt: In our case: Move the chair. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;rsquo;s it for this blog post. Just a simple observation brought to you by the staff and management of Red Robin :)&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=249650" width="1" height="1"&gt;</description></item><item><title>Silverlight Frankenstein</title><link>http://codebetter.com/blogs/rodpaddock/archive/2009/05/19/silverlight-frankenstein.aspx</link><pubDate>Tue, 19 May 2009 15:40:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:230403</guid><dc:creator>Rod Paddock [MVP]</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/rodpaddock/rsscomments.aspx?PostID=230403</wfw:commentRss><comments>http://codebetter.com/blogs/rodpaddock/archive/2009/05/19/silverlight-frankenstein.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rodpaddock/Frank2_5F00_661EE8EF.jpg"&gt;&lt;img border="0" align="left" width="114" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rodpaddock/Frank2_5F00_thumb_5F00_63E4F0E4.jpg" alt="Frank2" height="151" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;margin:0px 15px 0px 0px;border-right-width:0px;" title="Frank2" /&gt;&lt;/a&gt; For the last 6 months I have been working on a massive call center application that uses JavaScript heavily to provide a rich client experience. While working on this application a feature request was made that threw me for a loop. The requirement was that should the users browser die or lock up their session state would need to be recoverable, meaning when the browser was restarted&amp;nbsp; we would need to recover state. With a little head scratching and soul searching I came up with this idea:&lt;/p&gt;
&lt;p align="center"&gt;&lt;em&gt;&lt;strong&gt;&amp;ldquo;Why not user Silverlight, Jquery, JSON and .NET Isolated Storage to persist client information on the browser. It&amp;rsquo;s Alive!!!!&amp;rdquo; &lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p align="left"&gt;I then went to work to create this monster. &lt;/p&gt;
&lt;h2&gt;Constructing a Monster&lt;/h2&gt;
&lt;p align="left"&gt;1. Create a new Silverlight Application with the test site included.&amp;nbsp; Initially this application will have a visual representation. You will be changing this application to a&amp;nbsp; &amp;ldquo;headless&amp;rdquo; version later.&lt;/p&gt;
&lt;p align="left"&gt;2. Add a new class to your application. Lets&amp;nbsp; call that class Frank.&lt;/p&gt;
&lt;p align="left"&gt;3. Add a reference (and appropriate using statement) to System.Windows.Browser to your Silverlight Application. System.Windows.Browser is the assembly used to integrate Silverlight with its host application.&lt;/p&gt;
&lt;p align="left"&gt;4. Now add a function called wakeUp to your Frank class. Decorate wakeUp with the [ScriptableMember] attribute.&lt;/p&gt;
&lt;div style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;" id="codeSnippetWrapper"&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;" id="codeSnippet"&gt;[ScriptableMember]&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; wakeUp(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; input)&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; input + System.Guid.NewGuid().ToString();&lt;br /&gt;}&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;5. The next step is to expose your Frank class to your browser by registering it it with the Silverlight plugin. Registering classes is done in the Page.xaml.cs file. &lt;/div&gt;
&lt;p&gt;6. Open the Page.xaml.cs file and add a reference (and appropriate using statement) to the System.Windows.Browser assembly.&lt;/p&gt;
&lt;p&gt;7. Modify the constructor of the Page class adding the following code:&lt;/p&gt;
&lt;div style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;" id="codeSnippetWrapper"&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;" id="codeSnippet"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; Page()&lt;br /&gt;{&lt;br /&gt;    InitializeComponent();&lt;br /&gt;    HtmlPage.RegisterScriptableObject(&lt;span style="color:#006080;"&gt;&amp;quot;frank&amp;quot;&lt;/span&gt;,&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Frank());&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;8. Now your Silverlight Frankenstein is exposed to your browser&amp;rsquo;s scripting code. Now lets go to the browser and wake up the monster.&lt;/p&gt;
&lt;h2&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rodpaddock/Frank1_5F00_7F1D49E5.jpg"&gt;&lt;img border="0" align="left" width="116" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rodpaddock/Frank1_5F00_thumb_5F00_6C68502E.jpg" alt="Frank1" height="149" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;margin:0px 5px 0px 0px;border-right-width:0px;" title="Frank1" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h2&gt;Waking Up the Monster&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Our preferred method of working with the DOM and JavaScript is to use jQuery. jQuery found at &lt;a href="http://www.jquery.com"&gt;www.jquery.com&lt;/a&gt; is a very useful library that takes the pain away from working with client side applications.&lt;/p&gt;
&lt;p&gt;Along with jQuery we use the JSON library to serialize and de-serialize JavaScript objects. the JSON library can be found at &lt;a href="http://www.JSON.org/json2.js" title="http://www.JSON.org/json2.js"&gt;http://www.JSON.org/json2.js&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now lets go to work and call our monster from our JavaScript application.&lt;/p&gt;
&lt;p&gt;Important Step:&lt;/p&gt;
&lt;p&gt;Before you begin this exercise modify the &amp;lt;object&amp;gt; tag in the HTML page created when you started the silverlight application. You need to add an ID attribute to that tag. Your Silverlight tag should look like:&lt;/p&gt;
&lt;div style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;" id="codeSnippetWrapper"&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;" id="codeSnippet"&gt;&amp;lt;&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; id=&lt;span style="color:#006080;"&gt;&amp;quot;frank&amp;quot;&lt;/span&gt; data=&lt;span style="color:#006080;"&gt;&amp;quot;data:application/x-silverlight-2,&amp;quot;&lt;/span&gt; type=&lt;span style="color:#006080;"&gt;&amp;quot;application/x-silverlight-2&amp;quot;&lt;/span&gt; width=&lt;span style="color:#006080;"&gt;&amp;quot;100%&amp;quot;&lt;/span&gt; height=&lt;span style="color:#006080;"&gt;&amp;quot;100%&amp;quot;&lt;/span&gt;&amp;gt;&lt;br /&gt; &amp;lt;param name=&lt;span style="color:#006080;"&gt;&amp;quot;source&amp;quot;&lt;/span&gt; value=&lt;span style="color:#006080;"&gt;&amp;quot;ClientBin/SilverlightFrankenstein.xap&amp;quot;&lt;/span&gt;/&amp;gt;&lt;br /&gt; &amp;lt;param name=&lt;span style="color:#006080;"&gt;&amp;quot;onerror&amp;quot;&lt;/span&gt; value=&lt;span style="color:#006080;"&gt;&amp;quot;onSilverlightError&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br /&gt; &amp;lt;param name=&lt;span style="color:#006080;"&gt;&amp;quot;background&amp;quot;&lt;/span&gt; value=&lt;span style="color:#006080;"&gt;&amp;quot;blue&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br /&gt; &amp;lt;param name=&lt;span style="color:#006080;"&gt;&amp;quot;minRuntimeVersion&amp;quot;&lt;/span&gt; value=&lt;span style="color:#006080;"&gt;&amp;quot;2.0.31005.0&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br /&gt; &amp;lt;param name=&lt;span style="color:#006080;"&gt;&amp;quot;autoUpgrade&amp;quot;&lt;/span&gt; value=&lt;span style="color:#006080;"&gt;&amp;quot;true&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br /&gt; &amp;lt;a href=&lt;span style="color:#006080;"&gt;&amp;quot;http://go.microsoft.com/fwlink/?LinkID=124807&amp;quot;&lt;/span&gt; style=&lt;span style="color:#006080;"&gt;&amp;quot;text-decoration: none;&amp;quot;&lt;/span&gt;&amp;gt;&lt;br /&gt;    &amp;lt;img src=&lt;span style="color:#006080;"&gt;&amp;quot;http://go.microsoft.com/fwlink/?LinkId=108181&amp;quot;&lt;/span&gt; alt=&lt;span style="color:#006080;"&gt;&amp;quot;Get Microsoft Silverlight&amp;quot;&lt;/span&gt; style=&lt;span style="color:#006080;"&gt;&amp;quot;border-style: none&amp;quot;&lt;/span&gt;/&amp;gt;&lt;br /&gt;  &amp;lt;/a&amp;gt;&lt;br /&gt; &amp;lt;/&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;&amp;gt;&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;Now you can proceed to add the code to talk to your Silverlight application.&lt;/p&gt;
&lt;p&gt;1. Add the latest and greatest version of jQuery to your web application.&lt;/p&gt;
&lt;p&gt;2. Add the latest and greatest version of JSON to your web application.&lt;/p&gt;
&lt;p&gt;3. Add a new Jscript file to your application. call it Frank.main.js. This file will contain your custom JavaScript code.&lt;/p&gt;
&lt;p&gt;4. In the .html page generated for your Silverlight application add script references to jQuery, JSON and your Frank.main.js files.&lt;/p&gt;
&lt;p&gt;5. Add a script tag to your html page to launch your jQuery application. Your code should look like the following snippet:&lt;/p&gt;
&lt;div style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;" id="codeSnippetWrapper"&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;" id="codeSnippet"&gt;&amp;lt;script src=&lt;span style="color:#006080;"&gt;&amp;quot;Scripts/jquery-1.2.6.js&amp;quot;&lt;/span&gt; type=&lt;span style="color:#006080;"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;script src=&lt;span style="color:#006080;"&gt;&amp;quot;Scripts/json2.js&amp;quot;&lt;/span&gt; type=&lt;span style="color:#006080;"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;script src=&lt;span style="color:#006080;"&gt;&amp;quot;Scripts/Frank.Main.js&amp;quot;&lt;/span&gt; type=&lt;span style="color:#006080;"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;script type=&lt;span style="color:#006080;"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;&lt;br /&gt;   $(document).ready(main);&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;5. Add a function called main to the Frank.main.js file.&lt;/p&gt;
&lt;p&gt;6. Now you can add code to call your Frank class. The first step is to create a function that will return a reference to your referenced frank class. The following JavaScript function does just that:&lt;/p&gt;
&lt;div style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;" id="codeSnippetWrapper"&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;" id="codeSnippet"&gt;&lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; getFrank() {&lt;br /&gt;  &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; returnValue = document.getElementById(&lt;span style="color:#006080;"&gt;&amp;quot;frank&amp;quot;&lt;/span&gt;).content.frank;&lt;br /&gt;  &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; returnValue;&lt;br /&gt;}&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;7. You need to carefully examine that function. It does the following:&lt;/p&gt;
&lt;p&gt;&amp;nbsp; a) Grabs a handle to the Silverlight control via &lt;strong&gt;document.getElementByID(&amp;ldquo;frank&amp;rdquo;)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; b) Bores into the Silverlight control&amp;rsquo;s content property and grabs a reference to&amp;nbsp;&amp;nbsp; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; the frank variable you referenced in the first exercise.&lt;/p&gt;
&lt;p&gt;8. Now you can call your wakeUp() method as follows:&lt;/p&gt;
&lt;div style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;" id="codeSnippetWrapper"&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;" id="codeSnippet"&gt;alert(getFrank().wakeUp(&lt;span style="color:#006080;"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;));&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h2&gt;&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Now For Something Useful&lt;/h2&gt;
&lt;p&gt;Now that you have a basic understanding of how to call C# code from your web pages you can open up your horizons and do something useful.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rodpaddock/s_5F00_spider_5F00_399849BA.jpg"&gt;&lt;img border="0" align="right" width="244" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rodpaddock/s_5F00_spider_5F00_thumb_5F00_6955F239.jpg" alt="s_spider" height="178" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;margin-left:0px;margin-right:0px;border-right-width:0px;" title="s_spider" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h2&gt;Using the Visual Studio Debugger&lt;/h2&gt;
&lt;p&gt;One of the more interesting things I came up with was integrating the Visual Studio debugger into my JavaScript applications. Rather than debugging variables via the good old alert() function why not spit information to the debugger?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The following code blocks show how you can spit data from your JavaScript application into the Visual Studio debugger.&lt;/p&gt;
&lt;div style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;" id="codeSnippetWrapper"&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;" id="codeSnippet"&gt;[ScriptableMember]&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; writeline(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; output)&lt;br /&gt;{&lt;br /&gt; System.Diagnostics.Debug.WriteLine(output);&lt;br /&gt;}&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;" id="codeSnippetWrapper"&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;" id="codeSnippet"&gt;&lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; debuggerTest() {&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;for&lt;/span&gt; (i=0; i&amp;lt;100; i++) {&lt;br /&gt;        writeline(i);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rodpaddock/Frank3_5F00_327B9DF3.jpg"&gt;&lt;img border="0" align="left" width="244" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rodpaddock/Frank3_5F00_thumb_5F00_1B502375.jpg" alt="Frank3" height="184" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;margin:0px 5px 0px 0px;border-right-width:0px;" title="Frank3" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h2&gt;Calculating Ages&lt;/h2&gt;
&lt;p&gt;Lets face it JavaScript date support,especially when it comes to date calculations sucks.Date support in the .NET framework is much better. Especially when you use the &amp;ldquo;wrapped up&amp;rdquo; code found in the Microsoft.VisualBasic namespace.&lt;/p&gt;
&lt;p&gt;The following code calculates a person&amp;rsquo;s age (in years) using the DateDiff() function found in the Microsoft.VisualBasic assembly. To use this code add a reference to the Microsoft.VisualBasic assembly to your Silverlight Application. &lt;/p&gt;
&lt;p&gt;The following code snippets show how to calculate an age from a given date:&lt;/p&gt;
&lt;div style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;" id="codeSnippetWrapper"&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;" id="codeSnippet"&gt;[ScriptableMember]&lt;br /&gt;public long getAge(string inputDate)&lt;br /&gt;{&lt;br /&gt;    long returnValue = &lt;span style="color:#006080;"&gt;-1;&lt;/span&gt;&lt;br /&gt;    try&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; dateValue = System&lt;span style="color:#cc6633;"&gt;.Convert&lt;/span&gt;&lt;span style="color:#cc6633;"&gt;.ToDateTime&lt;/span&gt;(inputDate);&lt;br /&gt;        returnValue = Microsoft&lt;span style="color:#cc6633;"&gt;.VisualBasic&lt;/span&gt;&lt;span style="color:#cc6633;"&gt;.DateAndTime&lt;/span&gt;&lt;span style="color:#cc6633;"&gt;.DateDiff&lt;/span&gt;(Microsoft&lt;span style="color:#cc6633;"&gt;.VisualBasic&lt;/span&gt;&lt;span style="color:#cc6633;"&gt;.DateInterval&lt;/span&gt;&lt;span style="color:#cc6633;"&gt;.Year&lt;/span&gt;,&lt;br /&gt;                 dateValue,&lt;br /&gt;                 System&lt;span style="color:#cc6633;"&gt;.DateTime&lt;/span&gt;&lt;span style="color:#cc6633;"&gt;.Now&lt;/span&gt;,&lt;br /&gt;                 Microsoft&lt;span style="color:#cc6633;"&gt;.VisualBasic&lt;/span&gt;&lt;span style="color:#cc6633;"&gt;.FirstDayOfWeek&lt;/span&gt;&lt;span style="color:#cc6633;"&gt;.System&lt;/span&gt;,&lt;br /&gt;                 Microsoft&lt;span style="color:#cc6633;"&gt;.VisualBasic&lt;/span&gt;&lt;span style="color:#cc6633;"&gt;.FirstWeekOfYear&lt;/span&gt;&lt;span style="color:#cc6633;"&gt;.System&lt;/span&gt;);&lt;br /&gt;    }&lt;br /&gt;    catch (Exception)&lt;br /&gt;    {&lt;br /&gt;        returnValue = &lt;span style="color:#006080;"&gt;-2;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#006080;"&gt;}&lt;br /&gt;    return returnValue;&lt;/span&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;" id="codeSnippetWrapper"&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;" id="codeSnippet"&gt;alert(getFrank().getAge(&lt;span style="color:#006080;"&gt;&amp;quot;01/01/1981&amp;quot;&lt;/span&gt;));c&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rodpaddock/51XJ2eVrTaL_5F005F00_SL500_5F00_166D6FB9.jpg"&gt;&lt;img border="0" align="left" width="172" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rodpaddock/51XJ2eVrTaL_5F005F00_SL500_5F00_thumb_5F00_13C744B9.jpg" alt="51XJ2eVrTaL__SL500" height="244" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;margin:0px 10px 0px 0px;border-right-width:0px;" title="51XJ2eVrTaL__SL500" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h2&gt;Final Frankenstein&lt;/h2&gt;
&lt;p&gt;The original purpose of this exercise is to be able to save and restore form state from a client browser session. This is where a good plan comes together. Saving state involves a number of moving parts. &lt;/p&gt;
&lt;p&gt;0. Create a simple HTML form with some fields.&lt;/p&gt;
&lt;p&gt;1. Create an array of the objects representing the data from a set of web input fields.&lt;/p&gt;
&lt;p&gt;2. Serialize the array into a string using JSON (JavaScript Object Notation)&lt;/p&gt;
&lt;p&gt;3. Pass that string to Silverlight and save it to disk using Silverlight&amp;rsquo;s Isolated storage mechanism.&lt;/p&gt;
&lt;p&gt;4. Retrieve the JSON data from Isolated Storage and de-serialize it back to an array.&lt;/p&gt;
&lt;p&gt;5. Re-populate the controls on the form from the array.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Simple HTML&lt;/h3&gt;
&lt;p&gt;This code is about the simplest HTML form you could create. Two text fields and two buttons. The two buttons will be used to save and restore state (we save and restore state via a timer).&lt;/p&gt;
&lt;div style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;" id="codeSnippetWrapper"&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;" id="codeSnippet"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;label&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Last Name&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;label&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;input&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;id&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;txtLastname&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;br&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;label&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;First Name&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;label&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;input&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;id&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;txtFirstName&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;br&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;input&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;id&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;cmdSaveState&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;button&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;value&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Save State&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt; &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;input&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;id&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;cmdRestoreState&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;button&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;value&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Restore State&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt; &lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;The following code wires up the buttons to functions to save and restore state:&lt;/p&gt;
&lt;div style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;" id="codeSnippetWrapper"&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;" id="codeSnippet"&gt;$(&lt;span style="color:#006080;"&gt;&amp;quot;#cmdRestoreState&amp;quot;&lt;/span&gt;).click(restoreState);&lt;br /&gt;$(&lt;span style="color:#006080;"&gt;&amp;quot;#cmdSaveState&amp;quot;&lt;/span&gt;).click(saveState);&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;Gathering and Restoring Data &lt;/h3&gt;
&lt;p&gt;The next set of code creates an array of objects representing page content. It also serializes the content to a JSON string using the JSON library added to your project earlier. &lt;/p&gt;
&lt;div style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;" id="codeSnippetWrapper"&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;" id="codeSnippet"&gt;&lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; getContentAsJSON() {&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; inputControls = $(&lt;span style="color:#006080;"&gt;&amp;quot;:input&amp;quot;&lt;/span&gt;).not(&lt;span style="color:#006080;"&gt;&amp;quot;:button&amp;quot;&lt;/span&gt;).not(&lt;span style="color:#006080;"&gt;&amp;quot;.ignorestate&amp;quot;&lt;/span&gt;);&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; controlData = Array();&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;for&lt;/span&gt; (i = 0; i &amp;lt; inputControls.length; i++) {&lt;br /&gt;        controlData.push({ ID: inputControls&lt;img src="http://codebetter.com/emoticons/emotion-55.gif" alt="Idea" /&gt;.id, Value: inputControls&lt;img src="http://codebetter.com/emoticons/emotion-55.gif" alt="Idea" /&gt;.value, Type: inputControls&lt;img src="http://codebetter.com/emoticons/emotion-55.gif" alt="Idea" /&gt;.type });&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; jsondata = JSON.stringify(controlData);&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; jsondata;&lt;br /&gt;}&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;strong&gt;Note: this code gathers up data for all controls except for buttons and ones that have the .ignorestate style attached to them.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The next set of code is the converse of the prior. It takes a JSON string and de-serializes it back to an array and repopulates control values based on its content.&lt;/p&gt;
&lt;div style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;" id="codeSnippetWrapper"&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;" id="codeSnippet"&gt;&lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; restoreControlState(controlDataString) {&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (controlDataString.length &amp;gt; 0) {&lt;br /&gt;        &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; controlData = JSON.parse(controlDataString);&lt;br /&gt;        &lt;span style="color:#0000ff;"&gt;for&lt;/span&gt; (i = 0; i &amp;lt; controlData.length; i++) {&lt;br /&gt;            $(&lt;span style="color:#006080;"&gt;&amp;quot;#&amp;quot;&lt;/span&gt; + controlData&lt;img src="http://codebetter.com/emoticons/emotion-55.gif" alt="Idea" /&gt;.ID).val(controlData&lt;img src="http://codebetter.com/emoticons/emotion-55.gif" alt="Idea" /&gt;.Value);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Saving and Restoring State&lt;/h3&gt;
&lt;p&gt;Now you need a mechanism for storing and retrieving the data to client workstation. To do this, you will use the Isolated Storage mechanisms contained in the Silverlight framework. Isolated storage is a data storage mechanism available in both standard .NET and Silverlight applications. Isolated storage is a set of APIs used to read and write files to a virtual file system managed by the .NET framework. Silverlight applications have a default 1MB (yes 1MB) of storage available to them for reading and writing files.&amp;nbsp; To use the following code examples import System.IO and System.IO.IsolatedStorage to your applications:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;The first is used to preserve state. It&amp;nbsp; does the following:&lt;/p&gt;
&lt;p&gt;1.&amp;nbsp; Opens the &amp;ldquo;virtual file system&amp;rdquo; presented by IsolatedStorage&lt;/p&gt;
&lt;p&gt;2. Checks to see if the &amp;ldquo;sessioncontents.txt&amp;rdquo;&amp;nbsp; file exists&amp;nbsp; . If so it deletes it.&lt;/p&gt;
&lt;p&gt;3. Creates a file stream to write content to.&lt;/p&gt;
&lt;p&gt;4. Uses a standard StreamWriter to push content to the file.&lt;/p&gt;
&lt;p&gt;5. Flushes the buffer and closes the file handle&lt;/p&gt;
&lt;div style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;" id="codeSnippetWrapper"&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;" id="codeSnippet"&gt;[ScriptableMember]&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; saveState(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; stateString)&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color:#008000;"&gt;//yes this is a MAGIC string for a demo&lt;/span&gt;&lt;br /&gt;    var contentFileName = &lt;span style="color:#006080;"&gt;&amp;quot;sessionContents.txt&amp;quot;&lt;/span&gt;;&lt;br /&gt;    var userStore = IsolatedStorageFile.GetUserStoreForApplication();&lt;br /&gt;&lt;br /&gt;    &lt;span style="color:#008000;"&gt;//whack the file if it exists&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (userStore.FileExists(contentFileName))&lt;br /&gt;    {&lt;br /&gt;        userStore.DeleteFile(contentFileName);&lt;br /&gt;    }&lt;br /&gt;    var file = userStore.CreateFile(contentFileName);&lt;br /&gt;    var writer = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; StreamWriter(file);&lt;br /&gt;    writer.WriteLine(stateString);&lt;br /&gt;    writer.Flush();&lt;br /&gt;    writer.Close();&lt;br /&gt;    file.Close();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;The next step is to return the data from IsolatedStorage. It does the converse:&lt;/p&gt;
&lt;p&gt;1.&amp;nbsp; Opens the &amp;ldquo;virtual file system&amp;rdquo; presented by IsolatedStorage&lt;/p&gt;
&lt;p&gt;2. Checks to see if the &amp;ldquo;sessioncontents.txt&amp;rdquo;&amp;nbsp; file exists&amp;nbsp; . If so it opens it.&lt;/p&gt;
&lt;p&gt;3. Creates a file stream to read content from.&lt;/p&gt;
&lt;p&gt;4. Uses a standard StreamReader to read content from the file.&lt;/p&gt;
&lt;p&gt;5. Closes the file handle&lt;/p&gt;
&lt;p&gt;6 Returns the string to the caller.&lt;/p&gt;
&lt;div style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;" id="codeSnippetWrapper"&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;" id="codeSnippet"&gt;[ScriptableMember]&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; getState()&lt;br /&gt;{&lt;br /&gt;    var returnValue = &lt;span style="color:#006080;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;;&lt;br /&gt;    &lt;span style="color:#008000;"&gt;//yes this is a MAGIC string for a demo&lt;/span&gt;&lt;br /&gt;    var contentFileName = &lt;span style="color:#006080;"&gt;&amp;quot;sessionContents.txt&amp;quot;&lt;/span&gt;;&lt;br /&gt;    var userStore = IsolatedStorageFile.GetUserStoreForApplication();&lt;br /&gt;&lt;br /&gt;    &lt;span style="color:#008000;"&gt;//whack the file if it exists&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (userStore.FileExists(contentFileName))&lt;br /&gt;    {&lt;br /&gt;        var file = userStore.OpenFile(contentFileName,FileMode.Open,FileAccess.Read );&lt;br /&gt;        var reader = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; StreamReader(file);&lt;br /&gt;        returnValue = reader.ReadToEnd();&lt;br /&gt;        reader.Close();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; returnValue;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now all you need is the small glue code to put it all together:&lt;/p&gt;
&lt;div style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:97.5%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;" id="codeSnippetWrapper"&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;" id="codeSnippet"&gt;function saveState() {&lt;br /&gt;    getFrank().saveState(getContentAsJSON());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function restoreState() {&lt;br /&gt;    restoreControlState(getFrank().getState());&lt;br /&gt;}&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all you need to save and restore state from a HTML form&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Removing the Head&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rodpaddock/FRANKENSTEIN_5F00_JR_5F00_HEADSHOT_5F00_07C55485.jpg"&gt;&lt;img border="0" align="right" width="239" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rodpaddock/FRANKENSTEIN_5F00_JR_5F00_HEADSHOT_5F00_thumb_5F00_25A66937.jpg" alt="FRANKENSTEIN_JR_HEADSHOT" height="244" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;margin-left:0px;margin-right:0px;border-right-width:0px;" title="FRANKENSTEIN_JR_HEADSHOT" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;Finally you can go &amp;ldquo;remove the head&amp;rdquo; from your Silverlight application. this is rather simple. To remove the head from your Silverlight application you simply go to the Page.xaml file and change the size attributes to zero. Now you have a &amp;ldquo;headless&amp;rdquo; frankenstein for your fun and enjoyment.&lt;/p&gt;
&lt;div style="font-size:8pt;margin:20px 0px 10px;overflow:auto;width:64.82%;cursor:text;direction:ltr;max-height:200px;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;height:133px;background-color:#f4f4f4;text-align:left;border:silver 1px solid;padding:4px;" id="codeSnippetWrapper"&gt;
&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:68.83%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;height:93px;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;" id="codeSnippet"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;UserControl&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;x:Class&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;SilverlightFrankenstein.Page&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#ff0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;&lt;/span&gt; &lt;br /&gt;    &lt;span style="color:#ff0000;"&gt;xmlns:x&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;&lt;/span&gt; &lt;br /&gt;    &lt;span style="color:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;x:Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;LayoutRoot&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Background&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;White&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;UserControl&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;I hope you have enjoyed this post. You can find this code at &lt;a href="http://www.dashpoint.com/downloads/silverlightfrankenstein.zip"&gt;www.dashpoint.com/downloads/silverlightfrankenstein.zip&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=230403" width="1" height="1"&gt;</description></item><item><title>10,000 Hours to Graceland</title><link>http://codebetter.com/blogs/rodpaddock/archive/2009/04/26/10-000-hours-to-graceland.aspx</link><pubDate>Sun, 26 Apr 2009 20:29:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:204236</guid><dc:creator>Rod Paddock [MVP]</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/rodpaddock/rsscomments.aspx?PostID=204236</wfw:commentRss><comments>http://codebetter.com/blogs/rodpaddock/archive/2009/04/26/10-000-hours-to-graceland.aspx#comments</comments><description>&lt;p&gt;Lets take a look at some old code:&lt;/p&gt;
&lt;p&gt;&lt;img width="558" src="http://www.dashpoint.com/downloads/oldcode.jpg" height="768" alt="" /&gt;&amp;nbsp;&amp;nbsp; &lt;/p&gt;
&lt;p&gt;I know what you may be thinking. Why the heck are we looking at 20 yr old procedural code. Well...what you just witnessed was the first paid code written by a greenhorn application developer. For the curious that code was written in&amp;nbsp; dBaseIII+ hosted on a PC Limited (now Dell) server running Novell 2.0a. &lt;/p&gt;
&lt;p&gt;When you take a look at that code and the application in its entirety you will find an application riddled with poor coding constructs, amateurish coding principles (use of publics for example) and an application that misses fundamental features available to it from its core language (xBase). Basically what you will find code written by a wet behind the ears application developer, fresh out of college, and unleashed on a property management company to write an application to be known as : &amp;quot;The Hot Tub Management System&amp;quot;.&lt;/p&gt;
&lt;p&gt;When looking at that code you will see the type of code written by a junior application developer. That junior developer started his career with&amp;nbsp; with 1.5 years of college education and a burning desire to write code for a living.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;The learning didn&amp;#39;t stop there. The programmer that wrote that code went on to gain more education and more importantly more application development experience. That programmer moved from the property management company to a large hotel/resort where he was applied his craft for 18 months as an application developer/network admin. Eventually that programmer left small town Bend, Oregon for the bright lights and big city life in Seattle, Washington. &lt;/p&gt;
&lt;p&gt;It&amp;#39;s in Seattle where that developer went from being the lone wolf developer&amp;nbsp; in a small company to to being a member of a team of developers in a somewhat larger company. When he was hired the developer told he would be joining a group of the best FoxPro developers assembled in the Seattle area and would need to rise to the challenge. That is exactly what he did. &lt;/p&gt;
&lt;p&gt;It was at that company that the developer really came into his own. The developers on that team were a competitive and very talented group of developers. The primary concern of that group of developers was to create the correct solutions for the company and do it right the 1st time.&amp;nbsp; By the time the developer left that company he was writing some of the best code of his life, creating high performance and feature rich applications and finally re-caught the writing bug and was drafting articles for the magazine Data Based Advisor.&amp;nbsp; At that point the developer had been writing code (including college) for nearly 5 years. Which leads me back to the title of my post: 10,000 hours to Graceland.&lt;/p&gt;
&lt;p&gt;The normal employee works approximately 2,000 hours a year (40 hours * 50 weeks). When you factor in 5 years of work that comes out to 10,000 hours. This is the minimum amount of time it takes to master a craft.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;This epiphany didn&amp;#39;t come straight from my gray matter it came from a book I picked up earlier this month called &lt;a target="_blank" href="http://www.amazon.com/Outliers-Story-Success-Malcolm-Gladwell/dp/0316017922/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1240773616&amp;amp;sr=8-1"&gt;Outliers, by Malcolm Gladwell&lt;/a&gt;. In general I am not a big fan of overhyped books like Outliers. I couldn&amp;#39;t have been more wrong about this book. I found that this book was much like &lt;a target="_blank" href="http://www.amazon.com/Freakonomics-Revised-Expanded-Economist-Everything/dp/0061234001/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1240773749&amp;amp;sr=1-1"&gt;Freakanomics&lt;/a&gt; which challenged basic assumptions we have as a society. &lt;/p&gt;
&lt;p&gt;Malcolm starts this book with an analysis of a championship team&amp;nbsp; of young Canadian hockey players. People were attempting to figure out why some hockey players seem to excel while others to not. When analyzed a startling conclusion was made: Kids with birth dates falling in a specific range seemed to play better than the others.&amp;nbsp; As &lt;a target="_blank" href="http://en.wikipedia.org/wiki/Mars_Blackmon"&gt;Mars Blackmon&lt;/a&gt; would say &amp;quot;Gotta be the stars!&amp;quot; People born under a specific sign are better hockey players right ? Nope... Basically it boiled down to this. The kids falling in a certain birthday range were allowed to start playing hockey earlier than the other kids. Basically they got a head start by 6months to a year. Now these kids did have talent...but talent nurtured earlier has a better chance of success right?&lt;/p&gt;
&lt;p&gt;This was making sense. It got clearer as the book progressed. Gladwell wrote about two of the most regarded software developers of our day. The two Bills. Bill Gates and Bill Joy. One thing that Bill Gates and Bill Joy share was the fact that they had access to computers at a very early age and spent countless waking hours working on these machines. By the time real opportunities presented themselves in there 20&amp;#39;s both of these me had the requisite 10,000 hours under there belts and were able to apply their craft to great advantage. Once again it was not just the amount of time they spent, they did have talent by the truck load, but that talent was nurtured from an early age to yield some some real talent. &lt;/p&gt;
&lt;p&gt;With all the talk of Software Craftsmanship these days we must never forget that it takes a lot of time to master new skills. I moved from Visual FoxPro to Visual Studio .NET in 2001 it took me a few years to really master a&amp;nbsp; new way of development. It didn&amp;#39;t take me quite 10,000 hours, as I had a lot of experience in object oriented code and frameworks, but it did take a certain amount of time in the trenhes to master this new set of concepts.&lt;/p&gt;
&lt;p&gt;What is true in Software Craftsmanship is true life&amp;#39;s&amp;nbsp; other endeavors as well.&amp;nbsp; There is an old saying in poker:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;It takes 15 minutes to learn the game and a lifetime to master&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I completely relate to this statement. Around 10 years ago I sat down for my first real poker game in a casino. I was scared out of my wits but I held my own. I lost of course but I had caught the poker bug. I spent literally hundreds of hours grinding learning how to play this game effectively.&amp;nbsp; Do I consider myself a master? Heck now I am no Daniel Negraneu. But I can definitely hold my own with the best of em in the casinos in Vegas. I feel this way now when it comes to Agile and XP development processes. &lt;/p&gt;
&lt;p&gt;In 2000 I found a book called &lt;a target="_blank" href="http://www.amazon.com/Extreme-Programming-Explained-Embrace-Change/dp/0201616416"&gt;Extreme Programming Explained&lt;/a&gt;. This book seemed to be what I had been looking for when it came to developing software. At its core it talked about working directly with customers to develop exactly what they wanted correctly the 1st time. Kinda like that team I was on early in my career. Over the ensuing years I spent time attempting to implement these with customers and in my own practices. It seemed to me like I had started over once again as a web behind the ears programmer.&amp;nbsp; I didn&amp;#39;t have a lot of luck&amp;nbsp; getting clients to adopt these principles but I did keep growing my own personal knowledge. Flash forward to October 2007 in Austin Texas. I attended my first &lt;a target="_blank" href="http://www.altnetconf.com/home/closed"&gt;ALT NET Conference&lt;/a&gt; it was here that I spent time learning more about implementing agile practices in my company and with my clients. I was going to master this if it killed me. Over the last year and a half I have been putting in my time towards my 10,000 hours to Graceland. I have been fortunate that I have the opportunity to be mentored by, dialog with and become friends with a number of agile developers I respect. It&amp;#39;s this dialog that has been most important to my mastery of this stuff. Like poker I am not a master but I am beginning to &amp;quot;hold my own&amp;quot; with these folks. I am glad they have spent the time sharing their 10,000 hours to Graceland with me.&lt;/p&gt;
&lt;p&gt;One other thing that did for me was to give me another level of perspective when dealing with people new to agile development practices. I am an agile teacher and need to take into account that it takes a number of hours practicing thus stuff before you can see the real benefit. A lot of developers will take a surface glance at a subject like Test Driven Design and rule it out as a a waste&amp;nbsp; of time. We all have heard the question &amp;quot;Why do I need to waste my time with this?&amp;quot;. We need to address these questions with patience and understanding. We need to relate back to ourselves as greenhorn wet behind the ears developers. We need to remember that it took us 10,000 hours to get here and it will take people new to agile 10,000 hours to find their Graceland. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=204236" width="1" height="1"&gt;</description></item><item><title>jQuery 101 UG Samples and Slides</title><link>http://codebetter.com/blogs/rodpaddock/archive/2009/04/07/jquery-101-ug-samples-and-slides.aspx</link><pubDate>Tue, 07 Apr 2009 13:48:28 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:191259</guid><dc:creator>Rod Paddock [MVP]</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/rodpaddock/rsscomments.aspx?PostID=191259</wfw:commentRss><comments>http://codebetter.com/blogs/rodpaddock/archive/2009/04/07/jquery-101-ug-samples-and-slides.aspx#comments</comments><description>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Here is the slide deck and sample code from my jQuery 101 user group talks this week.Thanks you to everyone that attended my user group chats this week.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.dashpoint.com/downloads/jquery101slides.zip"&gt;jQuery 101 Slide Deck&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.dashpoint.com/downloads/jquery101sample.zip"&gt;jQuery 101 Sample Code&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=191259" width="1" height="1"&gt;</description></item><item><title>Come Learn jQuery</title><link>http://codebetter.com/blogs/rodpaddock/archive/2009/03/30/come-learn-jquery.aspx</link><pubDate>Mon, 30 Mar 2009 13:19:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:189872</guid><dc:creator>Rod Paddock [MVP]</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/rodpaddock/rsscomments.aspx?PostID=189872</wfw:commentRss><comments>http://codebetter.com/blogs/rodpaddock/archive/2009/03/30/come-learn-jquery.aspx#comments</comments><description>&lt;p&gt;After a brief stop in Houston for the &lt;a href="http://houston.altnetconf.com/home"&gt;Alt Net Houston Open Space&lt;/a&gt; and another brief stop in Seattle for &lt;a href="http://www.emeraldcitycomicon.com/"&gt;Emerald City ComicCon&lt;/a&gt; I will begin my trek north for another Canadian user group tour.&lt;/p&gt;
&lt;p&gt;Topic: Using jQuery with ASP.NET &lt;/p&gt;
&lt;p&gt;Web 2.0 is here to stay. jQuery is a JavaScript library that abstracts away all of the gory details of working with JavaScript for web applications. This session will demonstrate how to add jQuery to your ASP.NET applications today. This session will focus on proper uses of jQuery including how to organize your JavaScript code, how to use selectors in jQuery and how to manipulate your web content dynamically. Along with uses of the standard jQuery library, time will also be spent exploring some of the most useful jQuery plugs-ins. &lt;/p&gt;
&lt;p&gt;I will be at the following user groups&lt;/p&gt;
&lt;p&gt;April 6th &lt;a href="http://www.netbc.ca/DNCal/EventDetail.aspx?date=2009/04/06"&gt;.Net User Group of British Columbia (Vancouver BC)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;April 7th &lt;a href="http://www.edmug.net/"&gt;Edmonton .NET User Group&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;April 8th &lt;a href="http://reginadotnet.blogspot.com/"&gt;Regina .NET User Group&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;April 9th &lt;a href="http://www.dotnetwired.com/"&gt;Winnipeg .NET User Group&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I am looking forward to seeing old friends and making new ones on this tour. Hope to see you there!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=189872" width="1" height="1"&gt;</description></item><item><title>Underscoring A Point</title><link>http://codebetter.com/blogs/rodpaddock/archive/2009/03/28/underscoring-a-point.aspx</link><pubDate>Sat, 28 Mar 2009 12:43:06 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:189792</guid><dc:creator>Rod Paddock [MVP]</dc:creator><slash:comments>10</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/rodpaddock/rsscomments.aspx?PostID=189792</wfw:commentRss><comments>http://codebetter.com/blogs/rodpaddock/archive/2009/03/28/underscoring-a-point.aspx#comments</comments><description>&lt;p&gt;This last week I took a great class on TDD and BDD given by &lt;a href="http://ampgt.com/"&gt;Scott Bellware&lt;/a&gt;. During&amp;#160; the session&amp;#160;&amp;#160; he showed us a cool tool called &lt;a href="http://www.autohotkey.com/"&gt;AutoHotKey&lt;/a&gt;. AutoHotKey is a tool that allows you to control your keyboard behaviors. For instance you can use AutoHotKey to substitute the underscore character for a space when typing in a test name&lt;/p&gt;  &lt;p&gt;I had a discussion with my co-worker Greg Lawrence about using underscores vs.&amp;#160; &lt;a href="http://en.wikipedia.org/wiki/CamelCase"&gt;CamelCase&lt;/a&gt; for our test naming conventions. I have always liked underscores in test names. Test names are like sentences and should be read as such. To drive this point home (and to demonstrate it for an underscore bigot :) I present the following:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Original Test&lt;/strong&gt;&lt;/p&gt;  &lt;p align="center"&gt;&lt;em&gt;&lt;strong&gt;We hold these truths to be self-evident, that all men are created equal,        &lt;br /&gt;that they are endowed by their Creator with certain unalienable Rights, that among these are Life, Liberty and the pursuit of Happiness. &lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p align="left"&gt;&lt;strong&gt;CamelCase&lt;/strong&gt;&lt;/p&gt;  &lt;p align="center"&gt;&lt;em&gt;&lt;strong&gt;WeHoldTheseTruthsToBeSelfEvidentThatAllMenAreCreatedEqualThatTheyAreEndowed…&lt;/strong&gt;&lt;/em&gt;&lt;em&gt;&lt;strong&gt;WithCertainUnalienableRightsThatAmongTheseAreLifeLibertyAndThePursuitOfHappiness. &lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Underscored&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt;We_hold_these_truths_to_be_self_evident_that_all_men_are_created_equal_that_they_are_endowed_…&lt;/em&gt;&lt;/strong&gt;&lt;strong&gt;&lt;em&gt;with_certain_unalienable_rights_that_are_among_these_are_life_liberty_and_the_pursuit_of_happiness&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;BDD CamelCase Notation&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;WhenMenAreEndowedWithUnalienableRights&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;ShouldIncludeLife &lt;/li&gt;    &lt;li&gt;ShouldIncludeLiberty &lt;/li&gt;    &lt;li&gt;ShouldIncludeHappiness &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;BDD Notation (Underscored)&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;When_Men_Are_Endowed_With_Unalienable_Rights&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Should_Include_Life &lt;/li&gt;    &lt;li&gt;Should_Include_Liberty &lt;/li&gt;    &lt;li&gt;Should_Include_Happiness &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;As is self evident (pun intended) the underscored version is much easier to understand and read.&amp;#160; When you generate documentation from your BDD specs which one make more sense? Which will is easier to use by your customers? Which ones can you substitute underscores for spaces when printing documentation? Its pretty obvious which one to choose.&lt;/p&gt;  &lt;p&gt;Just a small thought on this march morning.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=189792" width="1" height="1"&gt;</description></item><item><title>What's in a Job Title</title><link>http://codebetter.com/blogs/rodpaddock/archive/2009/01/04/what-s-in-a-job-title.aspx</link><pubDate>Sun, 04 Jan 2009 21:17:58 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:186915</guid><dc:creator>Rod Paddock [MVP]</dc:creator><slash:comments>25</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/rodpaddock/rsscomments.aspx?PostID=186915</wfw:commentRss><comments>http://codebetter.com/blogs/rodpaddock/archive/2009/01/04/what-s-in-a-job-title.aspx#comments</comments><description>&lt;p&gt;One of the most frequently asked for attributes on a credit or job application is Job Title. As an independent business owner I have answered this question in multiple ways:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Programmer &lt;/li&gt;    &lt;li&gt;Software Developer &lt;/li&gt;    &lt;li&gt;Software Engineer &lt;/li&gt;    &lt;li&gt;Architect &lt;/li&gt;    &lt;li&gt;CTO &lt;/li&gt;    &lt;li&gt;Coder &lt;/li&gt;    &lt;li&gt;President &lt;/li&gt;    &lt;li&gt;Jedi Master &lt;/li&gt;    &lt;li&gt;Etc... &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The scary thing about this is there is no real way for a potential employer,&amp;#160; banker or client to certify what I say is legit. This is a fundamental issue with our industry. There is no way to verify whether a person is a quality software engineer or simply a charlatan. And for the record there are more of the latter than the former.&lt;/p&gt;  &lt;p&gt;For the most part programmers like to think of software development as engineering. We like to compare ourselves to engineers with a capital E, construction managers, manufacturing process managers, etc. But do we really practice engineering ? What is the bar for calling yourself a software engineer?&lt;/p&gt;  &lt;p&gt;I know for a fact that if I need an expert licensed plumber, electrician or ironworker I can take myself down to the local union hall and find someone that has gone from apprentice to journeyman over the course of many years.&amp;#160; And thanks to my friend &lt;a href="http://testinfected.blogspot.com/" target="_blank"&gt;Eric Anderson&lt;/a&gt; I learned that there is such a thing as a Professional Engineer. Here&amp;#39;s the list of requirements for Professional Engineers as taken from the &lt;a href="http://en.wikipedia.org/wiki/P.Eng." target="_blank"&gt;Wikipedia&lt;/a&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;em&gt;&lt;strong&gt;Graduate with a degree from an accredited four-year university program in engineering. &lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;    &lt;li&gt;&lt;em&gt;&lt;strong&gt;Complete a standard &lt;/strong&gt;&lt;/em&gt;&lt;a href="http://en.wikipedia.org/wiki/Fundamentals_of_Engineering_exam"&gt;&lt;em&gt;&lt;strong&gt;Fundamentals of Engineering&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;em&gt;&lt;strong&gt; (FE) written examination, which tests applicants on breadth of understanding of basic engineering principles, and optionally some elements of an engineering specialty. Completion of the first two steps typically qualifies for certification in the U.S. as an Engineer-In-Training (EIT), sometimes also called an Engineer Intern (EI).&lt;sup&gt;&lt;a href="http://en.wikipedia.org/#cite_note-4"&gt;[5]&lt;/a&gt;&lt;/sup&gt;&lt;/strong&gt;&lt;/em&gt; &lt;/li&gt;    &lt;li&gt;&lt;em&gt;&lt;strong&gt;Accumulate a certain amount of engineering experience under the supervision of a P.E. In most states the requirement is four years, but in others the requirement is lower. &lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;    &lt;li&gt;&lt;em&gt;&lt;strong&gt;Complete a written &lt;/strong&gt;&lt;/em&gt;&lt;a href="http://en.wikipedia.org/wiki/Principles_and_Practice_in_Engineering_Exam"&gt;&lt;em&gt;&lt;strong&gt;Principles and Practice in Engineering&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;em&gt;&lt;strong&gt; (&amp;#39;PE&amp;#39;) examination, testing the applicant&amp;#39;s knowledge and skills in a chosen engineering discipline (mechanical, electrical, civil, for example), as well as &lt;/strong&gt;&lt;/em&gt;&lt;a href="http://en.wikipedia.org/wiki/Engineering_ethics"&gt;&lt;em&gt;&lt;strong&gt;engineering ethics&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;em&gt;&lt;strong&gt;. &lt;/strong&gt;&lt;/em&gt;&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;For software engineering there is no similar accreditation process. Any Mort i.e (NOOB) with $500.00 and the ability to hit the keyboard with his/her forehead&amp;#160; can become a software engineer overnight.&amp;#160; &amp;quot;Yesterday I couldn&amp;#39;t spell it. Now I are one&amp;quot;. This has got to stop. &lt;/p&gt;  &lt;p&gt;A few weeks ago I came across a commentary made by my friend Billy Hollis in Visual Studio Magazine &lt;a href="http://visualstudiomagazine.com/columns/article.aspx?editorialsid=2952" target="_blank"&gt;Commentary: Is Agile Rock or Disco&lt;/a&gt;. In this commentary Billy mentions the following:&lt;/p&gt;  &lt;p align="center"&gt;&lt;em&gt;&lt;strong&gt;The Patterns and Practices group at Microsoft is heavily into agile development. Don Smith is in that group, and, at a conference last May, he said, &amp;quot;It&amp;#39;s hard to do agile without really good developers.&amp;quot; I&amp;#39;ve heard variations of the same thing said from others. &lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p align="center"&gt;&lt;em&gt;&lt;strong&gt;But not all developers are that good. Therefore, if Don is right, then agile isn&amp;#39;t for everyone. &lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt; The second statement is the core problem we face. It raises the white flag of surrender to all the half ass coders out there. Why shouldn&amp;#39;t we all strive to be good developers? Why is average acceptable? What does the author propose we do with the average programmer? &lt;/p&gt;  &lt;p&gt;Because programmers are less than good (LTG) does he propose we have no process whatsoever? It&amp;#39;s because of these LTG developers we need agile practices more not less. I want to point out something carefully at this point. &lt;em&gt;&lt;strong&gt;It&amp;#39;s agile practices... not agile&lt;/strong&gt;&lt;/em&gt;! There is no push button template&amp;#160; you can use and whoosh you are an agile coder or development shop. Nope agile is a set of principles and practices. &lt;/p&gt;  &lt;p&gt;Adopting agile principles is not quick or easy. It is a lifetime commitment that takes lots of study, practice, mentoring, and continuous education and improvement. There are lots of new terms, concepts and practices to examine, consider and implement. Every company and situation is different and there are a number of useful practices to adopt.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Agile Adoption&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;In the last year we have moves very heavily from our old RAD way of doing development to a more agile one.&amp;#160; Our goal in this process was to change how we design and develop software in a quality manner. These are the tools and practices we have adopted.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Shared State Source Control&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The first practice we adopted was changing from a pessimistic style of source code control into a shared state source code control system. It made no sense to limit a source code file to a single developer (the default behavior of Visual Sourcesafe). We moved to Subversion. Subversion is an industry standard source code control system that&amp;#39;s default behavior is multiple developers working on the same files and merging conflicts.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Automated Builds&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Another principle of agile we have adopted is that of automated builds. Another terms for this is Continuous Integration.&amp;#160; Whenever source code is committed to our repository an automated build fires off, checks out all the code, compiles it and runs a suite of automated tests.&amp;#160; Our goal is to find whether or not our code is in a Red (bad) state or Green (good) state.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Test Driven Development and Design&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Of all practices in agile I find this one to provide the most value.&amp;#160; Any software you build should be accompanied by a suite of tests to verify its long term quality and&amp;#160; integrity.&amp;#160; The ultimate goal of TDD is a good design.&amp;#160; While test driven development does not insure a good design your chances are better that your designs are more sound if they can be tested in an automated way. &lt;/p&gt;  &lt;p&gt;I had a conversation with &lt;a href="http://blog.scottbellware.com/" target="_blank"&gt;Scott Bellware&lt;/a&gt; and &lt;a href="http://www.lostechies.com/blogs/chad_myers/default.aspx" target="_blank"&gt;Chad Myers&lt;/a&gt; last night. We were discussing testing nomenclatures and Chad Developed this list of test types:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Proofs&amp;#160; - Code performs as expected. &lt;/li&gt;    &lt;li&gt;Examples of Client Access (API testing) - API Proving with tests. &lt;/li&gt;    &lt;li&gt;Specification (BDD) - Documenting intent. &lt;/li&gt;    &lt;li&gt;Contract Enforcement/Change Confidence - Regression testing &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;As you can see these nomenclatures provide you with a confidence that your code will work as expected, has its intent documented and allows for long term changeability inherent in all software development.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Pair Programming and Mentoring&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Union plumbers and electricians go through extensive apprenticeships before they are accepted&amp;#160; as journeymen. Software engineers should adopt similar practices. Pair programming facilitates knowledge transfer from master to apprentice,&amp;#160; mentor to student and in lots of cases from student to mentor. In the last year I have spent a lot of time discussing these practices with a number of different people I consider my mentors. My mentor list includes &lt;a href="http://blog.scottbellware.com/" target="_blank"&gt;Scott Bellware&lt;/a&gt;, &lt;a href="http://codebetter.com/blogs/jeremy.miller/default.aspx" target="_blank"&gt;Jeremy Miller&lt;/a&gt;, &lt;a href="http://www.lostechies.com/blogs/chad_myers/default.aspx" target="_blank"&gt;Chad Myers&lt;/a&gt;, &lt;a href="http://jeffreypalermo.com/feed/" target="_blank"&gt;Jeffery Palermo&lt;/a&gt; and numerous others. These practices are not always obvious or simple so it is a good idea to have a network of mentors to rely on. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Adoption of Dependency Patterns&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;One aspect of building testable systems is reduction of&amp;#160; development friction. One way to introduce friction is to tightly couple processes together by allowing them to instantiate there own resources internally.&amp;#160; It may seem strange&amp;#160; but information hiding is not necessarily a good practice in the agile space. The concept behind dependency injection is this: if a component or method has a dependency on another class, then&amp;#160; that dependency should be passed (injected) into the consumer.&amp;#160; This give you untold flexibility when it&amp;#160; comes to configuring and reconfiguring your systems. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Daily Stand Ups&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;In agile development a common set of practices revolve around daily developer meetings also known as stand ups. Every day developers stand in a circle, stands at there desks or in the hallway and talk about two items:&amp;#160; what the did yesterday and what they plan on doing today. This&amp;#160; has the benefit of keeping all&amp;#160; developers in the loop and facilitating communication.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Small Iterations&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;We all know that estimating timelines on most software projects is a fools errand.&amp;#160; Software estimates follow share a common trait with metrological predictions the shorter the span or time the more accurate the estimate is likely to be. Agile practices acknowledge this as a core principle.&amp;#160; Your applications should be developed in short sprints.&amp;#160; At the end of each sprint there should be &amp;quot;show and tell&amp;quot; for the client that demonstrates the deliverables for that sprint. After the sprint and accompanying demo the next sprint should be planned. And its rinse lather repeat from there. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;While not definitive this list is a good start to moving you or your development team closer to being professional software engineers. When you are evaluating a client, consultancy or even a potential employer consider the practices discussed in the list.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Do you think your a great coder or do you think your development shop is top notch? I challenge you to prove it. Can you develop quality software that stands the test of time ? Do you have software you can modify with a high level of confidence that your modifications don&amp;#39;t introduce software regressions? Can you repeat and improve on your successes? Do you have the processes in place that make this a possibility? When you can answer in the affirmative to some or all&amp;#160; of these questions you are closer to being a true software engineering shop.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=186915" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/rodpaddock/archive/tags/TDD/default.aspx">TDD</category><category domain="http://codebetter.com/blogs/rodpaddock/archive/tags/Agile/default.aspx">Agile</category></item><item><title>Twitter Conversations : First Refactoring</title><link>http://codebetter.com/blogs/rodpaddock/archive/2008/12/19/twitter-conversations-first-refactoring.aspx</link><pubDate>Sat, 20 Dec 2008 04:29:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:186473</guid><dc:creator>Rod Paddock [MVP]</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/rodpaddock/rsscomments.aspx?PostID=186473</wfw:commentRss><comments>http://codebetter.com/blogs/rodpaddock/archive/2008/12/19/twitter-conversations-first-refactoring.aspx#comments</comments><description>&lt;p&gt;Thanks for the feedback and encouragement so far. This project has been fun and I hope you keep enjoying it so far.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Refactoring Required&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;I knew going in that the first cut of this application needed some serious refactoring. The project had dependencies on internet connections , numerous classes contained redundant code and the user interface was lacking. In this first set of refactorings I hope to demonstrate how you can design your applications to be more testable and how to make the code cleaner at the same time. I will also attempt to make the UI better with my feeble UI skills.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;First Refactoring: Extracting Interfaces&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;The first cut of the Twitter Conversations application took a dependency on being connected to the Internet for testing. In order to remove this dependency I decided to extract the an interface from the Twitter.Communications.TwitterRequest class. This process is simple&amp;nbsp; when using a tool like ReSharper. I simply opened the class source code file, Right Clicked, Selected Refactor-&amp;gt;Extract Interface from the popup menu. The following screen shows the Extract Interface dialog from ReSharper.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://codebetter.com/blogs/rodpaddock/TwitterConversationRefactor_7BE70DBD.png"&gt;&lt;img title="TwitterConversationRefactor" style="BORDER-TOP-WIDTH:0px;DISPLAY:inline;BORDER-LEFT-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-RIGHT-WIDTH:0px;" height="328" alt="TwitterConversationRefactor" src="http://codebetter.com/blogs/rodpaddock/TwitterConversationRefactor_thumb_3A6C5B64.png" width="478" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;This process yielded the following interface&lt;/p&gt;
&lt;div style="BORDER-RIGHT:gray 1px solid;PADDING-RIGHT:4px;BORDER-TOP:gray 1px solid;PADDING-LEFT:4px;FONT-SIZE:8pt;PADDING-BOTTOM:4px;MARGIN:20px 0px 10px;OVERFLOW:auto;BORDER-LEFT:gray 1px solid;WIDTH:97.5%;CURSOR:text;MAX-HEIGHT:200px;LINE-HEIGHT:12pt;PADDING-TOP:4px;BORDER-BOTTOM:gray 1px solid;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BACKGROUND-COLOR:#f4f4f4;"&gt;
&lt;div style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   1:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;interface&lt;/span&gt; ITwitterRequest&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   2:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt; GetTwitterRequest(&lt;span style="COLOR:#0000ff;"&gt;ByVal&lt;/span&gt; URL &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;String&lt;/span&gt;) &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;String&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   3:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;end&lt;/span&gt; interface&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;After refactoring the interface from the Twitter.Communication.TwitterRequest class I created a new Twitter.Interfaces project. This project would all interfaces for this project including another new interface ITwitterCredentials. I created the ITwitterCredentials interface in order to provide a slightly cleaner design for creating instances of the TwitterRequest class.&lt;/p&gt;
&lt;div style="BORDER-RIGHT:gray 1px solid;PADDING-RIGHT:4px;BORDER-TOP:gray 1px solid;PADDING-LEFT:4px;FONT-SIZE:8pt;PADDING-BOTTOM:4px;MARGIN:20px 0px 10px;OVERFLOW:auto;BORDER-LEFT:gray 1px solid;WIDTH:97.5%;CURSOR:text;MAX-HEIGHT:200px;LINE-HEIGHT:12pt;PADDING-TOP:4px;BORDER-BOTTOM:gray 1px solid;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BACKGROUND-COLOR:#f4f4f4;"&gt;
&lt;div style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   1:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Interface&lt;/span&gt; ITwitterCredential&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   2:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Property&lt;/span&gt; UserName() &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;String&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   3:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Property&lt;/span&gt; Password() &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;String&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   4:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Interface&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Once I created the ITwitterCredentials interface I implemented it on a new class Twitter.Communication.TwitterCredentials. I also needed to refactor the guts of the TwitterRequest class. The new code for this class now looks like:&lt;/p&gt;
&lt;div style="BORDER-RIGHT:gray 1px solid;PADDING-RIGHT:4px;BORDER-TOP:gray 1px solid;PADDING-LEFT:4px;FONT-SIZE:8pt;PADDING-BOTTOM:4px;MARGIN:20px 0px 10px;OVERFLOW:auto;BORDER-LEFT:gray 1px solid;WIDTH:97.5%;CURSOR:text;MAX-HEIGHT:200px;LINE-HEIGHT:12pt;PADDING-TOP:4px;BORDER-BOTTOM:gray 1px solid;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;HEIGHT:259px;BACKGROUND-COLOR:#f4f4f4;"&gt;
&lt;div style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   1:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Class&lt;/span&gt; TwitterRequest&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   2:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Implements&lt;/span&gt; Twitter.Interfaces.ITwitterRequest&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   3:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Private&lt;/span&gt; _Credentials &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Twitter.Interfaces.ITwitterCredential&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   4:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   5:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Sub&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt;(&lt;span style="COLOR:#0000ff;"&gt;ByVal&lt;/span&gt; Credentials &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Twitter.Interfaces.ITwitterCredential)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   6:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;._Credentials = Credentials&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   7:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Sub&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   8:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   9:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt; GetTwitterRequest(&lt;span style="COLOR:#0000ff;"&gt;ByVal&lt;/span&gt; URL &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;String&lt;/span&gt;) &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;String&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Implements&lt;/span&gt; Twitter.Interfaces.ITwitterRequest.GetTwitterRequest&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  10:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; Credentials &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt; NetworkCredential(&lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;._Credentials.UserName, &lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;._Credentials.Password)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  11:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  12:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; Request &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; HttpWebRequest = HttpWebRequest.Create(URL)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  13:&lt;/span&gt;         Request.Method = &lt;span style="COLOR:#006080;"&gt;&amp;quot;POST&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  14:&lt;/span&gt;         Request.Credentials = Credentials&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  15:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  16:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; Response &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; WebResponse = Request.GetResponse&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  17:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; Reader &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt; StreamReader(Response.GetResponseStream)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  18:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; Results &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;String&lt;/span&gt; = Reader.ReadToEnd&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  19:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;Return&lt;/span&gt; Results&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  20:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  21:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  22:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Class&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;After extracting these interfaces I changed the constructors for Twitter.API.User and Twitter.Message.API to receive an ITwitterRequest rather than a concrete class.The following code demonstrates the constructor for the Twitter.API.User class.&lt;/p&gt;
&lt;div style="BORDER-RIGHT:gray 1px solid;PADDING-RIGHT:4px;BORDER-TOP:gray 1px solid;PADDING-LEFT:4px;FONT-SIZE:8pt;PADDING-BOTTOM:4px;MARGIN:20px 0px 10px;OVERFLOW:auto;BORDER-LEFT:gray 1px solid;WIDTH:97.5%;CURSOR:text;MAX-HEIGHT:200px;LINE-HEIGHT:12pt;PADDING-TOP:4px;BORDER-BOTTOM:gray 1px solid;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BACKGROUND-COLOR:#f4f4f4;"&gt;
&lt;div style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   1:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Class&lt;/span&gt; User&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   2:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   3:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; Communicator &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Twitter.Interfaces.ITwitterRequest = &lt;span style="COLOR:#0000ff;"&gt;Nothing&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   4:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; JsonSerializer &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt; System.Web.Script.Serialization.JavaScriptSerializer&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   5:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   6:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Sub&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt;(&lt;span style="COLOR:#0000ff;"&gt;ByVal&lt;/span&gt; TwitterCommunicator &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Twitter.Interfaces.ITwitterRequest)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   7:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.Communicator = TwitterCommunicator&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   8:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Sub&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Of course at this point all of our tests were broken but I waited to do a little more refactoring before fixing the tests. &lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Second Refactoring: Creating the Disconnected Twitter Service&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;The next step in the process was to create a disconnected version of Twitter. To accomplish this I took the following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Extracted JSON strings from the various calls to Twitter and put them into our testing project as embedded resource files. &lt;/li&gt;
&lt;li&gt;Added code to the testing project that could be used to extract the embedded text files &lt;/li&gt;
&lt;li&gt;Implemented the ITwitterRequest interface on a new class called TwitterRequestMock. &lt;/li&gt;
&lt;li&gt;Implemented the function GetTwitterRequest to return the appropriate text resource based on the URL. &lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;The first item on the list was to extract the JSON data from actual calls to Twitter. To satisfy the unit tests I created three file extracts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;singleuser.txt&amp;nbsp; - Contains the information for my user account &lt;/li&gt;
&lt;li&gt;friends.txt – A list of people I follow &lt;/li&gt;
&lt;li&gt;messages.txt – A list of twitter updates &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;All three of these files were marked as Embedded Resource files in the Visual Studio project.&lt;/p&gt;
&lt;p&gt;The next step was to add code that would allow these files to be extracted from the testing assembly. the following code extracts resources from the currently running assembly (i.e. our unit tests)&lt;/p&gt;
&lt;div style="BORDER-RIGHT:gray 1px solid;PADDING-RIGHT:4px;BORDER-TOP:gray 1px solid;PADDING-LEFT:4px;FONT-SIZE:8pt;PADDING-BOTTOM:4px;MARGIN:20px 0px 10px;OVERFLOW:auto;BORDER-LEFT:gray 1px solid;WIDTH:97.5%;CURSOR:text;MAX-HEIGHT:200px;LINE-HEIGHT:12pt;PADDING-TOP:4px;BORDER-BOTTOM:gray 1px solid;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BACKGROUND-COLOR:#f4f4f4;"&gt;
&lt;div style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   1:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Imports&lt;/span&gt; System.IO&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   2:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Imports&lt;/span&gt; System.Reflection&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   3:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   4:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Class&lt;/span&gt; ObjectMother&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   5:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Shared&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt; GetEmbeddedResource(&lt;span style="COLOR:#0000ff;"&gt;ByVal&lt;/span&gt; ResourceName &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;String&lt;/span&gt;) &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;String&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   6:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; ResStream &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Stream = System.Reflection.&lt;span style="COLOR:#0000ff;"&gt;Assembly&lt;/span&gt;.GetExecutingAssembly.GetManifestResourceStream(ResourceName)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   7:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; oStreamReader &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt; StreamReader(ResStream)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   8:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; RetVal &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;String&lt;/span&gt; = oStreamReader.ReadToEnd&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   9:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;Return&lt;/span&gt; RetVal&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  10:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  11:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Class&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Finally a new class TwitterRequestMock was created. The purpose of this class was to return the proper embedded resource files based on the URL passed to a request. The following code demonstrates the implementation of this:&lt;/p&gt;
&lt;div style="BORDER-RIGHT:gray 1px solid;PADDING-RIGHT:4px;BORDER-TOP:gray 1px solid;PADDING-LEFT:4px;FONT-SIZE:8pt;PADDING-BOTTOM:4px;MARGIN:20px 0px 10px;OVERFLOW:auto;BORDER-LEFT:gray 1px solid;WIDTH:97.5%;CURSOR:text;MAX-HEIGHT:200px;LINE-HEIGHT:12pt;PADDING-TOP:4px;BORDER-BOTTOM:gray 1px solid;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BACKGROUND-COLOR:#f4f4f4;"&gt;
&lt;div style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   1:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Class&lt;/span&gt; TwitterRequestMock&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   2:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Implements&lt;/span&gt; Twitter.Interfaces.ITwitterRequest&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   3:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   4:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Private&lt;/span&gt; _Credentials &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Twitter.Interfaces.ITwitterCredential&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   5:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   6:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Sub&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt;(&lt;span style="COLOR:#0000ff;"&gt;ByVal&lt;/span&gt; Credentials &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Twitter.Interfaces.ITwitterCredential)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   7:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;._Credentials = Credentials&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   8:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Sub&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   9:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  10:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt; GetTwitterRequest(&lt;span style="COLOR:#0000ff;"&gt;ByVal&lt;/span&gt; URL &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;String&lt;/span&gt;) &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;String&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Implements&lt;/span&gt; Interfaces.ITwitterRequest.GetTwitterRequest&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  11:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; ReturnValue &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;String&lt;/span&gt; = &lt;span style="COLOR:#006080;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  12:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  13:&lt;/span&gt;         &lt;span style="COLOR:#008000;"&gt;&amp;#39;-- urls we use so far&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  14:&lt;/span&gt;         &lt;span style="COLOR:#008000;"&gt;&amp;#39;Const UserMessageURL As String = &amp;quot;http://twitter.com/statuses/user_timeline/&amp;lt;&amp;lt;USERID&amp;gt;&amp;gt;.json&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  15:&lt;/span&gt;         &lt;span style="COLOR:#008000;"&gt;&amp;#39;Const MyMessagesURL As String = &amp;quot;http://twitter.com/statuses/friends_timeline.json?count=200&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  16:&lt;/span&gt;         &lt;span style="COLOR:#008000;"&gt;&amp;#39;Const FriendsURL As String = &amp;quot;http://twitter.com/statuses/friends.json&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  17:&lt;/span&gt;         &lt;span style="COLOR:#008000;"&gt;&amp;#39;Const GetUserURL As String = &amp;quot;http://twitter.com/users/show/&amp;lt;&amp;lt;USERID&amp;gt;&amp;gt;.json&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  18:&lt;/span&gt;         &lt;span style="COLOR:#008000;"&gt;&amp;#39;Const CredentialURL As String = &amp;quot;http://twitter.com/account/verify_credentials.json&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  19:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  20:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;If&lt;/span&gt; URL.Contains(&lt;span style="COLOR:#006080;"&gt;&amp;quot;verify_credentials&amp;quot;&lt;/span&gt;) &lt;span style="COLOR:#0000ff;"&gt;OrElse&lt;/span&gt; URL.Contains(&lt;span style="COLOR:#006080;"&gt;&amp;quot;users/show/&amp;quot;&lt;/span&gt;) &lt;span style="COLOR:#0000ff;"&gt;Then&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  21:&lt;/span&gt;             ReturnValue = ObjectMother.GetEmbeddedResource(&lt;span style="COLOR:#006080;"&gt;&amp;quot;Twitter.UnitTests.singleuser.txt&amp;quot;&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  22:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;ElseIf&lt;/span&gt; URL.Contains(&lt;span style="COLOR:#006080;"&gt;&amp;quot;friends_timeline&amp;quot;&lt;/span&gt;) &lt;span style="COLOR:#0000ff;"&gt;OrElse&lt;/span&gt; URL.Contains(&lt;span style="COLOR:#006080;"&gt;&amp;quot;user_timeline&amp;quot;&lt;/span&gt;) &lt;span style="COLOR:#0000ff;"&gt;Then&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  23:&lt;/span&gt;             ReturnValue = ObjectMother.GetEmbeddedResource(&lt;span style="COLOR:#006080;"&gt;&amp;quot;Twitter.UnitTests.messages.txt&amp;quot;&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  24:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;ElseIf&lt;/span&gt; URL.Contains(&lt;span style="COLOR:#006080;"&gt;&amp;quot;friends.json&amp;quot;&lt;/span&gt;) &lt;span style="COLOR:#0000ff;"&gt;Then&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  25:&lt;/span&gt;             ReturnValue = ObjectMother.GetEmbeddedResource(&lt;span style="COLOR:#006080;"&gt;&amp;quot;Twitter.UnitTests.friends.txt&amp;quot;&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  26:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;If&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  27:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  28:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;Return&lt;/span&gt; ReturnValue&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  29:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  30:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Class&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;I discussed this method with &lt;a href="http://codebetter.com/blogs/jeremy.miller/default.aspx" target="_blank"&gt;Jeremy Miller&lt;/a&gt; and his comment was if possible the text for the JSON strings should be embedded into the unit test if at all possible. I didn’t follow this recommendation because the JSON returns strings are long and very ugly. What are your thoughts on this ?&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Third Refactoring: Fixing the Unit Tests&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Once this class was implemented I went in and fixed up the unit tests. This was actually pretty simple. Basically I refactored the constructor and &amp;lt;Setup()&amp;gt; of the UnitTests class.&lt;/p&gt;
&lt;div style="BORDER-RIGHT:gray 1px solid;PADDING-RIGHT:4px;BORDER-TOP:gray 1px solid;PADDING-LEFT:4px;FONT-SIZE:8pt;PADDING-BOTTOM:4px;MARGIN:20px 0px 10px;OVERFLOW:auto;BORDER-LEFT:gray 1px solid;WIDTH:97.5%;CURSOR:text;MAX-HEIGHT:200px;LINE-HEIGHT:12pt;PADDING-TOP:4px;BORDER-BOTTOM:gray 1px solid;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;HEIGHT:269px;BACKGROUND-COLOR:#f4f4f4;"&gt;
&lt;div style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   1:&lt;/span&gt; &amp;lt;TestFixture()&amp;gt; _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   2:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Class&lt;/span&gt; UnitTests&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   3:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   4:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; UserAPI &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Twitter.API.User = &lt;span style="COLOR:#0000ff;"&gt;Nothing&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   5:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; MessageAPI &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Twitter.API.Message = &lt;span style="COLOR:#0000ff;"&gt;Nothing&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   6:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; Communicator &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Twitter.Interfaces.ITwitterRequest = &lt;span style="COLOR:#0000ff;"&gt;Nothing&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   7:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   8:&lt;/span&gt;     &amp;lt;SetUp()&amp;gt; _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   9:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Sub&lt;/span&gt; Setup()&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  10:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.Communicator = &lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt; TwitterRequestMock(&lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt; Twitter.Communication.TwitterCredentials)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  11:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  12:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.UserAPI = &lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt; Twitter.API.User(&lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.Communicator)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  13:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.MessageAPI = &lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt; Twitter.API.Message(&lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.Communicator)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  14:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now the tests for this application can be run in a disconnected mode.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Fourth Refactoring: Removing Redundant Code&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;The next step in this refactoring process was to clean up redundant code from the Twitter.API.User and Twitter.API.Message classes. In the first version each method was responsible for parsing data and creating collections of Messages and Users. The code started like the following snippet:&lt;/p&gt;
&lt;div style="BORDER-RIGHT:gray 1px solid;PADDING-RIGHT:4px;BORDER-TOP:gray 1px solid;PADDING-LEFT:4px;FONT-SIZE:8pt;PADDING-BOTTOM:4px;MARGIN:20px 0px 10px;OVERFLOW:auto;BORDER-LEFT:gray 1px solid;WIDTH:97.5%;CURSOR:text;MAX-HEIGHT:200px;LINE-HEIGHT:12pt;PADDING-TOP:4px;BORDER-BOTTOM:gray 1px solid;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BACKGROUND-COLOR:#f4f4f4;"&gt;
&lt;div style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   1:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt; GetUserMessages(&lt;span style="COLOR:#0000ff;"&gt;ByVal&lt;/span&gt; UserID &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;String&lt;/span&gt;) &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Twitter.Domain.Message()&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   2:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; ReturnMessages &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt; List(Of Twitter.Domain.Message)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   3:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   4:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; UserObjects &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Object&lt;/span&gt; = JsonSerializer.DeserializeObject(&lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.Communicator.GetTwitterRequest(UserMessageURL.Replace(&lt;span style="COLOR:#006080;"&gt;&amp;quot;&amp;lt;&amp;lt;USERID&amp;gt;&amp;gt;&amp;quot;&lt;/span&gt;, UserID)))&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   5:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   6:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;For&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Each&lt;/span&gt; UserObject &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Object&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;In&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;CType&lt;/span&gt;(UserObjects, Array)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   7:&lt;/span&gt;         ReturnMessages.Add(&lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt; Twitter.Domain.Message &lt;span style="COLOR:#0000ff;"&gt;With&lt;/span&gt; { _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   8:&lt;/span&gt;                            .MessageID = UserObject(&lt;span style="COLOR:#006080;"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;), _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   9:&lt;/span&gt;                            .MessageDate = UserObject(&lt;span style="COLOR:#006080;"&gt;&amp;quot;created_at&amp;quot;&lt;/span&gt;), _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  10:&lt;/span&gt;                            .MessageContent = UserObject(&lt;span style="COLOR:#006080;"&gt;&amp;quot;text&amp;quot;&lt;/span&gt;), _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  11:&lt;/span&gt;                            .UserID = UserObject(&lt;span style="COLOR:#006080;"&gt;&amp;quot;user&amp;quot;&lt;/span&gt;)(&lt;span style="COLOR:#006080;"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;), _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  12:&lt;/span&gt;                            .UserName = UserObject(&lt;span style="COLOR:#006080;"&gt;&amp;quot;user&amp;quot;&lt;/span&gt;)(&lt;span style="COLOR:#006080;"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;), _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  13:&lt;/span&gt;                            .ImageURL = UserObject(&lt;span style="COLOR:#006080;"&gt;&amp;quot;user&amp;quot;&lt;/span&gt;)(&lt;span style="COLOR:#006080;"&gt;&amp;quot;profile_image_url&amp;quot;&lt;/span&gt;)})&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  14:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Next&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  15:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Return&lt;/span&gt; ReturnMessages.ToArray&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  16:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  17:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The redundant code is the code contained in the For loop. I decided to extract this code into its own method.&lt;/p&gt;
&lt;div style="BORDER-RIGHT:gray 1px solid;PADDING-RIGHT:4px;BORDER-TOP:gray 1px solid;PADDING-LEFT:4px;FONT-SIZE:8pt;PADDING-BOTTOM:4px;MARGIN:20px 0px 10px;OVERFLOW:auto;BORDER-LEFT:gray 1px solid;WIDTH:97.5%;CURSOR:text;MAX-HEIGHT:200px;LINE-HEIGHT:12pt;PADDING-TOP:4px;BORDER-BOTTOM:gray 1px solid;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BACKGROUND-COLOR:#f4f4f4;"&gt;
&lt;div style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   1:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Sub&lt;/span&gt; PopulateMessages(&lt;span style="COLOR:#0000ff;"&gt;ByVal&lt;/span&gt; ListToPopulate &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; List(Of Twitter.Domain.Message), &lt;span style="COLOR:#0000ff;"&gt;ByVal&lt;/span&gt; Contents &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Object&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   2:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;For&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Each&lt;/span&gt; UserObject &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Object&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;In&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;CType&lt;/span&gt;(Contents, Array)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   3:&lt;/span&gt;             ListToPopulate.Add(&lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt; Twitter.Domain.Message &lt;span style="COLOR:#0000ff;"&gt;With&lt;/span&gt; { _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   4:&lt;/span&gt;                                .MessageID = UserObject(&lt;span style="COLOR:#006080;"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;), _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   5:&lt;/span&gt;                                .MessageDate = UserObject(&lt;span style="COLOR:#006080;"&gt;&amp;quot;created_at&amp;quot;&lt;/span&gt;), _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   6:&lt;/span&gt;                                .MessageContent = UserObject(&lt;span style="COLOR:#006080;"&gt;&amp;quot;text&amp;quot;&lt;/span&gt;), _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   7:&lt;/span&gt;                                .UserID = UserObject(&lt;span style="COLOR:#006080;"&gt;&amp;quot;user&amp;quot;&lt;/span&gt;)(&lt;span style="COLOR:#006080;"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;), _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   8:&lt;/span&gt;                                .UserName = UserObject(&lt;span style="COLOR:#006080;"&gt;&amp;quot;user&amp;quot;&lt;/span&gt;)(&lt;span style="COLOR:#006080;"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;), _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   9:&lt;/span&gt;                                .ImageURL = UserObject(&lt;span style="COLOR:#006080;"&gt;&amp;quot;user&amp;quot;&lt;/span&gt;)(&lt;span style="COLOR:#006080;"&gt;&amp;quot;profile_image_url&amp;quot;&lt;/span&gt;)})&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  10:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  11:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;Next&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  12:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Now the code for parsing off message looks like this:&lt;/p&gt;
&lt;div style="BORDER-RIGHT:gray 1px solid;PADDING-RIGHT:4px;BORDER-TOP:gray 1px solid;PADDING-LEFT:4px;FONT-SIZE:8pt;PADDING-BOTTOM:4px;MARGIN:20px 0px 10px;OVERFLOW:auto;BORDER-LEFT:gray 1px solid;WIDTH:97.5%;CURSOR:text;MAX-HEIGHT:200px;LINE-HEIGHT:12pt;PADDING-TOP:4px;BORDER-BOTTOM:gray 1px solid;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BACKGROUND-COLOR:#f4f4f4;"&gt;
&lt;div style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   1:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt; GetUserMessages(&lt;span style="COLOR:#0000ff;"&gt;ByVal&lt;/span&gt; UserID &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;String&lt;/span&gt;) &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Twitter.Domain.Message()&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   2:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; ReturnMessages &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt; List(Of Twitter.Domain.Message)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   3:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; UserObjects &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Object&lt;/span&gt; = JsonSerializer.DeserializeObject(&lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.Communicator.GetTwitterRequest(UserMessageURL.Replace(&lt;span style="COLOR:#006080;"&gt;&amp;quot;&amp;lt;&amp;lt;USERID&amp;gt;&amp;gt;&amp;quot;&lt;/span&gt;, UserID)))&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   4:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.PopulateMessages(ReturnMessages, UserObjects)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   5:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Return&lt;/span&gt; ReturnMessages.ToArray&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   6:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The Twitter.API.User Class is had a slightly different refactoring. Because this API returns a lot of single user information it was necessary to create a function to return a single user object. When a method returned multiople user records a looping structure similar to the one for messages was used.&lt;/p&gt;
&lt;div style="BORDER-RIGHT:gray 1px solid;PADDING-RIGHT:4px;BORDER-TOP:gray 1px solid;PADDING-LEFT:4px;FONT-SIZE:8pt;PADDING-BOTTOM:4px;MARGIN:20px 0px 10px;OVERFLOW:auto;BORDER-LEFT:gray 1px solid;WIDTH:97.5%;CURSOR:text;MAX-HEIGHT:200px;LINE-HEIGHT:12pt;PADDING-TOP:4px;BORDER-BOTTOM:gray 1px solid;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BACKGROUND-COLOR:#f4f4f4;"&gt;
&lt;div style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   1:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt; GetUsers() &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Twitter.Domain.User()&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   2:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; Users &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt; List(Of Twitter.Domain.User)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   3:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; UserObjects &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Object&lt;/span&gt; = JsonSerializer.DeserializeObject(&lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.Communicator.GetTwitterRequest(FriendsURL))&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   4:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.PopulateUsers(Users, UserObjects)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   5:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Return&lt;/span&gt; Users.ToArray&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   6:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   7:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   8:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt; GetUser(&lt;span style="COLOR:#0000ff;"&gt;ByVal&lt;/span&gt; id &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;String&lt;/span&gt;) &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Twitter.Domain.User&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   9:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; Users &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt; List(Of Twitter.Domain.User)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  10:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; UserObject &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Object&lt;/span&gt; = JsonSerializer.DeserializeObject(&lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.Communicator.GetTwitterRequest(GetUserURL.Replace(&lt;span style="COLOR:#006080;"&gt;&amp;quot;&amp;lt;&amp;lt;USERID&amp;gt;&amp;gt;&amp;quot;&lt;/span&gt;, id.ToString)))&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  11:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Return&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.GetUserFromObject(UserObject)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  12:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  13:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt; GetMyUser() &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Twitter.Domain.User&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  14:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; UserObject &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Object&lt;/span&gt; = JsonSerializer.DeserializeObject(&lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.Communicator.GetTwitterRequest(CredentialURL))&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  15:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Return&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.GetUserFromObject(UserObject)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  16:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  17:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt; GetUserFromObject(&lt;span style="COLOR:#0000ff;"&gt;ByVal&lt;/span&gt; UserObject &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Object&lt;/span&gt;) &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Twitter.Domain.User&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  18:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Return&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt; Twitter.Domain.User &lt;span style="COLOR:#0000ff;"&gt;With&lt;/span&gt; { _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  19:&lt;/span&gt;       .UserID = UserObject(&lt;span style="COLOR:#006080;"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;), _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  20:&lt;/span&gt;       .UserName = UserObject(&lt;span style="COLOR:#006080;"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;), _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  21:&lt;/span&gt;       .ScreenName = UserObject(&lt;span style="COLOR:#006080;"&gt;&amp;quot;screen_name&amp;quot;&lt;/span&gt;), _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  22:&lt;/span&gt;       .ImageURL = UserObject(&lt;span style="COLOR:#006080;"&gt;&amp;quot;profile_image_url&amp;quot;&lt;/span&gt;), _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  23:&lt;/span&gt;       .Followers = UserObject(&lt;span style="COLOR:#006080;"&gt;&amp;quot;followers_count&amp;quot;&lt;/span&gt;)}&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  24:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  25:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Sub&lt;/span&gt; PopulateUsers(&lt;span style="COLOR:#0000ff;"&gt;ByVal&lt;/span&gt; ListToPopulate &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; List(Of Twitter.Domain.User), &lt;span style="COLOR:#0000ff;"&gt;ByVal&lt;/span&gt; Contents &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Object&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  26:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;For&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Each&lt;/span&gt; UserObject &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Object&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;In&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;CType&lt;/span&gt;(Contents, Array)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  27:&lt;/span&gt;         ListToPopulate.Add(&lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.GetUserFromObject(UserObject))&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  28:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Next&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  29:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The nice thing about these refactoring is that when a new property is added to a domain object you only need to change the code in one place.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Fourth Refactoring: The WPF Interface&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;The final refactoring I added was to implement a slightly improved interface.&amp;nbsp; This basically consisted of changing the code that calls the Twitter API’s we write and adding three user interface elements. The elements added to the screen consisted of two fields for capturing username and password respectively and a new display element for the showing the Twitter users image. The VB code and XAML code now looks like this:&lt;/p&gt;
&lt;div style="BORDER-RIGHT:gray 1px solid;PADDING-RIGHT:4px;BORDER-TOP:gray 1px solid;PADDING-LEFT:4px;FONT-SIZE:8pt;PADDING-BOTTOM:4px;MARGIN:20px 0px 10px;OVERFLOW:auto;BORDER-LEFT:gray 1px solid;WIDTH:97.5%;CURSOR:text;MAX-HEIGHT:200px;LINE-HEIGHT:12pt;PADDING-TOP:4px;BORDER-BOTTOM:gray 1px solid;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BACKGROUND-COLOR:#f4f4f4;"&gt;
&lt;div style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   1:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Private&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Sub&lt;/span&gt; cmdGetThread_Click(&lt;span style="COLOR:#0000ff;"&gt;ByVal&lt;/span&gt; sender &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Object&lt;/span&gt;, &lt;span style="COLOR:#0000ff;"&gt;ByVal&lt;/span&gt; e &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; System.Windows.RoutedEventArgs) &lt;span style="COLOR:#0000ff;"&gt;Handles&lt;/span&gt; cmdGetThread.Click&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   2:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; Communicator &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Twitter.Interfaces.ITwitterRequest = &lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt; Twitter.Communication.TwitterRequest(&lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt; Twitter.Communication.TwitterCredentials &lt;span style="COLOR:#0000ff;"&gt;With&lt;/span&gt; {.UserName = &lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.txtUserName.Text, .Password = &lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.txtPassword.Password})&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   3:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.lstResults.ItemsSource = &lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.LoadConversation(&lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt; Twitter.API.Message(Communicator), &lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt; Twitter.API.User(Communicator), &lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.txtCriteria.Text)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   4:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Sub&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   5:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   6:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   7:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt; LoadConversation(&lt;span style="COLOR:#0000ff;"&gt;ByVal&lt;/span&gt; MessageAPI &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Twitter.API.Message, &lt;span style="COLOR:#0000ff;"&gt;ByVal&lt;/span&gt; UserAPI &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Twitter.API.User, &lt;span style="COLOR:#0000ff;"&gt;ByVal&lt;/span&gt; TextCriteria &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;String&lt;/span&gt;) &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Twitter.Domain.Message()&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   8:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   9:&lt;/span&gt;     &lt;span style="COLOR:#008000;"&gt;&amp;#39;-- create list of users from comma (,) delimited list of names in text box&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  10:&lt;/span&gt;     &lt;span style="COLOR:#008000;"&gt;&amp;#39;-- TODO we should scrub this&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  11:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; UserQuery &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;New&lt;/span&gt; List(Of Twitter.Domain.User)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  12:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;For&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Each&lt;/span&gt; UserName &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;String&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;In&lt;/span&gt; TextCriteria.Split(&lt;span style="COLOR:#006080;"&gt;&amp;quot;,&amp;quot;&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  13:&lt;/span&gt;         UserQuery.Add(UserAPI.GetUser(UserName))&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  14:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Next&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  15:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  16:&lt;/span&gt;     &lt;span style="COLOR:#008000;"&gt;&amp;#39;-- get messages for these users &lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  17:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; messages &lt;span style="COLOR:#0000ff;"&gt;As&lt;/span&gt; Twitter.Domain.Message() = MessageAPI.GetMultipleUserMessages(UserQuery.ToArray())&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  18:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  19:&lt;/span&gt;     &lt;span style="COLOR:#008000;"&gt;&amp;#39;-- filter messages based on who is in the contents&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  20:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Dim&lt;/span&gt; FilteredMessages = _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  21:&lt;/span&gt;        From Message _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  22:&lt;/span&gt;          &lt;span style="COLOR:#0000ff;"&gt;In&lt;/span&gt; messages _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  23:&lt;/span&gt;      Where MatchesCriteria(Message.MessageContent, &lt;span style="COLOR:#0000ff;"&gt;Me&lt;/span&gt;.txtCriteria.Text.Split(&lt;span style="COLOR:#006080;"&gt;&amp;quot;,&amp;quot;&lt;/span&gt;)) _&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  24:&lt;/span&gt;      Order By Message.MessageDate Descending&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  25:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  26:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;Return&lt;/span&gt; FilteredMessages.ToArray&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  27:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  28:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  29:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;Function&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div style="BORDER-RIGHT:gray 1px solid;PADDING-RIGHT:4px;BORDER-TOP:gray 1px solid;PADDING-LEFT:4px;FONT-SIZE:8pt;PADDING-BOTTOM:4px;MARGIN:20px 0px 10px;OVERFLOW:auto;BORDER-LEFT:gray 1px solid;WIDTH:97.5%;CURSOR:text;MAX-HEIGHT:200px;LINE-HEIGHT:12pt;PADDING-TOP:4px;BORDER-BOTTOM:gray 1px solid;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BACKGROUND-COLOR:#f4f4f4;"&gt;
&lt;div style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   1:&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;Grid&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;x:Name&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;LayoutRoot&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   2:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;StackPanel&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   3:&lt;/span&gt;             &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;StackPanel&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt;  &lt;span style="COLOR:#ff0000;"&gt;Orientation&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;Horizontal&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   4:&lt;/span&gt;                 &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;TextBlock&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;User Name&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;22&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;80&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   5:&lt;/span&gt;                 &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;TextBox&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;TextWrapping&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;Wrap&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;x:Name&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;txtUserName&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;151&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;27&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   6:&lt;/span&gt;                 &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;TextBlock&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;Password&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;22&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;67.957&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   7:&lt;/span&gt;                 &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;PasswordBox&lt;/span&gt;  &lt;span style="COLOR:#ff0000;"&gt;x:Name&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;txtPassword&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;143&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;27&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   8:&lt;/span&gt;             &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;StackPanel&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;   9:&lt;/span&gt;                         &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  10:&lt;/span&gt;             &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;StackPanel&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt;  &lt;span style="COLOR:#ff0000;"&gt;Orientation&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;Horizontal&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  11:&lt;/span&gt;             &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;TextBlock&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;Screen Names&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;22&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;80&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  12:&lt;/span&gt;             &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;TextBox&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;rodpaddock,bellware&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;TextWrapping&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;Wrap&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;x:Name&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;txtCriteria&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;500&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;22&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  13:&lt;/span&gt;             &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;Button&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Content&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;Get Thread&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;x:Name&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;cmdGetThread&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  14:&lt;/span&gt;             &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;StackPanel&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  15:&lt;/span&gt;             &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;StackPanel&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  16:&lt;/span&gt;                 &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;ScrollViewer&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;600&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  17:&lt;/span&gt;                 &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;ListBox&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;600&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;IsSynchronizedWithCurrentItem&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;True&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;x:Name&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;lstResults&amp;quot;&lt;/span&gt;    &lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  18:&lt;/span&gt;                     &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;ListBox.ItemTemplate&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  19:&lt;/span&gt;                         &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;DataTemplate&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  20:&lt;/span&gt;                             &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;StackPanel&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Orientation&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;Horizontal&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  21:&lt;/span&gt;                                 &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;Image&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;100&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;100&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Source&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;{Binding Path=ImageURL}&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  22:&lt;/span&gt;                                     &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;StackPanel&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  23:&lt;/span&gt;                                         &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;TextBlock&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;{Binding Path=MessageContent}&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  24:&lt;/span&gt;                                         &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;TextBlock&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;{Binding Path=MessageDate}&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  25:&lt;/span&gt;                                         &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;TextBlock&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;{Binding Path=UserName}&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  26:&lt;/span&gt;                                         &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;TextBlock&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;----------&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  27:&lt;/span&gt;                                     &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;StackPanel&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  28:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  29:&lt;/span&gt;                             &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;StackPanel&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  30:&lt;/span&gt;                             &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  31:&lt;/span&gt;                         &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;DataTemplate&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  32:&lt;/span&gt;                     &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;ListBox.ItemTemplate&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  33:&lt;/span&gt;             &lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  34:&lt;/span&gt;                 &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;ListBox&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  35:&lt;/span&gt;             &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;ScrollViewer&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  36:&lt;/span&gt;             &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;StackPanel&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:white;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  37:&lt;/span&gt;         &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;StackPanel&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="PADDING-RIGHT:0px;PADDING-LEFT:0px;FONT-SIZE:8pt;PADDING-BOTTOM:0px;MARGIN:0em;OVERFLOW:visible;WIDTH:100%;COLOR:black;BORDER-TOP-STYLE:none;LINE-HEIGHT:12pt;PADDING-TOP:0px;FONT-FAMILY:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;BORDER-RIGHT-STYLE:none;BORDER-LEFT-STYLE:none;BACKGROUND-COLOR:#f4f4f4;BORDER-BOTTOM-STYLE:none;"&gt;&lt;span style="COLOR:#606060;"&gt;  38:&lt;/span&gt;     &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;Grid&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;One item to notice is that all of the code for calling the Twitter API is no longer embedded in the Click() event of the Search button. It has been extracted into its own method and no longer relies on user interface elements. This refactoring was done with integration testing in mind. In a later installment we will be looking at testing the user interface along with just the API calls.&lt;/p&gt;
&lt;p&gt;Now the user interface looks like:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://codebetter.com/blogs/rodpaddock/TwitterConversationWindowRefactor_795DDBFF.png"&gt;&lt;img title="TwitterConversationWindowRefactor" style="BORDER-RIGHT:0px;BORDER-TOP:0px;DISPLAY:inline;BORDER-LEFT:0px;BORDER-BOTTOM:0px;" height="451" alt="TwitterConversationWindowRefactor" src="http://codebetter.com/blogs/rodpaddock/TwitterConversationWindowRefactor_thumb_62BB8DB8.png" width="529" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Google Code&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;The source code for this project can now be found on Google Code&amp;nbsp; The URL for this project is:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;UPDATE&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://code.google.com/p/twitterplayground/"&gt;http://code.google.com/p/twitterplayground/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;a href="http://twitterplayground.googlecode.com/svn/trunk/twitterplayground-read-only"&gt;&lt;strike&gt;http://twitterplayground.googlecode.com/svn/trunk/twitterplayground-read-only&lt;/strike&gt;&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;More Coming&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;I hope you have enjoyed these posts so far.&amp;nbsp; Lets take a look at the list from the last post and strike out some tasks that were accomplished in this post:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;1. Introduce a Dependency Injection container. For this application I want to use StructureMap. &lt;br /&gt;2. &lt;strike&gt;Introduce more mocking to remove dependencies on Twitter (maybe we can write a Twitter mock layer) &lt;br /&gt;&lt;/strike&gt;3. &lt;strike&gt;Further refine the design of the libraries. There’s still redundant code left we can remove. &lt;br /&gt;&lt;/strike&gt;4. &lt;strike&gt;Improve the UI&lt;/strike&gt; and create some alternate UI’s with MVC&amp;nbsp; or maybe Silverlight &lt;br /&gt;5. &lt;strike&gt;Open up the code to contributions from other developers&lt;/strike&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We accomplished quite a bit in this post. Is all of the code done? Not by any stretch. I plan on revisiting all of the items on the list in every refactoring (rinse-lather-repeat)… I will also add new items to the list, like:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Adding Proxy code to the communications class.&lt;/li&gt;
&lt;li&gt;Adding error handling to the communications class.&lt;/li&gt;
&lt;li&gt;Creating some mechanism for preserving credentials and other settings&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;RE #5: I did put it in Google code and would be happy to have other contributors. I would especially appreciate help with the UI.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE: One of the cool things about this process so far is the confidence I have in changes I make to the code. Having a repeatable set of tests is invaluable.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Thanks &lt;br /&gt;Rodman&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=186473" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/rodpaddock/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://codebetter.com/blogs/rodpaddock/archive/tags/VB+DevCenter/default.aspx">VB DevCenter</category><category domain="http://codebetter.com/blogs/rodpaddock/archive/tags/VB/default.aspx">VB</category><category domain="http://codebetter.com/blogs/rodpaddock/archive/tags/TDD/default.aspx">TDD</category><category domain="http://codebetter.com/blogs/rodpaddock/archive/tags/Agile/default.aspx">Agile</category></item><item><title>Twitter Conversations an Agile Case Study</title><link>http://codebetter.com/blogs/rodpaddock/archive/2008/12/11/twitter-conversations-an-agile-case-study.aspx</link><pubDate>Fri, 12 Dec 2008 04:47:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:186000</guid><dc:creator>Rod Paddock [MVP]</dc:creator><slash:comments>14</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/rodpaddock/rsscomments.aspx?PostID=186000</wfw:commentRss><comments>http://codebetter.com/blogs/rodpaddock/archive/2008/12/11/twitter-conversations-an-agile-case-study.aspx#comments</comments><description>&lt;p&gt;&lt;strong&gt;Twitter Conversations&lt;/strong&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;From time to time Twitter Users engage in conversations. It is a royal pain to follow these conversations using the native Twitter programs including the web version of Twitter.&amp;nbsp; As an exercise I began creating an application that would allow me to follow Twitter conversations. This is the story of creating that application.&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;User Story&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; As a Twitter user I want to be able to follow conversations between other Twitter users.&lt;br /&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This post will accomplish two things. &lt;br /&gt;1.&amp;nbsp;Fulfill the requirements of the user story.&lt;br /&gt;2.&amp;nbsp;Create a small application that can be used by the ALT.NET/Agile/Lean community to learn numerous agile software development concepts including:&amp;nbsp; test driven development, dependency injection, how good design affects testing, etc. &lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Note: The second item in the list came from conversations at KaizenConf (&lt;a href="http://www.kaizenconf.com/"&gt;www.kaizenconf.com&lt;/a&gt;&amp;nbsp; kaizenconf.pbwiki.com). These conversations centered on the need to create a learning application. I am submitting this application as a case study so that we all may learn from it.&lt;br /&gt;To accomplish the story we need the following parts:&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;1.&amp;nbsp;A mechanism for communicating with Twitter.&lt;br /&gt;2.&amp;nbsp;Query Twitter UserID’s based on list of screen names.&lt;br /&gt;3.&amp;nbsp;Query messages for each user in list of screen names.&lt;br /&gt;4.&amp;nbsp;Filter messages where the message content contains any of the names in the list of screen names.&lt;br /&gt;The first step is to define a domain model. The following domain model represents the different elements that will help in fulfilling the requirements of the user story.&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;•&amp;nbsp;User&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; o&amp;nbsp;UserID(int)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; o&amp;nbsp;ScreenName(string)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; o&amp;nbsp;UserName (string)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; o&amp;nbsp;Followers (int)&lt;br /&gt;•&amp;nbsp;Message&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; o&amp;nbsp;MessageID(int)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; o&amp;nbsp;MessageDate(string)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; o&amp;nbsp;MessageContent(string)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; o&amp;nbsp;UserID (int)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; o&amp;nbsp;UserName(string)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Unit Tests (Part 1)&lt;br /&gt;&lt;/strong&gt;After creating the domain model began creating unit tests for my API. I decided to divide my API into two subject areas: Users and Messages. The User API is used to query Twitter User information. The Message API is used to query Twitter Status(s) aka messages. The following code is the first set of unit tests.&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;TestFixture()&amp;gt; _&lt;br /&gt;Public Class UnitTests&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;lt;Test()&amp;gt; _&lt;br /&gt;&amp;nbsp; Sub Should_Return_My_Following()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim UserAPI As New Twitter.API.User&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.That(UserAPI.GetUsers().count &amp;gt; 0)&lt;br /&gt;&amp;nbsp; End Sub&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;lt;Test()&amp;gt; _&lt;br /&gt;&amp;nbsp; Sub Should_Return_Single_User()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim UserAPI As New Twitter.API.User&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.That(UserAPI.GetUser(UserAPI.GetMyUser().UserID.ToString).ScreenName _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = &amp;quot;rodpaddock&amp;quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Sub&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;lt;Test()&amp;gt; _&lt;br /&gt;&amp;nbsp; Sub Should_Return_Single_User_ByName()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim UserAPI As New Twitter.API.User&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.That(UserAPI.GetUser(&amp;quot;rodpaddock&amp;quot;).ScreenName = &amp;quot;rodpaddock&amp;quot;)&lt;br /&gt;&amp;nbsp; End Sub&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;lt;Test()&amp;gt; _&lt;br /&gt;&amp;nbsp; Sub Should_Return_My_User()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim UserAPI As New Twitter.API.User&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim User As Twitter.Domain.User = UserAPI.GetMyUser&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.That(UserAPI.GetMyUser().ScreenName = &amp;quot;rodpaddock&amp;quot;)&lt;br /&gt;&amp;nbsp; End Sub&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;lt;Test()&amp;gt; _&lt;br /&gt;&amp;nbsp; Sub Should_Return_My_Messages()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim MessageAPI As New Twitter.API.Message&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.That(MessageAPI.GetMyMessages().Count &amp;gt; 0)&lt;br /&gt;&amp;nbsp; End Sub&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;lt;Test()&amp;gt; _&lt;br /&gt;&amp;nbsp; Sub Should_Return_Messages_By_User()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim MessageAPI As New Twitter.API.Message&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.That(MessageAPI.GetUserMessages(&amp;quot;rodpaddock&amp;quot;).Count &amp;gt; 0)&lt;br /&gt;&amp;nbsp; End Sub&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;lt;Test()&amp;gt; _&lt;br /&gt;&amp;nbsp; Sub Should_Return_Messages_From_MultipleUsers()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim MessageAPI As New Twitter.API.Message&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim UserAPI As New Twitter.API.User&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim UserQuery As New List(Of Twitter.Domain.User)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; UserQuery.Add(UserAPI.GetUser(&amp;quot;rodpaddock&amp;quot;))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; UserQuery.Add(UserAPI.GetUser(&amp;quot;chriswilliams&amp;quot;))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.That(MessageAPI.GetMultipleUserMessages(UserQuery.ToArray).Count &amp;gt; 0)&lt;br /&gt;&amp;nbsp; End Sub&lt;br /&gt;End Class&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;This set of unit tests does a good job of covering our API’s and insuring they all work as planned. But the tests do have a number of design flaws. For now we’ll leave them alone and look at some of the code they are testing.&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Twitter Basics&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now that you have looked at the domain model and the unit tests, take a look at the process of fulfilling these unit tests. For this exercise consider the following unit test.&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;Test()&amp;gt; _&lt;br /&gt;Sub Should_Return_Single_User_ByName()&lt;br /&gt;&amp;nbsp;&amp;nbsp; Dim UserAPI As New Twitter.API.User&lt;br /&gt;&amp;nbsp;&amp;nbsp; Assert.That(UserAPI.GetUser(&amp;quot;rodpaddock&amp;quot;).ScreenName = &amp;quot;rodpaddock&amp;quot;)&lt;br /&gt;End Sub&lt;/p&gt;
&lt;p&gt;To fulfill the requirements of this test the following things must occur:&lt;br /&gt;1.&amp;nbsp;Application must connect to Twitter&lt;br /&gt;2.&amp;nbsp;Application must retrieve user data based on the passed in username&lt;br /&gt;3.&amp;nbsp;The data returned must be transformed into a usable User domain object.&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;The following code fulfills the requirements of this test:&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Const GetUserURL As String = &amp;quot;&lt;a href="http://twitter.com/users/show/%3C%3CUSERID%3E%3E.json"&gt;http://twitter.com/users/show/&amp;lt;&amp;lt;USERID&amp;gt;&amp;gt;.json&lt;/a&gt;&amp;quot;&lt;br /&gt;Public Function GetUser(ByVal id As String) As Twitter.Domain.User&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim Credentials As New NetworkCredential(&amp;quot;&amp;lt;&amp;lt;YourUserName&amp;gt;&amp;gt;&amp;quot;, &amp;quot;&amp;lt;&amp;lt;YourPassword&amp;gt;&amp;gt;&amp;quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim Request As HttpWebRequest = _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HttpWebRequest.Create(GetUserURL.Replace(&amp;quot;&amp;lt;&amp;lt;USERID&amp;gt;&amp;gt;&amp;quot;, id.ToString))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Request.Method = &amp;quot;GET&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Request.Credentials = Credentials&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim Response As WebResponse = Request.GetResponse&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim Reader As New StreamReader(Response.GetResponseStream)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim Results As String = Reader.ReadToEnd&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim JsonSerializer As New System.Web.Script.Serialization.JavaScriptSerializer&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim UserObject As Object = JsonSerializer.DeserializeObject(Results)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Return New Twitter.Domain.User With { _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .UserID = UserObject(&amp;quot;id&amp;quot;), _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .UserName = UserObject(&amp;quot;name&amp;quot;), _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .ScreenName = UserObject(&amp;quot;screen_name&amp;quot;), _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Followers = UserObject(&amp;quot;followers_count&amp;quot;)}&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Function&lt;/p&gt;
&lt;p&gt;This code performs the following tasks:&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;1.&amp;nbsp;Created a&amp;nbsp; NetworkCredentials object with your Twitter user name and password. All twitter requests use basic authentication.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim Credentials As New NetworkCredential(&amp;quot;&amp;lt;&amp;lt;YourUserName&amp;gt;&amp;gt;&amp;quot;, &amp;quot;&amp;lt;&amp;lt;YourPassword&amp;gt;&amp;gt;&amp;quot;)&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;2.&amp;nbsp;Created an HttpWebRequest based on Twitter’s REST API. This call will return data in JSON format as specified via the .json extension on the URL.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim Request As HttpWebRequest = _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HttpWebRequest.Create(GetUserURL.Replace(&amp;quot;&amp;lt;&amp;lt;USERID&amp;gt;&amp;gt;&amp;quot;, id.ToString))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Request.Method = &amp;quot;GET&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Request.Credentials = Credentials&lt;/p&gt;
&lt;p&gt;3.&amp;nbsp;Read data from the web request stream using a Stream Reader.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Const GetUserURL As String = &amp;quot;&lt;a href="http://twitter.com/users/show/%3C%3CUSERID%3E%3E.json"&gt;http://twitter.com/users/show/&amp;lt;&amp;lt;USERID&amp;gt;&amp;gt;.json&lt;/a&gt;&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim Response As WebResponse = Request.GetResponse&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim Reader As New StreamReader(Response.GetResponseStream)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim Results As String = Reader.ReadToEnd&lt;/p&gt;
&lt;p&gt;4.&amp;nbsp;Deserialize the JSON data into an array of Name/Value pair data using the .Net JSON serializer.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim JsonSerializer As New System.Web.Script.Serialization.JavaScriptSerializer&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim UserObject As Object = JsonSerializer.DeserializeObject(Results)&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;5.&amp;nbsp;Turn the returned user information into a User domain object&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Return New Twitter.Domain.User With { _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .UserID = UserObject(&amp;quot;id&amp;quot;), _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .UserName = UserObject(&amp;quot;name&amp;quot;), _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .ScreenName = UserObject(&amp;quot;screen_name&amp;quot;), _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Followers = UserObject(&amp;quot;followers_count&amp;quot;)}&lt;br /&gt;&amp;nbsp; &lt;br /&gt;That’s pretty much how all communication works with Twitter. If you closely examine the code you will find a number of design flaws. Basically this code was developed as a spike: “&lt;em&gt;&lt;strong&gt;Let’s see how we can pull data from Twitter&lt;/strong&gt;&lt;/em&gt;”. The basic pattern: authenticate, request and parse was cut and pasted into each API call. I did this knowing that that the code (and tests) would be refactored into a proper design.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Refactoring the Code&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;After completing the first run through the code (getting it working) it was time to refactor. I gave myself some of goals:&lt;br /&gt;1.&amp;nbsp;Reduce the amount of redundant code.&lt;br /&gt;2.&amp;nbsp;Create a better designed set of test code (remove redundancy)&lt;br /&gt;3.&amp;nbsp;Prepare the code for dependency injection (current tests require internet connections)&lt;/p&gt;
&lt;p&gt;The “authenticate and request” process received the first refactoring. This process can be pseudo coded as follows:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Given a valid set of user credentials and a REST URL return a string result.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;From this pseudo code we created a Twitter communication class.&lt;/p&gt;
&lt;p&gt;Imports System.Web&lt;br /&gt;Imports System.Net&lt;br /&gt;Imports System.IO&lt;/p&gt;
&lt;p&gt;Public Class TwitterRequest&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Private UserName As String = &amp;quot;&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Private Password As String = &amp;quot;&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sub New(ByVal UserName As String, ByVal Password As String)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Me.UserName = UserName&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Me.Password = Password&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Sub&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Function GetTwitterRequest(ByVal URL As String) As String&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim Credentials As New NetworkCredential(Me.UserName, Me.Password)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim Request As HttpWebRequest = HttpWebRequest.Create(URL)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Request.Method = &amp;quot;POST&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Request.Credentials = Credentials&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim Response As WebResponse = Request.GetResponse&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim Reader As New StreamReader(Response.GetResponseStream)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim Results As String = Reader.ReadToEnd&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Return Results&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Function&lt;br /&gt;End Class&lt;/p&gt;
&lt;p&gt;Now we have a wrapped class that needs two items in its constructor (UserName , Password) and has a single method GetTwitterRequest(URL). The GetTwitterRequest(URL)’s job is to return a JSON string that will be used by the subsequent API call. &lt;/p&gt;
&lt;p&gt;All of the code necessary for&amp;nbsp; communicating with Twitter is encapsulated into this class. &lt;/p&gt;
&lt;p&gt;Next step was to refactor the User and Message API’s.&amp;nbsp; The first step involved creating a constructor that accepted a TwitterRequest object. The constructor for the Message API changed to:&amp;nbsp;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;Dim Communicator As Twitter.Communication.TwitterRequest = Nothing&lt;br /&gt;&amp;nbsp;Dim JsonSerializer As New System.Web.Script.Serialization.JavaScriptSerializer&lt;/p&gt;
&lt;p&gt;&amp;nbsp; Sub New(ByVal TwitterCommunicator As Twitter.Communication.TwitterRequest)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Me.Communicator = TwitterCommunicator&lt;br /&gt;&amp;nbsp; End Sub&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;These two refactorings reduced the code radically. The following code shows the new GetUser() method.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;Public Function GetUser(ByVal id As String) As Twitter.Domain.User&lt;br /&gt;&amp;nbsp;Dim UserObject As Object = JsonSerializer.DeserializeObject(_ &lt;br /&gt;&amp;nbsp;&amp;nbsp; Me.Communicator.GetTwitterRequest(GetUserURL.Replace(&amp;quot;&amp;lt;&amp;lt;USERID&amp;gt;&amp;gt;&amp;quot;, id.ToString)))&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp; Return New Twitter.Domain.User With { _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .UserID = UserObject(&amp;quot;id&amp;quot;), _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .UserName = UserObject(&amp;quot;name&amp;quot;), _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .ScreenName = UserObject(&amp;quot;screen_name&amp;quot;), _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Followers = UserObject(&amp;quot;followers_count&amp;quot;)}&lt;/p&gt;
&lt;p&gt;End Function&lt;/p&gt;
&lt;p&gt;The code went from 10 lines of code to 2.&amp;nbsp; The same results were seen across the entire API.&amp;nbsp; &lt;br /&gt;Refactoring Tests&lt;br /&gt;Once the API’s were refactored&amp;nbsp; the tests were then refactored. The following code shows the new set of tests.&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Imports NUnit.Core&lt;br /&gt;Imports NUnit.Framework&lt;/p&gt;
&lt;p&gt;&amp;lt;TestFixture()&amp;gt; _&lt;br /&gt;Public Class UnitTests&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim UserAPI As Twitter.API.User = Nothing&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim MessageAPI As Twitter.API.Message = Nothing&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim Communicator As New Twitter.Communication.TwitterRequest(&amp;quot;&amp;quot;, &amp;quot;”)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;SetUp()&amp;gt; _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sub Setup()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Me.UserAPI = New Twitter.API.User(Me.Communicator)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Me.MessageAPI = New Twitter.API.Message(Me.Communicator)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Sub&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Test()&amp;gt; _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sub Should_Return_My_Following()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.That(UserAPI.GetUsers().Count &amp;gt; 0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Sub&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Test()&amp;gt; _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sub Should_Return_Single_User()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.That(UserAPI.GetUser(UserAPI.GetMyUser().UserID.ToString).ScreenName _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = &amp;quot;rodpaddock&amp;quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Sub&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Test()&amp;gt; _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sub Should_Return_Single_User_ByName()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.That(UserAPI.GetUser(&amp;quot;rodpaddock&amp;quot;).ScreenName = &amp;quot;rodpaddock&amp;quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Sub&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Test()&amp;gt; _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sub Should_Return_My_User()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.That(UserAPI.GetMyUser().ScreenName = &amp;quot;rodpaddock&amp;quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Sub&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Test()&amp;gt; _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sub Should_Return_My_Messages()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.That(MessageAPI.GetMyMessages().Count &amp;gt; 0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Sub&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Test()&amp;gt; _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sub Should_Return_Messages_By_User()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.That(MessageAPI.GetUserMessages(&amp;quot;rodpaddock&amp;quot;).Count &amp;gt; 0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Sub&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Test()&amp;gt; _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sub Should_Return_Messages_From_MultipleUsers()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim UserQuery As New List(Of Twitter.Domain.User)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; UserQuery.Add(UserAPI.GetUser(&amp;quot;rodpaddock&amp;quot;))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; UserQuery.Add(UserAPI.GetUser(&amp;quot;chriswilliams&amp;quot;))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.That(MessageAPI.GetMultipleUserMessages(UserQuery.ToArray).Count &amp;gt; 0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Sub&lt;br /&gt;End Class&lt;/p&gt;
&lt;p&gt;As you can see the testing class now has member variables for each API class and the &amp;lt;Setup()&amp;gt; section instantiates the APIs with the injected communication class.&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;User Interface&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Finally a small WPF application was built to track conversations between users. The following code creates instances of the User and Message APIs, creates an array of user objects from a string (split by commas), retrieves messages for the specified users and finally queries them using LINQ to ferret out a conversation. This code is as follows:&lt;br /&gt;Partial Public Class Main&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim UserAPI As Twitter.API.User = Nothing&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim MessageAPI As Twitter.API.Message = Nothing&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim Communicator As New Twitter.Communication.TwitterRequest(&amp;quot;&amp;quot;, &amp;quot;&amp;quot;)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Public Sub New()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MyBase.New()&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Me.InitializeComponent()&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39; Insert code required on object creation below this point.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39; Add any initialization after the InitializeComponent() call.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Me.UserAPI = New Twitter.API.User(Me.Communicator)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Me.MessageAPI = New Twitter.API.Message(Me.Communicator)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Sub&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Private Sub cmdGetThread_Click(ByVal sender As Object, _&lt;br /&gt;&amp;nbsp;&amp;nbsp; ByVal e As System.Windows.RoutedEventArgs) Handles cmdGetThread.Click&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;-- create list of users from comma (,) delimited list of names in text box&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;-- TODO we should scrub this&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim UserQuery As New List(Of Twitter.Domain.User)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; For Each UserName As String In Me.txtCriteria.Text.Split(&amp;quot;,&amp;quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; UserQuery.Add(UserAPI.GetUser(UserName))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Next&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;-- get messages for these users &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim messages As Twitter.Domain.Message() = _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MessageAPI.GetMultipleUserMessages(UserQuery.ToArray())&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;-- filter messages based on who is in the contents&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim FilteredMessages = _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; From Message _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; In messages _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Where MatchesCriteria(Message.MessageContent, Me.txtCriteria.Text.Split(&amp;quot;,&amp;quot;)) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Order By Message.MessageDate Descending&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Me.lstResults.ItemsSource = FilteredMessages.ToArray&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Sub&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Function MatchesCriteria(ByVal Content As String, _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ByVal SearchCriteria As String()) As Boolean&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim llRetVal As Boolean = False&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; For Each SearchString In SearchCriteria&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If Content.ToLower.Contains(SearchString) Then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; llRetVal = True&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Exit For&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; End If&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Next&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Return llRetVal&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Function&lt;/p&gt;
&lt;p&gt;Lastly the information is displayed using the following XAML code:&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&amp;lt;Window&lt;br /&gt;xmlns=&amp;quot;&lt;a href="http://schemas.microsoft.com/winfx/2006/xaml/presentation"&gt;http://schemas.microsoft.com/winfx/2006/xaml/presentation&lt;/a&gt;&amp;quot;&lt;br /&gt;xmlns:x=&amp;quot;&lt;a href="http://schemas.microsoft.com/winfx/2006/xaml"&gt;http://schemas.microsoft.com/winfx/2006/xaml&lt;/a&gt;&amp;quot;&lt;br /&gt;x:Class=&amp;quot;Main&amp;quot;&lt;br /&gt;x:Name=&amp;quot;Window&amp;quot;&lt;br /&gt;Title=&amp;quot;Main&amp;quot;&lt;br /&gt;&amp;nbsp;xmlns:Custom=&amp;quot;&lt;a href="http://schemas.microsoft.com/wpf/2008/toolkit"&gt;http://schemas.microsoft.com/wpf/2008/toolkit&lt;/a&gt;&amp;quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;Grid x:Name=&amp;quot;LayoutRoot&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;StackPanel Margin=&amp;quot;0,0,0,37&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Button Content=&amp;quot;Get Thread&amp;quot; x:Name=&amp;quot;cmdGetThread&amp;quot;/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;lt;TextBox Text=&amp;quot;bellware,pandamonial,chadmyers&amp;quot;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TextWrapping=&amp;quot;Wrap&amp;quot; x:Name=&amp;quot;txtCriteria&amp;quot; Width=&amp;quot;622.627&amp;quot;/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;ScrollViewer&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;ListBox Width=&amp;quot;Auto&amp;quot; Height=&amp;quot;500&amp;quot; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IsSynchronizedWithCurrentItem=&amp;quot;True&amp;quot; x:Name=&amp;quot;lstResults&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;ListBox.ItemTemplate&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;DataTemplate&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;StackPanel&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;TextBlock Text=&amp;quot;{Binding Path=MessageDate}&amp;quot;/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;TextBlock Text=&amp;quot;{Binding Path=UserName}&amp;quot;/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;TextBlock Text=&amp;quot;----------&amp;quot;/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/StackPanel&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/DataTemplate&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;/ListBox.ItemTemplate&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;/ListBox&amp;gt;&lt;br /&gt;&amp;lt;/ScrollViewer&amp;gt;&lt;br /&gt;&amp;lt;/StackPanel&amp;gt;&lt;br /&gt;&amp;lt;/Grid&amp;gt;&lt;br /&gt;&amp;lt;/Window&amp;gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;The following screen shot demonstrates a conversation that occurred today between three people I follow on Twitter:&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;img title="Twitter Conversation Window" style="WIDTH:824px;HEIGHT:628px;" height="628" alt="Twitter Conversation Window" src="http://www.dashpoint.com/images/TwitterConversationWindow.png" width="824" /&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Next Steps&lt;br /&gt;&lt;/strong&gt;There is more work to be done here. In the future posts I hope to do the following:&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;1.&amp;nbsp;Introduce a Dependency Injection container. For this application I want to use StructureMap.&lt;br /&gt;2.&amp;nbsp;Introduce more mocking to remove dependencies on Twitter (maybe we can write a Twitter mock layer)&lt;br /&gt;3.&amp;nbsp;Further refine the design of the libraries. There’s still redundant code left we can remove.&lt;br /&gt;4.&amp;nbsp;Improve the UI and create some alternate UI’s with MVC&amp;nbsp; or maybe Silverlight&lt;br /&gt;5.&amp;nbsp;Open up the code to contributions from other developers.&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Summary&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;What I hoped to accomplish in this post was a brief introduction to building a useful tool using the agile principles of Test Driven Development and Dependency Injection. Another goal of this post is to open a conversation on these agile principles. A lot of these practices may seem simple to a lot of the folks I blog with here but a lot of folks out there they seem foreign. I appreciate the comments.&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;The full code for this post can be found at &lt;a href="http://www.dashpoint.com/downloads/TwitterPlayGround.Zip"&gt;www.dashpoint.com/downloads/TwitterPlayGround.Zip&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Note: There are two sections where you will need to use your own username and password.&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Thanks&lt;br /&gt;Rodman&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=186000" width="1" height="1"&gt;</description></item><item><title>Roundtables vs. Lunch Counters    </title><link>http://codebetter.com/blogs/rodpaddock/archive/2008/12/02/roundtables-vs-lunch-counters.aspx</link><pubDate>Tue, 02 Dec 2008 08:28:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:185525</guid><dc:creator>Rod Paddock [MVP]</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/rodpaddock/rsscomments.aspx?PostID=185525</wfw:commentRss><comments>http://codebetter.com/blogs/rodpaddock/archive/2008/12/02/roundtables-vs-lunch-counters.aspx#comments</comments><description>&lt;p class="MsoNormal" style="MARGIN:0in 0in 10pt;"&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;I have a strange pet peeve. I hate rectangular tables.&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;It’s a strange pet peeve but its mine and I stick by it. I hate rectangular because they don’t scale. They don’t scale conversations for groups of people greater than say 6 people. &lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&lt;/span&gt;I became aware of just how much I hate rectangular tables last week. I was at QCON in San Francisco and went to dinner with some friends at a great seafood restaurant. There were 4 of us and because there were no tables available but we had to sit at the bar. The bar had 4 empty seats side by side so we took them. Dinner was great and some good conversations took place. The problem is that there were basically two conversations of two people. It would have been my preference to have one conversation with all four people involved.&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;I cemented my hatred further two days later at another dinner with another rectangular table.&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;We had a larger group (12+ people) this time. &lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&lt;/span&gt;The communication situation was marginally better for the “middle” people. A larger conversation “cluster” formed in the center with smaller satellites of communication for the “edge” people.&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="MARGIN:0in 0in 10pt;"&gt;&lt;font face="Calibri" size="3"&gt;Flash back two weeks earlier to Kaizen Conf. Kaizen Conf is a conference centered on concepts of continuous improvement, agile and lean software development practices. Most of the sessions I attended were large groups (some 50+) sitting in large circles having healthy and involved discussions on some healthy topics. The benefit of the structure is that everyone can see and hear everyone else.&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;Communication is more fluid and minimizes the “clustering” effect.&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;Another benefit of the roundtable structure is its channel balancing effect. No channel is more important or larger than another. There is no “head” of the circle. &lt;/font&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="MARGIN:0in 0in 10pt;"&gt;&lt;font face="Calibri" size="3"&gt;I find a lot of similarity in software development practices today.&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;Classic waterfall development is what I call lunch counter development. Communications happen in differing stages along the lunch counter with the bulk of quality communication happening in the middle. The edge people are generally left out of the main communication and never have their concerns every really addressed. Just think of your customer sitting at one end of the table trying to communicate there needs to the other end of the table.&lt;/font&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="MARGIN:0in 0in 10pt;"&gt;&lt;font face="Calibri" size="3"&gt;Now take a look at agile/lean and RAD (iterative) software development practice. &lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&lt;/span&gt;These practices are what I am seeing as round table development. It’s all about value systems. Agile/Lean/RAD developments value communication between all stakeholders at all stages of the development process. Every stakeholder has seat at the table. The cornerstone of these practices is the active communication between all constituents at all times.&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;Stand up meetings, iteration planning meetings, retrospectives.&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;All of these (and many more) practices relate to facilitating communications between project stakeholders. &lt;/font&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="MARGIN:0in 0in 10pt;"&gt;&lt;font face="Calibri" size="3"&gt;The more I develop software using round table (agile/lean) methodologies and practices the more I find the lunch counter development (waterfall) detestable. Software development practices that emphasize and promote communicating down lunch counter are destined to disappoint and generally leave bad tastes in stakeholder’s mouths. This is not limited to just users being disappointed. All stakeholders are disappointed. How many developers do you know that don’t really care about their end users or the quality of their software? I take it personally when my software doesn’t work, doesn’t deliver its expected value or frustrates my end users who I truly care about. I am betting you feel the same way. Let’s not forget that it’s not just you the developer or the end user that feel the effects of software development process. Along with end users and developers; project managers, managers, executives and customers all feel the true quality of the software process. &lt;/font&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="MARGIN:0in 0in 10pt;"&gt;&lt;font face="Calibri" size="3"&gt;Stories differ but legend says King Arthur created his round table to emphasize equal status among all that had a seat.&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;The most important aspect of any software development process is the communication of requirements. Does your company communicate down a lunch counter or do they sit at the round table?&lt;/font&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="MARGIN:0in 0in 10pt;"&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;It&amp;#39;s been&amp;nbsp;too long between blog posts so here ya go. This post will end up as my editorial in CoDe Magazine next month. I have more posts in the works related to my recent spelunking into all things agile. Stay tuned. &lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
crossposted from blog.dashpoint.com&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=185525" width="1" height="1"&gt;</description></item><item><title>Unlearn</title><link>http://codebetter.com/blogs/rodpaddock/archive/2008/05/09/unlearn.aspx</link><pubDate>Fri, 09 May 2008 13:37:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:177959</guid><dc:creator>Rod Paddock [MVP]</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/rodpaddock/rsscomments.aspx?PostID=177959</wfw:commentRss><comments>http://codebetter.com/blogs/rodpaddock/archive/2008/05/09/unlearn.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;“You must unlearn what you have learned.”&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Yoda to Luke Skywalker Empire Strikes Back 1981&lt;/p&gt;
&lt;p&gt;I have become convinced that we are entering a new dawn of software development and we must take time to unlearn that which we know. Over the last 2 months I have been researching building business applications using Silverlight 2.0. In case you don’t know Silverlight 2.0 is a tool used to build Rich Internet Applications (RIA’s) Silverlight 1.1 (released in 2007) gave us a small glimpse of the future of RIA development.&amp;nbsp; This glimpse proved that Silverlight 1.1 was wholly lacking for business developers (it didn’t even have a button). Silverlight Version 2.0 (released at Mix 08 in Las Vegas, NV) is a different story. Silverlight 2.0 has all of the features a business developer might need. The control set includes: textboxes, buttons, watermark textboxes and, drum roll please, a DataGrid component. &lt;/p&gt;
&lt;p&gt;During my research I began experimenting with the DataGrid. I started (in XAML) adding columns to the DataGrid’s columns collection, setting data binding attributes, column widths and header properties. I then turned to the code portion of my research and DataGrid’s ItemSource property to a list of objects. I ran the application and lo-and-behold it worked (not the first time of course but eventually).&amp;nbsp; After getting my simple grid demo working I wanted to implement a simple, but common use case. I wanted to allow the user to sort the data by clicking on the column.&amp;nbsp; Here’s how it went:&lt;/p&gt;
&lt;p&gt;1.&amp;nbsp;Look for DataGrid properties called something like “AllowSort” &lt;br /&gt;2.&amp;nbsp;Look for header properties that would turn this feature on.&lt;br /&gt;3.&amp;nbsp;Look into the documentation for the DataGrid (samples, online, etc)&lt;br /&gt;4.&amp;nbsp;Download and open the source code for the DataGrid (yup you read that right its available to developers)&lt;/p&gt;
&lt;p&gt;I struck out on all accounts. It looked like I would be waiting for a new rev for this feature. I did take one more step though. I turned to my trusty search engine Google and typed in “silverilght 2.0 datagrid sort”. And look what I found: Matt Berseth (&lt;a href="http://mattberseth.com/blog/"&gt;http://mattberseth.com/blog/&lt;/a&gt;) had already figured this out in a very creative and enlightening way. Matt’s unique solution was to put a HyperlinkButton control into the DataGrid’s Header Content property. The Header object’s Content Property is defined as Object. The normal use case for this property is to specify a string as your header. But this is Silverlight and when a property says it’s an object it’s an object. This means you can replace the header content with a Hyperlink rather than a textbox. This is where my epiphany occurred:&lt;/p&gt;
&lt;p&gt;My typical path took me to the control itself. I searched for properties, events and even considered for a moment hacking up a hit test set of code to do this. It hadn’t occurred to me to composite some controls together to do what I wanted.&amp;nbsp; This is where I told myself I must unlearn what I know.&amp;nbsp; I must think of new and interesting ways to combine these controls to do new and interesting things. &lt;/p&gt;
&lt;p&gt;This epiphany raised its head again over the last 2 weeks. Over the last 6 months we have started the trek down the Agile Development path. This path has included installing and researching agile development applications including:&amp;nbsp; Nant, Nunit and Subversion.&amp;nbsp; We are using Nant and Nunit to automate our testing, and in the last two weeks we moved a large quantity of our source code into a Subversion repository. It’s this last application that has provided me with another epiphany.&amp;nbsp; Source code control in Subversion is “just different” than in Visual SourceSafe (our previous source code provider).&amp;nbsp; Visual SourceSafe is a pessimistic version control system (you lock files when you check them out) Subversion is just the opposite. All files are worked on in shared mode. Meaning two developers can work on the same file at the same time. It’s up to the developer to merge changes into the development branch of code when conflicts occur. Along with a different philosophy Subversion uses different terms: In Subversion Checkout means get a fresh set of code from the repository, Import means send source code to the repository. Commit means send your changes to the repository. Visual SourceSafe had different meanings for all of these terms. &lt;/p&gt;
&lt;p&gt;When I started using Subversion I found it difficult until I told myself what Yoda said: “You must unlearn what you have learned.” I closed the book on Visual SourceSafe and opened a new one on Subversion. I consulted the documentation to see what the Subversion philosophy is and what the terms in Subversion really mean. When I “forgot” what I knew about source code control from the VSS POV things began to become clear and the process of migrating much simpler.&lt;/p&gt;
&lt;p&gt;In today’s development world new technologies require new thinking. You need to unlearn what you already know. To find comfort in the unlearning process, take shelter in the words of Jedi Master Obi-Wan Kenobi to Luke Skywalker: “Luke… Let go. Trust the force”.&amp;nbsp; &lt;br /&gt;&lt;/p&gt;
crossposted from blog.dashpoint.com&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=177959" width="1" height="1"&gt;</description></item><item><title>DevTeach Toronto 2008 = Agile Immersion</title><link>http://codebetter.com/blogs/rodpaddock/archive/2008/04/29/devteach-toronto-2008-agile-immersion.aspx</link><pubDate>Tue, 29 Apr 2008 17:30:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:177384</guid><dc:creator>Rod Paddock [MVP]</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/rodpaddock/rsscomments.aspx?PostID=177384</wfw:commentRss><comments>http://codebetter.com/blogs/rodpaddock/archive/2008/04/29/devteach-toronto-2008-agile-immersion.aspx#comments</comments><description>&lt;p class="MsoNormal" style="MARGIN:0in 0in 10pt;"&gt;&lt;font face="Calibri" size="3"&gt;&lt;/font&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal" style="MARGIN:0in 0in 10pt;"&gt;&lt;font face="Calibri" size="3"&gt;If you want a good general immersion in Agile practices look no further than DevTeach (&lt;/font&gt;&lt;a href="http://www.devteach.com/"&gt;&lt;font face="Calibri" size="3"&gt;www.devteach.com&lt;/font&gt;&lt;/a&gt;&lt;font face="Calibri" size="3"&gt;)&lt;/font&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="MARGIN:0in 0in 10pt;"&gt;&lt;font face="Calibri" size="3"&gt;Last DevTeach (in Vancouver) I sat through a number of Agile sessions with a fellow development partner. This parter had virtually no experience with Agile practices. After DevTeach we began discussions on implementing Agile practices in his 15+ developer shop. It was good for him to&amp;nbsp;hear from other developers about their experiences with Agile.&lt;/font&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="MARGIN:0in 0in 10pt;"&gt;&lt;font face="Calibri" size="3"&gt;So if you want to get your management, developers or development buddies on board with Agile then send them Toronto in May for DevTeach.&lt;/font&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="MARGIN:0in 0in 10pt;"&gt;&lt;font face="Calibri" size="3"&gt;PS: You can also stay for a post-con session on Building Business Apps with Silverlight 2.0 given by me and my business partner Jim Duffy &lt;/font&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="MARGIN:0in 0in 10pt;"&gt;&lt;font face="Calibri" size="3"&gt;PSS: Small conferences like DevTeach are MUCH better than large ones. Why: Because the speaker to attendee ratio is much lower and we can all interact much more…. I personally prefer small conferences over large ones.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
crossposted from blog.dashpoint.com&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=177384" width="1" height="1"&gt;</description></item><item><title>OT: SilverLight 2.0 = iPhone SDK</title><link>http://codebetter.com/blogs/rodpaddock/archive/2008/03/06/ot-silverlight-2-0-iphone-sdk.aspx</link><pubDate>Thu, 06 Mar 2008 17:08:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:174998</guid><dc:creator>Rod Paddock [MVP]</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/rodpaddock/rsscomments.aspx?PostID=174998</wfw:commentRss><comments>http://codebetter.com/blogs/rodpaddock/archive/2008/03/06/ot-silverlight-2-0-iphone-sdk.aspx#comments</comments><description>&lt;p&gt;Maybe it&amp;#39;s&amp;nbsp; just a coincidence but I am thinking its not.&lt;/p&gt;
&lt;p&gt;I am at MIX 08 in Las Vegas and am eagerly awating&amp;nbsp;today&amp;#39;s keynote with Steve Ballmer and Guy Kawasaki.&lt;/p&gt;
&lt;p&gt;Funny thing is the whole timing of it all....&lt;/p&gt;
&lt;p&gt;1. Apple&amp;#39;s iPhone SDK Meeting is at 1:00pm Pacific&lt;/p&gt;
&lt;p&gt;2. MIX 08 Keynote is at 1:00pm Pacific.&lt;/p&gt;
&lt;p&gt;3. Guy Kawasaki is the former evangelist for Apple. Heck he started the whole software/hardware platform concept.&lt;/p&gt;
&lt;p&gt;4. Silverlight is a full functioned player on the Apple.&lt;/p&gt;
&lt;p&gt;5. Steve Jobs hates Flash &lt;a href="http://www.informationweek.com/blog/main/archives/2008/03/jobs_flash_not.html"&gt;http://www.informationweek.com/blog/main/archives/2008/03/jobs_flash_not.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We got to see that Silverlight is a player in the Nokia space. Will we be developing iPhone and iTouch apps with Silverlight? As the Apple ad&amp;#39;s say: Imagine....&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE: Oh Well! It was a fun thought for a few hours in any case.&amp;nbsp; &lt;/strong&gt;&lt;/p&gt;
crossposted from blog.dashpoint.com&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=174998" width="1" height="1"&gt;</description></item></channel></rss>