<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Rex Morgan Dot Net</title><link>http://www.rexmorgan.net/</link><description>Rex Morgan's thoughts on software development, design, architecture, business, et cetera.</description><language>en-us</language><lastBuildDate>Tue, 28 Jul 2009 23:41:00 -0500</lastBuildDate><pubDate>Tue, 28 Jul 2009 23:41:00 -0500</pubDate><image><title>Rex Morgan Dot Net</title><url>http://www.rexmorgan.net/content/feed_logo.png</url><width>225</width><height>82</height><link>http://www.rexmorgan.net/</link></image><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item><guid isPermaLink="false">http://www.rexmorgan.net/journal/The_millionth_Twitter_parser</guid><pubDate>Tue, 28 Jul 2009 23:41:00 -0500</pubDate><title>The millionth Twitter parser</title><link>http://feedproxy.google.com/~r/rexmorgan/~3/aE2N7FpnN6E/The_millionth_Twitter_parser</link><category /><description><![CDATA[<p>For some reason the thing I get contacted the most about my site is that thing in the right column:</p>  <blockquote>   <p>I’m trying to show my latest tweet on my website like yours. How do you make the names and links show up like that?</p> </blockquote>  <p>Conceptually it’s very simple. If you like Regular Expressions, the implementation is very simple too. If you don’t, those bits might be described as hellish. Here’s the workflow:</p>  <ul>   <li>Fetch latest tweet <a href="http://apiwiki.twitter.com/Twitter-REST-API-Method%3A-statuses-user_timeline">via the Twitter API</a></li>    <li>Find all @name references, <a href="http://apiwiki.twitter.com/Twitter-REST-API-Method%3A-users%C2%A0show">look up their real name</a>, and replace with a link</li>    <li>Find all URLs (“http(s)://…”) and replace with a link to that URL</li>    <li>Find all hashtags (#hashtag) and replace with a link to <a href="http://twitter.com/#search?q=%23hashtag">Twitter Search</a></li>    <li>If the tweet starts with @name(s), wrap them in a “To {@name(s)}:”</li> </ul>  <p>Simple! Right? Right. So we take a <a href="http://twitter.com/rexm/status/2772241681">tweet</a> which looks like:</p>  <blockquote>   <p>@ballance @bspotter a summary of my view on #sharepoint - http://rexmorgan.net/media/spcomparison.jpg</p> </blockquote>  <p>And format it to look like:</p>  <pre class="prettyprint"><code>&lt;span class="salutation"&gt;To 
&#160;&#160;&#160;&#160;&lt;a href="http://twitter.com/ballance"&gt;Chris&lt;/a&gt;,
&#160;&#160;&#160;&#160;&lt;a href="http://twitter.com/bspotter"&gt;Brandon&lt;/a&gt;:
&lt;/span&gt;
a summary of my view on &lt;a href="http://twitter.com/#search?q=%23sharepoint"&gt;#sharepoint&lt;/a&gt;
 - &lt;a href="http://rexmorgan.net/media/spcomparison.jpg"&gt;http://rexmorgan.net/media/spcomparison.jpg&lt;/a&gt;

&lt;a class="date" href="http://twitter.com/rexm/status/2772241681"&gt;— &lt;span&gt;8:06 PM yesterday&lt;/span&gt;&lt;/a&gt;
</code></pre>


<p>The code’s a bit too long to paste in this format, so I got to take <a href="http://www.west-wind.com/weblog/">Rick Strahl</a>’s sweet <a href="http://codepaste.net/home/about">CodePaste.NET</a> for a spin and <a href="http://codepaste.net/1yhne8">dropped the code here</a>.</p>

<p>Two thing to keep in mind: <strong>(1) Twitter can sometimes be slow.</strong> Multiple lookups to get people’s real names means this can be <em>even slower</em>. Now, Twitter is pretty cool, but it’s not worth making your audience wait for it to time out. <a href="http://www.svennerberg.com/2008/12/page-load-times-vs-conversion-rates/">It’s not worth making your audience wait at all.</a> Stick all this code in an HttpHandler and include it as a JavaScript at the bottom of your page, so it will execute after your page is safely in your user's browser. If it fails, you'll just have a blank spot on your page:</p>

<pre class="prettyprint"><code>&lt;/body&gt;
&lt;script type="text/javascript" src="twitter.ashx"&gt;&lt;/script&gt;
</code></pre>

<p><strong>(2) The Twitter's REST API has a <a href="http://apiwiki.twitter.com/Rate-limiting">150-request-per-hour limit</a></strong> from a single account or IP. Cache your tweet results enough not to go over that limit, or you will be blacklisted! I cache mine for two minutes. Cheers!</p>]]></description><feedburner:origLink>http://www.rexmorgan.net/journal/The_millionth_Twitter_parser</feedburner:origLink></item><item><guid isPermaLink="false">http://www.rexmorgan.net/journal/Rotate_Image_Hue_in_cNET</guid><pubDate>Fri, 3 Jul 2009 13:08:00 -0500</pubDate><title>Rotate Image Hue in c#/.NET</title><link>http://feedproxy.google.com/~r/rexmorgan/~3/HksFUBxkFZE/Rotate_Image_Hue_in_cNET</link><category /><description><![CDATA[<p>I am on vacation <a href="http://en.wikipedia.org/wiki/Outer_Banks">at the beach</a> with my wife and a few friends, and was perusing Stackoverflow at the house while waiting for everyone to get ready to go out. I ran across a question about <a href="http://stackoverflow.com/questions/1079820/rotate-hue-using-imageattributes-in-c">how to rotate hue in code</a>, which I myself have wondered before but never really needed to. Here's what I started with:</p> <ul> <li>I do enough design work to know the difference between <a href="http://en.wikipedia.org/wiki/HSL_color_space"><abbr title="Hue, Saturation, Brightness">HSB</abbr> (also called <abbr title="Hue, Saturation, Value">HSV</abbr>)</a> and <abbr title="Red, Green, Blue">RGB</abbr>, so I know changing the hue is extremely easy if I have the HSB value (the "H" stands for Hue!).</li> <li>I also know GDI+ in .NET works primarily in (A)RGB. I can iterate over the pixels of a Bitmap object and <a href="http://msdn.microsoft.com/en-us/library/system.drawing.bitmap.getpixel.aspx">Get</a> and <a href="http://msdn.microsoft.com/en-us/library/system.drawing.bitmap.setpixel.aspx">Set</a> the pixel value in RGB.</li>  <li>There is a mathematical way to convert an RGB value to HSB and vice-versa, but I have no idea what that is.</li></ul> <p>A few minutes on Google yielded the equations, so I slammed this together in a few minutes more. The basic workflow is:</p> <ul> <li>Load an image and an amount to shift the hue by</li> <li>Iterate over all the pixels in the image</li>  <li>For each pixel, convert its RGB value to HSB, change the hue, convert back to RGB, set the pixel's new RGB value</li>  <li>Save the image</li></ul> <p>Here's a sample input/output:</p> <img height="165" alt="Original" src="http://www.rexmorgan.net/media/RotateImageHueinc.NET_B7C5/original.jpg" width="220" /> <img height="165" alt="Hue Shifted" src="http://www.rexmorgan.net/media/RotateImageHueinc.NET_B7C5/hueshifted.jpg" width="220" /> <p>Here's the central code which changes the hue for a single pixel:</p> <pre class="prettyprint"><code>
private Color CalculateHueChange(Color oldColor, float hue)
{
&#160;&#160;&#160;&#160;HLSRGB colorConverter = new HLSRGB(
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;oldColor.R,
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;oldColor.G,
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;oldColor.B);
&#160;&#160;&#160;&#160;float startHue = colorConverter.Hue;
&#160;&#160;&#160;&#160;colorConverter.Hue = startHue + hue;
&#160;&#160;&#160;&#160;return Color.FromArgb(
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;colorConverter.Red,
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;colorConverter.Green,
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;colorConverter.Blue);
}
</code></pre>
<p>Not exactly rocket science, but interesting to me and presumably the person who asked the question. <a href="http://rexmorgan.net/content/imagehuer.zip">Here's the source</a>. <b>Disclaimer</b>: This is *not* an efficient way to do any kind of image manipulation. It is just a proof-of-concept. Cheers!</p>]]></description><feedburner:origLink>http://www.rexmorgan.net/journal/Rotate_Image_Hue_in_cNET</feedburner:origLink></item><item><guid isPermaLink="false">http://www.rexmorgan.net/journal/Fixing_ASPNET_ldquoKeep</guid><pubDate>Thu, 18 Jun 2009 22:49:00 -0500</pubDate><title>Fixing ASP.NET &amp;ldquo;Keep Alive&amp;rdquo;</title><link>http://feedproxy.google.com/~r/rexmorgan/~3/dG7YxOY6EAU/Fixing_ASPNET_ldquoKeep</link><category /><description><![CDATA[<p>One issue that has plagued ASP.NET developers for several years now is IIS’ default behavior to shut down the .NET worker process after an idle time (usually 20 minutes). Since ASP.NET’s biggest bottleneck is usually the application startup (compiling ASPX files and loading assemblies into the AppDomain), this means the first visitor to your site after 20+ minutes of no activity can have a <em>very</em> long wait before that page comes back. Embarrassingly long, for you. Subsequent pages come through at the speed you know your site is capable of, but the first impression is done and gone.</p>  <p>If you control the web server, this isn’t a big deal. A simple config change <a href="http://stackoverflow.com/questions/838318/how-to-keep-asp-net-assemblies-in-appdomain-alive/838348#838348">in IIS6 or IIS7</a> will keep the worker process alive – and your site code in memory, waiting to be served - indefinitely.</p>  <p>But plenty of sites run on shared hosting. In that case, you don’t have any real access to IIS settings. It’s also not really in the interest of your shared hosting provider to offer to keep your site in memory any more than it absolutely needs to be. So what to do? There is a handful of <a href="http://www.keepaliveforever.com/">services</a> which offer to hit your site every x minutes to keep IIS from killing your application. Those just don’t seem right, though. Keeping an application alive should be something we have very granular control over – not some one-off service that might disappear tomorrow.</p>  <p>So I wrote a little class that will let an ASP.NET application decide when and whether to “keep alive” itself. Nothing special, really – it puts an object into cache for 10 minutes, and when the 10 minutes are up, the object requests a page in your site through IIS and re-inserts itself into the cache for 10 more minutes.</p>  <p>As long as your application wants to keep itself alive, it can call <strong>KeepAlive.Start(url)</strong>. Just pass in any URL in your site (e.g. "<a href="http://www.rexmorgan.net/journal">http://www.rexmorgan.net/journal</a>"). You can check <strong>IsKeepingAlive</strong> to see if your app is currently keeping itself alive. If you want to stop, call <strong>KeepAlive.Stop()</strong>. (Of course, that won’t actually kill your app – just allows IIS to eventually kill the process if it goes idle).</p>  <p>Here’s the code. If you find it useful, let me know! Cheers:</p>  <pre class="prettyprint"><code>
public class KeepAlive
{
&#160;&#160;&#160;&#160; private static KeepAlive instance;
&#160;&#160;&#160;&#160; private static object sync = new object();
&#160;&#160;&#160;&#160; private string _applicationUrl;
&#160;&#160;&#160;&#160; private string _cacheKey;

&#160;&#160;&#160;&#160; private KeepAlive(string applicationUrl)
&#160;&#160;&#160;&#160; {
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; _applicationUrl = applicationUrl;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; _cacheKey = Guid.NewGuid().ToString();
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; instance = this;
&#160;&#160;&#160;&#160; }

&#160;&#160;&#160;&#160; public static bool IsKeepingAlive
&#160;&#160;&#160;&#160; {
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; get
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; lock (sync)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return instance != null;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }
&#160;&#160;&#160;&#160; }

&#160;&#160;&#160;&#160; public static void Start(string applicationUrl)
&#160;&#160;&#160;&#160; {
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if(IsKeepingAlive)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; lock (sync)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; instance = new KeepAlive(applicationUrl);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; instance.Insert();
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }
&#160;&#160;&#160;&#160; }

&#160;&#160;&#160;&#160; public static void Stop()
&#160;&#160;&#160;&#160; {
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; lock (sync)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; HttpRuntime.Cache.Remove(instance._cacheKey);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; instance = null;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }
&#160;&#160;&#160;&#160; }

&#160;&#160;&#160;&#160; private void Callback(string key, object value, CacheItemRemovedReason reason)
&#160;&#160;&#160;&#160; {
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (reason == CacheItemRemovedReason.Expired)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; FetchApplicationUr();
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Insert();
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }
&#160;&#160;&#160;&#160; }

&#160;&#160;&#160;&#160; private void Insert()
&#160;&#160;&#160;&#160; {
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; HttpRuntime.Cache.Add(_cacheKey,
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; this,
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; null,
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Cache.NoAbsoluteExpiration,
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; new TimeSpan(0, 10, 0),
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; CacheItemPriority.Normal,
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; this.Callback);
&#160;&#160;&#160;&#160; }

&#160;&#160;&#160;&#160; private void FetchApplicationUrl()
&#160;&#160;&#160;&#160; {
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; try
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; HttpWebRequest request = HttpWebRequest.Create(this._applicationUrl) as HttpWebRequest;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; using(HttpWebResponse response = request.GetResponse() as HttpWebResponse)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; HttpStatusCode status = response.StatusCode;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; //log status
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; catch (Exception ex)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; //log exception
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }
&#160;&#160;&#160;&#160; }
}
</code></pre>]]></description><feedburner:origLink>http://www.rexmorgan.net/journal/Fixing_ASPNET_ldquoKeep</feedburner:origLink></item><item><guid isPermaLink="false">http://www.rexmorgan.net/journal/Stack_Overflow_Search_Provider</guid><pubDate>Mon, 2 Mar 2009 17:18:00 -0500</pubDate><title>Stack Overflow Search Provider</title><link>http://feedproxy.google.com/~r/rexmorgan/~3/XAOOEyCijNw/Stack_Overflow_Search_Provider</link><category /><description><![CDATA[<p><a href="http://stackoverflow.com">Stack Overflow</a> is a fantastic site. From the standpoint of a consumer (me), it’s a huge success on nearly all fronts. Kudos to <a href="http://www.codinghorror.com/">Jeff</a> and <a href="http://www.joelonsoftware.com/">Joel</a> and the team for the great work. However, I’ve noticed one glaring piece of suck on the site – the search. We are way too spoiled by Google to put up with this circa-2000-quality search results. So, until they fix it (given their track record so far, I expect it to eventually excel), I have taken to using <a href="http://www.google.com/search?q=site:stackoverflow.com%20visitor+pattern&amp;ie=utf-8&amp;oe=utf-8&amp;aq=t">Google’s index of the site</a>. Typing <b>site:stackoverflow.com</b> gets old though, so to save me (and now, you) the extra 23 keystrokes, I’ve made a Stack Overflow Google Search provider for Firefox: </p>  <pre class="prettyprint"><code>
&lt;searchplugin xmlns=&quot;http://www.mozilla.org/2006/browser/search/&quot;&gt;
&#160;&#160;&#160;&#160; &lt;shortname&gt;Stack Overflow&lt;/shortname&gt;
&#160;&#160;&#160;&#160; &lt;description&gt;Stack Overflow Google Search&lt;/description&gt;
&#160;&#160;&#160;&#160; &lt;inputencoding&gt;UTF-8&lt;/inputencoding&gt;
&#160;&#160;&#160;&#160; &lt;img height=&quot;16&quot; width=&quot;16&quot; /&gt;data:image/x-icon;base64,R0lGODlhEAAQAMQAAGZmZu6+gNhWI+aeQfvv35lmM8+4oOB4T/fd0+CGEbuZd9bCrf///+HClvPPoOSWMbSPaeWObOiae9thMvro4vffwOTWyequYPj18f337/XXsOimUAAAAAAAAAAAAAAAACH5BAAHAP8ALAAAAAAQABAAAAVhICOOYjYJCKmSkjBRaxwJRxZXzpgdQhRviYdGRDlJVoRLIjgsTmyrTOARrCBSJMPCgmEQNINNrEAmKwyNSsyggJTJKgBAhbEsDAy5SC/v9/NzgIB+fIF6MXuGhIuHjIwMIQA7&lt;/img&gt;
&#160;&#160;&#160;&#160; &lt;url template=&quot;http://www.google.com/search&quot; method=&quot;GET&quot; type=&quot;text/html&quot;&gt;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;param value=&quot;site:stackoverflow.com {searchTerms}&quot; name=&quot;q&quot; /&gt;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;param value=&quot;utf-8&quot; name=&quot;ie&quot; /&gt;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;param value=&quot;utf-8&quot; name=&quot;oe&quot; /&gt;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;param value=&quot;t&quot; name=&quot;aq&quot; /&gt;
&#160;&#160;&#160;&#160; &lt;/url&gt;
&#160;&#160;&#160;&#160; &lt;searchform&gt;http://www.google.com/search?q=site%3Astackoverflow.com&lt;/searchform&gt;
&lt;/searchplugin&gt;
</code></pre>

<p>Just create a new xml file in your Mozilla Firefox\searchplugins folder, paste the above in, and restart FF. You should see something like this:</p>

<p><img title="sosearch" style="display: inline; margin-left: 0px; margin-right: 0px" height="215" alt="sosearch" src="http://www.rexmorgan.net/media/StackOverflowSearchProvider_DCC0/sosearch.jpg" width="382" /></p>]]></description><feedburner:origLink>http://www.rexmorgan.net/journal/Stack_Overflow_Search_Provider</feedburner:origLink></item><item><guid isPermaLink="false">http://www.rexmorgan.net/journal/Code_Name_Velocity</guid><pubDate>Wed, 4 Jun 2008 23:01:00 -0500</pubDate><title>Code Name Velocity</title><link>http://feedproxy.google.com/~r/rexmorgan/~3/gt-qi9NdbRE/Code_Name_Velocity</link><category /><description><![CDATA[<p>At TechEd 2008 (which unfortunately I was not able to attend, but a few colleagues are providing me continuous updates), Microsoft announced a <a href="http://blogs.msdn.com/sharepoint/archive/2008/02/11/announcing-the-final-release-of-vsewss-1-1-and-the-upcoming-version-1-2.aspx">lot</a> <a href="http://weblogs.asp.net/dwahlin/archive/2008/06/03/new-features-in-silverlight-2-beta-2.aspx">of</a> <a href="http://blogs.msdn.com/ie/archive/2008/06/03/ie8-beta-2-coming-in-august.aspx">things</a> that are really important to me. New breakthroughs in voice recognition are always cool, but I am a web guy at my core so that's what turns my crank.</p> <p>I have a few side projects that need a distributed in-memory cache. These projects are all in .NET so my obvious choices were <a href="http://www.sharedcache.com/">SharedCache</a>, <a href="http://www.scaleoutsoftware.com/products/stateServer/index.html">ScaleOut StateServer</a>, <a href="http://www.alachisoft.com/ncache/">NCache</a> or <a href="http://jehiah.cz/projects/memcached-win32/">memcached Win32</a> with <a href="https://sourceforge.net/projects/memcacheddotnet/">one</a> <a href="http://www.codeplex.com/EnyimMemcached/">of</a> <a href="http://code.google.com/p/beitmemcached/">several</a> .NET clients. Memcached is a lot more free than the latter two and more well-regarded than the first, so last week I started a little personal project of porting <a href="http://www.danga.com/memcached/">memcached</a> to .NET. My C is pretty rusty but relatively speaking memcached is pretty simple, and it seems like a managed version could perform quite well. Since I know c# better than English, it makes enhancements and customizations to my caching layer much easier.</p> <p>Thankfully I didn't burn too much time on memcached.NET before Microsoft announced <a href="http://blogs.msdn.com/velocity/">Velocity</a> - a distributed cache written to natively support the .NET stack. After digging in to the CTP code, I came away very impressed. In the past I've viewed the caching layer of an application very simplistically from a usage perspective - a persistent dictionary of keys and frequently used objects. Distributing it across multiple machines adds complexity to the service but not the consumers. Velocity has some features with huge implications in the kind of value a cache can deliver:</p> <ul> <li><strong>Lookups by tag</strong>. This means one thing to me: <em>multi-dimensional object keying</em>. No more ugly pointers or multiple copies of an object per key. This increases the value of the caching layer by orders of magnitude over a simple key-value pair table.</li> <li><strong>In-process storage</strong>. With a typical cache service, our cache will store a serialized copy of User::Bob in memory. Bob is very popular in our application, so his user object is deserialized into the application process on almost every request. This is wasteful and contributes to memory pressure since we are essentially storing the same object at least twice - sometimes more. In-process storage allows heavily used items like User::Bob to stay in the application process space <em>instead</em> of being serialized to the cache service.</li> <li><strong>OOTB Session Provider</strong>. Velocity includes a SessionStateStoreProvider implementation out of the box. A high performance, high availability state server for free without putting any pressure on your SQL box (which is probably why you are considering Velocity in the first place).</li> <li><strong>Atomic operations &amp; concurrency management</strong>. Optimistic locking with versioning opens the door to much more sophisticated functionality than would otherwise be practical with the typical pessimistic locking. I predict applications that are able to align themselves with actual usage patterns much more intelligently.</li></ul> <p>As I noted in the beginning, memcached is pretty simple. And as my short list of highlights suggests, Velocity is anything but. Although memcached and Velocity solve the same problem - offloading high-volume requests from the data tier to an in-memory intermediary - they serve surprisingly different purposes. Scott Watermasysk <a href="http://simpable.com/code/velocity/">summarizes the distinction neatly</a>:</p> <blockquote> <p>On one hand you have Memcached which treats the cache as something you should never rely on. It is there to help but you should always assume it is going to fail on you and even more importantly (to Memcached) you should accept that as a fact. If you read the <a href="http://www.socialtext.net/memcached/index.cgi?faq">Memcached FAQ</a> you can almost here the author laughing when talking about fault tolerance. On the other side of the fence you have features like replication and high availability.</p></blockquote> <p>The practical implications are significant. What kind of service are you running? What kind of data are you moving? Who is your audience? These are very high level architectural questions that help shape whether to go with a memcached-like solution or a Velocity-like solution. Jim Benedetto, in an interview with Baseline Magazine, <a href="http://www.baselinemag.com/c/a/Projects-Networks-and-Storage/Inside-MySpacecom/6/">described MySpace's answer</a> to these questions:</p> <blockquote> <p>100% reliability is not necessarily [the] top priority. "That's one of the benefits of not being a bank, of being a free service"...on MySpace the occasional glitch might mean the Web site loses track of someone's latest profile update, but it doesn't mean the site has lost track of that person's money. "That's one of the keys to the Web site's performance, knowing that we can accept some loss of data"</p></blockquote> <p>Usually my default reaction such an idea is "no way!" Loosely coupling system components to the point where data in one layer might not make it to the next layer every time makes me feel very uncomfortable. Embracing discomfort is necessary for growth though, so let's give it a big bear hug and dive in. The original purpose of memcached was to support <a href="http://www.livejournal.com/">LiveJournal</a>. In this environment, a failure rate of the caching layer might just mean an extra few round trips to the database. As long as the caching layer works some of the time, we still see a benefit. But then issues start to get sticky. What if the failure comes when we try to invalidate a cache item because a journal post was updated? The old version will be exposed to the public longer than intended. Is this acceptable behavior? Obviously I don't know the answer to that for LiveJournal's case. But the point is significant - how does reliability affect the business value of your application? For MySpace, responding promptly to a hundred million requests and failing a percentage of those delivers greater value than rolling service brownouts or throttling everyone.</p> <p>Ultimately, the Velocity announcement has brought these questions to the forefront of my mind. I'll be relaxing in Ireland for the next week and a half, but I'm sure I'll be thinking about how to answer these questions for my apps. Make sure to do the same for yours.</p>]]></description><feedburner:origLink>http://www.rexmorgan.net/journal/Code_Name_Velocity</feedburner:origLink></item><item><guid isPermaLink="false">http://www.rexmorgan.net/journal/Procrastinate_Whenever_Possible</guid><pubDate>Thu, 8 May 2008 18:43:00 -0500</pubDate><title>Procrastinate Whenever Possible</title><link>http://feedproxy.google.com/~r/rexmorgan/~3/KWwTLM52lnI/Procrastinate_Whenever_Possible</link><category /><description><![CDATA[<p><a href="http://www.wilshipley.com/">Wil Shipley</a> has a lot of wisdom in the arena of software development. And he regularly backs up his advice with results that prove him right. There is one particular theme of his, however, that really sticks with me:</p> <blockquote> <p>START WITH BREVITY. Increase the other dimensions AS REQUIRED BY TESTING.</p></blockquote> <p>He actually takes his time to elaborate on the justifications and implications of this advice, culminating in an oft-linked-to post that is really <a href="http://www.wilshipley.com/blog/2007/05/pimp-my-code-part-14-be-inflexible.html">worth reading</a>. The first time I read it I thought it sounded nice, but it didn't quite *click*. It took about 6 more months of fumbling through base classes that I haven't implemented and interfaces that only get used in one place before I punted.</p> <img alt="Class design checklist - bad" src="http://www.rexmorgan.net/media/ProcrastinateWheneverPossible_10EEB/checklistbad_3.jpg" class="left" /> <p>When you are handed a problem, if your first thought is "I will need a base class that does x and probably an interface for y" you are creating extra work for yourself. Writing abstract classes first is, very literally, solving problems that don't exist. When you're writing code, you don't have a problem until you are calling a method that doesn't exist, or doesn't do what you need. No programmer, no matter how good, can accurately predict what calls he will be making from hypothetical classes before they are written. Even if you have a complete class diagram for your entire application (and if you do, why didn't you spend that time writing the code?), it will be wrong. You will have to make changes as your ideas break on the rocky reality of implementation.</p> <blockquote> <p>Many programmers, when they create a new class, add a ton of features to that class to make it "complete" -- that is, they try to anticipate everyone who may ever use this class, and they add methods that those hypothetical users may want...you may be saying to yourself, "What's wrong with flexibility?" Strangely, I was about to tell you. The problem is YOU ARE NOT A LIBRARY PROGRAMMER.</p></blockquote> <img alt="Class design checklist - good" src="http://www.rexmorgan.net/media/ProcrastinateWheneverPossible_10EEB/checklistgood_3.jpg" class="right" /><p>What Would Wil Do? "Start with brevity." Break the tasks into easily defined units of functionality, and take the first item off the list and code it <em>concretely</em>. Only build what you need to make that functionality work. <b>After</b> you encounter code that can be shared, write your base class. <b>After</b> you hit a problem that can only be solved with an interface, stub it out.</p> <p><b>If you just wrote </b>public abstract<b> and you don't <i>already</i> have a class written that will be inheriting from it, stop right there.</b> Backspace over that abstract keyword and start building your concrete implementation first. Put off best practice 'till tomorrow for what you can get working today. I guarantee you will have a more stable, maintainable product in the longest run, and you'll ship sooner.</p> <p>This all is not to say that you should not have good design to your software. A good architecture is invaluable and irreplaceable. In a later post, I'll elaborate on design approaches that can be built in as your code takes shape, without burning time creating a base library instead of getting things done.</p>]]></description><feedburner:origLink>http://www.rexmorgan.net/journal/Procrastinate_Whenever_Possible</feedburner:origLink></item><item><guid isPermaLink="false">http://www.rexmorgan.net/journal/Getting_the_Right_Domain_Name</guid><pubDate>Thu, 10 Apr 2008 1:11:00 -0500</pubDate><title>Finding the Right Domain Name</title><link>http://feedproxy.google.com/~r/rexmorgan/~3/CeLcLKC97Ok/Getting_the_Right_Domain_Name</link><category /><description><![CDATA[<p>Recently Jeff Atwood <a href="http://www.codinghorror.com/blog/archives/001095.html">wrote about</a> his startup's struggle to come up with a good name:</p> <blockquote><p>I've been brainstorming names for the web site we're building. I've surveyed some of the finest minds in the software developer community (for very small values of "fine"), and we've come to a collective realization: <b>naming a website is hard. Really, <i>really</i> hard.</b></p></blockquote> <p>No kidding. This isn't just true of websites, or even of companies, but of ventures in general. That's why there are <a href="http://www.lexicon-branding.com/">firms</a> that charge tens of thousands of dollars to do it for you. And it's hard to blame them - would BlackBerries be <em>quite</em> as popular if they were called <a href="http://en.wikipedia.org/wiki/BlackBerry#Name_origin">LeapFrogs</a> instead?</p> <p>But Jeff shoots himself in the foot from the beginning by (almost) eliminating any name that isn't available as a .com. Anyone reading this has some inkling of the sheer volume of domains that have already been registered, and no guess at what percentage of those are squatted would be too cynical. When practically every common and obvious .com name is already taken, companies have to resort to <a href="http://www.lightsphere.com/dev/web20.html">more and more contrived</a> names just so they can say they have theirname.com. But is it really worth it?</p> <p>In their book <a href="http://gettingreal.37signals.com/">Getting Real</a>, 37signals discusses their emphasis on names <a href="http://gettingreal.37signals.com/ch13_Name_Hook.php">that make sense</a>:</p> <blockquote><p>Give your app a name that's easy to remember. A big mistake a lot of people make is thinking their app's name needs to be ultradescriptive. Don't worry about picking a name that vividly describes your tool's purpose; That usually just leads to a generic, forgettable name. Basecamp is a better name than something like Project Management Center or ProjectExpress.</p></blockquote> <p>The name should be simple, with a blend of familiarity and uniqueness - <a href="http://www.basecamphq.com/">Basecamp</a>, <a href="http://www.campfirenow.com/">Campfire</a>, <a href="http://www.backpackit.com/">Backpack</a>, etc. are all familiar word-phrases to English speakers, but are unique enough as product names to stick. Here's the really interesting part - they don't have the .com for <em>any </em>of those products. Basecamp is basecamphq.com; Campfire is campfirenow.com; Backpack is backpackit.com. 37signals doesn't exactly need publicity by now, but they weren't always known. How did they violate the common domain name wisdom and still succeed?</p> <p>Jason et al recognized something that most of us just can't seem to get past: <strong>the precise domain name really isn't that important:</strong></p> <blockquote><p>[D]on't sweat it if you can't get the exact domain name you want. You can always be creative and get close with a couple of extra letters</p></blockquote> <p>They looked past appearances and went straight for <strong>use</strong>. How do people use domain names? If you have a great service, people are going to</p> <ul> <li>Bookmark it</li><li>E-mail it</li><li>Twitter it</li><li>IM it</li></ul> <p>What people will <em>almost never</em> do is try to remember the service by name and retype the address from scratch. At worst, they will Google it, which should be easy because it's an easy, short, memorable name. In every case, it doesn't even matter what the domain name is. Your users will never have to remember it or type it. People love or <a href="http://roy.tabulas.com/2007/08/07/why-sometimes-i-hate-37signals/">hate</a> 37signals for one reason or another, but I've never heard of anyone begrudging them or their services because their domain names are slightly off. If a service is delivering value, the particular domain name just falls into the background.</p> <p>Ultimately, I think people get too caught up in selecting "the right" domain name because they are insecure about the website behind that name, and they feel like they need every bit of help they can get, like agonizing over SEO and having "the right" name. If there's one thing 37signals is not, it's <a href="http://www.wired.com/techbiz/media/magazine/16-03/mf_signals?currentPage=all">insecure</a>. And although their word is thrown down as gospel <em>way</em> too much among bloggers, a bank statement is <a href="http://blog.jedchristiansen.com/2008/02/25/37signals-is-one-hell-of-a-profitable-business/">hard to argue with</a>.</p> <p>Be confident with your service and your name, and success will follow. Your .com is only as central to your business as you make it.</p>]]></description><feedburner:origLink>http://www.rexmorgan.net/journal/Getting_the_Right_Domain_Name</feedburner:origLink></item><item><guid isPermaLink="false">http://www.rexmorgan.net/journal/getting_what_you_want</guid><pubDate>Mon, 24 Mar 2008 22:36:00 -0500</pubDate><title>Getting What You Want</title><link>http://feedproxy.google.com/~r/rexmorgan/~3/ZUKydQItTqI/getting_what_you_want</link><category /><description><![CDATA[<p>Over the past year or so, I've really started paying closer attention to the people aspect of software development. Reading <a href="http://www.codinghorror.com">Jeff Atwood</a> has been a significant part of that evolution for me. Jeff noted how very important <a href="http://www.codinghorror.com/blog/archives/000890.html">interpersonal interaction</a> is to a successful programmer:</p> <blockquote> <p>How can you possibly learn the craft without being exposed to other programmers with different ideas, different approaches, and different skillsets? Who will review your code and tell you when there's an easier approach you didn't see? <b>If you're serious about programming, you should <i>demand</i> to work with your peers</b>.</p></blockquote><a href="http://www.amazon.com/gp/product/0671027034?ie=UTF8&amp;tag=rexm-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0671027034"><img class="right" alt="image" src="http://www.rexmorgan.net/media/dealingwithpeople_A9A0/image_3.png" /></a>  <p>One of the more unfortunate traits common to the programmer demographic is our remarkable ability to be <a href="http://www.loudthinking.com/">off-putting</a>. It's certainly more true for some than for others, but even when a programmer is considered "quite personable", he's probably a lot closer to <a href="http://www.personalitypathways.com/">ISTP than to ENFP</a>.</p> <p>So I'm trying to improve. The single best resource I've found for this is Dale Carnegie's <a href="http://www.amazon.com/gp/product/0671027034?ie=UTF8&amp;tag=rexm-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0671027034">How to Win Friends &amp; Influence People</a>. It's an immersive read - Carnegie is an excellent storyteller and uses clear, concise examples to communicate his "Fundamental Techniques". It's practically written for a programmer, removing all fluff and assumptions about interpersonal interactions - a literal API reference for people:</p> <ul> <li>"Give people a feeling of importance by praising the good parts of them"</li> <li>"Become genuinely interested in other people"</li> <li>"Encourage others to talk about themselves"</li> <li>"Start with questions the person will answer yes to"</li> <li>"Let the other person feel the idea is his/hers."</li></ul> <p>The brief sampling above evidences the paradox of effectively dealing with people - we have to give what we want to the person we want things from. On the surface, the advice sounds so simple - "be nice to people and you're more likely to get what you want." But how often do we do it in practice? How often do you really give up all the credit for a job well done, even if you did most of the work - or it was even your idea? Not often enough.</p> <p>Carnegie's thin paperback is so full of behaviors to change that it's overwhelming, so it's good to start with a select few and make them habitual. I've been developing a few habits of my own, slowly but surely. These things will seem like Life 101 to some, and far-fetched to others:</p> <ul> <li>Being very direct and task-oriented (a major programmer trait), when I need something from someone my first action is to start a new e-mail and politely ask for what I need. New habit: before I hit send, I backtrack to the beginning of the e-mail and write a sentence or two complimenting something they've done recently, or asking about something that is important to them.</li> <li>I am trying to remember to append the person's name every time I say "hello", "thanks", or "goodbye" to them.</li> <li>When someone compliments me directly, I try to think of someone who contributed, even indirectly, to whom I can credit some of the success.</li></ul> <p>Hopefully the pattern here is pretty obvious: make other people feel important. People like feeling like other people are interested in them and their issues; people like hearing their name; people like receiving credit. At first it feels a little shallow, maybe even a little sociopathic - having to consciously fish for nice things to say to or about people. But I can say from experience that it doesn't take long to become habitual, and then become natural. When you think about these things all the time, you actually do start to become interested in other people's issues. You become invested in the success other people get to enjoy when you give them credit for a job well done. And that's the real trick - not faking pleasantness to manipulate people into doing what you want, but genuinely being the kind of person other people like getting along with. That kind of person naturally gets what they want, which is really where we all want to be.</p>]]></description><feedburner:origLink>http://www.rexmorgan.net/journal/getting_what_you_want</feedburner:origLink></item><item><guid isPermaLink="false">http://www.rexmorgan.net/journal/Never_Be_a_Five</guid><pubDate>Fri, 14 Mar 2008 21:24:00 -0500</pubDate><title>Never Be a Five</title><link>http://feedproxy.google.com/~r/rexmorgan/~3/pDULEB9UG6w/Never_Be_a_Five</link><category /><description><![CDATA[<p>Roughly once a month we have a group meeting. It's really the only time where the entire web platform team is in the same room, so we cover big topics at a high level. One of the major discussion points yesterday centered around an unsolicited, unscheduled review of our group by our corporate masters. It rated our performance in key areas on a scale of 1-5 (5 being perfect, 1 being &quot;why haven't you been fired yet?&quot;):</p>  <ul>   <li>Hosting &amp; infrastructure </li>    <li>Quality of developers </li>    <li>Project management &amp; delivery </li>    <li>Etc. </li> </ul>  <p>The rating &quot;quality of developers&quot; got a 4. For a minute, I was a little shocked and offended. If there is one thing our group is known for and prides itself on, it is the quality of our development team. I work on one of the best development teams I've ever known, and my opinion is not atypical. I hear on a weekly basis how above-par we are as a group. The web platform team is &quot;leet&quot;, as they say.</p>  <p>Four is good - great, even. Three being &quot;average-competitive&quot;, it's highly desirable to be a 4. That being the case, why do I care so badly about being a 5? Is it realistic to want to be a 5? Is it that much of a shock to be told you're only really good when you thought you were the best?</p>  <p>Like I said, my reaction lasted for a minute. But then I asked myself, &quot;is it possible to be a 4 and also be the best?&quot; I think it is. When I say best, I definitely don't mean best in the world. There's always someone better. But &quot;best&quot; in a very localized sense can be different for everyone and still be useful. Like my track coach told me so many times, you're only racing against yourself. The other people out there on the track with you are just useful tools to help benchmark your progress, but the competition is internal. </p>  <p>Anyone who has done any kind of race, especially track, knows that you get your best times when you consistently run with people a little bit better than yourself. The person ahead of you is an attainable goal. If you're alone, you have no baseline with which to construct the bounds of potential achievement. If you're half a mile behind the nearest competitor, any effort would be wasted. If I'm a 5, I've peaked. Any improvement from there on is sheer luck. Personally, I don't want to peak yet. </p>  <p>Never be comfortable. If you think you're on top of the world, it's impossible to go any higher. You've established a mental model of your profession that prevents you from truly aspiring to improve. Instead, if you think you're a 5, <em>make</em> yourself a 4. Keep besting yourself. Spend some time and effort identifying some aspect of development you don't fully understand. Actively seek to work with people who make you <a href="http://www.codinghorror.com/blog/archives/000890.html">feel a little stupid</a>. It's only as uncomfortable <a href="http://markeseremet.blogspot.com/2006/12/dumbest-guy-in-room.html">as you make it</a>. Be a 4, forever.</p>]]></description><feedburner:origLink>http://www.rexmorgan.net/journal/Never_Be_a_Five</feedburner:origLink></item><item><guid isPermaLink="false">http://www.rexmorgan.net/journal/A_Brief_reIntroduction</guid><pubDate>Tue, 11 Mar 2008 2:53:00 -0500</pubDate><title>A Brief (re)Introduction</title><link>http://feedproxy.google.com/~r/rexmorgan/~3/RbVLUdzytUY/A_Brief_reIntroduction</link><category /><description><![CDATA[<p>A long-overdue restart of my weblog, this time on my long-unused domain. Please explore and <a href="http://www.rexmorgan.net/me/contact">let me know</a> if you find a bug or seven. This blog platform is <a href="http://www.rexmorgan.net/me/blog">home-grown</a> and a work in progress. There are a number of projects I'm actively working on, and I really needed a way to try out some <a href="http://msdn.microsoft.com/data/ref/linq/">new</a> <a href="http://weblogs.asp.net/scottgu/archive/2007/10/14/asp-net-mvc-framework.aspx">technologies</a> in a non-threatening, small-scale playground setting. The timing happened to coincide with my desire to resume blogging and my frustration with many existing blogging platforms. So, finding them all to be too difficult or flaky, I threw this together instead. The design is something I've been incubating for awhile. It's nothing special, but it gets the job done.</p>]]></description><feedburner:origLink>http://www.rexmorgan.net/journal/A_Brief_reIntroduction</feedburner:origLink></item></channel></rss>
