<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-10533270</id><updated>2011-10-25T14:09:38.505-05:00</updated><category term='ruby'/><category term='tofuhash'/><category term='twitter'/><category term='color-block'/><title type='text'>Greg Houston</title><subtitle type='html'>Fun and cool stuff that most of my tech friends would find interesting.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default?start-index=101&amp;max-results=100'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>118</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-10533270.post-6120579250687677268</id><published>2011-10-25T14:04:00.002-05:00</published><updated>2011-10-25T14:09:38.534-05:00</updated><title type='text'>NBuilder with Prototypes</title><content type='html'>I've created an extension method for NBuilder's SingleObjectBuilder.   This allows setting property values based on a prototype.   A typical usage would supply an anonymous object as the prototype...&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;            var prototypeStyle = Builder&amp;lt;Subject&amp;gt;&lt;br /&gt;                .CreateNew()&lt;br /&gt;                .Prototype(new&lt;br /&gt;                               {&lt;br /&gt;                                   Id = 11,&lt;br /&gt;                                   Name = &amp;quot;prototypeStyle&amp;quot;,&lt;br /&gt;                                   ParentName = &amp;quot;Dad&amp;quot;&lt;br /&gt;                               })&lt;br /&gt;                .Build();&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I like this style because the property name/value pairs are easier to see.&lt;br /&gt;&lt;br /&gt;You can find an implementation at &lt;a href="http://code.google.com/p/nbuilder/issues/detail?id=78"&gt;http://code.google.com/p/nbuilder/issues/detail?id=78&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-6120579250687677268?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/6120579250687677268/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=6120579250687677268' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/6120579250687677268'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/6120579250687677268'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2011/10/nbuilder-with-prototypes.html' title='NBuilder with Prototypes'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-3434415325820430927</id><published>2010-12-16T09:48:00.000-06:00</published><updated>2010-12-16T09:51:26.713-06:00</updated><title type='text'>Installing Curb (ruby gem) on Windows</title><content type='html'>This turned out to be a bit involved.   I found a great blogpost by Pete Higgins that gives the steps involved at &lt;a href="http://beginrescue.blogspot.com/2010/07/installing-curb-with-ruby-191-in.html"&gt;http://beginrescue.blogspot.com/2010/07/installing-curb-with-ruby-191-in.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Thanks Pete!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-3434415325820430927?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/3434415325820430927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=3434415325820430927' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/3434415325820430927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/3434415325820430927'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2010/12/installing-curb-ruby-gem-on-windows.html' title='Installing Curb (ruby gem) on Windows'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-3993943519206517132</id><published>2010-10-14T12:03:00.003-05:00</published><updated>2010-10-14T12:22:17.521-05:00</updated><title type='text'>SpecFlow is Cucumber for .Net</title><content type='html'>I'm a big fan of &lt;a href="http://cukes.info/"&gt;Cucumber&lt;/a&gt;, a testing tool in Ruby.  Cucumber lets you write tests in a language that business people can read (Gherkin).  This really helps when working out requirements and edge cases.&lt;br /&gt;&lt;br /&gt;These days I am working .Net for my day job.  So I was happy to find &lt;a href="http://specflow.org/"&gt;SpecFlow - Pragmatic BDD for .Net&lt;/a&gt;.  SpecFlow implements Cucumber for .Net.  I've tried it a couple of times and found it works really well.  One more tool for my tool box!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-3993943519206517132?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/3993943519206517132/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=3993943519206517132' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/3993943519206517132'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/3993943519206517132'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2010/10/specflow-is-cucumber-for-net.html' title='SpecFlow is Cucumber for .Net'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-1046889736564687989</id><published>2010-01-23T21:37:00.002-06:00</published><updated>2010-01-23T21:59:30.079-06:00</updated><title type='text'>IronRuby 1.0 RC1 on Rails</title><content type='html'>Tonight I put 20,000 Leagues Under the Sea (1916 silent film) in the DVD player and started playing with IronRuby while the movie ran.  It didn't take long for me to get engrossed in IronRuby and now I'll need to watch the movie some other time.  No loss, the sound track for the movie makes good enough background music.&lt;br /&gt;&lt;br /&gt;I decided to try the &lt;a href="http://ironruby.net/Documentation/Real_Ruby_Applications/Rails"&gt;Rails tutorial on IronRuby's site&lt;/a&gt;.  I was pleasently surprised to find instructions for ironruby_sqlserver gem which provides ActiveRecord support.  The tutorial uses SQL Express, but I had no trouble using SQL 2008 Developer instead.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_cPO1tVrLjiw/S1vFbog6okI/AAAAAAAAAXs/STWSEesklPo/s1600-h/ironrubyonrails.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 330px; height: 400px;" src="http://2.bp.blogspot.com/_cPO1tVrLjiw/S1vFbog6okI/AAAAAAAAAXs/STWSEesklPo/s400/ironrubyonrails.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5430150854247883330" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Everything in the tutorial worked great.   After entering a few commands and creating the Post scaffold, I had a working Rails site (2.3.5) running on WEBrick with IronRuby!&lt;br /&gt;&lt;br /&gt;The only problem I ran into was the last step of the tutorial which runs script/console.  When I ran script console, as the tutorial specified (ir script\console --irb="c:\ironruby\bin\iirb.bat") I got the following error...&lt;br /&gt;&lt;br /&gt;IronRuby.Libraries:0:in `GetExecutable': c:\ironruby\bin\iirb.bat  -r irb/comple&lt;br /&gt;tion -r "C:/Users/Greg/Documents/dev/ironruby/ironrubyonrails/config/environment&lt;br /&gt;" -r console_app -r console_with_helpers --simple-prompt &lt;strong&gt;(Errno::ENOENT)&lt;/strong&gt;&lt;br /&gt;        from IronRuby.Libraries:0:in `CreateProcess'&lt;br /&gt;        from :0:in `exec'&lt;br /&gt;        from C:/ironruby/lib/ironruby/gems/1.8/gems/&lt;strong&gt;rails-2.3.5/lib/commands/console.rb:47&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;To get around the error, I found I could run the commandline that line 47 was attempting run through Ruby's exec:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;iirb.bat  -r irb/completion -r "config/environment" -r console_app -r console_with_helpers --simple-prompt&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;This launched a good iirb console with access to the Rails environment!&lt;br /&gt;&lt;br /&gt;Overall I was very pleased with IronRuby and I'll have to spend more time with it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-1046889736564687989?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/1046889736564687989/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=1046889736564687989' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/1046889736564687989'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/1046889736564687989'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2010/01/ironruby-10-rc1-on-rails.html' title='IronRuby 1.0 RC1 on Rails'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_cPO1tVrLjiw/S1vFbog6okI/AAAAAAAAAXs/STWSEesklPo/s72-c/ironrubyonrails.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-2673954665185107752</id><published>2009-10-12T19:08:00.006-05:00</published><updated>2009-10-13T20:27:31.073-05:00</updated><title type='text'>TechMixer University 2009</title><content type='html'>&lt;iframe src="http://docs.google.com/present/embed?id=df8bp35b_107f4cqbsg7&amp;interval=30&amp;size=m" frameborder="0" width="555" height="451"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;October 13th, 2009: TechMixer University is a one-day conference in Birmingham AL.  This year it had ~500 people attending.  I gave the "Getting Started with Ruby" presentation to ~40 people.  Almost everyone in the meeting had never seen Ruby before, so this presentation was perfect for them.&lt;br /&gt;&lt;br /&gt;This presentation is an update from last year's presentation.  The differences are: 1) shortened the Ruby language syntax details 2) Changed the Bonus Slides to "Ruby in Action" and added Cucumber, Sinatra, Rake to this section.&lt;br /&gt;&lt;br /&gt;Thanks to all that attended.  If anyone needs help getting started, please post questions to the &lt;a href="http://tech.groups.yahoo.com/group/rubyham"&gt;Rubyham message board&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-2673954665185107752?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/2673954665185107752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=2673954665185107752' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/2673954665185107752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/2673954665185107752'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2009/10/techmixer-university-2009.html' title='TechMixer University 2009'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-8817670397949968552</id><published>2009-08-19T09:55:00.002-05:00</published><updated>2009-08-19T10:00:22.959-05:00</updated><title type='text'>Free E-Book:  O'Reilly  C# 3 Pocket Reference</title><content type='html'>RedGate is running a marketing campaign where they are giving away O’Reilly’s C# 3 Pocket Reference.  You can get it by following &lt;a href="http://www.red-gate.com/products/ants_performance_profiler/be_ahead_of_the_game_ebook.htm?utm_source=msdnflash&amp;utm_medium=email&amp;utm_content=nlv-aheadgame-ebook&amp;utm_campaign=antsperformanceprofiler"&gt;this link&lt;/a&gt;.  The book is available by a download link at the bottom of the page.  Kudos to RedGate, especially since you dont have to fill out any forms to get the book.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-8817670397949968552?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/8817670397949968552/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=8817670397949968552' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/8817670397949968552'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/8817670397949968552'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2009/08/free-e-book-oreilly-c-3-pocket.html' title='Free E-Book:  O&apos;Reilly  C# 3 Pocket Reference'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-8462470796399461351</id><published>2009-07-16T13:46:00.002-05:00</published><updated>2009-07-16T14:09:53.841-05:00</updated><title type='text'>IronRuby 0.6 and TofuHash</title><content type='html'>I took a quick look at IronRuby 0.6 which was release earlier this month.  My first test of it was to run the TofuHash gem's unit tests.&lt;br /&gt;&lt;br /&gt;Running in MRI (Matt's Ruby Interpreter) the result was:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Loaded suite test-tofuhash&lt;br /&gt;Started&lt;br /&gt;............................................................&lt;br /&gt;Finished in 0.031 seconds.&lt;br /&gt;&lt;br /&gt;60 tests, 220 assertions, 0 failures, 0 errors&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;.&lt;br /&gt;&lt;br /&gt;Running in Iron Ruby the result was:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Loaded suite test-tofuhash&lt;br /&gt;Started&lt;br /&gt;...........................F.................F..............&lt;br /&gt;Finished in 2.031315 seconds.&lt;br /&gt;&lt;br /&gt;{stack traces for the failed cases removed to keep the output short}&lt;br /&gt;&lt;br /&gt;60 tests, 220 assertions, 2 failures, 0 errors&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;.&lt;br /&gt;&lt;br /&gt;The first thing to notice is the execution time difference 0.03 sec vs 2.03; which shows IronRuby still needs work on it's performance.  These times are a good improvement over prior versions.  Not show here is the start-up time.  MRI was practically unnoticable, while IronRuby was noticable at ~5 seconds.  The  startup time is now fast enough to not be annoying.&lt;br /&gt;&lt;br /&gt;The second noticable difference is that two tests failed under IronRuby.&lt;br /&gt;&lt;br /&gt;The first was the #invert method.  TofuHash doesn't have a custom implementation of #invert because in MRI's Hash #invert makes use of other methods in Hash.  In IronRuby, it appears #invert has it's own implementation, so I'll have to give TofuHash a custom #invert to get that test to pass in IronRuby.&lt;br /&gt;&lt;br /&gt;The second failed test was with YAML serialization and deserialization.  I'll have to dig to find the root cause.  Making a roundtrip from TofuHash to YAML and back, IronRuby resulted in a Hash object instead of a TofuHash.  Just like the prior error, TofuHash doesn't have a custom implementation for #to_yaml, it just inherits it from Hash.  I'm guessing there are differences between the implementations of Hash#to_yaml in MRI and IronRuby that work for Hash but dont work for the subclass TofuHash.&lt;br /&gt;&lt;br /&gt;I'll probably wait until IronRuby 1.0 is released before updating TofuHash to correct these two errors.  Until then, it appears &lt;strong&gt;TofuHash 1.0 will work in IronRuby 0.6 except for #invert and #to_yaml.&lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-8462470796399461351?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/8462470796399461351/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=8462470796399461351' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/8462470796399461351'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/8462470796399461351'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2009/07/ironruby-06-and-tofuhash.html' title='IronRuby 0.6 and TofuHash'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-1577318213311918787</id><published>2009-06-03T11:30:00.002-05:00</published><updated>2009-06-03T11:49:51.388-05:00</updated><title type='text'>White - UI Testing Library (.Net)</title><content type='html'>&lt;a href="http://white.codeplex.com/"&gt;White&lt;/a&gt; is an open source .Net library designed to support Unit Testing of Windows GUIs.  I used it for the first time this week.  The results were good enough to recommend using it again.  The performance was a little slow, so I wouldn't want to have lots of tests.  I prefer to avoid UI Unit Tests by separating the presentation from the logic.  However, sometimes you need to unit test an interaction.  For those cases, White can be useful.&lt;br /&gt;&lt;br /&gt;I'm not going to blog an example here.  The documentation for White has some examples.  See &lt;a href="http://white.codeplex.com/Wiki/View.aspx?title=Get%20Started"&gt;Getting Started&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-1577318213311918787?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/1577318213311918787/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=1577318213311918787' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/1577318213311918787'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/1577318213311918787'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2009/06/white-ui-testing-library-net.html' title='White - UI Testing Library (.Net)'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-3102013020253324039</id><published>2009-04-29T16:02:00.003-05:00</published><updated>2009-04-29T16:58:27.348-05:00</updated><title type='text'>Using Cucumber Testing Framework without Rails</title><content type='html'>Most of the articles for Cucumber are given as Rails examples.  While Cucumber was born for Rails testing, it isn't limited to that environment.  A few simple steps will allow you to use Cucumber with any Ruby project.&lt;br /&gt;&lt;br /&gt;This example will use Rake to run cucumber because the Cucumber::Rake::Task does a lot of work for you.  It will automatically load (require) the features and steps for you.&lt;br /&gt;&lt;br /&gt;First, you should follow Cucumber's pattern for directories:&lt;br /&gt;&lt;table border="1"&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;{project home}/features&lt;/td&gt;&lt;td&gt;stores all the .feature files&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;{project home}/features/step_definitions&lt;/td&gt;&lt;td&gt;stores the .rb files containing steps&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;{project home}/features/support&lt;/td&gt;&lt;td&gt;contains the env.rb file&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;First create a rakefile for your project and add a Cucumber::Rake::Task as follows...&lt;br /&gt;&lt;br /&gt;&lt;script src='http://pastie.org/463087.js'&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Next create the features file(s).  The rake task will automatically require all the .feature files in the features directory.  This example reproduces the additions.feature shown on Cucumber's homepage.&lt;br /&gt;&lt;br /&gt;&lt;script src='http://pastie.org/463094.js'&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;At this time, you may run "rake features" to see Cucumber runs.  The results will show that 4 steps are undefined.  To define the steps create features\step_definitions\addition_steps.rb.  The rake task will automatically require all the step_definitions files.&lt;br /&gt;&lt;br /&gt;&lt;script src='http://pastie.org/463107.js'&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;This example uses a class Calculator from my project.  So lets define that class under lib\calculator.rb.&lt;br /&gt;&lt;br /&gt;&lt;script src='http://pastie.org/463108.js'&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;This calculator isn't very exciting.  It just uses a stack to remember values.  The first item in the stack is the "screen".  The add method will add the top two values.  This is the bare minimum needed to meet the defined feature.  (Normally you would define the class and fill in the details in a test-first fashion.  But to keep this article short, I've posted the completed class.)&lt;br /&gt;&lt;br /&gt;The rake features task doesn't automatically require the calculator.rb file.  Also, if you noticed the addition_steps.rb makes use of rspec expectations, which isn't available by default.  To require these files, create the features/support/env.rb file.  The rake features task will automatically require any file under features/support&lt;br /&gt;&lt;br /&gt;&lt;script src='http://pastie.org/463113.js'&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Now when you run "rake features" everything will work together.  Your steps should all run and pass with green color!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-3102013020253324039?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/3102013020253324039/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=3102013020253324039' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/3102013020253324039'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/3102013020253324039'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2009/04/using-cucumber-testing-framework.html' title='Using Cucumber Testing Framework without Rails'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-7361846754490971859</id><published>2009-04-04T19:42:00.002-05:00</published><updated>2009-04-04T19:47:19.159-05:00</updated><title type='text'>TofuHash is done!</title><content type='html'>I've released &lt;a href="http://tofuhash.rubyforge.org/"&gt;TofuHash&lt;/a&gt; v1.0 which supports the entire Hash interface for both Ruby 1.8.x and Ruby 1.9.1.&lt;br /&gt;&lt;br /&gt;On Monday April 6, I'll be presenting a lightning talk on TofuHash to &lt;a href="http://tech.groups.yahoo.com/group/rubyham/"&gt;Rubyham&lt;/a&gt;.  The talk will mostly cover the ruby 1.9.1 issues encountered.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-7361846754490971859?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/7361846754490971859/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=7361846754490971859' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/7361846754490971859'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/7361846754490971859'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2009/04/tofuhash-is-done.html' title='TofuHash is done!'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-3967665330587724198</id><published>2009-03-12T08:45:00.002-05:00</published><updated>2009-03-12T08:47:35.881-05:00</updated><title type='text'>TofuHash is now a ruby gem.</title><content type='html'>I've released v0.1.0 as a ruby gem.  The documentation is online at &lt;a href="http://tofuhash.rubyforge.org/"&gt;http://tofuhash.rubyforge.org/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;To install it, simply use:&lt;br /&gt;&lt;br /&gt;gem install tofuhash&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-3967665330587724198?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/3967665330587724198/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=3967665330587724198' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/3967665330587724198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/3967665330587724198'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2009/03/tofuhash-is-now-ruby-gem.html' title='TofuHash is now a ruby gem.'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-1398816274521492615</id><published>2009-02-03T09:25:00.002-06:00</published><updated>2009-02-03T09:28:29.033-06:00</updated><title type='text'>wordle.net</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_cPO1tVrLjiw/SYhiJOFY8DI/AAAAAAAAAW0/xsfIoYHb1eo/s1600-h/wordle.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 260px;" src="http://3.bp.blogspot.com/_cPO1tVrLjiw/SYhiJOFY8DI/AAAAAAAAAW0/xsfIoYHb1eo/s400/wordle.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5298592872140435506" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I found &lt;a href="http://www.wordle.net/"&gt;wordle.net&lt;/a&gt; which can generate word clouds from text, blogs, etc.  Just for fun, I created one from my blog.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-1398816274521492615?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/1398816274521492615/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=1398816274521492615' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/1398816274521492615'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/1398816274521492615'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2009/02/wordlenet.html' title='wordle.net'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_cPO1tVrLjiw/SYhiJOFY8DI/AAAAAAAAAW0/xsfIoYHb1eo/s72-c/wordle.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-1172776455052077350</id><published>2008-12-08T09:57:00.001-06:00</published><updated>2008-12-08T10:25:01.849-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='tofuhash'/><title type='text'>tufuhash 0.0.1 available</title><content type='html'>&lt;a href="http://github.com/ghouston/tofuhash/tree/master"&gt;TufuHash is posted on github&lt;/a&gt;.  TofuHash is a case-insensitive hash plus string/symbol indifferent access version of Ruby's Hash.  It is implemented as a subclass of Hash. The behavior is easily modifiable by creating a different TofuKey.  So you could have it perform key lookups anyway you want!&lt;br /&gt;&lt;br /&gt;The current release 0.0.1 hasn't been used in many places.  So if you find defects, send them to me.  I'll get it fixed asap.  So far I've create a bunch of unit tests to verify TofuHash behavior.  These unit tests include modified versions of Ruby's Hash unit tests, sourcecode examples from the ri documentation of Hash, plus some of my own tests.&lt;br /&gt;&lt;br /&gt;So far I've avoided monkey patching Hash.  So there is a known issue where Hash doesn't always know how to handle TofuHash.  For example, you can't compare Hash to TofuHash(myHash == myTofuHash), but the reverse is possible (myTofuHash == myHash).&lt;br /&gt;&lt;br /&gt;The easiest way to create and populate a TofuHash is to use Hash's [ ] syntax as shown here:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;require 'tofuhash'&lt;br /&gt;h = TofuHash[ :aSymbol =&amp;gt; &amp;quot;symbol&amp;quot;, &amp;quot;MixedCaseString&amp;quot; =&amp;gt; &amp;quot;string&amp;quot;, 11 =&amp;gt; &amp;quot;number&amp;quot; ]&lt;br /&gt;puts h[&amp;quot;asymbol&amp;quot;]         #=&amp;gt; &amp;quot;symbol&amp;quot;&lt;br /&gt;puts h[:mixedCaseString]  #=&amp;gt; &amp;quot;string&amp;quot;&lt;br /&gt;puts h[11]                #=&amp;gt; &amp;quot;number&amp;quot;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-1172776455052077350?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/1172776455052077350/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=1172776455052077350' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/1172776455052077350'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/1172776455052077350'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2008/12/tufuhash-001-available.html' title='tufuhash 0.0.1 available'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-334035768979262773</id><published>2008-12-08T09:36:00.001-06:00</published><updated>2008-12-08T09:57:10.605-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='color-block'/><title type='text'>color-block 0.2.0 released</title><content type='html'>Several weeks ago I made &lt;a href="http://github.com/ghouston/color-block/tree/master"&gt;color-block available on github&lt;/a&gt;.  This is a small library to colorize ruby output.  Specifically I wanted to colorize my rake output.  In some rake tasks, I didn't have access to the details of the task.  So I couldn't add color to each string.  Instead color-block allows me to colorize an entire block of code.&lt;br /&gt;&lt;br /&gt;Several friends have tested color-block on Windows, Linux and Apple Mac.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;require 'color-block'&lt;br /&gt;include ColorBlock&lt;br /&gt;&lt;br /&gt;color( :blue ) { &amp;quot;everything in this block is blue!&amp;quot; }&lt;br /&gt;&lt;br /&gt;color( :white, :blue ) do&lt;br /&gt;  puts &amp;quot;now everything is white on blue!&amp;quot;&lt;br /&gt;  color( :green, :black ) { &amp;quot;nesting is supported&amp;quot; }&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;color( :white, :black, :bold ) { &amp;quot;third parameter to specify :bold or :dim&amp;quot; }&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-334035768979262773?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/334035768979262773/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=334035768979262773' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/334035768979262773'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/334035768979262773'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2008/12/color-block-020-released.html' title='color-block 0.2.0 released'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-6099324888725375573</id><published>2008-08-18T15:48:00.002-05:00</published><updated>2008-08-21T13:14:53.951-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>TechMixer University 2008</title><content type='html'>Here is the presentation from &lt;a href="http://techmixeruniversity.com/"&gt;TechMixer University 2008&lt;/a&gt;.  The topic is "Getting Started With Ruby" which is designed to teach an introduction of Ruby.  Along the way, we will see some interesting Ruby features:  dynamic programming, mixins, dependency injection (e.g. how Ruby doesn't require a DI framework).  The slide set contains a couple of bonus slides covering Databases, Builder, Hpricot, RSS::Maker.&lt;br /&gt;&lt;br /&gt;&lt;iframe src='http://docs.google.com/EmbedSlideshow?docid=df8bp35b_16d4w3msfj&amp;amp;size=l' frameborder='0' width='700' height='559'&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;or view it &lt;a href="http://docs.google.com/Presentation?id=df8bp35b_16d4w3msfj"&gt;here on Google Docs&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-6099324888725375573?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/6099324888725375573/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=6099324888725375573' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/6099324888725375573'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/6099324888725375573'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2008/08/techmixer-university-2008.html' title='TechMixer University 2008'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-5594508076275805669</id><published>2008-07-23T11:12:00.004-05:00</published><updated>2008-07-28T14:41:13.018-05:00</updated><title type='text'>Rake Quick Reference</title><content type='html'>I've created a &lt;a href="http://pastie.org/242691"&gt;Rake Quick Reference&lt;/a&gt; available on pastie.org.&lt;br /&gt;&lt;br /&gt;Update : 7/28/2008 paste &lt;a href="http://pastie.org/242691"&gt;#242691&lt;/a&gt; - reworked task generation section; added command-line tip&lt;br /&gt;Update : 7/24/2008 paste &lt;a href="http://pastie.org/240284"&gt;#240284&lt;/a&gt; - added details on namespace.&lt;br /&gt;Release: 7/23/2008 paste &lt;a href="http://pastie.org/239387"&gt;#239387&lt;/a&gt; - original release.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-5594508076275805669?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/5594508076275805669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=5594508076275805669' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/5594508076275805669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/5594508076275805669'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2008/07/rake-quick-reference.html' title='Rake Quick Reference'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-6240020341911188532</id><published>2008-07-16T09:03:00.001-05:00</published><updated>2008-08-22T10:19:05.506-05:00</updated><title type='text'>Hudson (build and continuous integration tool)</title><content type='html'>If you haven't seen &lt;a href="https://hudson.dev.java.net/"&gt;Hudson (https://hudson.dev.java.net/)&lt;/a&gt;, you should give it a look.  I was introduced to it by &lt;a href="http://claymccoy.blogspot.com/"&gt;Clay McCoy&lt;/a&gt; at Rubyham.  After playing with it, I decided to switch from CruiseControl.Net to Hudson.  The switch didn't take long.  In all, I spent &lt; 3 hours total to make the swtich (most was learning time).  The setup was fast (~10min).  Conversion from CC.Net wasn't hard.  I'm very happy with the features of Hudson and it's plugins.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-6240020341911188532?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/6240020341911188532/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=6240020341911188532' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/6240020341911188532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/6240020341911188532'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2008/07/hudson-build-and-continuous-integration.html' title='Hudson (build and continuous integration tool)'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-5655204923585392568</id><published>2008-06-16T10:46:00.000-05:00</published><updated>2008-06-16T11:13:21.674-05:00</updated><title type='text'>How to call Rake from CruiseControl.Net</title><content type='html'>CruiseControl.Net is a great Continuous Integration tool.  It is easier to setup than CruiseControl (java).  Plus it makes more sense to use CC.Net if you work at a .Net shop.&lt;br /&gt;&lt;br /&gt;To script the Continuous Integration process, I first investigated using MSBuild.  At this time, I found MSBuild to work well for building Visual Studio projects.  But MSBuild wasn't mature enough to accomplish much else.  NAnt is a more mature alternative to MSBuild, which I've used on some projects.  NAnt is fairly powerful (even better in my opinion than the original Ant).  However, there is one problem with both these tools:  XML is not a programming language.&lt;br /&gt;&lt;br /&gt;Rake is a programming language.  Rake is actually Ruby, with some additional stuff to give it the powers of Make.  Rake also makes sense in a .Net shop because 1) Ruby can call .Net objects using the Ruby/.Net Bridge.  2) John Lam is currently porting Ruby to run directly on the .Net DLR.&lt;br /&gt;&lt;br /&gt;So how do you get CruiseControl.Net to call Rake?  The best solution would be to create a CC.Net plugin to call Rake.  But if your like me, time is limited.  So an easy kludge will suffice.  The kludge is this: 1) CC.Net calls either MSBuild or NAnt, which is already built in.  2) MSBuild or NAnt executes Rake via an Exec task.&lt;br /&gt;&lt;br /&gt;(You may be wondering why not use CC.Net exec task.  The short answer, I couldn't get CC.Net exec task to call Rake.  I'm not sure why.  It just didn't work well.)&lt;br /&gt;&lt;br /&gt;First - CC.Net calls MSBuild or NAnt.  This is very simple.  In the CC.Net config file you add a task...&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;   &amp;lt;tasks&amp;gt;&lt;br /&gt;      &amp;lt;nant buildFile=&amp;quot;nant.xml&amp;quot; /&amp;gt;&lt;br /&gt;   &amp;lt;/tasks&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;or&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;   &amp;lt;tasks&amp;gt;&lt;br /&gt;      &amp;lt;msbuild projectFile=&amp;quot;msbuild.xml&amp;quot; /&amp;gt;&lt;br /&gt;    &amp;lt;/tasks&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then you have NAnt or MSBuild call Rake.  Here are the nant.xml and msbuild.xml files:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;&amp;lt;project name=&amp;quot;Rake Runner&amp;quot; default=&amp;quot;RakeBuild&amp;quot; basedir=&amp;quot;.&amp;quot;&amp;gt;&lt;br /&gt;  &amp;lt;target name=&amp;quot;RakeBuild&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;exec program=&amp;quot;c:\ruby\bin\rake.bat&amp;quot; /&amp;gt;&lt;br /&gt;  &amp;lt;/target&amp;gt;&lt;br /&gt;&amp;lt;/project&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;lt;Project xmlns=&amp;quot;http://schemas.microsoft.com/developer/msbuild/2003&amp;quot;&lt;br /&gt;    DefaultTargets=&amp;quot;RakeBuild&amp;quot;&amp;gt;&lt;br /&gt;  &amp;lt;Target Name=&amp;quot;RakeBuild&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;Exec Command=&amp;quot;rake&amp;quot; /&amp;gt;&lt;br /&gt;  &amp;lt;/Target&amp;gt;&lt;br /&gt;&amp;lt;/Project&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Notice that each just calls the RakeBuild target, which is the default target.&lt;br /&gt;&lt;br /&gt;Rake will then run the default target (you could specify a Rake task in the scripts above).  Here is an example Rake script which displays all the environment variables:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;task :default =&amp;gt; [:test]&lt;br /&gt;&lt;br /&gt;task :test do&lt;br /&gt;    ENV.each {&amp;#124;k,v&amp;#124; puts &amp;quot;#{k}=#{v}&amp;quot; }&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;CC.Net captures the output a little different for MSBuild vs NAnt.  MSBuild's output is append to the end of the build log.  Which results in a long build log.  NAnt's output is captured to a different page "NAnt Output".  However, NAnt prepends each line with "[exec]".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-5655204923585392568?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/5655204923585392568/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=5655204923585392568' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/5655204923585392568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/5655204923585392568'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2008/06/how-to-call-rake-from-cruisecontrolnet.html' title='How to call Rake from CruiseControl.Net'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-5951292954977365313</id><published>2008-05-11T16:47:00.000-05:00</published><updated>2008-05-11T16:58:28.108-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='twitter'/><title type='text'>Twitter fun</title><content type='html'>Last Friday I attend the &lt;a href="http://www.ipsaonline.org/"&gt;IPSA&lt;/a&gt; meeting on Social Media.  That got me interested in two products: &lt;a href="http://twitter.com/neversleep360"&gt;Twitter&lt;/a&gt; and &lt;a href="http://www.oovoo.com/"&gt;ooVoo&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I've now got a Twitter account using the nickname &lt;a href="http://twitter.com/neversleep360"&gt;neversleep360&lt;/a&gt;.  For which I got curious about the reach of Twitter.  So I wrote a quick ruby script to search out Friends and Friends of Friends, then score everything they were following based on the number of Friends/FriendsX2 following.  This should point out nicks of common interest.  Also, I found several interesting nicks sitting out in the wings.&lt;br /&gt;&lt;br /&gt;I've posted everything on my wiki at &lt;a href="http://ghouston.wiki.zoho.com/Twitter-Friends-of-Friends.html"&gt;Twitter Friends of Friends&lt;/a&gt;.  One interesting result is the number of links to BarackObama.  Personally I'm not a fan of BarackObama; but it is interesting to see him score highly among this circle of friends on Twitter.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-5951292954977365313?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/5951292954977365313/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=5951292954977365313' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/5951292954977365313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/5951292954977365313'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2008/05/twitter-fun.html' title='Twitter fun'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-4182633265748065808</id><published>2008-04-23T13:52:00.000-05:00</published><updated>2008-04-23T13:53:36.052-05:00</updated><title type='text'>Ten Free Must-Have Security Tools</title><content type='html'>eWeek published &lt;a href="http://www.eweek.com/c/a/Security/Ten-Free-MustHave-Security-Tools/"&gt;this list&lt;/a&gt; of useful security tools.  have fun!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-4182633265748065808?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/4182633265748065808/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=4182633265748065808' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/4182633265748065808'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/4182633265748065808'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2008/04/ten-free-must-have-security-tools.html' title='Ten Free Must-Have Security Tools'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-2796726888670398041</id><published>2008-02-19T20:46:00.001-06:00</published><updated>2008-02-19T23:05:59.744-06:00</updated><title type='text'>Unexpected Hash Behavior With String Keys</title><content type='html'>I was looking for a way to create a case-insensitive Hash class.  One suggestion was to use NormalizedHash (&lt;a href="http://pastie.caboo.se/154304"&gt;http://pastie.caboo.se/154304&lt;/a&gt;), and override methods on the String keys.  This doesn't work as expected.&lt;br /&gt;&lt;br /&gt;I found that &lt;strong&gt;Hash makes a duplicate of the String key&lt;/strong&gt;.  This unfortunately removes any methods added in the singleton class.  (surprise!)&lt;br /&gt;&lt;br /&gt;Here is the code to demonstrate this behavior: &lt;a href="http://pastie.caboo.se/154595"&gt;http://pastie.caboo.se/154595&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;----&lt;br /&gt;&lt;br /&gt;Shortly after writing the above post, I came across a little footnote in &lt;a href="http://www.ruby-doc.org/core/classes/Hash.html#M002878"&gt;Hash#[]=&lt;/a&gt; which says... "(a String passed as a key will be duplicated and frozen)"&lt;br /&gt;&lt;br /&gt;I learn something new every day.  (I wish this information was given in the class description instead of the method description where it is easly missed.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-2796726888670398041?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/2796726888670398041/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=2796726888670398041' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/2796726888670398041'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/2796726888670398041'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2008/02/unexpected-hash-behavior-with-string.html' title='Unexpected Hash Behavior With String Keys'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-5332007439468196047</id><published>2007-12-12T11:33:00.000-06:00</published><updated>2007-12-12T11:38:12.029-06:00</updated><title type='text'>How to redefine or mock a class method in Ruby</title><content type='html'>&lt;a href="http://pastie.caboo.se/127608"&gt;http://pastie.caboo.se/127608&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-5332007439468196047?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/5332007439468196047/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=5332007439468196047' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/5332007439468196047'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/5332007439468196047'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2007/12/how-to-redefine-class-method-in-ruby.html' title='How to redefine or mock a class method in Ruby'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-6142314848326035434</id><published>2007-11-26T17:31:00.000-06:00</published><updated>2007-11-26T17:33:21.633-06:00</updated><title type='text'>link: Introduction to Abject-Oriented Programming</title><content type='html'>Funny blog: &lt;a href="http://typicalprogrammer.com/programming/abject-oriented/"&gt;http://typicalprogrammer.com/programming/abject-oriented/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-6142314848326035434?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/6142314848326035434/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=6142314848326035434' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/6142314848326035434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/6142314848326035434'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2007/11/link-introduction-to-abject-oriented.html' title='link: Introduction to Abject-Oriented Programming'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-3951683564013278145</id><published>2007-09-17T15:18:00.000-05:00</published><updated>2007-09-17T15:33:49.997-05:00</updated><title type='text'>My SQL Server 2005 is Slow</title><content type='html'>Testing code that queries SQL Server 2005, I kept observing long delays.  Sometimes my tests would execute in less than one second, which was expected.  Frequently, they would take 30 to 120 seconds!&lt;br /&gt;&lt;br /&gt;A little digging into the SQL Server, I found the two top waits were SQLTRACE_BUFFER_FLUSH and RESOURCE_SEMAPHORE, both of which would grow in correlation to delays I observed when running my unit tests.&lt;br /&gt;&lt;br /&gt;A little reading found: &lt;a href="http://www.sqlnewsgroups.net/group/microsoft.public.sqlserver.server/topic17681.aspx"&gt;this forum topic&lt;/a&gt; and &lt;a href="http://www.microsoft.com/technet/prodtechnol/sql/2005/tsprfprb.mspx"&gt;this kb article&lt;/a&gt;.  The former being the most useful.  It turns out SQL 2005 will run a trace by default; to assist in fixing problems later.  (read "default trace enabled" in SQL Books Online) Unfortunately on my development box, it appears the trace is the source of my delays.  So my solution is to turn off the default trace using:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;exec sp_configure 'show advanced options',1&lt;br /&gt;reconfigure&lt;br /&gt;exec sp_configure 'default trace enabled',0&lt;br /&gt;reconfigure&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;After this, my tests always ran in less than one second!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-3951683564013278145?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/3951683564013278145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=3951683564013278145' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/3951683564013278145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/3951683564013278145'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2007/09/my-sql-server-2005-is-slow.html' title='My SQL Server 2005 is Slow'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-3112458758311511374</id><published>2007-08-08T12:52:00.000-05:00</published><updated>2007-08-08T12:53:37.112-05:00</updated><title type='text'>fun with ruby meta-programming</title><content type='html'>see &lt;a href="http://pastie.caboo.se/86055"&gt;http://pastie.caboo.se/86055&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-3112458758311511374?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/3112458758311511374/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=3112458758311511374' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/3112458758311511374'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/3112458758311511374'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2007/08/fun-with-ruby-meta-programming.html' title='fun with ruby meta-programming'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-8878320340330195331</id><published>2007-08-01T09:03:00.000-05:00</published><updated>2007-08-01T09:07:14.749-05:00</updated><title type='text'>IronRuby alpha</title><content type='html'>John Lam has posted a nice &lt;a href="http://www.iunknown.com/2007/07/a-first-look-at.html"&gt;article about the current work on IronRuby&lt;/a&gt;.  My development team has already started using Ruby to write unit tests.  We are currently using CRuby but plan to port to IronRuby once it is released.  Our product is written on .Net so IronRuby will fit our project very well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-8878320340330195331?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/8878320340330195331/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=8878320340330195331' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/8878320340330195331'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/8878320340330195331'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2007/08/ironruby-alpha.html' title='IronRuby alpha'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-2699154937737547966</id><published>2007-08-01T08:51:00.000-05:00</published><updated>2007-08-01T09:01:11.626-05:00</updated><title type='text'>Diff tools</title><content type='html'>SourceGear just released an update to their free &lt;a href="http://sourcegear.com/diffmerge/downloads.html"&gt;DiffMerge&lt;/a&gt; program.  This product caught my eye because it has a 3-way merge.  My current favorit Diff tool is &lt;a href="http://scootersoftware.com/"&gt;Beyond Compare 2&lt;/a&gt; from Scooter Software ($30).  It has more features than DiffMerge, but doesn't include the 3-way merge which I sometimes need.  The best merge tool I've ever used is &lt;a href="http://www.araxis.com/merge/"&gt;Araxis Merge&lt;/a&gt;, but it costs $269 for the pro edition, I can't justify the extra cost vs the $30 Beyond Compare 2.  Araxis Merge's price tag was worth it when I was working with an offshore team.  I had to 3-way merge code from the US and India across many files and directories.  It would have been too expensive in time if I didn't use Araxis Merge for that task.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-2699154937737547966?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/2699154937737547966/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=2699154937737547966' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/2699154937737547966'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/2699154937737547966'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2007/08/diff-tools.html' title='Diff tools'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-6786038224380437032</id><published>2007-07-05T13:26:00.000-05:00</published><updated>2007-07-05T13:36:11.100-05:00</updated><title type='text'>IIS Authentication and Access Diagnostics Tool</title><content type='html'>I just got through configuring SQL Server 2005 for a Scale-Out Deployment.  One problem I ran into was the NTML "Dual Hop" issue.  Fortunately I found the &lt;a href="http://www.microsoft.com/downloads/results.aspx?pocId=&amp;freetext=Authentication%20and%20Access%20Control%20Diagnostics%20&amp;DisplayLang=en"&gt;IIS Authentication and Access Diagnostics Tool&lt;/a&gt; which helped quickly identify the issue.  This tool hasn't been mentioned much, so I am recommending it.&lt;br /&gt;&lt;br /&gt;Now I've got a happy system with Report Server running separately from Reporting Services Database.  Everything is working great: Reports and Report Builder.  I've seen other sites which said this configuration would not work.  I managed to get it working using Integrated Authentication and Kerberos.&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-6786038224380437032?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/6786038224380437032/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=6786038224380437032' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/6786038224380437032'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/6786038224380437032'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2007/07/iis-authentication-and-access.html' title='IIS Authentication and Access Diagnostics Tool'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-8532616591609506292</id><published>2007-05-21T15:39:00.000-05:00</published><updated>2007-05-24T16:00:32.945-05:00</updated><title type='text'>Ruby Require Idiom</title><content type='html'>Ruby's "require" command can accidentally load the same file twice.  &lt;br /&gt;&lt;br /&gt;The following example shows this problem (2 files)...&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;#----------&lt;br /&gt;# file: problem.rb&lt;br /&gt;puts &amp;quot;#{__FILE__} loaded&amp;quot;&lt;br /&gt;&lt;br /&gt;#----------&lt;br /&gt;# file: run_me.rb&lt;br /&gt;require '././problem'   #=&amp;gt;  .\problem.rb loaded&lt;br /&gt;require 'problem'       #=&amp;gt;  ./problem.rb loaded&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When run_me requires problem.rb using slightly different paths, Kernel#require loads it twice.  This happens because Kernel#require tracks the files it has loaded in the $" array.  It only does a String compare, so if the file names differ it doesn't find the match.&lt;br /&gt;&lt;br /&gt;There are several ways to avoid loading the same file twice.  The first technique is to call require using the absolute path of the file.  Since every file only has one absolute path, Kernal#require will not get confused.  To get the absolute path, we can use File.expand_path as shown in the following example.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;#----------&lt;br /&gt;# file: ok.rb&lt;br /&gt;puts &amp;quot;#{__FILE__} loaded&amp;quot;&lt;br /&gt;&lt;br /&gt;#----------&lt;br /&gt;# file: run_me.rb&lt;br /&gt;require File.expand_path('././ok')  #=&amp;gt; C:/ruby/require/expand_path/ok.rb loaded &lt;br /&gt;require File.expand_path('ok')      #=&amp;gt; &lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Another effective technique is using indirection.  That is, require a file that requires other files.  This technique works really well for loading libraries and gems.  The first file may get loaded multiple times because of arguments to Kernel#require.  But once inside this file, all calls to Kernel#require are the same.  So the sub-files are not loaded multiple times.  The following example illustrates this solution.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;#----------&lt;br /&gt;# file: run_me.rb&lt;br /&gt;require 'base'  #=&amp;gt; ./required_by_base.rb loaded&lt;br /&gt;require '././base'&lt;br /&gt;&lt;br /&gt;#----------&lt;br /&gt;# file: base.rb&lt;br /&gt;$:.unshift(File.expand_path(File.dirname(__FILE__))) unless&lt;br /&gt;  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))&lt;br /&gt;&lt;br /&gt;require 'required_by_base'&lt;br /&gt;&lt;br /&gt;#----------&lt;br /&gt;# file: required_by_base.rb&lt;br /&gt;puts &amp;quot;#{__FILE__} loaded&amp;quot;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;See how "base.rb" is required twice using different file paths.  Kernel#require actually loaded "base.rb" twice.  But "base.rb" didn't do anything except call Kernel#require to load other files.  Since the parameter 'required_by_base' was the same in both calls, "required_by_base.rb" was only loaded once.&lt;br /&gt;&lt;br /&gt;The first two lines of "base.rb" add the current directory to the search path.  This wasn't really necessary for this example since the "required_by_base.rb" file is in the same directory.  However, if the require used a relative path to another directory, it would have failed.  By adding the current directory to the front of the search path this ensures the correct files are loaded.&lt;br /&gt;&lt;br /&gt;If you look closely, you will see that the File.expand_path is used to put the absolute path into the search path.  This avoids adding the same path twice.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-8532616591609506292?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/8532616591609506292/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=8532616591609506292' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/8532616591609506292'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/8532616591609506292'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2007/05/ruby-require-idiom.html' title='Ruby Require Idiom'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-9127550539881087810</id><published>2007-05-02T14:21:00.000-05:00</published><updated>2007-05-02T14:27:04.101-05:00</updated><title type='text'>DLR is here!  Ruby soon to follow!</title><content type='html'>&lt;a href="http://www.codeplex.com/IronPython/Release/ProjectReleases.aspx?ReleaseId=438"&gt;IronPython (2.0 Alpha)&lt;/a&gt; is now available with the Dynamic Language Runtime (DLR).  &lt;br /&gt;&lt;br /&gt;Microsoft also announced support for JScript on the DLR.  They say releases of Ruby and VB will soon follow.  (source: &lt;a href="http://blogs.msdn.com/hugunin/archive/2007/04/30/a-dynamic-language-runtime-dlr.aspx"&gt;Jim Hugunin's Thinking Dynamic: A Dynamic Language Runtime&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;This is great news to me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-9127550539881087810?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/9127550539881087810/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=9127550539881087810' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/9127550539881087810'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/9127550539881087810'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2007/05/dlr-is-here-ruby-soon-to-follow.html' title='DLR is here!  Ruby soon to follow!'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-2077825887924940587</id><published>2007-04-25T09:17:00.001-05:00</published><updated>2007-04-25T09:23:25.548-05:00</updated><title type='text'>Microsoft to support dynamic languages?</title><content type='html'>&lt;a href='http://blogs.zdnet.com/microsoft/?p=404'&gt;ZDNet published news that Microsoft will publish a "Dynammic Language Runtime" (DLR)&lt;/a&gt; to provide support for dynamic languages like Ruby to run on the .Net CLR.&amp;amp;nbsp; This is great news to me.&amp;amp;nbsp; I've tried many dynamic languages for .Net, but haven't found anything I could use in production.&amp;amp;nbsp; IronPython is the best I've found.&amp;amp;nbsp; But you can't fully integrate it into existing C# projects.&amp;amp;nbsp; IronPython can use C# classes, but C# can't use IronPython classes.&amp;amp;nbsp; I cant wait until the day I can run Ruby on .Net, with full integration to non-dynamic language projects.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-2077825887924940587?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/2077825887924940587/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=2077825887924940587' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/2077825887924940587'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/2077825887924940587'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2007/04/microsoft-to-support-dynamic-languages.html' title='Microsoft to support dynamic languages?'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-2833088507909599035</id><published>2007-04-18T08:53:00.000-05:00</published><updated>2007-04-18T09:38:01.032-05:00</updated><title type='text'>RSpec</title><content type='html'>I been using &lt;a href="http://rspec.rubyforge.org/"&gt;RSpec&lt;/a&gt; for about 1 week now.  I must say I really love it.  Anyone who has worked with me knows I'm a test-first style developer.  Now I switched to a spec-first developer!&lt;br /&gt;&lt;br /&gt;RSpec is a ruby library for Behavior Driven Development (BDD).  It accomplishes the same purpose as Unit Testing, automated tests for development.  The big difference is BDD changes the way you think about tests.&lt;br /&gt;&lt;br /&gt;With BDD, you begin by defining a "context" which is a situation or state of the system under test.  For example, for a Stack object one context would be an "empty stack".&lt;br /&gt;&lt;br /&gt;Next, you define the "specifications" for the "context".  BDD uses language such as "should be", "should not" to describe the specification.  In the "empty stack" context, the specification might include "should be empty", and "pop should throw exception".  Within the specification we add the test code to check that the specification is followed.  Here is the ruby code for this example:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;context &amp;quot;A new stack&amp;quot; do&lt;br /&gt;  &lt;br /&gt;  setup do&lt;br /&gt;    @stack = Stack.new&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  specify &amp;quot;should be empty&amp;quot; do&lt;br /&gt;    @stack.should be_empty&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  specify &amp;quot;pop must throw exception&amp;quot; do&lt;br /&gt;    lambda { @stack.pop }.should raise_error&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Notice how easy it is to read the code above.  This is what I like about RSpec verses xUnit.  The contexts and specifications provide guidance about how to orginize your tests.&lt;br /&gt;&lt;br /&gt;RSpec does not stop there.  RSpec also includes RCov so you can easily see a report of test coverage.  This is very handy to find holes in your specifications and tests.  RSpec includes a mock object framework to help isolate the system under test.  You can also use the mock objects to test the object interation of the system under test.  RSpec does support Rails development.&lt;br /&gt;&lt;br /&gt;Anyone interested in learning Behavior Driven Development or RSpec, I highly recommend working through the &lt;a href="http://rspec.rubyforge.org/tutorials/index.html"&gt;RSpec tutorial&lt;/a&gt;.  The tutorial really provides a great exercise in BDD.  I had read about BDD, but it wasn't until I completed the tutorial that I internalized it.  (If you need Ruby, you can download it from &lt;a href="http://www.ruby-lang.org/en/downloads/"&gt;ruby-lang.org&lt;/a&gt;, I use the Windows One-Click Install.  Then type "gem install rspec" on the command-line to get rspec.  Very quick and easy!)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-2833088507909599035?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/2833088507909599035/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=2833088507909599035' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/2833088507909599035'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/2833088507909599035'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2007/04/rspec.html' title='RSpec'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-117088095511138041</id><published>2007-02-07T14:40:00.000-06:00</published><updated>2007-02-07T14:42:35.633-06:00</updated><title type='text'>Rubyham</title><content type='html'>Our local user group holds it's &lt;a href="http://rubyham.wordpress.com/2007/02/07/our-first-code-day/"&gt;First Code Day&lt;/a&gt;!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-117088095511138041?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/117088095511138041/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=117088095511138041' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/117088095511138041'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/117088095511138041'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2007/02/rubyham.html' title='Rubyham'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-116820821586847223</id><published>2007-01-07T16:12:00.000-06:00</published><updated>2007-01-07T16:16:56.033-06:00</updated><title type='text'>XBox 360</title><content type='html'>I joined the ranks of XBox 360 players this holiday season.  My gamer profile link is &lt;a href="http://live.xbox.com/member/NeverSleep360"&gt;NeverSleep360&lt;/a&gt;.  I've also put my gamer card on the side bar.  Game On!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-116820821586847223?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/116820821586847223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=116820821586847223' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/116820821586847223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/116820821586847223'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2007/01/xbox-360.html' title='XBox 360'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-116800881850239474</id><published>2007-01-05T08:05:00.000-06:00</published><updated>2007-01-05T08:53:39.120-06:00</updated><title type='text'>I'm on Google EngEDU!</title><content type='html'>Jack Herrington in his presentation &lt;a href="http://video.google.com/videoplay?docid=1541014406319673545&amp;q=google+engedu"&gt;Code Generation With Ruby&lt;/a&gt; (Google Video), a comment references &lt;a href="http://blogs.pragprog.com/cgi-bin/pragdave.cgi/Tech/Ruby/ActiveRecordAndLegacyDatabases.rdoc"&gt;Dave Thomas's Blog post Rails and the Legacy World&lt;/a&gt; which talks about my post &lt;a href="http://ghouston.blogspot.com/2006/07/let-activerecord-support-enterprise.html"&gt;Let ActiveRecord support Enterprise Databases&lt;/a&gt;!  The reference is part of the after presentation discussion at about 35 min in the video.  One of the developers talks about the technique I used to modify ActiveRecord to support Sql Server, and references my blog post.  Wow!  I only thought a couple of my friends read this blog.&lt;br /&gt;&lt;br /&gt;Mr. Herrington's presentation provides a good overview of Code Generation, different options, and notes about when it is appropriate or not.  He then shows some implementations of Code Generation using Ruby and ERb.  The discussion after the presentation is very interesting.  They talk about different experiences with Code Generation and Active Record.&lt;br /&gt;&lt;br /&gt;A couple of months ago I did some SQL code generation in Ruby.  I should create a post about it soon.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-116800881850239474?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/116800881850239474/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=116800881850239474' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/116800881850239474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/116800881850239474'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2007/01/im-on-google-engedu.html' title='I&apos;m on Google EngEDU!'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-116679916284627434</id><published>2006-12-22T08:48:00.000-06:00</published><updated>2006-12-22T08:56:11.126-06:00</updated><title type='text'>Wii Browser</title><content type='html'>Nintendo released a demo of their browser for the Wii.  It seems to work pretty well for checking the weather, email, google.  I tried a few of the kids sites like NickJr, but it only played some of the flash content.  The videos didn't work since they were windows media.  Since I can now check Weather.com using the browser, I doubt I would use their Forcast Channel.&lt;br /&gt;&lt;br /&gt;If you have a Wii, try &lt;a href="http://www.wiicade.com/"&gt;WiiCade&lt;/a&gt; which has some good games optimized for the Wii.  There are also some wii flash games at &lt;a href="http://www.albinoblacksheep.com/games/wii/"&gt;Albino Black Sheep Wii Games&lt;/a&gt;;  but I havent tried them so I cant comment on the quality of the games at Albino.  WiiCade had certainly done a good job making a Wii optimized page, and providing good games.&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-116679916284627434?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/116679916284627434/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=116679916284627434' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/116679916284627434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/116679916284627434'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/12/wii-browser.html' title='Wii Browser'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-115958506855783931</id><published>2006-09-29T21:51:00.000-05:00</published><updated>2006-09-29T21:57:48.853-05:00</updated><title type='text'>RSS feeds from Ruby</title><content type='html'>A friend asked me if I knew a good way to create RSS feeds.  He want RSS feeds created for some web sites that didn't already have them.  My favorit answer: Ruby.&lt;br /&gt;&lt;br /&gt;So I created a demo script in Ruby that parses Fatwallet.com and creates an RSS feed for topics that are rated "Better" or higher.  The hardest part of this problem was parsing the HTML, but Ruby made that pretty easy.  Creating the RSS information was very simple.&lt;br /&gt;&lt;br /&gt;The code below has plenty of comments because my friend doesn't know Ruby.  His background is more .Net, Java, and Perl.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;#  This is a simple example.  It reads the Hot Topics forum&lt;br /&gt;#  on Fatwallet.com finding all topics rated &amp;quot;Better&amp;quot; or higher.&lt;br /&gt;#  It will print these topics and their URL as it finds them.&lt;br /&gt;#  Finally, it prints the RSS feed for this information.&lt;br /&gt;#  See: http://www.fatwallet.com/c/18/&lt;br /&gt;#&lt;br /&gt;#  Three steps to run this script...&lt;br /&gt;#&lt;br /&gt;#  You can get Ruby from http://www.ruby-lang.org/en/downloads/&lt;br /&gt;#  I highly recommend the One-click Installer for Windows&lt;br /&gt;#&lt;br /&gt;#  This program uses an extra library, Hpricot, to parse HTML.&lt;br /&gt;#  To get Hpricot installed, use Ruby's package manager &amp;quot;Gems&amp;quot;&lt;br /&gt;#  Just run the follow at your DOS cmd prompt&lt;br /&gt;#            gem install hpricot&lt;br /&gt;#&lt;br /&gt;#  To run the program from the DOS cmd prompt...&lt;br /&gt;#            ruby RubyBot-forRich.rb&lt;br /&gt;#&lt;br /&gt;#  RSS feed creation using the RSS library for Ruby&lt;br /&gt;#  see: http://www.ruby-doc.org/stdlib/libdoc/rss/rdoc/index.html&lt;br /&gt;#  tutorial: http://www.cozmixng.org/~rwiki/?cmd=view;name=RSS+Parser%3A%3ATutorial.en&lt;br /&gt;&lt;br /&gt;# &amp;quot;require&amp;quot; is not like &amp;quot;using&amp;quot; in C# nor &amp;quot;#include&amp;quot; in C++.&lt;br /&gt;# require searches the library for the correct ruby file and executes it.&lt;br /&gt;require 'rubygems'&lt;br /&gt;require 'open-uri'&lt;br /&gt;require 'rss/maker'&lt;br /&gt;begin&lt;br /&gt;  require 'hpricot'&lt;br /&gt;rescue LoadError  # this is like a Try Catch, but there are nifty differences&lt;br /&gt;  puts 'Please run &amp;quot;gem install hpricot&amp;quot; before running this program.'&lt;br /&gt;  exit&lt;br /&gt;end&lt;br /&gt; &lt;br /&gt;BETTER = 4  # a constant&lt;br /&gt; &lt;br /&gt;doc = Hpricot(open('http://www.fatwallet.com/c/18/'))&lt;br /&gt;&lt;br /&gt;rss = RSS::Maker.make(&amp;quot;1.0&amp;quot;) { &amp;#124;maker&amp;#124;&lt;br /&gt;  #&lt;br /&gt;  # Let me explain what is happening...&lt;br /&gt;  # The &amp;quot;.make&amp;quot; method created a Maker object, passed it into&lt;br /&gt;  #  the block (i.e. everything between { and }) as the variable 'maker'.&lt;br /&gt;  #  Executed the block.  Then &amp;quot;.make&amp;quot; returns the RSS object that&lt;br /&gt;  #  was built while executing the block.&lt;br /&gt;  #&lt;br /&gt;  maker.channel.about = 'http://www.fatwallet.com/c/18/'&lt;br /&gt;  maker.channel.title = 'Fatwallet.com Hot Deals Forum'&lt;br /&gt;  maker.channel.description = 'Hot deals rated &amp;quot;Better&amp;quot; or higher.'&lt;br /&gt;  maker.channel.link = 'http://www.fatwallet.com/c/18/'&lt;br /&gt;&lt;br /&gt;  puts 'Searching...'  # puts is similar to WriteLine in .Net&lt;br /&gt;  &lt;br /&gt;  (doc/'tr').each { &amp;#124; tr &amp;#124;&lt;br /&gt;    # &lt;br /&gt;    # (doc/'tr')  =&amp;gt; performed an XPath search on doc and got a collection of &amp;lt;tr&amp;gt; nodes&lt;br /&gt;    # .each  =&amp;gt; iterates over the collection passing elements one at a time to the &amp;quot;{ &amp;#124;tr&amp;#124; ... }&amp;quot; block&lt;br /&gt;    # { &amp;#124; tr &amp;#124; ... } =&amp;gt; this is a Closure, the variable 'tr' gets set to the element passed in&lt;br /&gt;    #&lt;br /&gt;    # similar to C#...&lt;br /&gt;    # foreach( Node tr in doc.FindAllNodes( 'tr' ) ) { ... }&lt;br /&gt;    # but not really since it is using a closure.&lt;br /&gt;    #&lt;br /&gt;    # I had to loop on &amp;lt;TR&amp;gt; html tags because I will need to reference this tag later.&lt;br /&gt;    #&lt;br /&gt;   (tr/'td/img[@title]').each { &amp;#124;img&amp;#124;&lt;br /&gt;      if img['title'] =~ /rating: (\d+)/&lt;br /&gt;        # $1 is the first group from the match, the rating number&lt;br /&gt;        if $1.to_i &amp;gt;= BETTER&lt;br /&gt;          (tr/'a[@href]').each { &amp;#124; a &amp;#124;&lt;br /&gt;            if a['href'] =~ /^\/t\/18/&lt;br /&gt;              puts &amp;quot;http://fatwallet.com#{a['href']} #{a.inner_html}&amp;quot;&lt;br /&gt;&lt;br /&gt;              item = maker.items.new_item&lt;br /&gt;              item.link = &amp;quot;http://fatwallet.com#{a['href']}&amp;quot;&lt;br /&gt;              item.title = a.inner_html&lt;br /&gt;              &lt;br /&gt;            end &lt;br /&gt;          } # each a&lt;br /&gt;        end # if rating &amp;gt;= better&lt;br /&gt;      end # if title is rating&lt;br /&gt;    } # each img&lt;br /&gt;  } # each tr&lt;br /&gt;} # RSS maker&lt;br /&gt;&lt;br /&gt;puts &amp;quot;\nRSS...&amp;quot;&lt;br /&gt;puts rss&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-115958506855783931?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/115958506855783931/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=115958506855783931' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/115958506855783931'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/115958506855783931'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/09/rss-feeds-from-ruby.html' title='RSS feeds from Ruby'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-115958465283775875</id><published>2006-09-29T21:50:00.000-05:00</published><updated>2006-09-29T21:50:53.036-05:00</updated><title type='text'>Long time no post... why?</title><content type='html'>Two months and nothing posted.  The reason is my wife is pregnant with our third child.  Just like the first two, the pregnancy is very difficult.  So I haven't done much blogging nor extra coding.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-115958465283775875?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/115958465283775875/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=115958465283775875' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/115958465283775875'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/115958465283775875'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/09/long-time-no-post-why.html' title='Long time no post... why?'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-115360931439052329</id><published>2006-07-22T17:57:00.000-05:00</published><updated>2006-07-22T18:03:49.620-05:00</updated><title type='text'>Let ActiveRecord support Enterprise Databases.</title><content type='html'>I am currently investigating using ActiveRecord's Migrations to support a legacy enterprise application.  Migrations could help us because we currently support multiple versions of the product, which means multiple versions of the schema.  Development and QA are already spending too much time reinstalling different versions of the database.&lt;br /&gt;&lt;br /&gt;So can ActiveRecord Migrations support my application?  Nope; not right out of the box.&lt;br /&gt;&lt;br /&gt;Can I tweak ActiveRecord to support my application?  &lt;strong&gt;YES! It isn't too hard to extend/override ActiveRecord.&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Why can't ActiveRecord support my application out of the box?  The short answer is ActiveRecord was written to only support a database neutral schema.  Supporting multiple databases means only supporting the lowest common denominator.  So db specific types in my schema like tinyint and smallint get simplified to integer.  ActiveRecord doesn't support all the different constraints that are available: foreign keys, composite keys, triggers.  Also, I noticed ActiveRecord did not capture any of my Views (SqlServer).&lt;br /&gt;&lt;br /&gt;In addition, I have a deployment problem.  I have to ship and deploy my application to customers.  Right now, I can't ship and install Ruby on those machines.  So I'd rather just have ActiveRecord Migrations produce a SQL file that I can deploy.&lt;br /&gt;&lt;br /&gt;After a little experimentation, I discovered it is possible to easily overcome these issues.  The first is can I run Migrations without Rails?  This is easily accomplished as described on &lt;a href="http://blogs.pragprog.com/cgi-bin/pragdave.cgi/Tech/Ruby/MigrationsOutsideRails.rdoc"&gt;PragDave's blog&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Next, I wanted to know how I could modify ActiveRecord to serve my needs.  Thankfully Ruby is such a flexible language that it allows modification of existing classes.  So I can override ActiveRecord methods as needed.  For example:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;require 'rubygems'&lt;br /&gt;require 'active_record'&lt;br /&gt;&lt;br /&gt;module ActiveRecord&lt;br /&gt;  module ConnectionAdapters # :nodoc:&lt;br /&gt;    class SQLServerAdapter&lt;br /&gt;      def execute( sql, name = nil )&lt;br /&gt;        puts sql&lt;br /&gt;        puts &amp;quot;GO&amp;quot;&lt;br /&gt;        puts &lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In the example above, I first load ActiveRecord, then modify the SQLServerAdapter's execute method (my database is SqlServer).  It turns out that this method is called by Migration to send SQL to the database.  So in this example, I am simply sending the SQL to STDOUT.  Notice that I can also modify the output.  In this example I add the “GO” command between SQL statements.  I could have just as easily added transactions or error checking.  With a few more tweaks, I could have sent this to a file to generate a SQL script from the Migration.&lt;br /&gt;&lt;br /&gt;ActiveRecord contains code to simplify data types for database neutrality.  Since the legacy database uses many other types, this simplification is an issue.  So after examining the source, I found a couple of places where the simplification is applied.  By overriding these methods it is easy to get all ActiveRecord to support the data types required.  For example, the code below adds several types.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;module ActiveRecord&lt;br /&gt;  module ConnectionAdapters # :nodoc:&lt;br /&gt;    class SQLServerAdapter&lt;br /&gt;      def native_database_types&lt;br /&gt;        SQLServerAdapter.native_database_types&lt;br /&gt;      end&lt;br /&gt;      &lt;br /&gt;      def self.native_database_types&lt;br /&gt;        {&lt;br /&gt;          :binary =&amp;gt; { :name =&amp;gt; &amp;quot;binary&amp;quot;, :haslimit =&amp;gt; true },&lt;br /&gt;          :bit     =&amp;gt; { :name =&amp;gt; &amp;quot;bit&amp;quot;},&lt;br /&gt;          :char =&amp;gt; { :name =&amp;gt; &amp;quot;char&amp;quot;, :haslimit =&amp;gt; true },&lt;br /&gt;          :decimal =&amp;gt; { :name =&amp;gt; &amp;quot;decimal&amp;quot; },&lt;br /&gt;          :int     =&amp;gt; { :name =&amp;gt; &amp;quot;int&amp;quot; },&lt;br /&gt;          :nvarchar =&amp;gt; { :name =&amp;gt; &amp;quot;nvarchar&amp;quot; },&lt;br /&gt;          :real =&amp;gt; { :name =&amp;gt; &amp;quot;real&amp;quot; },&lt;br /&gt;          :smallint =&amp;gt; { :name =&amp;gt; &amp;quot;smallint&amp;quot; },&lt;br /&gt;          :tinyint =&amp;gt; { :name =&amp;gt; &amp;quot;tinyint&amp;quot; },&lt;br /&gt;          :timestamp =&amp;gt; { :name =&amp;gt; &amp;quot;timestamp&amp;quot; },&lt;br /&gt;          :uniqueidentifier =&amp;gt; { :name =&amp;gt; &amp;quot;uniqueidentifier&amp;quot; },&lt;br /&gt;          :varchar      =&amp;gt; { :name =&amp;gt; &amp;quot;varchar&amp;quot;, :limit =&amp;gt; 255, :haslimit =&amp;gt; true  },&lt;br /&gt;          :primary_key =&amp;gt; &amp;quot;int NOT NULL IDENTITY(1, 1) PRIMARY KEY&amp;quot;,&lt;br /&gt;          :text        =&amp;gt; { :name =&amp;gt; &amp;quot;text&amp;quot; },&lt;br /&gt;          :float       =&amp;gt; { :name =&amp;gt; &amp;quot;float&amp;quot;, :limit =&amp;gt; 8 },&lt;br /&gt;          :datetime    =&amp;gt; { :name =&amp;gt; &amp;quot;datetime&amp;quot; },&lt;br /&gt;          :image      =&amp;gt; { :name =&amp;gt; &amp;quot;image&amp;quot;},&lt;br /&gt;        }&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    class ColumnWithIdentity&lt;br /&gt;      def initialize(name, default, sql_type = nil, is_identity = false, null = true, scale_value = 0)&lt;br /&gt;        super(name, default, sql_type, null)&lt;br /&gt;        @identity = is_identity&lt;br /&gt;        @is_special = sql_type =~ /text&amp;#124;ntext&amp;#124;image/i ? true : false&lt;br /&gt;        @scale = scale_value&lt;br /&gt;        # SQL Server only supports limits on a few types&lt;br /&gt;        @limit = nil unless SQLServerAdapter.native_database_types[@type][:haslimit] == true&lt;br /&gt;      end&lt;br /&gt;&lt;br /&gt;      &lt;br /&gt;      #DO NOT SIMPLIFY, Just use the native type name; trim off size&lt;br /&gt;      def simplified_type(field_type)&lt;br /&gt;        field_type.slice( /[^\(]*/).to_sym &lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This example shows how easy it is to change ActiveRecord's behavior as needed.&lt;br /&gt;&lt;br /&gt;Now the code above isn't a complete solution, but it will get SchemaDump to output the correct types that my legacy system is using.  If you look at the original methods you can see the changes were pretty simple to make.  One refactoring I did was to make SQLServerAdapter's instance method native_database_types into a class method.  Then I could access it from ColumnWithIdentity, where it was copied code before.  Also, I added the :haslimit key to make the code in ColumnWithIdentity more data driven off the native_database_types hash.  Before, it had the types with limits hard coded into the ColumnWithIdentity initialize method.&lt;br /&gt;&lt;br /&gt;What about adding new features?  This is probably the easiest of all.  A frequent request is to support composite keys.  Just as an example of extending the DSL, the following will create a primary key constraint and support multiple columns in the key.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;module ActiveRecord&lt;br /&gt;  module ConnectionAdapters # :nodoc:&lt;br /&gt;    module SchemaStatements&lt;br /&gt;      def add_pk(table_name, column_names)&lt;br /&gt;        quoted_column_names = column_names.map { &amp;#124;e&amp;#124; quote_column_name(e) }.join(&amp;quot;, &amp;quot;)&lt;br /&gt;        sql = &amp;quot;ALTER TABLE #{table_name} ADD CONSTRAINT PK_#{table_name} PRIMARY KEY CLUSTERED ( #{quoted_column_names} ) ON [PRIMARY]&amp;quot;&lt;br /&gt;        execute(sql)&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is simple DSL programming in Ruby.  Another approach is to allow the :primarykey option for the create_table method to take an array of column names.  I'll leave that exercise for later.&lt;br /&gt;&lt;br /&gt;These examples show what is possible.  I know there is a raging debate about supporting db neutrality verses db specifics.  DHH has expressed his intention to keep Rails db neutral, because that is best for the world he lives within.  For those of us unfortunate enough to live with legacy databases, we need an ActiveRecord that fully supports our database.  &lt;strong&gt;Why not support both?&lt;/strong&gt;  Why not setup a method for the enterprise folks to add the database specifics to ActiveRecord?  Maybe some form of plug-in or stable API that we could extend (my changes above risk being broken by future versions of ActiveRecord).  To satisfy the db neutral camp, just generate warnings or errors if db specific extensions are used when ActiveRecord is configured to be db neutral.&lt;br /&gt;&lt;br /&gt;Happy Migrating!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-115360931439052329?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/115360931439052329/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=115360931439052329' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/115360931439052329'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/115360931439052329'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/07/let-activerecord-support-enterprise.html' title='Let ActiveRecord support Enterprise Databases.'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-115169825282062425</id><published>2006-06-30T15:07:00.000-05:00</published><updated>2006-06-30T15:10:57.776-05:00</updated><title type='text'>Ruby compiler for .Net !!!!!</title><content type='html'>The &lt;a href="http://plas.fit.qut.edu.au/Ruby.NET/"&gt;Gardens Point Ruby.NET Compiler&lt;/a&gt; has released its first beta version!  Good work!  I really want to use Ruby on the CLR.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-115169825282062425?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/115169825282062425/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=115169825282062425' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/115169825282062425'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/115169825282062425'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/06/ruby-compiler-for-net.html' title='Ruby compiler for .Net !!!!!'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-115109362437036083</id><published>2006-06-23T15:13:00.000-05:00</published><updated>2006-06-23T15:13:44.720-05:00</updated><title type='text'>YAGNI</title><content type='html'>LOL: &lt;a href="The Yagni Development Assistant"&gt;The Yagni Development Assistant&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-115109362437036083?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/115109362437036083/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=115109362437036083' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/115109362437036083'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/115109362437036083'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/06/yagni.html' title='YAGNI'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-115101332801459602</id><published>2006-06-22T16:54:00.000-05:00</published><updated>2006-10-06T10:49:40.570-05:00</updated><title type='text'>Ruby: Meta Programming and Stack Traces</title><content type='html'>A couple of times I have run into trouble debugging or tracing a method in Ruby.  Usually you can just call Kernal.caller to get a stack trace.  But what if the method was generated?  You don't get the correct location.  For example:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;class Kung&lt;br /&gt;  mstr = %-&lt;br /&gt;        def foo&lt;br /&gt;          puts 'Hello World from Kung.foo'&lt;br /&gt;          puts caller(0)&lt;br /&gt;        end&lt;br /&gt;      -&lt;br /&gt;  module_eval mstr&lt;br /&gt;end&lt;br /&gt;    &lt;br /&gt;Kung.new.foo&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Which generates the following output:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Hello World from Kung.foo&lt;br /&gt;(eval):4:in `foo'&lt;br /&gt;Kung-foo.rb:11&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The stack trace only shows "(Eval):4:in 'foo'" which is almost useless.  The "(Eval)" is a clue that the method was dynamically created using meta-programming.  In this simple example, it is easy to find the dynamic code since it is near the caller "Kung-foo.rb:11".   However in a real project it is frequently located far away, possibly in other source files.&lt;br /&gt;&lt;br /&gt;To fix the stack trace, the author should use the optional arguments to method_eval as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;class Monkey&lt;br /&gt;  line, mstr = __LINE__, %-&lt;br /&gt;        def see&lt;br /&gt;          puts 'Hello World from Monkey.see'&lt;br /&gt;          puts caller(0)&lt;br /&gt;        end&lt;br /&gt;      -&lt;br /&gt;  module_eval mstr, __FILE__, line&lt;br /&gt;end&lt;br /&gt;    &lt;br /&gt;Monkey.new.see&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The output now shows the correct line number and file name:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Hello World from Monkey.see&lt;br /&gt;Monkey-see.rb:5:in `see'&lt;br /&gt;Monkey-see.rb:11&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Update&lt;/b&gt; after reading the code in ActiveSupport core_ext\attribute_accessors.rb I found a nice way to do the above with fewer lines of code:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;class Monkey&lt;br /&gt;  module_eval(&amp;lt;&amp;lt;-EOS, __FILE__, __LINE__)&lt;br /&gt;        def see&lt;br /&gt;          puts 'Hello World from Monkey.see'&lt;br /&gt;          puts caller(0)&lt;br /&gt;        end&lt;br /&gt;      EOS&lt;br /&gt;end&lt;br /&gt;    &lt;br /&gt;Monkey.new.see&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-115101332801459602?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/115101332801459602/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=115101332801459602' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/115101332801459602'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/115101332801459602'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/06/ruby-meta-programming-and-stack-traces.html' title='Ruby: Meta Programming and Stack Traces'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-115075191084335346</id><published>2006-06-19T16:14:00.001-05:00</published><updated>2008-06-16T09:33:56.750-05:00</updated><title type='text'>Ruby Class Variables, Attributes and Constants</title><content type='html'>Ruby Class Variables, Attributes and Constants&lt;br /&gt;&lt;br /&gt;(For a related post, see &lt;a href="http://blog.thinkrelevance.com/2006/11/16/use-class-instance-variables-not-class-variables"&gt;Use Class Instance Variables Not Class Variables&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Writing a little ruby code the other day, I wanted to use a class variables but it didn't behave as expected.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;01: class Class_Variable&lt;br /&gt;02:   @@var = 1&lt;br /&gt;03:   def Class_Variable.report; @@var end&lt;br /&gt;04: end&lt;br /&gt;05: &lt;br /&gt;06: class Child_V &amp;lt; Class_Variable&lt;br /&gt;07:   @@var = 2&lt;br /&gt;08: end&lt;br /&gt;09:&lt;br /&gt;10: puts Class_Variable.report    #=&amp;gt; 2&lt;br /&gt;11: puts Child_V.report           #=&amp;gt; 2&lt;br /&gt;12: &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I was surprised by the result.  Most other languages would have the child class shadow the parent field, but Ruby shared it!  Ruby does provide Class Attributes and Constants as alternatives, but each has it's own symantics.&lt;br /&gt;&lt;br /&gt;I threw together the following code to show the differences.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;01: class Class_Variable&lt;br /&gt;02:   @@var = 1&lt;br /&gt;03:   def Class_Variable.report; @@var end&lt;br /&gt;04: end&lt;br /&gt;05: &lt;br /&gt;06: class Child_V &amp;lt; Class_Variable&lt;br /&gt;07:   @@var = 2&lt;br /&gt;08: end&lt;br /&gt;09:&lt;br /&gt;10: puts Class_Variable.report    #=&amp;gt; 2&lt;br /&gt;11: puts Child_V.report           #=&amp;gt; 2&lt;br /&gt;12: &lt;br /&gt;13:&lt;br /&gt;14:&lt;br /&gt;15: class Class_Attribute&lt;br /&gt;16:   @var = 1 #class attribute&lt;br /&gt;17:   &lt;br /&gt;18:   def initialize&lt;br /&gt;19:     @var = 2 #instance attribute&lt;br /&gt;20:   end&lt;br /&gt;21:  &lt;br /&gt;22:   def report&lt;br /&gt;23:     @var # instance attribute, not the class attribute&lt;br /&gt;24:   end&lt;br /&gt;25: &lt;br /&gt;26:   def Class_Attribute.report&lt;br /&gt;27:     @var # class attribute&lt;br /&gt;28:   end&lt;br /&gt;29: end&lt;br /&gt;30:&lt;br /&gt;31: class Child_A &amp;lt; Class_Attribute&lt;br /&gt;32:   @var = 3&lt;br /&gt;33: end&lt;br /&gt;34: &lt;br /&gt;35: puts Class_Attribute.report        #=&amp;gt; 1&lt;br /&gt;36: puts Class_Attribute.new.report    #=&amp;gt; 2&lt;br /&gt;37: puts Child_A.report                #=&amp;gt; 3&lt;br /&gt;38: puts Child_A.new.report            #=&amp;gt; 2&lt;br /&gt;39: &lt;br /&gt;40:&lt;br /&gt;41: &lt;br /&gt;42: class Class_Constant&lt;br /&gt;43:   VAR = [ 'a' ]&lt;br /&gt;44:   VAR2 = [ 'b' ]&lt;br /&gt;45:  &lt;br /&gt;46:   def self.report&lt;br /&gt;47:     VAR2[0]&lt;br /&gt;48:   end&lt;br /&gt;49: end&lt;br /&gt;50:&lt;br /&gt;51: class Child_C &amp;lt; Class_Constant&lt;br /&gt;52:   VAR2 = [ 'c' ]&lt;br /&gt;53: end&lt;br /&gt;54: &lt;br /&gt;55: puts Class_Constant::VAR[0]     #=&amp;gt; 'a'&lt;br /&gt;56: puts Class_Constant::VAR2[0]    #=&amp;gt; 'b'&lt;br /&gt;57: puts Class_Constant.report      #=&amp;gt; 'b'&lt;br /&gt;58: #puts Child_C::VAR[0]           #=&amp;gt; uninitialized constant error&lt;br /&gt;59: puts Child_C::VAR2[0]           #=&amp;gt; 'c'&lt;br /&gt;60: puts Child_C.report             #=&amp;gt; 'b'&lt;br /&gt;61:&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;First notice that Class Variables are shared with their subclass (lines 1-11) .  This differs greatly from Java and C# which shadow inherited variables.&lt;br /&gt;&lt;br /&gt;The Class Attributes and Constants are "class private".  That is, the child has no access to the parent attribute/constant with the same name. Class methods however are inherited.  So calling "report" for Child_A and Child_C displays a significant difference between using Class Attributes and Constants (lines 37 and 60).&lt;br /&gt;&lt;br /&gt;Unfortunately none of these alternatives matches the behavior seen in other languages.  This can cause some confusion when going from Java or C# to Ruby.  Class Attributes using accessor methods is the closest match to other languages.  However the syntax similarities between class attributes and instance attributes can cause problems (lines 16, 19, 23, 27).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-115075191084335346?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/115075191084335346/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=115075191084335346' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/115075191084335346'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/115075191084335346'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/06/ruby-class-variables-attributes-and.html' title='Ruby Class Variables, Attributes and Constants'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-114962521350463364</id><published>2006-06-06T15:16:00.000-05:00</published><updated>2006-06-06T15:20:14.073-05:00</updated><title type='text'>Updated: Format My Source Code for Blogging</title><content type='html'>I have updated &lt;a href="http://formatmysourcecode.blogspot.com/"&gt;Format My Source Code for Blogging&lt;/a&gt; site to handle 2 space tabs.  2 space tabs are generally used in Ruby programs.&lt;br /&gt;&lt;br /&gt;Go &lt;a href="http://ruby-lang.org/"&gt;Ruby&lt;/a&gt;!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-114962521350463364?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/114962521350463364/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=114962521350463364' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/114962521350463364'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/114962521350463364'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/06/updated-format-my-source-code-for.html' title='Updated: Format My Source Code for Blogging'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-114849476605559042</id><published>2006-05-24T12:39:00.000-05:00</published><updated>2006-05-24T13:20:05.196-05:00</updated><title type='text'>attr_accessor meta programming</title><content type='html'>Reading &lt;a href="http://jamis.jamisbuck.org/articles/2006/04/20/writing-domain-specific-languages"&gt;Jamis Buck's article Writing Domain Specific Languages&lt;/a&gt; I decided to attempt his challenge to write my own attr_accessor function.&lt;br /&gt;&lt;br /&gt;First, I was curious to see how attr_accessor was implemented in Ruby.  I found the source in object.c which simply calls "rb_attr(klass, rb_to_id(argv[i]), 1, 1, Qtrue);".  The "rb_attr" function is located in eval.c.  If you spend a few min looking at it, you will see it has special code for handling Access Control (public, private, protected).  For now, I will ignore Access Control, and just implement creating the accessor methods.&lt;br /&gt;&lt;br /&gt;Where should attr_accessor go?  Looking at the docs, you will find attr_accessor is a member of Module.  To see if I had the correct location, I quickly wrote...&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;module Module&lt;br /&gt;  alias old_attr_accessor attr_accessor&lt;br /&gt;  &lt;br /&gt;  def attr_accessor( *symbols )&lt;br /&gt;    puts &amp;quot;attr_accessor called with #{symbols.join(' ')}.&amp;quot;&lt;br /&gt;    old_attr_accessor( *symbols )&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This failed since Module is not a module, it is a class!  Laughing at myself and Ruby, I corrected the definition.  The code above also demonstrates how easy you can implement simple Aspect Oriented Programming in Ruby.  Using alias, I give the old attr_accessor method an new name old_attr_accessor.  Then overwrite attr_accessor with my own code.  Any call to attr_accessor will now print out the information that it was called.&lt;br /&gt;&lt;br /&gt;Fun so far, but I haven't really defined my own version of attr_accessor.  I've simple called the old one.  I found module_eval does the trick (class_eval also works since it is a synonym for Module.module_eval).  The final code is...&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;class Module&lt;br /&gt;  def attr_accessor( *symbols )&lt;br /&gt;    symbols.each { &amp;#124; symbol &amp;#124;&lt;br /&gt;      module_eval( &amp;quot;def #{symbol}() @#{symbol}; end&amp;quot; )&lt;br /&gt;      module_eval( &amp;quot;def #{symbol}=(val) @#{symbol} = val; end&amp;quot; )&lt;br /&gt;    }&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class Foobar &lt;br /&gt;  attr_accessor :foo&lt;br /&gt;  private&lt;br /&gt;    attr_accessor :bar&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;fb = Foobar.new&lt;br /&gt;fb.foo = &amp;quot;hello&amp;quot;&lt;br /&gt;fb.bar = &amp;quot;world&amp;quot;&lt;br /&gt;puts fb.foo  # &amp;gt;&amp;gt; hello&lt;br /&gt;puts fb.bar  # &amp;gt;&amp;gt; world&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Pretty simple.  Unfortunately, this demonstrates the problem where my attr_accessor doesn't know about the Access Control.  Looking at the Ruby library and source, I could not find any way to query the Access Control level from within my attr_accessor.  So the only solution I could find is the following hack...&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;class Module&lt;br /&gt;  alias old_public public&lt;br /&gt;  alias old_private private&lt;br /&gt;  alias old_protected protected&lt;br /&gt;  &lt;br /&gt;  def public( aSymbol = nil )&lt;br /&gt;    if aSymbol.nil? &lt;br /&gt;      @__module_access_level = 'public' &lt;br /&gt;      old_public&lt;br /&gt;    else&lt;br /&gt;      old_public( aSymbol )&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def private( aSymbol = nil )&lt;br /&gt;    if aSymbol.nil? &lt;br /&gt;      @__module_access_level = 'private' &lt;br /&gt;      old_private&lt;br /&gt;    else&lt;br /&gt;      old_private( aSymbol )&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def protected( aSymbol = nil )&lt;br /&gt;    if aSymbol.nil? &lt;br /&gt;      @__module_access_level = 'protected' &lt;br /&gt;      old_private&lt;br /&gt;    else&lt;br /&gt;      old_private( aSymbol )&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def attr_accessor( *symbols )&lt;br /&gt;    symbols.each { &amp;#124; symbol &amp;#124;&lt;br /&gt;      module_eval( &amp;quot;def #{symbol}() @#{symbol}; end&amp;quot; )&lt;br /&gt;      module_eval( &amp;quot;def #{symbol}=(val) @#{symbol} = val; end&amp;quot; )&lt;br /&gt;      module_eval( &amp;quot;#{@__module_access_level} :#{symbol}; #{@__module_access_level} :#{symbol}=&amp;quot; )&lt;br /&gt;    }&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  @__module_access_level = 'public'&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class Foobar &lt;br /&gt;  attr_accessor :foo&lt;br /&gt;  private&lt;br /&gt;    attr_accessor :bar&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;fb = Foobar.new&lt;br /&gt;fb.foo = &amp;quot;hello&amp;quot;&lt;br /&gt;fb.bar = &amp;quot;world&amp;quot; #&amp;gt;&amp;gt; private method `bar=' called for #&amp;lt;Foobar:0x2855710 @foo=&amp;quot;hello&amp;quot;&amp;gt; (NoMethodError)&lt;br /&gt;puts fb.foo  #&lt;br /&gt;puts fb.bar  # &lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Anyone got a better idea for handling Access Control?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-114849476605559042?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/114849476605559042/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=114849476605559042' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/114849476605559042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/114849476605559042'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/05/attraccessor-meta-programming.html' title='attr_accessor meta programming'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-114783342041396648</id><published>2006-05-16T21:27:00.000-05:00</published><updated>2006-05-16T21:37:00.773-05:00</updated><title type='text'>Rubyham</title><content type='html'>It has been over a month since my last post.  I have been playing around with Ruby Rails in the little spare time I can find.  Sometime I might post more of my experiences with it.&lt;br /&gt;&lt;br /&gt;In breaking news, Birmingham is getting a Ruby users group named &lt;a href="http://groups.yahoo.com/group/rubyham/"&gt;Rubyham&lt;/a&gt;.  Kicked off by Josh Adams, Kevin Russell and Myself.  It will be fun!&lt;br /&gt;&lt;br /&gt;Playing with Rails, I used the &lt;a href="http://technoweenie.stikipad.com/plugins/show/Acts+as+Authenticated"&gt;Act As Authenticated&lt;/a&gt; plugin.  The plugin seems to work fine.  When adding the User Activation feature, I found a few changes were needed to make me happy.  I have posted them back to the &lt;a href="http://technoweenie.stikipad.com/plugins/show/User+Activation"&gt;User Activation&lt;/a&gt; page.  Here is the &lt;a href="http://technoweenie.stikipad.com/plugins/revision/show/5/User+Activation"&gt;revision with my changes at the bottom&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-114783342041396648?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/114783342041396648/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=114783342041396648' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/114783342041396648'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/114783342041396648'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/05/rubyham.html' title='Rubyham'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-114409087030138965</id><published>2006-04-03T13:55:00.000-05:00</published><updated>2006-04-03T14:01:13.983-05:00</updated><title type='text'>SQL on Rails</title><content type='html'>&lt;a href="http://photos1.blogger.com/blogger/238/819/1600/SqlOnRails.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/238/819/400/SqlOnRails.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;Looks like Rails is taking over the world.  Here is the first new langauge fork of Rails that implements all the Rails goodness: &lt;a href="http://www.sqlonrails.org/"&gt;SQL on Rails&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The a short screen cast is located &lt;a href="http://www.sqlonrails.org/"&gt;HERE&lt;/a&gt;.  Eight minutes that will change your life.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-114409087030138965?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/114409087030138965/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=114409087030138965' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/114409087030138965'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/114409087030138965'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/04/sql-on-rails.html' title='SQL on Rails'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-114161724617087475</id><published>2006-03-05T21:10:00.000-06:00</published><updated>2006-03-05T21:54:06.183-06:00</updated><title type='text'>Using SSL with Ruby http-access2</title><content type='html'>Expanding on my Ruby scripts, I wanted to download information from my yahoo account.  Using Ruby to get HTTP is super easy.  For example, the following will print the contents of &lt;a href="http://www.w3.org/"&gt;http://www.w3.org/&lt;/a&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;require 'http-access2'&lt;br /&gt;client = HTTPAccess2::Client.new()&lt;br /&gt;puts client.get('http://www.w3.org/').content&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Sometime later, I may post some examples of parsing HTML which is also super easy.  For now I will talk about getting SSL to work.&lt;br /&gt;&lt;br /&gt;Ruby &lt;a href="http://raa.ruby-lang.org/project/http-access2/"&gt;http-access2&lt;/a&gt; is a great library for writting web servers and clients.  In this instance I am writting a simple client to login to yahoo and download information like my bookmarks.  To login to yahoo, Ruby must use SSL.&lt;br /&gt;&lt;br /&gt;It turns out that calling SSL from ruby is pretty easy.  Just add the SSL configuration information.  [Also, I changed the URL in this example.]&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;require 'http-access2'&lt;br /&gt;client = HTTPAccess2::Client.new()&lt;br /&gt;client.ssl_config.set_trust_ca('ca.cert')&lt;br /&gt;puts client.get('https://login.yahoo.com/config/login?').content&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This works great, if you have the correct certificate.  If you don't (which happened to me), you get the message:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;at depth 0 - 20: unable to get local issuer certificate&lt;br /&gt;http-access2.rb:1001:in `connect': certificate verify failed (OpenSSL::SSL::SSLError)&lt;br /&gt;        from c:/codetiger/ruby/tools/ruby/lib/ruby/site_ruby/1.8/http-access2.rb:1001:in `ssl_connect'&lt;br /&gt;        from c:/codetiger/ruby/tools/ruby/lib/ruby/site_ruby/1.8/http-access2.rb:1363:in `connect'&lt;br /&gt;        ...&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Figuring out what caused this error was a little confusing because of the &amp;quot;unable to get local issuer certificate&amp;quot; message.  It really means &amp;quot;Unable to validate the certificate of the host because the trusted root certificate was not found locally.&amp;quot;  Unfortunately http-access2's docs are almost non-existent.  I eventually found this information from the &lt;a href="http://curl.haxx.se/docs/faq.html"&gt;cURL faq&lt;/a&gt;!  cURL and http-access2 both use OpenSSL, so the faq about this error is correct.  The error message in the stack trace was from OpenSSL.&lt;br /&gt;&lt;br /&gt;To solve this error, I had to get the correct root certificate.  This is easily accomplished.  First, check the web page properties in your browser.  For the yahoo page, you will find yahoo is signed by &amp;quot;Equifax Secure Certificate Authority&amp;quot;.  I'm using Windows XP, so all I had to do was go into Control Panel -&amp;gt; Internet Options -&amp;gt; Content tab -&amp;gt; Certificates -&amp;gt; Trusted Root Certificates -&amp;gt; select &amp;quot;Equifax Secure Certificate Authority&amp;quot; -&amp;gt; Export -&amp;gt select Base 64 Encoding -&amp;gt; save to file (EquifaxSecureCertificateAuthority.cer).  [Firefox did not have an export option.]&lt;br /&gt;&lt;br /&gt;Now that the trusted root cert is in a file, Ruby can use it...&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;require 'http-access2'&lt;br /&gt;client = HTTPAccess2::Client.new()&lt;br /&gt;client.ssl_config.set_trust_ca('EquifaxSecureCertificateAuthority.cer')&lt;br /&gt;puts client.get('https://login.yahoo.com/config/login?').content&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Yahoo!!!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-114161724617087475?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/114161724617087475/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=114161724617087475' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/114161724617087475'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/114161724617087475'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/03/using-ssl-with-ruby-http-access2.html' title='Using SSL with Ruby http-access2'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-114144600262180152</id><published>2006-03-03T21:32:00.000-06:00</published><updated>2006-03-03T22:20:02.640-06:00</updated><title type='text'>.Net in Ruby</title><content type='html'>While creating a simple backup script (see &lt;a href="http://ghouston.blogspot.com/2006/01/from-ant-to-ruby-122-lines-of-fun.html"&gt;previous post&lt;/a&gt;), I needed to copy more than the file's data.  The backup copy needed to include the meta-data that Windows keeps for the file.  Ruby (and Java or Ant) can easily copy the contents of a file, but they don't know how to copy the meta-data.  The solution is to use .Net, but I wanted to write my script in Ruby.&lt;br /&gt;&lt;br /&gt;I found the &lt;a href="http://www.saltypickle.com/rubydotnet"&gt;Ruby/.Net Bridge&lt;/a&gt; worked like magic. For example to copy a file, just use...&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;require 'dotnet' # Ruby / .Net bridge&lt;br /&gt;System.IO.File.Copy( srcpath, destpath )&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The install of Ruby/.Net Bridge was very simple.  Just download, unzip, and run deploy.cmd.  The ease of installation made me very happy.&lt;br /&gt;&lt;br /&gt;After I created my backup script.  I wondered if this Bridge worked with .Net v2.0.  So I took a spare machine and removed .Net v1.1 to make sure the Bridge could only use v2.0.  Everything worked perfect!&lt;br /&gt;&lt;br /&gt;The one area that I had trouble was handling .Net's Enum.  In .Net, the &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemiofileattributesclasstopic.asp"&gt;FileAttributes&lt;/a&gt; class is an Enum which is also a bit field (see &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemflagsattributeclasstopic.asp"&gt;FlagsAttribute&lt;/a&gt;).  Using the Ruby/.Net Bridge, I could not perform bit-wise math operations on the Enum.  I asked the authors, who gave me a good solution using the Parse method.  For example:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;require 'dotnet' # Ruby / .Net bridge&lt;br /&gt;&lt;br /&gt;def attributeRemove( fileattribute, attribute )&lt;br /&gt;    Enum.parse( System.IO.FileAttributes, (fileattribute.ToString().split(', ') - [attribute]).join( ', ' ) )&lt;br /&gt;end&lt;br /&gt;    &lt;br /&gt;def setReadWrite( dospath )&lt;br /&gt;    attrs = attributeRemove( System.IO.File.GetAttributes( dospath ), 'ReadOnly' )&lt;br /&gt;    System.IO.File.SetAttributes( dospath, attrs )&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The last feature that I wanted, was to decrypt files and folders that were stored in encrypted file systems.  Since Windows encryption used a key tied to the machine and user, the backup should not stay encrypted.   If the machine failed it may be impossible to get the necessary key to decrypt.  Unfortunately there wasn't a .Net method to decrypt the file or folder.  Instead I had to call the win32api.  This was pretty easy to do (however, I found the available documentation very lacking.)  The following is a combination of some Utility methods, and the DecryptFile method I created for my script.  &lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;require 'Win32API'&lt;br /&gt;require 'dotnet' # Ruby / .Net bridge http://www.saltypickle.com/rubydotnet/ just download it, uncompress and run deploy.cmd (per instructions on site)&lt;br /&gt;&lt;br /&gt;class Utils&lt;br /&gt;    def Utils.attribute?( dospath, attribute )&lt;br /&gt;        if attribute.is_a?(String)&lt;br /&gt;            return System.IO.File.GetAttributes( dospath ).ToString().split(', ').include?( attribute )&lt;br /&gt;        else&lt;br /&gt;            raise &amp;quot;attribute parameter must be a String.  attribute.class=#{attribute.class}&amp;quot;&lt;br /&gt;        end&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    def Utils.attributeAdd( fileattribute, attribute )&lt;br /&gt;        Enum.parse( System.IO.FileAttributes, fileattribute.ToString() + ', ' + attribute )&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    def Utils.attributeRemove( fileattribute, attribute )&lt;br /&gt;        Enum.parse( System.IO.FileAttributes, (fileattribute.ToString().split(', ') - [attribute]).join( ', ' ) )&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    def Utils.setReadWrite( dospath )&lt;br /&gt;        attrs = Utils.attributeRemove( System.IO.File.GetAttributes( dospath ), 'ReadOnly' )&lt;br /&gt;        System.IO.File.SetAttributes( dospath, attrs )&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    def Utils.setReadOnly( dospath )&lt;br /&gt;        attrs = Utils.attributeAdd( System.IO.File.GetAttributes( dospath ), 'ReadOnly' )&lt;br /&gt;        System.IO.File.SetAttributes( dospath, attrs )&lt;br /&gt;    end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class Win32API&lt;br /&gt;    def Win32API.DecryptFile( dospath )&lt;br /&gt;        Utils.setReadWrite( dospath ) if  isReadOnly = Utils.attribute?( dospath, 'ReadOnly' )&lt;br /&gt;        result = Win32API.new('Advapi32', 'DecryptFile', %w(p i), 'i').call(dospath,0)&lt;br /&gt;        #todo better error checking&lt;br /&gt;        if result == 0&lt;br /&gt;            Utils.setReadOnly( dospath ) if isReadOnly&lt;br /&gt;            raise &amp;quot;DecryptFile call failed on path: \&amp;quot;#{dospath}\&amp;quot;.  see also: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/decryptfile.asp&amp;quot;&lt;br /&gt;        end&lt;br /&gt;        Utils.setReadOnly( dospath ) if isReadOnly&lt;br /&gt;        return result&lt;br /&gt;    end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;An example usage...&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;if Utils.attribute?( path, 'Encrypted' )&lt;br /&gt;    Win32API.DecryptFile( path )&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-114144600262180152?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/114144600262180152/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=114144600262180152' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/114144600262180152'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/114144600262180152'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/03/net-in-ruby.html' title='.Net in Ruby'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-114047590194340092</id><published>2006-02-20T15:24:00.000-06:00</published><updated>2006-02-20T17:01:24.870-06:00</updated><title type='text'>About: Format My Source Code</title><content type='html'>Several times I have wanted to post code to my blog.  Only to find the process frustrating.  To put the code on a blog you have to convert the source text into HTML.  This also involves converting tabs to spaces; converting special characters to HTML encoding; setting a nice fixed-width font; and fixing a couple of other minor issues.&lt;br /&gt;&lt;br /&gt;After searching around, I found a web page that would format C# and other Microsoft languages at &lt;a href="http://www.manoli.net/csharpformat/"&gt;C# code format&lt;/a&gt;.  Which was great for C#, but I wanted to post Ruby, Java and other languages.  My answer was to code my own source code to HTML converter.  After hacking a little java-script, I have created:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://formatmysourcecode.blogspot.com/"&gt;&lt;span style="font-size:180%;"&gt;Format My Source Code&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The application is just a little bit of Java Script and DHTML to perform the conversion.  I decided to publish it on blogspot since it was a tool for blogging.  Getting everything to fit in the confines of a Blog page was a little limiting.  I might change the layout when I've got more time.&lt;br /&gt;&lt;br /&gt;The application has a few interesting features.  When you press the "Format" button, I have the output section perform a &lt;a href="http://www.37signals.com/svn/archives/000558.php"&gt;yellow fade &lt;/a&gt;which was invented by Matthew Linderman at &lt;a href="http://www.37signals.com/"&gt;37 Signals&lt;/a&gt;.  I modified their technique a little to adjust the timing.&lt;br /&gt;&lt;br /&gt;One problem I encountered was Blogger's editor.  The "Compose" option would eat vertical pipe characters: |.  Since my favorite language Ruby uses this character a lot, I tried hard to find a way to fix it.  But "Compose" would always remove the characters.  Fortunately, the "Edit HTML" option leaves the | character alone.  So I added the detection of this character and a small warning will display.&lt;br /&gt;&lt;br /&gt;To increase the usability, I added some code to automatically select the first input when the page loads.  So a simple ctrl-v will paste into the input field without requiring any additional typing or mousing.  Likewise, the generated HTML is automatically selected so all you need is to hit ctrl-c to copy to the clipboard.&lt;br /&gt;&lt;br /&gt;I have the example output clipped to 25 lines.  Also, if Embed Stylesheet is not used, an example style sheet will appear.&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;br /&gt;&lt;br /&gt;If you are curious, here is the source code (at the time it was first posted):&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;!-- THIS STUFF GOES IN THE HEADER TEMPLATE --&amp;gt;&lt;br /&gt;&amp;lt;style type=&amp;quot;text/css&amp;quot;&amp;gt;&lt;br /&gt;pre.source-code {&lt;br /&gt;  font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; &lt;br /&gt;  color: #000000;&lt;br /&gt;  background-color: #eee;&lt;br /&gt;  font-size: 12px;&lt;br /&gt;  border: 1px dashed #999999;&lt;br /&gt;  line-height: 14px;&lt;br /&gt;  padding: 5px;&lt;br /&gt;  overflow: auto;&lt;br /&gt;  width: 100%&lt;br /&gt;}&lt;br /&gt;p.warning {&lt;br /&gt;  color: #000000;&lt;br /&gt;  background-color: #FFB6C1;&lt;br /&gt;  font-size: 12px;&lt;br /&gt;  border: 3px double #333333;&lt;br /&gt;  line-height: 14px;&lt;br /&gt;  padding: 5px;&lt;br /&gt;  overflow: auto;&lt;br /&gt;  width: 100%&lt;br /&gt;}&lt;br /&gt;&amp;lt;/style&amp;gt; &lt;br /&gt;&amp;lt;SCRIPT LANGUAGE=&amp;quot;JavaScript&amp;quot;&amp;gt; &lt;br /&gt;&amp;lt;!-- &lt;br /&gt;var Color= new Array();&lt;br /&gt;Color[1] = &amp;quot;ff&amp;quot;;&lt;br /&gt;Color[2] = &amp;quot;ee&amp;quot;;&lt;br /&gt;Color[3] = &amp;quot;dd&amp;quot;;&lt;br /&gt;Color[4] = &amp;quot;cc&amp;quot;;&lt;br /&gt;Color[5] = &amp;quot;bb&amp;quot;;&lt;br /&gt;Color[6] = &amp;quot;aa&amp;quot;;&lt;br /&gt;Color[7] = &amp;quot;99&amp;quot;;&lt;br /&gt;&lt;br /&gt;function fadeIn(where) {&lt;br /&gt;  if (where &amp;gt;= 1) {&lt;br /&gt;      document.getElementById('fade').style.backgroundColor = &amp;quot;#ffff&amp;quot; + Color[where];&lt;br /&gt;    if (where &amp;gt; 1) {&lt;br /&gt;      where -= 1;&lt;br /&gt;      setTimeout(&amp;quot;fadeIn(&amp;quot;+where+&amp;quot;)&amp;quot;, 200);&lt;br /&gt;    } else {&lt;br /&gt;      where -= 1;&lt;br /&gt;      setTimeout(&amp;quot;fadeIn(&amp;quot;+where+&amp;quot;)&amp;quot;, 200);&lt;br /&gt;      document.getElementById('fade').style.backgroundColor = &amp;quot;transparent&amp;quot;;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function format() {&lt;br /&gt;    var strIn = document.getElementById(&amp;quot;textin&amp;quot;).value;&lt;br /&gt;    var strOut = null;&lt;br /&gt;    if ( document.getElementById(&amp;quot;embedstyle&amp;quot;).checked ) {&lt;br /&gt;        strOut = &amp;quot;&amp;lt;pre style=\&amp;quot;font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%\&amp;quot;&amp;gt;&amp;lt;code&amp;gt;&amp;quot;;&lt;br /&gt;        hideElement(&amp;quot;style&amp;quot;);&lt;br /&gt;    } else {&lt;br /&gt;        strOut = &amp;quot;&amp;lt;pre class=\&amp;quot;source-code\&amp;quot;&amp;gt;&amp;lt;code&amp;gt;&amp;quot;;&lt;br /&gt;        showElement(&amp;quot;style&amp;quot;);&lt;br /&gt;    }&lt;br /&gt;    var strOut25 = null;&lt;br /&gt;    var line = 1;&lt;br /&gt;    var strTab;&lt;br /&gt;    var hasVerticalPipe = false;&lt;br /&gt;    &lt;br /&gt;    if ( document.getElementById(&amp;quot;tab4&amp;quot;).checked ) {&lt;br /&gt;    strTab = &amp;quot;    &amp;quot;;&lt;br /&gt;    } else {&lt;br /&gt;        strTab = &amp;quot;        &amp;quot;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    for ( i = 0; i &amp;lt; strIn.length; i++ ) {&lt;br /&gt;        var code = strIn.charCodeAt(i);&lt;br /&gt;        switch( code ) {&lt;br /&gt;            case 9: // tab&lt;br /&gt;                strOut += strTab;&lt;br /&gt;        break;&lt;br /&gt;            case 10:  // line-feed&lt;br /&gt;            case 13:  &lt;br /&gt;                strOut += &amp;quot;\n&amp;quot;;&lt;br /&gt;                line += 1;&lt;br /&gt;                if ( line == 26 ) {&lt;br /&gt;                    strOut25 = strOut + &amp;quot;[only the first 25 lines shown in this example]\n\n&amp;quot;;&lt;br /&gt;                }&lt;br /&gt;                if ( code == 13 &amp;amp;&amp;amp; (i + 1) &amp;lt; strIn.length &amp;amp;&amp;amp; strIn.charCodeAt(i + 1) == 10 ) {&lt;br /&gt;                    i++;&lt;br /&gt;                }&lt;br /&gt;                break;&lt;br /&gt;            case 34:&lt;br /&gt;                strOut += &amp;quot;&amp;amp;quot;&amp;quot;;&lt;br /&gt;                break;&lt;br /&gt;            case 38:&lt;br /&gt;                strOut += &amp;quot;&amp;amp;amp;&amp;quot;;&lt;br /&gt;                break;&lt;br /&gt;            case 60:&lt;br /&gt;                strOut += &amp;quot;&amp;amp;lt;&amp;quot;;&lt;br /&gt;                break;&lt;br /&gt;            case 62:&lt;br /&gt;                strOut += &amp;quot;&amp;amp;gt;&amp;quot;;&lt;br /&gt;                break;&lt;br /&gt;            case 124: // vertical pipe (blogger modifies this)&lt;br /&gt;                strOut += &amp;quot;&amp;amp;#124;&amp;quot;;&lt;br /&gt;                hasVerticalPipe = true;&lt;br /&gt;                break;&lt;br /&gt;            default:&lt;br /&gt;                if ( code &amp;gt;= 32 &amp;amp;&amp;amp; code &amp;lt;= 127 ) {&lt;br /&gt;                    strOut += strIn.charAt(i);&lt;br /&gt;                } else {&lt;br /&gt;                    strOut += &amp;quot;&amp;amp;#&amp;quot; + code + &amp;quot;;&amp;quot;;&lt;br /&gt;                }&lt;br /&gt;                break;&lt;br /&gt;        } // switch&lt;br /&gt;    } // for&lt;br /&gt;    strOut += &amp;quot;\n&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;quot;;&lt;br /&gt;    var textoutelement = document.getElementById(&amp;quot;textout&amp;quot;)&lt;br /&gt;    textoutelement.value = strOut;&lt;br /&gt;    textoutelement.focus();&lt;br /&gt;    textoutelement.select();&lt;br /&gt;&lt;br /&gt;    if ( hasVerticalPipe ) {&lt;br /&gt;        showElement( &amp;quot;vert-pipe-warning&amp;quot; );&lt;br /&gt;    } else {&lt;br /&gt;        hideElement( &amp;quot;vert-pipe-warning&amp;quot; );&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    var resultselement = document.getElementById(&amp;quot;results&amp;quot;);&lt;br /&gt;    if ( strOut25 != null ) {&lt;br /&gt;        resultselement.innerHTML = strOut25;&lt;br /&gt;    } else {&lt;br /&gt;        resultselement.innerHTML = strOut;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    fadeIn(7);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function onloadEvent() {&lt;br /&gt;    var textinelement = document.getElementById(&amp;quot;textin&amp;quot;);&lt;br /&gt;    textinelement.focus();&lt;br /&gt;    textinelement.select();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function showElement(strId) {&lt;br /&gt;    var ref = document.getElementById(strId);&lt;br /&gt;    if ( ref.style) { ref = ref.style; }&lt;br /&gt;    ref.display = '';&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function hideElement(strId) {&lt;br /&gt;    var ref = document.getElementById(strId);&lt;br /&gt;    if ( ref.style) { ref = ref.style; }&lt;br /&gt;    ref.display = 'none';&lt;br /&gt;}&lt;br /&gt;//--&amp;gt;&lt;br /&gt;&amp;lt;/SCRIPT&amp;gt; &lt;br /&gt;&amp;lt;!-- END STUFF GOES IN THE HEADER TEMPLATE --&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;!-- THE BODY ELEMENT NEEDS THE ONLOAD EVENT --&amp;gt;&lt;br /&gt;&amp;lt;body onLoad=&amp;quot;javascript:onloadEvent()&amp;quot;&amp;gt;&lt;br /&gt;&amp;lt;!-- THIS STUFF GOES IN POST --&amp;gt;&lt;br /&gt;&amp;lt;form&amp;gt;&lt;br /&gt;&amp;lt;p&amp;gt;&lt;br /&gt;&amp;lt;textarea wrap=&amp;quot;off&amp;quot; rows=&amp;quot;5&amp;quot; cols=&amp;quot;50&amp;quot; id=&amp;quot;textin&amp;quot;&amp;gt;Paste your text here.&amp;lt;/textarea&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;&amp;lt;table&amp;gt;&lt;br /&gt;    &amp;lt;tr&amp;gt;&lt;br /&gt;        &amp;lt;td&amp;gt;&amp;lt;button onclick=&amp;quot;format()&amp;quot; type=&amp;quot;button&amp;quot;&amp;gt;Format Text&amp;lt;/button&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;td&amp;gt;&lt;br /&gt;            Tab size: &amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;tabsize&amp;quot; id=&amp;quot;tab4&amp;quot; checked=&amp;quot;true&amp;quot;&amp;gt;4&amp;lt;/input&amp;gt; &amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;tabsize&amp;quot; id=&amp;quot;tab8&amp;quot;&amp;gt;8&amp;lt;/input&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;            Embed Stylesheet: &amp;lt;input type=&amp;quot;checkbox&amp;quot; id=&amp;quot;embedstyle&amp;quot; checked=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/input&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;        &amp;lt;/td&amp;gt;&lt;br /&gt;    &amp;lt;/tr&amp;gt;&lt;br /&gt;&amp;lt;/table&amp;gt;&lt;br /&gt;&amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;p&amp;gt;&lt;br /&gt;&amp;lt;div class=&amp;quot;step-instr&amp;quot; id=&amp;quot;fade&amp;quot;&amp;gt;Copy the HTML below to your clipboard. Insert the HTML of your blog or wiki.&amp;lt;br/&amp;gt;&lt;br /&gt;&amp;lt;textarea wrap=&amp;quot;off&amp;quot; rows=&amp;quot;12&amp;quot; cols=&amp;quot;50&amp;quot; id=&amp;quot;textout&amp;quot;&amp;gt;formatted HTML will appear in here.&amp;lt;/textarea&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;div id=&amp;quot;vert-pipe-warning&amp;quot; style=&amp;quot;display: none&amp;quot;&amp;gt;&lt;br /&gt;&amp;lt;p class=&amp;quot;warning&amp;quot;&amp;gt;&lt;br /&gt;&amp;lt;b&amp;gt;Vertival Pipe Character Warning:&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;The text contains the vertical pipe character '&amp;#124;' which Blogger's editor may remove.  Blogger's editor on the web has two edit tabs: &amp;quot;Edit HTML&amp;quot; and &amp;quot;Compose&amp;quot;.  The &amp;quot;Compose&amp;quot; tab will remove all &amp;#124; characters!  Use the &amp;quot;Edit HTML&amp;quot; tab only.&lt;br /&gt;&amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;div id=&amp;quot;results&amp;quot;&amp;gt;&amp;lt;pre class=&amp;quot;source-code&amp;quot;&amp;gt;&amp;lt;code&amp;gt;This is an example of what your text will look like.&lt;br /&gt;    &amp;amp;#8226; Tabs are converted to spaces.&lt;br /&gt;    &amp;amp;#8226; Quotes and other special characters are converted to HTML.&lt;br /&gt;    &amp;amp;#8226; Everything is enclose in HTML's 'pre' and 'code' tags.&lt;br /&gt;    &amp;amp;#8226; Style is set:&lt;br /&gt;        &amp;amp;#8226; Fixed width font.&lt;br /&gt;        &amp;amp;#8226; Shaded box.&lt;br /&gt;        &amp;amp;#8226; Dotted line border.&lt;br /&gt;&lt;br /&gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;p&amp;gt;&lt;br /&gt;&amp;lt;div id=&amp;quot;style&amp;quot; style=&amp;quot;display: none&amp;quot;&amp;gt;&lt;br /&gt;Example Stylesheet:&amp;lt;br/&amp;gt;&lt;br /&gt;&amp;lt;textarea wrap=&amp;quot;off&amp;quot; rows=&amp;quot;13&amp;quot; cols=&amp;quot;50&amp;quot; id=&amp;quot;textout&amp;quot;&amp;gt;&amp;lt;style type=&amp;quot;text/css&amp;quot;&amp;gt;&lt;br /&gt;pre.source-code {&lt;br /&gt;  font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; &lt;br /&gt;  color: #000000;&lt;br /&gt;  background-color: #eee;&lt;br /&gt;  font-size: 12px;&lt;br /&gt;  border: 1px dashed #999999;&lt;br /&gt;  line-height: 14px;&lt;br /&gt;  padding: 5px;&lt;br /&gt;  overflow: auto;&lt;br /&gt;  width: 100%&lt;br /&gt;}&lt;br /&gt;&amp;lt;/style&amp;gt;&amp;lt;/textarea&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;!-- END STUFF IN POST --&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-114047590194340092?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/114047590194340092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=114047590194340092' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/114047590194340092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/114047590194340092'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/02/about-format-my-source-code.html' title='About: Format My Source Code'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-114010949379607928</id><published>2006-02-16T11:02:00.000-06:00</published><updated>2006-02-16T11:04:53.813-06:00</updated><title type='text'>JUnit 4.0 is here!</title><content type='html'>Download: &lt;a href="http://sourceforge.net/project/showfiles.php?group_id=15278&amp;package_id=12472&amp;release_id=394034"&gt;http://sourceforge.net/project/showfiles.php?group_id=15278&amp;package_id=12472&amp;release_id=394034&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;v 3.8.1 was release in September 2002.  It has been a long time since the last update.  V4.0 requires Java5, as it uses annotations to mark tests.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-114010949379607928?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/114010949379607928/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=114010949379607928' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/114010949379607928'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/114010949379607928'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/02/junit-40-is-here.html' title='JUnit 4.0 is here!'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-113958793527813798</id><published>2006-02-10T10:10:00.000-06:00</published><updated>2006-02-10T10:12:15.293-06:00</updated><title type='text'>Death by UML Fever</title><content type='html'>Funny ACM article: &lt;a href="http://www.acmqueue.com/modules.php?name=Content&amp;pa=showpage&amp;pid=130"&gt;Death by UML Fever&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-113958793527813798?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/113958793527813798/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=113958793527813798' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113958793527813798'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113958793527813798'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/02/death-by-uml-fever.html' title='Death by UML Fever'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-113958297575825949</id><published>2006-02-10T08:47:00.000-06:00</published><updated>2006-02-10T08:49:35.770-06:00</updated><title type='text'>Waterfall 2006</title><content type='html'>Sent in my registration for &lt;a href="http://waterfall2006.com/"&gt;Waterfall 2006&lt;/a&gt;!  This is going to be a great event.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-113958297575825949?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/113958297575825949/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=113958297575825949' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113958297575825949'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113958297575825949'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/02/waterfall-2006.html' title='Waterfall 2006'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-113927529594475419</id><published>2006-02-06T19:20:00.000-06:00</published><updated>2006-02-06T19:21:35.960-06:00</updated><title type='text'>VMWare Server for Free :)</title><content type='html'>VMWave is making a new VMWare Server product available for free.  See http://www.theregister.com/2006/02/03/vmware_goes_free/ for a better write up.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-113927529594475419?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/113927529594475419/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=113927529594475419' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113927529594475419'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113927529594475419'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/02/vmware-server-for-free.html' title='VMWare Server for Free :)'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-113777479700841775</id><published>2006-01-20T10:10:00.000-06:00</published><updated>2006-01-20T10:33:17.023-06:00</updated><title type='text'>.Net Generics vs Java Generics</title><content type='html'>I'm a big fan of Java.  It is nice to see the fan base for Java is still far above .Net (and outpacing .Net in growth); see &lt;a title="http://www.tiobe.com/tpci.htm" href="http://www.tiobe.com/tpci.htm"&gt;http://www.tiobe.com/tpci.htm&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;One area I've found .Net outshines Java is the implementation of Generics.  Java's Generics exist in source-code only.  The Java compiler "Erases" the generic information after the compiler determines that everything is correct.  This approach outshines C++ templates, but it creates a lot of other issues.  See the &lt;a href="http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html"&gt;Java Generics FAQ &lt;/a&gt;which lists pages of special rules and edge cases caused by Erasers.  Java Generics is more complex than Java the language!&lt;br /&gt;&lt;br /&gt;.Net Generics on the other hand are implemented at runtime.  So the Generic type information is not lost and is available through reflection.  When the .Net CLR encounters the usage of a Generic type for the first time, it instantiates a non-Generic type based on the type parameters.  The Generic type is never executed, it is just used by the CLR to create concrete instances.  So Array&amp;lt;string&amp;gt; and Array&amp;lt;float&amp;gt;  are two seperate classes at runtime.  Java would have just used Array.  So .Net memory grows a little more (but not like the bloat of templates in C++), which is a great trade off since it avoids the problems and complexities of Erasures.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-113777479700841775?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/113777479700841775/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=113777479700841775' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113777479700841775'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113777479700841775'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/01/net-generics-vs-java-generics.html' title='.Net Generics vs Java Generics'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-113708127313739458</id><published>2006-01-12T09:45:00.000-06:00</published><updated>2006-01-12T09:54:33.156-06:00</updated><title type='text'>Stop running that startup junk.</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/238/819/1600/Autoruns.gif"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://photos1.blogger.com/blogger/238/819/320/Autoruns.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;A friend asked me how to stop some of those annoying programs that always startup when he starts windows. The best solution I've found is a freeware tool Autoruns from Sysinternals (&lt;a href="http://www.sysinternals.com/Utilities/Autoruns.html"&gt;http://www.sysinternals.com/Utilities/Autoruns.html&lt;/a&gt;). Autoruns is a powertool that gives you easy access to everything that is executed at startup. Autoruns allows you to simply uncheck the programs that you don't want to run.&lt;br /&gt;&lt;br /&gt;Sysinternals has a number of great tools for performing other tasks. For example, Regmon and Filemon are handy to see what is really going on when installing a program. They are also handy for debugging programs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-113708127313739458?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/113708127313739458/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=113708127313739458' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113708127313739458'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113708127313739458'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/01/stop-running-that-startup-junk.html' title='Stop running that startup junk.'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-113677424991783669</id><published>2006-01-08T20:13:00.000-06:00</published><updated>2006-01-08T20:37:54.143-06:00</updated><title type='text'>From Ant to Ruby - 122 lines of fun</title><content type='html'>Last month a friend of mine had a disk failure.  Fortunately most of his files are still in good shape.  Right now, he is going through the difficult process of trying to recover what files he can.  This task is extra difficult since Windows XP encrypts everything under the 'My Documents' folder so that other accounts and OS cant read them.  If you are not doing regular backups, you are just asking for trouble.&lt;br /&gt;&lt;br /&gt;For almost a year now, I've used a simple Ant script to backup my files.  I use a very simple method of copying everything to a separate drive using Ant.  The backup also has a few extras that require special steps.  For example, backing up my subversion repository requires calling the subversion svnadmin hotcopy command.  I've been happy with this process until I wanted to automate backing up data I have stored on the internet.  For example, my bookmarks and address book are in yahoo.  So I had to manually export them from yahoo to a file, then run my backup script.  I looked at using Ant's 'Post' task to automate the web stuff, but I was really unhappy that it wasn't very nice code.  Also it was hard to verify that everything worked correctly.  If yahoo ever changed a page, the backup might stop getting my data and Ant wouldn't tell me.&lt;br /&gt;&lt;br /&gt;So I decided to convert the backup to one of my favorite languages Ruby!&lt;br /&gt;&lt;br /&gt;My first task was just a straight conversion of my Ant script to Ruby.  The original Ant script was 122 lines of code.  When I finished the Ruby version, it came to exactly 122 lines of code!   Very funny!   This completely surprised me.  I had thought Ruby would take more lines of code than Ant.  In Ruby I had to write a lengthy backup function (40 lines), and add a few convenience functions.  However, when I finished the initial conversion they came out to exactly the same number of lines.&lt;br /&gt;&lt;br /&gt;Right now I'm adding more advanced features to my script.  Which I will blog about later.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-113677424991783669?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/113677424991783669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=113677424991783669' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113677424991783669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113677424991783669'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2006/01/from-ant-to-ruby-122-lines-of-fun.html' title='From Ant to Ruby - 122 lines of fun'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-113397599003274642</id><published>2005-12-07T11:07:00.000-06:00</published><updated>2005-12-07T13:28:04.083-06:00</updated><title type='text'>Java vs C# vs C++</title><content type='html'>Take a quick look at &lt;a href="http://www.artima.com/articles/io_design_patterns3.html"&gt;Comparing Two High-Performance I/O Design Patterns, page 3&lt;/a&gt; which graphs the results of writting the same I/O code in Java, C# and C++. It is really cool to see how well Java and C# stack up against C++.&lt;br /&gt;&lt;br /&gt;I've written a couple of servers in Java using NIO, and in C++ using raw sockets. I was very impressed with the performance of Java. Factor in how easy it was to write the Java code and Java is a clear winner to me.&lt;br /&gt;&lt;br /&gt;One thing that isn't shown in the article is the difference between Java and C#'s class library. In Java, most everything is a CharacterSequence. All the conversion and string manipulation features in Java work with CharacterSequence.  For example you can perform Regex functions directly on the NIO buffers!&lt;br /&gt;&lt;br /&gt;Unfortunately in C#, the various strings and buffers do not have a common parent.  The String and StringBuilder classes only have Object as the common parent.  Also classes like RegEx do not support a wide range of targets.  RegEx only works on String and serialization streams.  You can't perform a RegEx directly on StringBuilder in .Net!&lt;br /&gt;&lt;br /&gt;In conclusion, go Java :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-113397599003274642?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/113397599003274642/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=113397599003274642' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113397599003274642'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113397599003274642'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/12/java-vs-c-vs-c.html' title='Java vs C# vs C++'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-113112455167876331</id><published>2005-11-04T10:57:00.000-06:00</published><updated>2005-11-04T11:15:51.713-06:00</updated><title type='text'>Development at Valve</title><content type='html'>Game Developer Magazine (&lt;a href="http://gdmag.com/"&gt;http://gdmag.com/&lt;/a&gt;) had a real great article about Valve's process and practices that they used to produce Half-Life 2 (Nov 2005 issue).  Go get your hands on the article it is really an interesting read.&lt;br /&gt;&lt;br /&gt;Their process incuded many elements that are also found in Agile processes.  They used a lot of prototyping and interations in the development.  The iteration strategy really paid off for them.  When faced with trade-offs they favored reducing scope to get more iterations.  More iterations forced them to reduce the overhead costs of iterations.  Having more iterations helped them increase quailty, experimentation, and enabled them to delay decisions until later in the process.  They said "Decisions made later in the project were always better than decisions made earlier.&lt;span style=""&gt;" &lt;br /&gt;&lt;br /&gt;Their team culture is also very interesting.  They worked in small 4-5 person teams (Cabal).  Each Cabal shared an office space to increase communication and avoid getting side-tracked.  They discouraged "sole ownership".  They promoted positive competition between team members and across teams.  Also they created demanding comsumers for everyone on the team.&lt;br /&gt;&lt;br /&gt;I've only touched on some aspects of their system.  You'll have to read the article to get the full story.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: &amp;quot;Times New Roman&amp;quot;;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-113112455167876331?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/113112455167876331/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=113112455167876331' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113112455167876331'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113112455167876331'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/11/development-at-valve.html' title='Development at Valve'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-113077028429663096</id><published>2005-10-31T08:33:00.000-06:00</published><updated>2005-10-31T08:51:24.316-06:00</updated><title type='text'>OpenCsv</title><content type='html'>Today I needed to parse some CSV data.  A quick search found a project called &lt;a href="http://opencsv.sourceforge.net/"&gt;OpenCsv&lt;/a&gt; that was added to sourceforge last month.  I pulled it down and found it did a great job on the data I was parsing.   The data I am parsing contained newlines, commas and quoted strings inside the csv elements.  Some other libraries would not handle this correctly but &lt;a href="http://opencsv.sourceforge.net/"&gt;OpenCsv&lt;/a&gt; did!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-113077028429663096?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/113077028429663096/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=113077028429663096' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113077028429663096'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113077028429663096'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/10/opencsv.html' title='OpenCsv'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-113050834863429548</id><published>2005-10-28T08:42:00.000-05:00</published><updated>2005-10-28T09:49:31.996-05:00</updated><title type='text'>Rapid Prototyping - Recommended Reading</title><content type='html'>Gamasutra published a feature article "&lt;a href="http://www.gamasutra.com/features/20051026/gabler_01.shtml"&gt;How to Prototype a Game in Under 7 Days:&lt;br /&gt;Tips and Tricks from 4 Grad Students Who Made Over 50 Games in 1 Semester&lt;/a&gt;"&lt;br /&gt;&lt;br /&gt;This article provides an interesting story on rapid prototyping. Several points made directly oppose the ideas pushed by Agile Development. Specifically they devalue working together during the coding phases of the project. Also, they denounce formal Brainstorming. While at the same time, some points re-enforce Agile Practices. Their call for picking the solution done the fastest is similar to the Agile practice of making the "simplest thing that could possibly work".&lt;br /&gt;&lt;br /&gt;Overall, I think there is more need for Rapid Prototyping in Business Application development. The Agile community calls this a "Spike Solution". Far too often I see product managers and developers writing production solutions without first creating a prototype.&lt;br /&gt;&lt;br /&gt;Also, I agree with their assertion that "Complexity is not necessary for Fun" in game play. I think this also applies to application development in that "Complexity != Productive Solutions." Application designers seem to want to add flexibility and options. This adds Complexity and reduces the productivity of the users and developers. Most users just want a simple solution to their problem. Once they find the solution, they don't use those extra options.&lt;br /&gt;&lt;br /&gt;They said their Brainstorming sessions did not produce immediate results.  But it did get them thinking and at a later time (maybe while driving home), an idea would pop into their head.  This is exactly the same process that I have read from a successful inventor.  (Sorry I don't have the reference).  The inventor said he could always find a new idea or solution with a two step process.  First he would focus and concentrate on the problem for some time.  He wouldn't expect to get any results from this activity.  But somehow it got his subconcious mind working on the problem.  Then the second step was just to do something else.  Driving, going to a park, etc.  At a later time his mind would bring up a new solution or invention related to the problem he had focused on in the first step.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-113050834863429548?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/113050834863429548/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=113050834863429548' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113050834863429548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113050834863429548'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/10/rapid-prototyping-recommended-reading.html' title='Rapid Prototyping - Recommended Reading'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-113016276919595042</id><published>2005-10-24T09:03:00.000-05:00</published><updated>2005-10-24T09:06:09.203-05:00</updated><title type='text'>Funny New Process at Microsoft</title><content type='html'>Microsoft is trying to help developers better understand their customers.  &lt;a href="http://a3.v14853d.c14853.g.vm.akamaistream.net/5/3/14853/v003/1a1a1a72db3eb01f920167db4fb41745a9188ffd69d8399dcb2c97f865c62f5dc02f9ccbfc30689dd0ff6cdf44bc2c5bc83ba01888b7fc356ea7e0/9999_w.asf"&gt;Very interesting process (short video)&lt;/a&gt; with tools support.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-113016276919595042?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/113016276919595042/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=113016276919595042' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113016276919595042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/113016276919595042'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/10/funny-new-process-at-microsoft.html' title='Funny New Process at Microsoft'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-112912667447479896</id><published>2005-10-12T09:15:00.000-05:00</published><updated>2005-10-12T09:17:54.480-05:00</updated><title type='text'>Cross-site scripting</title><content type='html'>Java.net has posted a good little &lt;a href="http://today.java.net/pub/a/today/2005/09/20/handling-web-app-input.html"&gt;article on Cross-Site Scripting&lt;/a&gt;.  Makes a great summary or beginners guide on the subject.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-112912667447479896?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/112912667447479896/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=112912667447479896' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112912667447479896'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112912667447479896'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/10/cross-site-scripting.html' title='Cross-site scripting'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-112906300925409352</id><published>2005-10-11T15:30:00.000-05:00</published><updated>2005-10-11T15:36:49.266-05:00</updated><title type='text'>Virtual CD-Rom for XP from Microsoft (unsupported)</title><content type='html'>Need to mount an ISO image?   Here is a simple tool from Microsoft: &lt;a href="http://download.microsoft.com/download/7/b/6/7b6abd84-7841-4978-96f5-bd58df02efa2/winxpvirtualcdcontrolpanel_21.exe"&gt;Virtual CD-ROM Control Panel for XP&lt;/a&gt;.  While unsupported, it seems to work fine.&lt;br /&gt;&lt;br /&gt;I found it on the PDC Vista Beta install disk.  Looking around Microsoft's web, I found this reference to it... &lt;a href="http://msdn.microsoft.com/subscriptions/faq/#iso"&gt;MSDN Subscriptions FAQ see question "What are ISO images files and how do I use them?&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I was surprised to find they also linked to some 3rd party tools in the FAQ.  Also, kudos to M$ for having java script on the page that worked with Firefox.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-112906300925409352?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/112906300925409352/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=112906300925409352' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112906300925409352'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112906300925409352'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/10/virtual-cd-rom-for-xp-from-microsoft.html' title='Virtual CD-Rom for XP from Microsoft (unsupported)'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-112904414153462659</id><published>2005-10-11T10:14:00.000-05:00</published><updated>2005-10-11T10:22:21.540-05:00</updated><title type='text'>How to determine if .Net app is having Lock Contention</title><content type='html'>Open perfmon and add the .Net CLR LocksAndThreads. Select "Contention rate / sec" and "Total # of Contentions" (use ctrl-click).  Then select your application from the "instances" list. Then click the Add and Close buttons.  The report view is the best way to see the results.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-112904414153462659?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/112904414153462659/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=112904414153462659' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112904414153462659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112904414153462659'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/10/how-to-determine-if-net-app-is-having.html' title='How to determine if .Net app is having Lock Contention'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-112860990566478217</id><published>2005-10-06T09:37:00.000-05:00</published><updated>2005-10-06T09:45:05.673-05:00</updated><title type='text'>DoD: anti-MG tactics</title><content type='html'>Playing &lt;a href="http://www.dayofdefeat.com/media.php"&gt;Day of Defeat Source&lt;/a&gt; I see a lot of players using smoke grenades to try and sneak past machine guns.  While this has slight success, there is a better way.&lt;br /&gt;&lt;br /&gt;An MG in a good bunker can be difficult to throw a grenade into for a kill.  However, it seems many players dont realize how a near-miss grenade really shakes up the MG.  The Source engine violently shakes and blurs the gunner's view.  So for a second or two, the MG is unable to effectively see and aim.  This provides a great oppertunity to get a clear shot on the MG.&lt;br /&gt;&lt;br /&gt;Just time your attack to take place the moment after the nade goes off and you will greatly increase your chance for success.  Good luck!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-112860990566478217?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/112860990566478217/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=112860990566478217' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112860990566478217'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112860990566478217'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/10/dod-anti-mg-tactics.html' title='DoD: anti-MG tactics'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-112845998663746842</id><published>2005-10-04T15:51:00.000-05:00</published><updated>2005-10-07T15:38:45.550-05:00</updated><title type='text'>Software that makes my day</title><content type='html'>Software that I use everyday...&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;Java - the best language and platform.&lt;/li&gt;   &lt;li&gt;Eclipse - Living with eclipse only because I cant spend the $$ for IntelliJ just for home use.&lt;/li&gt;   &lt;li&gt;Subversion and TortoiseSVN - Keeping the code safe&lt;/li&gt;   &lt;li&gt;Beyond Compare 2 - handy diff tool, and cheap enough (I'd rather use Araxis Merge but can't afford it)&lt;/li&gt;   &lt;li&gt;OpenOffice - Better than Office!&lt;/li&gt;   &lt;li&gt;Office - only because my co-workers keep buying it.&lt;/li&gt;   &lt;li&gt;Trillian - for those fun interruptions during the work day (yeah it gets lonely in a cube)&lt;/li&gt;   &lt;li&gt;Half-life and Half-life 2 plus mods CS, DoD, Natural Selection, HL2 DM - for my adrenaline rush and game fix.&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;Firefox - for the internet, and web-based email.&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;Remote Desktop - because there are too many machines in my office&lt;/li&gt;   &lt;li&gt;Audacity - A poor man's 'tivo' for internet audio.&lt;/li&gt;   &lt;li&gt;Azureus - Because bittorrent rocks!&lt;/li&gt;   &lt;li&gt;Windows XP - Only because you have to have an OS, and this is the only one that runs all the other stuff easily.&lt;br /&gt;  &lt;/li&gt; &lt;/ul&gt; It is interesting to see that half of these applications are opensource.  What software helps you get through the day?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-112845998663746842?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/112845998663746842/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=112845998663746842' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112845998663746842'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112845998663746842'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/10/software-that-makes-my-day.html' title='Software that makes my day'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-112800477795387825</id><published>2005-09-29T08:55:00.000-05:00</published><updated>2005-10-04T15:50:24.876-05:00</updated><title type='text'>Learn something new everyday...</title><content type='html'>I've been using wndows since version 3.1. So it surprised me to find a new trick today. You can ctrl-click multiple windows in the taskbar then right-click one to get options to tile and cascade the windows. I found this tip in a &lt;a href="http://www.pcworld.com/howto/article/0,aid,92923,pg,4,00.asp"&gt;PCWorld article&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Anyone know how to arrange the taskbar window buttons?  (Yes, I've seen &lt;a href="http://users.forthnet.gr/pat/efotinis/programs/taskarrange.html"&gt;TaskArrange&lt;/a&gt; which works fairly well.  But I'd rather be able to drag and drop the buttons on the taskbar itself and have windows remember the order.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-112800477795387825?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/112800477795387825/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=112800477795387825' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112800477795387825'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112800477795387825'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/09/learn-something-new-everyday.html' title='Learn something new everyday...'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-112784699265672912</id><published>2005-09-27T13:33:00.000-05:00</published><updated>2005-09-27T13:49:52.663-05:00</updated><title type='text'>Day of Defeat Source</title><content type='html'>DoD Source was released to the public yesterday.  This game plays great on the Source engine.  The graphics, physics and sound make the game great fun.  There were few changes to the gameplay.  Mostly UI changes and some changes to the weapons and loadout.  I really like the MG's ability to deploy on any surface.  This adds a lot of strategic options for the MG player.  The new weapons for each class will take a little getting used too.  For example, one time I snuck up on a camping sniper and was about to use the knife.  But I couldn't find the knife!  As a noob on the version, I didn't know the class I had choosen didn't come with a knife.  The sniper thought is was funny to turn around and see my avatar swapping weapons like crazy.&lt;br /&gt;&lt;br /&gt;The game isn't without bugs.  Once while playing Flash, I bumped into a teammate and our avatars got stuck together.  We couldn't move!   An enemy came along and happily ended our troubles.&lt;br /&gt;&lt;br /&gt;DoD Source is great for any fan of the original Day of Defeat.  Many of the guns fire differently so expect minor changes from the original.  The Allied rifleman gets a new grenade launcher.  It give the rifleman more range to toss a grenade.  However, you cant control the fuse time.  Another great change is the grenades start their fuse when you begin to throw them.  So you dont need to use the "toss on the ground and rethrow" trick used in the first DoD.&lt;br /&gt;&lt;br /&gt;The new maps might look familiar, but many have new paths added.  So explore a bit on the DoD maps to find all the options.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-112784699265672912?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/112784699265672912/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=112784699265672912' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112784699265672912'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112784699265672912'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/09/day-of-defeat-source.html' title='Day of Defeat Source'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-112734889908326491</id><published>2005-09-21T19:04:00.000-05:00</published><updated>2005-09-21T19:28:19.090-05:00</updated><title type='text'>Say "Yahoo" for cool tools!</title><content type='html'>Here are two very useful tools from Yahoo that you might add to your tool box... &lt;a href="http://desktop.yahoo.com/"&gt;Yahoo Desktop Search&lt;/a&gt; and &lt;a href="http://myweb.yahoo.com/"&gt;MyWeb&lt;/a&gt;.  In my current job I have to work on a large legacy application.  The application has been in development for more than eight years.  It has a large amount of source-code and documentation.  Finding information in this mass of files was very difficult until I used Yahoo Desktop Search.   Search has a great interface for performing the searches and previewing the results.  It handles source code, word, pdf and many other documents.  So when I look up a function in source, I can easily spot everywhere it is used in code and in the documentation!  Very very nice.   I tried using Google's desktop search tool, but found the Yahoo Desktop Search to richer and easier to use.&lt;br /&gt;&lt;br /&gt;I read a lot of technical articles, whitepapers and blogs.  On any given day I probably read 2 to 10 articles about technologies I'm using.  That is a lot of information to keep track of.  My solution is Yahoo's My Web.  Since late May (see &lt;a href="http://ghouston.blogspot.com/2005/05/great-stuff-from-yahoo-soon.html"&gt;previous post&lt;/a&gt;) I've been dropping every article I read into MyWeb at Yahoo.  MyWeb captures a copy of the webpages so I can search them later.  [Hint, use Yahoo Toolbar to make it easy to add to MyWeb.]  So the next time I need to find that article on JTidy, Derby, or AspectJ I can use MyWeb to search only the articles I've read.&lt;br /&gt;&lt;br /&gt;Maybe one day Yahoo will get the Desktop Search to also include MyWeb.  That would be Nerdvana!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-112734889908326491?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/112734889908326491/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=112734889908326491' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112734889908326491'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112734889908326491'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/09/say-yahoo-for-cool-tools.html' title='Say &quot;Yahoo&quot; for cool tools!'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-112724642018630607</id><published>2005-09-20T14:53:00.000-05:00</published><updated>2005-09-20T15:00:20.193-05:00</updated><title type='text'>ODBMS.ORG</title><content type='html'>There is a new portal for Object Databases: &lt;a href="http://www.odbms.org/index.html"&gt;ODBMS.ORG&lt;/a&gt;.  A good resource for information and software.  It is rather interesting that this site is sponsored by db4objects.  I hope the site doesn't become biased.  Anyway it is a good starting point for getting into object databases.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-112724642018630607?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/112724642018630607/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=112724642018630607' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112724642018630607'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112724642018630607'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/09/odbmsorg.html' title='ODBMS.ORG'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-112491770813080044</id><published>2005-08-24T15:52:00.000-05:00</published><updated>2005-08-24T16:08:28.136-05:00</updated><title type='text'>Funny stuff... Escape from Yesterworld</title><content type='html'>Microsoft published the &lt;a href="http://escapeyesterworld.com/"&gt;Escape from Yesterworld&lt;/a&gt; site to promote 2005 development tools. It contains some funny parody videos on the first page (Main Control Room). Only four more months and 2005 will be Yester-year.  Microsoft had better start shipping fast.  Enjoy!&lt;br /&gt;&lt;br /&gt;I found it interesting that MS used Flash to make the site.  Didn't MS make that fancy IE browser to deliver rich content?  Also, using IE the pop-ups to show the movies would not appear.  When I clicked on the controls to show the movies, IE would just make a weak "beep" sound (maybe that was flash.)  IE did not provide an error, neither did the yellow bar appear to enable the popup.  So with IE, I couldn't easily view the movies!  Good old Firefox worked just fine.  (Who made this site?)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-112491770813080044?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/112491770813080044/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=112491770813080044' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112491770813080044'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112491770813080044'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/08/funny-stuff-escape-from-yesterworld.html' title='Funny stuff... Escape from Yesterworld'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-112472490976134277</id><published>2005-08-22T09:45:00.000-05:00</published><updated>2006-02-20T15:09:00.156-06:00</updated><title type='text'>How to Create and Change Environment Variables using C# or .Net</title><content type='html'>Modifying environment variables seems like one of those easy tasks that you would expect .Net to support. Unfortunatley the System.Environment class only supports reading environment variables. So an alternative solution is needed. After a long search on the internet, I found one site that describes some options: &lt;a href="http://ukamen.hp.infoseek.co.jp/Programming/Environment/"&gt;Environment variable is handled&lt;/a&gt;.  Unfortunately, this page is written in Japanese.  An english translation is &lt;a href="http://translate.google.com/translate?u=http%3A%2F%2Fukamen.hp.infoseek.co.jp%2FProgramming%2FEnvironment%2F&amp;langpair=ja%7Cen&amp;amp;amp;amp;hl=en&amp;ie=UTF-8&amp;amp;oe=UTF-8&amp;prev=%2Flanguage_tools"&gt;here&lt;/a&gt;. There are several options available, each with it's own limitations and issues. I tried each option and found they wouldn't work for me.&lt;br /&gt;&lt;br /&gt;Windows Management Instrumentation (WMI) has the ability to easily read the environment. If an environment variable already exists, you can modify it using WMI. However, I could not find a good example of creating a new environment variable through WMI. I installed and ran Microsoft's WMI Tools (&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=6430f853-1120-48db-8cc5-f2abdc3ed314&amp;amp;DisplayLang=en"&gt;available here&lt;/a&gt;) to see if I could create an environment variable through the CIM Studio. No luck. There might be a way to use WMI to create a new environment variable, but I haven't seen it.  Also, calling WMI causes a noticable performance hit on the first call.&lt;br /&gt;&lt;br /&gt;Another solution is to modify the Registry (see &lt;a href="http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B104011"&gt;MS KB Article&lt;/a&gt;) to create and modify environment variables.  This seems to work, however the class Microsoft.Win32.RegistryKey doesn't provide the ability to create a REG_EXPAND_SZ value.  Without REG_EXPAND_SZ, you can't use the %VAR% expansion!  So using .Net framework falls short.  (This is one example of my frustration with .Net, many framework interfaces are incomplete.  Java never had this problem, instead Java tends to err on the side of giving you too much.)&lt;br /&gt;&lt;br /&gt;The solution I found to work the best was to call Windows Scripting Host (WSH) Shell from .Net.  This is described in &lt;a href="http://msdn.microsoft.com/library/?url=/library/en-us/script56/html/wsconmanipulatingsystemregistryprogrammatically.asp"&gt;Basic WSH Tasks: Manipulating the System Registry&lt;/a&gt;.  I found an example of calling WSH from .Net in the article &lt;a href="http://www.codeproject.com/dotnet/shelllink.asp"&gt;The Code Project - Creating Shell Links (Shortcuts) in .NET Programs Using WSH&lt;/a&gt;.  Using WSH, it is easy to create and modify environment variables.  Also, WSH allows you to set REG_EXPAND_SZ values.  The final step after changing the environment variables in the registry is to broadcast the change by calling &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/messagesandmessagequeues/messagesandmessagequeuesreference/messagesandmessagequeuesfunctions/sendmessagetimeout.asp"&gt;SendMessageTimeout&lt;/a&gt; as described in the &lt;a href="http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B104011"&gt;KB article&lt;/a&gt;.  I found this example &lt;a href="http://www.dotnet247.com/247reference/msgs/32/164585.aspx"&gt;calling SendMessageTimeout from C#&lt;/a&gt; on .Net 247.&lt;br /&gt;&lt;br /&gt;So in short, here is the example code for creating and modifying environment variables from C#...&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; background-color: #eee;font-size: 12px;color: #000000; border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;        public static void SetUserVariable( string name, string value, bool isRegExpandSz )&lt;br /&gt;        {&lt;br /&gt;            SetVariable( &amp;quot;HKEY_CURRENT_USER\\Environment\\&amp;quot; + name, value, isRegExpandSz );&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public static void SetSystemVariable( string name, string value, bool isRegExpandSz )&lt;br /&gt;        {&lt;br /&gt;            SetVariable( &amp;quot;HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\\&amp;quot; + name, value, isRegExpandSz );&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private static void SetVariable( string fullpath, string value, bool isRegExpandSz )&lt;br /&gt;        {&lt;br /&gt;            object objValue = value;&lt;br /&gt;            object objType = (isRegExpandSz) ? &amp;quot;REG_EXPAND_SZ&amp;quot; : &amp;quot;REG_SZ&amp;quot;;&lt;br /&gt;            WshShell shell = new WshShell();&lt;br /&gt;            shell.RegWrite( fullpath, ref objValue, ref objType );&lt;br /&gt;&lt;br /&gt;            int result;&lt;br /&gt;            SendMessageTimeout( (System.IntPtr)HWND_BROADCAST,&lt;br /&gt;                WM_SETTINGCHANGE,0,&amp;quot;Environment&amp;quot;,SMTO_BLOCK &amp;#124; SMTO_ABORTIFHUNG &amp;#124;&lt;br /&gt;                SMTO_NOTIMEOUTIFNOTHUNG, 5000, out result);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        [DllImport(&amp;quot;user32.dll&amp;quot;,&lt;br /&gt;             CharSet=CharSet.Auto, SetLastError=true)]&lt;br /&gt;        [return:MarshalAs(UnmanagedType.Bool)]&lt;br /&gt;        public static extern bool&lt;br /&gt;            SendMessageTimeout(&lt;br /&gt;            IntPtr hWnd,&lt;br /&gt;            int Msg,&lt;br /&gt;            int wParam,&lt;br /&gt;            string lParam,&lt;br /&gt;            int fuFlags,&lt;br /&gt;            int uTimeout,&lt;br /&gt;            out int lpdwResult&lt;br /&gt;            );&lt;br /&gt;&lt;br /&gt;        public const int HWND_BROADCAST = 0xffff;&lt;br /&gt;        public const int WM_SETTINGCHANGE = 0x001A;&lt;br /&gt;        public const int SMTO_NORMAL = 0x0000;&lt;br /&gt;        public const int SMTO_BLOCK = 0x0001;&lt;br /&gt;        public const int SMTO_ABORTIFHUNG = 0x0002;&lt;br /&gt;        public const int SMTO_NOTIMEOUTIFNOTHUNG = 0x0008;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Call either SetUserVariable or SetSystemVariable with the name and value.  Set the boolean argument isRegEpandSz true if you need REG_EXPAND_SZ or false for REG_SZ type.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-112472490976134277?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/112472490976134277/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=112472490976134277' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112472490976134277'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112472490976134277'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/08/how-to-create-and-change-environment.html' title='How to Create and Change Environment Variables using C# or .Net'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-112378467405937209</id><published>2005-08-11T12:54:00.000-05:00</published><updated>2005-08-11T13:24:34.066-05:00</updated><title type='text'>TopCoder on Pair Programming</title><content type='html'>Shortly after blogging about pair-programming on TopCoder, the folks at TopCoder contacted me.  They asked for more information about what we did while pair-programming.  I gave them the details and tried to make a case for pair-programming in their Single Round Matches.  The case I tried to make focused on the fun involved in pair-programming during their contest.  Which for me was the whole reason to play TopCoder anyway.  Pair-programming in the competition for me was a lot more fun than playing it by myself.  Just like any sport, playing in pairs you build excitement and energy from your teammate.  The added social-factor made the event very entertaining.  Some of the discussions and comments we made while trying to hack code and race the clock would probably make a good reality-tv show.  Pair-programming combined with the time-limit created a fun, social and exciting environment.  This was simply FUN! &lt;br /&gt;&lt;br /&gt;Unfortunately TopCoder's reply included...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt; Our current environment is setup to promote individual results and ratings.  At this time, we dot not intend to add any type of pair programming or team competitions, but we'll consider your request.  We've considered team contests in the past, but ultimately were hesitant due to the high potential for abuse.&lt;br /&gt;&lt;br /&gt;If you like the pair programming experience within TopCoder, I encourage you attempt the same format but use the practice rooms instead of an SRM.&lt;/blockquote&gt;Ok, TopCoder has both technical and business issues to overcome before they can support team events.  I'm sure if they really want to, they could find a way to support pair-programming.  After all, don't they have access to the *Top Coders*?  I hope TopCoder changes one day to allow team events.  It really was a great form of Recreational Programming.  Until then, Tom and I will look for other programming games to pair and play.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-112378467405937209?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/112378467405937209/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=112378467405937209' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112378467405937209'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112378467405937209'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/08/topcoder-on-pair-programming.html' title='TopCoder on Pair Programming'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-112299234461039248</id><published>2005-08-02T09:17:00.000-05:00</published><updated>2005-08-02T09:19:04.616-05:00</updated><title type='text'>Outsourcing article</title><content type='html'>&lt;a href="http://www.entrepreneur.com/article/0,4621,311034,00.html"&gt;If you're outsourcing projects right and left, make sure the information you need is rolling back to you.&lt;/a&gt; a good little article about managing outsourcing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-112299234461039248?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/112299234461039248/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=112299234461039248' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112299234461039248'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112299234461039248'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/08/outsourcing-article.html' title='Outsourcing article'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-112267167627669550</id><published>2005-07-29T15:31:00.000-05:00</published><updated>2005-08-11T15:25:20.036-05:00</updated><title type='text'>Remote pair programming on TopCoder</title><content type='html'>Last night Tom and I tried our second match on TopCoder using Remote &lt;a href="http://www.pairprogramming.com/"&gt;Pair Programming&lt;/a&gt;.  (Our first match we had some technical difficulties that limited our success.)&lt;br /&gt;&lt;br /&gt;The tools we used were:&lt;br /&gt;&lt;ul&gt;   &lt;li&gt; Eclipse 3.1 for our Java IDE.&lt;/li&gt;   &lt;li&gt;Microsoft Remote Assistant for sharing my desktop with Tom.&lt;/li&gt;   &lt;li&gt;Skype for voice over IP.&lt;/li&gt;   &lt;li&gt;Microsoft  Messenger to launch Remote Assistant and text chat.&lt;/li&gt;   &lt;li&gt;Firefox browser.&lt;/li&gt; &lt;/ul&gt; I have a 3MB/384k DSL connection which handled the sharing of my desktop in 1280x1024 and voice over IP on Skype very well. Only once Tom complained that his refresh got behind his typing when he was driving. An earlier attempt where we used VNC and a 1.5MB/256k DSL connection at the host had more refresh problems, but was generally workable.&lt;br /&gt;&lt;br /&gt;The contest went well. TopCoder provides three problems of increasing difficulty worth 250, 500 and 1000 points max (points decrease over time). The problem set is listed on &lt;a href="http://www.topcoder.com/index?t=statistics&amp;c=srm255_prob"&gt;http://www.topcoder.com/index?t=statistics&amp;amp;c=srm255_prob&lt;/a&gt; We jumped into the 500 point problem first called WordCompositionGame. As a pair, Tom was immediately thinking ahead about how to implement the next steps as I coded the steps that we knew. This eliminated some hesitations and pauses that might have slowed down either of us alone.&lt;br /&gt;&lt;br /&gt;On the 1000 point problem, KthElement we also quickly hacked out the solution. Our code was more brute force than elegant because we were racing the clock. Our JUnit tests failed showing we had the right sequence, just not the correct KthElement. I immediately guessed we had an "index off by one" bug. So rather than puzzling out the bug, I simply added one to the index and re-ran the unit test... it passed!!! (Thanks to Tom for creating a program that converts the TopCoder problem statement into Unit Tests). We submitted the code.&lt;br /&gt;&lt;br /&gt;Next we opened the 250 problem with lots of time left. While reading the problem statement, something bugged us about our solution to the 1000point KthElement problem. KthElement ran a long time for large numbers. Tom checked the rules and realized there is a 8 second limit on runtime. So we reopened KthElement. This cost us more points because the clock was now ticking down points on the 250 problem, and reopened the countdown on KthElement.&lt;br /&gt;&lt;br /&gt;A quick look at the data in the KthElement unit tests made us realize the sequences started to repeat. So the solution was to collect the sequence until it repeats and calculate the KthElement from the repeating pattern. This took a bit of effort, but saved us from total failure. At one point in this, Tom and I disagreed about how to find the KthElement from the repeating pattern. Tom started to go off on his own solution (he has two monitors at home), while I was hacking out my solution. Fortunately this split didn't last more than a minute or two. I was able to draw Tom back to look at my solution because I was so close to getting it, but needed another pair of eyes. Together we got the pattern identified and the calculation for the Kth element correct.&lt;br /&gt;&lt;br /&gt;Finally back to the 250 problem SequenceOfNumbers. It was a real easy one, but we only had 9 min left on the clock. We got rushed and made some mistakes in our approach. Thankfully as a pair we quickly saw when things were off track and got back together. At one point we went off in a tangent trying to make an elegant solution. It wasn't panning out, so we trashed it and did a quick brute force. Adrenaline was pumping as we compiled and ran unit tests with less than one minute remaining. It pass the tests and we got everything submitted with ony 34 sec left in the contest.&lt;br /&gt;&lt;br /&gt;Final score... all our solutions worked and scored. We could have scored higher on KthElement and SequenceOfNumbers if we had looked at the unit tests and realized KthElement involved a repeating pattern. Having both problems opened at the same time was not good.&lt;br /&gt;&lt;br /&gt;Remote Pair Programming worked great! We performed as well as we would have sitting right next to each other. In fact we probably performed better being remote because it was easier to swap control since we each had our own mouse and keyboard.&lt;br /&gt;&lt;br /&gt;(Yes, we know TopCoder considers collaboration as cheating. Sorry. We were just trying to experiment with Pair Programming and enjoy the contest. We assume this is ok during a *not for money* match. It would be nice if TopCoder had a division for Pair Programmers.)&lt;br /&gt;&lt;br /&gt;[Aug 11, 2005.  I've posted a &lt;a href="http://ghouston.blogspot.com/2005/08/topcoder-on-pair-programming.html"&gt;follow up article&lt;/a&gt;.]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-112267167627669550?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/112267167627669550/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=112267167627669550' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112267167627669550'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112267167627669550'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/07/remote-pair-programming-on-topcoder.html' title='Remote pair programming on TopCoder'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-112266821728853309</id><published>2005-07-29T14:48:00.000-05:00</published><updated>2005-07-29T15:16:57.296-05:00</updated><title type='text'>Learning Iterated Development from the Game Industry</title><content type='html'>Julian Gold published a great article &lt;a href="http://www.gamasutra.com/features/20050720/gold_01.shtml"&gt;"Object-Oriented Game Development: Iterative Development Techniques"&lt;/a&gt; on Gamasutra.com.  Most Agile developers will recognize the basic iterative development techniques.  Julian adds the concept of defining features into three catagories: Core, Required, and Desired.  (Most projects I've worked we just identified features as either Required or Desired.)  You will have to read the article to understand the difference between Core and Required.&lt;br /&gt;&lt;br /&gt;Julian also divides up the object development into well defined levels of quality: null, base, nominal and optimal.  I really like the idea of defining the quality of object develop along a well defined scale.  This quailty scale is then used to divide up the development into prioritized iterations and evolve the objects through the project's life.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-112266821728853309?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/112266821728853309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=112266821728853309' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112266821728853309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112266821728853309'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/07/learning-iterated-development-from.html' title='Learning Iterated Development from the Game Industry'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-112197647850251755</id><published>2005-07-21T15:01:00.000-05:00</published><updated>2005-07-21T15:07:58.506-05:00</updated><title type='text'>Reflector == Cool Tool</title><content type='html'>&lt;a href="http://photos1.blogger.com/blogger/238/819/1600/reflector.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/238/819/400/reflector.jpg" border="0" alt="" /&gt;&lt;/a&gt; [image of Reflector]&lt;br /&gt;&lt;br /&gt;A co-worker introduced me to this little utility for .Net.  Reflector is a nice assembly browser that includes a disassembler, call graph and callee graphs.  Very nice! I can point it at my assemblies.  Then with a few clicks I can drill down into disassembled source for system libraries and third-party libraries that I am calling.  Reflector also has some plugins for DB browsing and other stuff.&lt;br /&gt;&lt;br /&gt;Reflector is available from &lt;a href="http://www.aisto.com/roeder/dotnet/"&gt;http://www.aisto.com/roeder/dotnet/&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-112197647850251755?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/112197647850251755/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=112197647850251755' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112197647850251755'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112197647850251755'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/07/reflector-cool-tool.html' title='Reflector == Cool Tool'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-112197459786207366</id><published>2005-07-21T14:30:00.000-05:00</published><updated>2005-07-21T14:36:37.870-05:00</updated><title type='text'>BORG everywhere</title><content type='html'>I wonder how many things in the I.T. world are named "BORG".  On my previous job we had a project named BORG.  On my current job, we've also got a project named "BORG".  I was just reading the tutorial doc for DbEncrypt &lt;a href="http://www.appsecinc.com/products/dbencrypt/mssql/dbencrypt_demo_msde.pdf"&gt;here&lt;/a&gt;.  Guess what, the DB in the tutorial is also "BORG".  :)&lt;br /&gt;&lt;br /&gt;I wonder, after the &lt;a href="http://www.serenitymovie.com/"&gt;Firefly movie&lt;/a&gt; will I start seeing things named Serenity?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-112197459786207366?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/112197459786207366/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=112197459786207366' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112197459786207366'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112197459786207366'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/07/borg-everywhere.html' title='BORG everywhere'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-112187177460290565</id><published>2005-07-20T09:53:00.000-05:00</published><updated>2005-07-20T10:02:54.610-05:00</updated><title type='text'>Byecycle</title><content type='html'>&lt;a href="http://byecycle.sourceforge.net/"&gt;http://byecycle.sourceforge.net/&lt;/a&gt; looks like a cool idea.  The homepage has a wink demo of the plugin (very nice).  Byecycle will display a dependency graph of you modules and highlight dependency cycles (plugin for Eclipse).  This makes it easy to see problems in design.   One realy cool features of byecycle is the way performs automatic layout.   The layout engine will keep shifting the diagram as it finds better layouts.  Also, check out the people behind this plugin.  Some really smart folks.&lt;br /&gt;&lt;br /&gt;Yes, a code metrics tool could provide similar information.  But the cool graph display makes this a lot more fun.  Plus the layout helps you understand the dependencies.  Hopefully, if you system is well designed the layout would show your architecture layers since it tries to make the arrows go top to bottom.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-112187177460290565?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/112187177460290565/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=112187177460290565' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112187177460290565'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112187177460290565'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/07/byecycle.html' title='Byecycle'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-112180766733216018</id><published>2005-07-19T16:10:00.000-05:00</published><updated>2006-02-20T15:10:43.386-06:00</updated><title type='text'>VS.Net customization</title><content type='html'>After my eyes got tired from looking at the screen too long, I found a macro that will let me easily change the font size in Visual Studio .Net. The macro is here: &lt;a href="http://dotnetjunkies.com/WebLog/demiliani/archive/2004/11/24/33422.aspx"&gt;Zooming your code in Visual Studio .NET&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I wish VS.Net provided some styles or themes with different color schemes. The plain white gets old. I looked at modifying the colors. But the settings were too detailed. It would take hours or days to get a good looking set of colors and fonts setup.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-112180766733216018?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/112180766733216018/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=112180766733216018' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112180766733216018'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112180766733216018'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/07/vsnet-customization.html' title='VS.Net customization'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-112144325102648038</id><published>2005-07-15T10:54:00.000-05:00</published><updated>2005-07-15T11:00:51.036-05:00</updated><title type='text'>Remote Collaboration</title><content type='html'>The NetBeans folks have a very interesting collab module.  It was designed to assist remote peer-review of code.  The model is really cool.  You take a file and share it with others.  The shared file goes into a "sandbox" so your original is not modified.  Everyone can collaborate in the sandbox.  Then the sondbox file changes can be merged back into the original file.  This could even help assist remote pair-programming (something I've been experimenting with).&lt;br /&gt;&lt;br /&gt;There is an article about it here... &lt;a href="http://www.artima.com/forums/flat.jsp?forum=106&amp;thread=117079"&gt;http://www.artima.com/forums/flat.jsp?forum=106&amp;thread=117079&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The collab project is here ... &lt;a href="http://collab.netbeans.org/"&gt;http://collab.netbeans.org/&lt;/a&gt;.  You can see a demo of it.  Just look under "Getting Started" for the "&lt;a href="http://collab.netbeans.org/files/documents/186/522/NB-Collab-Code-Review-for-JavaOne-v2.swf"&gt;See&lt;/a&gt;" link.&lt;br /&gt;&lt;br /&gt;If only it worked in IntelliJ and Eclipse.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-112144325102648038?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/112144325102648038/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=112144325102648038' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112144325102648038'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/112144325102648038'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/07/remote-collaboration.html' title='Remote Collaboration'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-111991738822727498</id><published>2005-06-27T19:04:00.000-05:00</published><updated>2005-06-27T19:11:46.580-05:00</updated><title type='text'>Rainbow</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/238/819/1600/IMG_2290.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/238/819/400/IMG_2290.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Today I got to enjoy a Rainbow as the storm came into our neighborhood.  If you look carefully to the right of the rainbow, you will see a faint second rainbow.   This was a quick snapshot.  So I just took the default landscape settings on my camera.  I dont have PaintShop Pro installed at the moment (reloaded computer), so I didn't get a chance to straighten the shot.  Sorry, my daughter wont give me enough time to install it.  :)&lt;br /&gt;&lt;br /&gt;[Looks like blogger reduced the image detail when I posted it.  Sorry that you cant see the original image.]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-111991738822727498?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/111991738822727498/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=111991738822727498' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111991738822727498'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111991738822727498'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/06/rainbow.html' title='Rainbow'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-111990284475369581</id><published>2005-06-27T15:01:00.000-05:00</published><updated>2005-06-27T15:07:24.756-05:00</updated><title type='text'>Microsoft on Security</title><content type='html'>I was listening to an MSDN TV clip on SQL Server 2005.  Thomas Rizzo makes this interesting, and funny comment...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-style:italic;"&gt;One thing I want to point out is both SQL CLR and Web Services are off by default when you install SQL Server. I don't want developers out there saying, oh, my god, is this on by default? What if a virus comes along or anything like that? &lt;span style="font-weight:bold;"&gt;You do have to explicitly turn it on&lt;/span&gt;, both the CLR and the Web Services support. &lt;span style="font-weight:bold;"&gt;We are making sure that it is very secure out of the box.&lt;/span&gt; &lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Ok, secure out of the box... &lt;span style="font-weight:bold;"&gt;by turning it off!&lt;/span&gt;  Very nice, maybe I should turn off my Windows XP machine to make sure it is secure as well. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-111990284475369581?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/111990284475369581/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=111990284475369581' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111990284475369581'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111990284475369581'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/06/microsoft-on-security.html' title='Microsoft on Security'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-111962968103716075</id><published>2005-06-24T10:48:00.000-05:00</published><updated>2005-06-24T11:14:41.046-05:00</updated><title type='text'>Reporting Fun</title><content type='html'>This is for my Java friends using SQL Server.&lt;br /&gt;&lt;br /&gt;Yesterday I went to the MSDN Event and got to see some presentations on SQL Server 2005 Reporting Services.  While it is still in beta, it really looked great.  SQL Server 2005 adds Web Services directly into SQL Server.  So you dont need IIS to talk to a Web Services (SOAP) with SQL Server.  A Java application could easily remotely call stored procedures or services on SQL Server using HTTP/SOAP.&lt;br /&gt;&lt;br /&gt;Calling SQL Server over web services gets exciting because you can call Reporting Services on SQL Server.  Reporting Services looks really powerful and easy to use.  So you could use Reporting Services to create those pretty reports (without BizObjects or Crystal Reports), and display the results in your java front end (HTML and other formats are available).&lt;br /&gt;&lt;br /&gt;Another nice feature of Reporting Services is the Report Builder.  With this, you can export a "Model" of your database.  This model contains the definitions of tables, views, relations that the end-user can use to create their own reports.  The model lets you decide what tables the user should query in their reports.  Then running Report Builder they can drag and drop columns to build reports.  Very easy!    What if they dont have Report Builder installed?  No problem, MS has made it a "no touch install", which means you can simple follow a link on a webpage and the app gets installed and run.  Very similar to Java's Webstart.   Ok, so now the user has created the report design.  In Report Builder, they can post the report design back to SQL Server Reporting Services (it uses secure HTTP/Soap webservices).  Then the report is available for future use.  Since Reporting Service is exposed as a WebService you can easily call it from your Java code.  Super cool.  It sure beats the things we had to do at my last job to get some very basic Crystal Reports functions into the application.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-111962968103716075?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/111962968103716075/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=111962968103716075' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111962968103716075'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111962968103716075'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/06/reporting-fun.html' title='Reporting Fun'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-111947818743665333</id><published>2005-06-22T17:02:00.000-05:00</published><updated>2005-06-22T17:09:47.440-05:00</updated><title type='text'>Eric Gamma on pair programming</title><content type='html'>In &lt;a href="http://www.artima.com/lejava/articles/patterns_practice.html"&gt;Patterns and Practice&lt;/a&gt; Part IV, Eric Gamma is quoted: &lt;br /&gt;"It's also an excellent way to improve your skills. I always learn something from a pair programming session and I wish I would do it more often."&lt;br /&gt;&lt;br /&gt;I must agree that pair programming is very educational.  I think I've picked up skills better by pair programming than from other activities.  Plus it is more fun.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-111947818743665333?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/111947818743665333/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=111947818743665333' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111947818743665333'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111947818743665333'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/06/eric-gamma-on-pair-programming.html' title='Eric Gamma on pair programming'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-111945881758212029</id><published>2005-06-22T11:29:00.000-05:00</published><updated>2005-06-22T11:46:57.586-05:00</updated><title type='text'>Prevayler everywhere, maybe not.</title><content type='html'>&lt;a href="http://www.prevayler.org/wiki.jsp"&gt;Prevayler&lt;/a&gt; is a great persistence engine for Java. I've used it a couple of times at home when I needed to persist small amounts of data. Prevayler is based on Serialization and the Command pattern. Overall the engine is pretty fast and lightweight.  Writing code to use Prevayler is fairly simple.  You just have to put your collection into Prevayler and create command objects for every update.  The collection and commands have to be serializable.&lt;br /&gt;&lt;br /&gt;So now that I'm working in the .Net world, I had a need to persist a small set of objects.   I found &lt;a href="http://bbooprevalence.sourceforge.net/"&gt;Bamboo.Prevalence&lt;/a&gt; on SourceForge. I was real excited to find a prevayler for .Net. So I started a test project to get familiar with Bamboo (v1.4.4.4). My simple test failed. I kept getting mysterious exceptions while creating the Bamboo engine. So I thought I would look for docs, but there were none. So I thought I'd look at user groups / mail-lists; they were practically empty. I found a couple of articles, but they were out of date. Bamboo's API has changed since the articles were written. So Bamboo is now getting deleted from my disk. It is a tragic end. Using undocumented open-source is not practical.&lt;br /&gt;&lt;br /&gt;Recommended: Prevayler for Java&lt;br /&gt;&lt;br /&gt;Not Recommended: Bamboo.Prevalence v1.4.4.4 for .Net&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-111945881758212029?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/111945881758212029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=111945881758212029' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111945881758212029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111945881758212029'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/06/prevayler-everywhere-maybe-not.html' title='Prevayler everywhere, maybe not.'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-111922272691212541</id><published>2005-06-19T18:01:00.000-05:00</published><updated>2005-06-19T18:12:06.916-05:00</updated><title type='text'>Vancouver</title><content type='html'>Last week I had a great trip to Vancouver.   The weather was sunny most of the week which is really great for that time of year.  Sunil and I tried every Indian restraunt we could find in the area.  Plus, I got to eat African and Maylsian food.  Also the area had plenty of healthy food.   I had a great time trying out all the foods.  I think my favorite was a Tai place near our office.  We walked all around during the week.   IT was really good for me to walk so much.&lt;br /&gt;&lt;br /&gt;The trip was productive even though it was short.  For myself it was really great to meet the guys from India.  I realize now that I had some resentment towards the India team.  Mostly because of the unwelcome change to my job and for those who lost their jobs in Bham.  But after getting to know those guys better, I've put my resentment behind.  These guys are just computer geeks like myself.   They are in much the same place in life as myself.  Trying to raise families and make a good living.   Unfortunately for them, they have to be displaced more than me to meet the demands of their career.  After getting to know them, I now look forward to working with them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-111922272691212541?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/111922272691212541/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=111922272691212541' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111922272691212541'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111922272691212541'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/06/vancouver.html' title='Vancouver'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-111842863478834915</id><published>2005-06-10T13:29:00.000-05:00</published><updated>2005-06-10T13:37:14.796-05:00</updated><title type='text'>Good reading... Eric Gamma on Design Patterns</title><content type='html'>I've been reading a series of articles on Design Patterns.  The articles are &lt;a href="http://www.artima.com/lejava/articles/gammadp.html"&gt;here&lt;/a&gt;, &lt;a href="http://www.artima.com/lejava/articles/reuse.html"&gt;here&lt;/a&gt;  and &lt;a href="http://www.artima.com/lejava/articles/designprinciples.html"&gt;here&lt;/a&gt;.  Eric Gamma shows great experience with developing using Design Patterns, Frameworks, etc.  I particularly like the way he defines toolkits, frameworks, and class libraries.  Providing some tips about the pros and cons of each.  There might be more articles in this series, so keep watching out for them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-111842863478834915?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/111842863478834915/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=111842863478834915' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111842863478834915'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111842863478834915'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/06/good-reading-eric-gamma-on-design.html' title='Good reading... Eric Gamma on Design Patterns'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-111834795677054823</id><published>2005-06-09T15:09:00.000-05:00</published><updated>2005-06-09T15:12:36.773-05:00</updated><title type='text'>Office fun... MYTOB.AR</title><content type='html'>This afternoon we are getting lots of emails.  The &lt;a href="http://www.trendmicro.com/vinfo/virusencyclo/default5.asp?VName=WORM_MYTOB.AR"&gt;MYTOB.AR&lt;/a&gt; worm has taken a bite out of office productivity.  Ah the adventures of cyberspace.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-111834795677054823?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/111834795677054823/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=111834795677054823' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111834795677054823'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111834795677054823'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/06/office-fun-mytobar.html' title='Office fun... MYTOB.AR'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-111832503523277735</id><published>2005-06-09T08:37:00.000-05:00</published><updated>2005-06-09T08:50:35.236-05:00</updated><title type='text'>What's up?</title><content type='html'>Life is going well in my new home.  The kids are just getting over the latest round of colds.  David is teething.  Michelle and I have picked up the cold.  So everyone is happy.  Heather started swim lessons, so she is loving the time to get into the pool.  We got a slip and slide for her.  Lots of fun!  (No I didn't slide on it.)  I would grab Heather and pull her down the slide.  Since it was her first encounter with it, I didn't think she was ready to try taking a running dive at the slide.  Overall, she played in the slides sprikler more than sliding.&lt;br /&gt;&lt;br /&gt;In my new house, I ran a cat5 cable to the location where I want to place my computer.  I don't want to go wireless.  So I had all the fun of drilling holes and pulling cables.   It took a lot longer than I expected because I had to keep going to the store to get different supplies.  Plus trying to work on the house with two toddlers constently interrupting slowed me down.  Now I just need the  time to move the furniture and setup the PC properly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-111832503523277735?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/111832503523277735/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=111832503523277735' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111832503523277735'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111832503523277735'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/06/whats-up.html' title='What&apos;s up?'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-111783307324626718</id><published>2005-06-03T16:05:00.000-05:00</published><updated>2005-06-03T16:11:13.250-05:00</updated><title type='text'>Guidance</title><content type='html'>My friend Richard sent me this funny explination of &lt;a href="http://www.teamodb.com/phpnuke/modules/My_Uploads/user_folders/CorvetteODB/Guidance.wav"&gt;Missile Guidance&lt;/a&gt;.  Enjoy!&lt;br /&gt;&lt;br /&gt;I also found this one: &lt;a href="http://www.teamodb.com/phpnuke/modules/My_Uploads/user_folders/CorvetteODB/battleship.jpg"&gt;Battleship.jpg&lt;/a&gt;  which made me think of Raf for some unknown reason.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-111783307324626718?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/111783307324626718/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=111783307324626718' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111783307324626718'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111783307324626718'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/06/guidance.html' title='Guidance'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-111782446997201329</id><published>2005-06-03T13:36:00.000-05:00</published><updated>2005-06-03T13:47:49.976-05:00</updated><title type='text'>No Phones, No Lights, No Motor Cars; Not a Single Luxury</title><content type='html'>I now know that I'm living out in the country.  I have no phone service!  The last set of thunderstorms knocked out dial-tone in my area.  It has been gone for 24+ hrs now (Friday), and BellSouth currently estimates it will be **TUESDAY** to get it fixed.&lt;br /&gt;&lt;br /&gt;Thankfully my DSL still works great, so I'm not completely cut off from civilization like the crew on Gilligan's Island.  Unfortunately I'm one of those dead-beats who refuses to get a cell-phone.  So I don't have any phone at home.   I guess I could use Skype to make a call out using the internet.  In a pinch I could always run to a neighbors and use their cell phone :)&lt;br /&gt;&lt;br /&gt;So not having a phone for a few days will be an adventure.  Especially since it falls on a weekend.  It makes it harder to coordinate getting together with friends and family.  But, it wont be that difficult.  If I had lost internet service, then I think I would start looking for a new house.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-111782446997201329?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/111782446997201329/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=111782446997201329' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111782446997201329'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111782446997201329'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/06/no-phones-no-lights-no-motor-cars-not.html' title='No Phones, No Lights, No Motor Cars; Not a Single Luxury'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-111688847486099742</id><published>2005-05-23T17:40:00.000-05:00</published><updated>2005-05-23T17:47:54.863-05:00</updated><title type='text'>Great stuff from Yahoo, soon</title><content type='html'>I've been playing around with MyWeb (beta) from Yahoo.   It provides the ability to save a copy of a webpage to yahoo's servers.  Then you can search your saved pages at a later time.  This is wonderful for me since I'm always reading a lot of tech articles.  So now I can save the articles and use search to find something I've read before.  This works so much better than using Google or Yahoo seach on a topic because it is like searching through your own memory.&lt;br /&gt;&lt;br /&gt;I've run into some problems with the beta of MyWeb.  Currently it only works well if you use Yahoo Toolbar.  Unfortunately the toolbar can slow down your browser.  So I have to turn off the Yahoo Toolbar most of the time.  Then just turn it on to save a page.&lt;br /&gt;&lt;br /&gt;Yahoo 360 is another product in beta.  I'm not in their invitation only beta.  So I cant really say how well it works.  However, it looks like it has many features I've wanted.   You can check it out on Yahoo's site.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-111688847486099742?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/111688847486099742/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=111688847486099742' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111688847486099742'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111688847486099742'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/05/great-stuff-from-yahoo-soon.html' title='Great stuff from Yahoo, soon'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-111582032266522221</id><published>2005-05-11T08:54:00.000-05:00</published><updated>2005-05-11T09:05:22.683-05:00</updated><title type='text'>Java + XQuery + JTidy to parse HTML!</title><content type='html'>Occasionally I've written little programs to scrape webpages for useful information.  In the past I've used various open-source libraries with varying satisfaction.  My favorite approach so far is to use Ruby and it's HTML parsing libraries.  Today I found an article published by IBM Developerworks that provides another approach that looks really cool:  &lt;a href="http://www-128.ibm.com/developerworks/library/j-jtp03225.html?ca=dnt-612"&gt;Java theory and practice: Screen-scraping with XQuery&lt;/a&gt;.  The approach is to first use JTidy to cleanup the badly structured HTML and return the document and XML (4 lines of code).  Then using XML tools like Saxon XQuery to easily query XML and reformat the data (several examples that were &lt;10 lines of code, very readable!).  Very nice solution!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-111582032266522221?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/111582032266522221/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=111582032266522221' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111582032266522221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111582032266522221'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/05/java-xquery-jtidy-to-parse-html.html' title='Java + XQuery + JTidy to parse HTML!'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-111551752577660252</id><published>2005-05-07T20:31:00.000-05:00</published><updated>2005-05-07T21:11:55.300-05:00</updated><title type='text'>Short Game Anyone?</title><content type='html'>After a long battle (47 turns via email... spanning 6months), the glorious battle resulted in a **DRAW**.   Maybe I should look into a short game.  Gamasutra has a great article &lt;a href="http://www.gamasutra.com/features/20050502/carlson_01.shtml"&gt;"Making a Case for Short Games"&lt;/a&gt; by the author of Strange Adventures in Infinite Space.  A great little game.  A short game is a nice change from the 20+ hour games I've been playing.  While the Author makes a great case for 20min games.   I personally tend to like 6 - 10 hour games.  Enough time to be engaging, but not so long that I get bored or tired of the gameplay.  One of my favorites on the PS2 ... &lt;a href="http://ps2.ign.com/objects/014/014833.html"&gt;"Ico"&lt;/a&gt; was a delightful 10 hours of play.  The game was outstanding, especially considering it was an early release when the PS2 was new to the market.   Ico stood out to me because of the castle you played in.  Ico's world wasn't just a bunch of designed "levels" that you jumped from one to the other.  Instead the castle was wonderfully designed and architected.  Each set of rooms which made a small level, fit beautifully into the design of the entire castle.  From the towers and parapets of some areas you could see other areas of the castle.  All the rooms fit together and made sense.  It really felt like you were inside a old castle that was once real and functioning medieval castle.  I hear the Ico team is cooking up a new creation that sounds really really cool... &lt;a href="http://ps2.ign.com/objects/490/490849.html"&gt;Shadow of the Colossus&lt;/a&gt; where the level isn't a static castle; instead its a living behemoth colossus creatures.  The E3 videos look fantastic!&lt;br /&gt;&lt;br /&gt;Soon I will get back in the general's seat and start off another battle against my nemesis Matt in Combat Mission.  Our last battle, while a draw, did have some really cool events.  I would have completely lost if I hadn't made a desperate and crazy dash up the middle to get behind his tanks.   Even then he made a great move to repel my assault on the strongest hill on the map.  Only then did a single shot from an overwatching tank stop him.  The battle really did spell victory or shattering defeat on that single shot.  If I hadn't gotten the kill (and that was a really lucky line of sight); he would have been able to secure a great position and hold my forces off.  The results would have been a defeat.  Instead, my play worked and finished off his tanks.  It was just a mop-up operation after that.  Unfortunately, I didn't have enough time to take the highest scoring object from him before the time ran out.   Matt was able to claim a draw.   We shall have to fight again!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-111551752577660252?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/111551752577660252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=111551752577660252' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111551752577660252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111551752577660252'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/05/short-game-anyone.html' title='Short Game Anyone?'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-111523832289057620</id><published>2005-05-04T15:23:00.000-05:00</published><updated>2005-05-04T15:25:22.946-05:00</updated><title type='text'>... disconnected ...</title><content type='html'>I don't have Internet service at my new house.  It will take a few days more to get setup.  So I haven't been able to add to the blog.  Sorry, more to come later.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-111523832289057620?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/111523832289057620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=111523832289057620' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111523832289057620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111523832289057620'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/05/disconnected.html' title='... disconnected ...'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-111386498231932886</id><published>2005-04-18T17:53:00.000-05:00</published><updated>2005-04-18T17:56:22.320-05:00</updated><title type='text'>More AOP and Annotations...</title><content type='html'>Blogger crashed with a 500 error when I first made a great post on this topic.   So instead you are getting the shortened version now.  I'm too lazy to retype all the stuff I said before my post was lost to the bit bucket.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www-128.ibm.com/developerworks/java/library/j-aopwork4/"&gt;AOP and metadata: A perfect match, Part 2&lt;/a&gt; go get it, read it, learn from it, enjoy it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-111386498231932886?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/111386498231932886/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=111386498231932886' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111386498231932886'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111386498231932886'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/04/more-aop-and-annotations.html' title='More AOP and Annotations...'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-111358878535865240</id><published>2005-04-15T13:01:00.000-05:00</published><updated>2005-04-15T13:13:05.360-05:00</updated><title type='text'>Ratchet and Clank (Playstation 2)</title><content type='html'>I have to give Ratchet and Clank it's own post because I've found it such an enjoyable game.  I just completed R&amp;C 2 (Going Commando) and found myself diving into the *Challenge Mode* where the game is replayed with all the stuff you gained, but the enemies are 10x stronger.  The game is one of the best platform games I've played.  The levels are nicely designed and fun to complete (not a lot of exploring, each level usually has a couple of branches).  One aspect of the game I've liked is the variety.  The game has a lot of variety in weapons, gadgets, levels, and things to interact with.  Another fun part of the game is the cut scenes.  They are really well matched to the game world and plot.  In addition the designers did a great job of adding nice touches of humor to it.&lt;br /&gt;&lt;br /&gt;If you haven't tried R&amp;C, I recommend it.  It is rare that a game holds my interest to 100% completion.  Even rarer that I'll complete both the original and the sequel.   Yes, I did complete R&amp;C the original game a year or two ago.  Fortunately I kept my save game.  In R&amp;C 2 I was able to recover the weapons from R&amp;C 1 that were in my saved game.  This really is a fun game series.   Now if only R&amp;C 3 would become a *Greatest Hit* so I can buy it cheap.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-111358878535865240?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/111358878535865240/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=111358878535865240' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111358878535865240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111358878535865240'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/04/ratchet-and-clank-playstation-2.html' title='Ratchet and Clank (Playstation 2)'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10533270.post-111358806785406010</id><published>2005-04-15T12:40:00.000-05:00</published><updated>2005-04-15T13:01:07.856-05:00</updated><title type='text'>I'm going to Vancouver... or India... or both?</title><content type='html'>The latest news on my job is that I'm the "Solution Architect" on one of our products that is developed up in Vancouver.   Nice! I'm think free trips to Canada.  But then our top management makes an big announcement... all development and QA is getting outsourced to India.  Ok, free trips to India?  Fortunately as an Architect I get to keep my job.  {I'm learning to expect anything with this company.}  So now I've got to take knowledge from the unfortunate folks in Vancouver, and give it to a new offshore team.  We will have to see how this new mandate works out.   The reason behind the move to offshoring is the same found at the previous company.  The good old boys at the top are involved with both companies.  I really feel for the guys I've gotten to know here in Birmingham that are loosing their jobs.  I pray they can all find something better.&lt;br /&gt;&lt;br /&gt;On a lighter note, I've had the chance to remotely develop from my old house in Atlanta to my new job in Birmingham.  It worked very well.  I was able to concentrate while at home.  Connectivity was good over my dsl.  I was able to interact with the Bham folks over IM.  Overall, I'd say I got a bit more done from home than I would from the office.  At home I was able to keep interruptions to a minimum.  I was also able to focus more.  At home I was less concerned with the time of day.  Which means I took lunch when it was convienent with my work tasks, and was usually much shorter.  Also, the work day was a little longer because I started earlier and didn't stop until later.   I don't think I'd want to telecommute all the time, but it is nice.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10533270-111358806785406010?l=ghouston.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ghouston.blogspot.com/feeds/111358806785406010/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10533270&amp;postID=111358806785406010' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111358806785406010'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10533270/posts/default/111358806785406010'/><link rel='alternate' type='text/html' href='http://ghouston.blogspot.com/2005/04/im-going-to-vancouver-or-india-or-both.html' title='I&apos;m going to Vancouver... or India... or both?'/><author><name>Greg Houston</name><uri>http://www.blogger.com/profile/10710797803413263120</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry></feed>
