<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>casey.in.point &#187; Uncategorized</title>
	<atom:link href="http://caseywatson.com/category/uncategorized/feed/" rel="self" type="application/rss+xml" />
	<link>http://caseywatson.com</link>
	<description>keepin' it real... real simple.</description>
	<lastBuildDate>Tue, 16 Feb 2010 05:42:15 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>The Next Chapter</title>
		<link>http://caseywatson.com/2010/02/15/the-next-chapter/</link>
		<comments>http://caseywatson.com/2010/02/15/the-next-chapter/#comments</comments>
		<pubDate>Tue, 16 Feb 2010 05:39:16 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://caseywatson.com/?p=295</guid>
		<description><![CDATA[Change.  If I could choose only one word to define the last couple of months, that&#8217;s the word that I would choose.
Friday was my last day as a member of the Improving Enterprises team.  I was offered a position at another company in the Irving area that I simply could not, for my sake and [...]]]></description>
			<content:encoded><![CDATA[<p>Change.  If I could choose only one word to define the last couple of months, that&#8217;s the word that I would choose.</p>
<p>Friday was my last day as a member of the Improving Enterprises team.  I was offered a position at another company in the Irving area that I simply could not, for my sake and my family&#8217;s, refuse.  I will admit, however, that the decision to leave Improving was not an easy one.  I&#8217;ve learned more, not just about software development but about myself and what I want out of my career, in the last two years than I did in the entire time before I joined Improving.  My time at Improving has been a blessing and it has been both an honor and a privilege to work with some of the most talented technology folks in the metroplex.  Along the way I&#8217;ve dropped a few bad habits (regions, etc.) and picked up a ton of new ones but I can guarantee that I would not be embarking upon the opportunity that I am now without my experiences at Improving.</p>
<p>Besides the change in employer, I&#8217;ve also had a lot of other things going on recently.  I&#8217;ve developed a deep interest in mobile technology (specifically MonoTouch) and have had the privilege of being invited to speak at several user groups including the Dallas C# Special Interest Group, the Shreveport .NET User Group and the Aggieland .NET User Group in College Station.  I&#8217;ve learned a lot from these engagements and have had the opportunity to meet some very interesting folks.  By the way, if you&#8217;re interested in learning more about MonoTouch, <a href="http://live.ineta.org/Videos/Player.aspx?video=26f86829-3ecd-4bc5-bbbb-799d4ecabc2d">check out my talk on INETA Live.</a></p>
<p>Beyond that, I also have a lot of other stuff going on that I&#8217;m not really at liberty to speak about at the moment.  Don&#8217;t worry, though&#8230; more details should be forthcoming soon.  Let&#8217;s just say that I don&#8217;t have a lot of free time lately and I feel very blessed to have an understanding wife.  You may have noticed that I haven&#8217;t been posting nearly as often to this blog lately, but, again, I&#8217;ve been incredibly busy.  Hopefully the updates will pick up again soon.</p>
<p>In the meantime, keep building better code.  Stay tuned for more information soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://caseywatson.com/2010/02/15/the-next-chapter/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>MonoTouch Goodness</title>
		<link>http://caseywatson.com/2009/12/03/monotouch-goodness/</link>
		<comments>http://caseywatson.com/2009/12/03/monotouch-goodness/#comments</comments>
		<pubDate>Fri, 04 Dec 2009 05:40:55 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://caseywatson.com/?p=286</guid>
		<description><![CDATA[Hey, folks.  For those of you that attended tonight&#8217;s Dallas C# SIG meeting, thank you.  I also want to extend a special thanks to my employer, Improving Enterprises, for hosting the meeting and providing refreshments.
If you&#8217;re interested in digging deeper into MonoTouch, take a look at these resources that I&#8217;ve pulled together.  There&#8217;s some good [...]]]></description>
			<content:encoded><![CDATA[<p>Hey, folks.  For those of you that attended tonight&#8217;s Dallas C# SIG meeting, thank you.  I also want to extend a special thanks to my employer, Improving Enterprises, for hosting the meeting and providing refreshments.</p>
<p>If you&#8217;re interested in digging deeper into MonoTouch, <a href="http://www.delicious.com/caseywatson/monotouch">take a look at these resources that I&#8217;ve pulled together</a>.  There&#8217;s some good stuff in there.  I&#8217;m going to clean up the application that we built tonight a little and post it to CodePlex at some point next week.   I&#8217;ll be sure to send out a tweet and let you guys know when it&#8217;s available.</p>
<p>Again, thanks to those of you that attended and I look forward to seeing all of you at the next meeting in January.  As always, feel free to contact me directly if you have any questions about the material that we went over tonight.  Viva la C#!</p>
<p><strong>UPDATE: The source code from last night has been cleaned up and <a href="http://sigtweet.codeplex.com/">published to CodePlex</a>.  Word.</strong></p>
<p><strong>YET ANOTHER UPDATE: You can watch this session in its entirety <a href="http://www.drowningintechnicaldebt.com/ShawnWeisfeld/archive/2009/12/06/monotouch-for-the-iphone-dallas-c-sig-on-1232009.aspx">here</a></strong><strong>.  I want to extend a special thanks to Shawn Weisfeld for recording and editing the video.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://caseywatson.com/2009/12/03/monotouch-goodness/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WriteThisNotThat.com</title>
		<link>http://caseywatson.com/2009/10/14/writethisnotthat-com/</link>
		<comments>http://caseywatson.com/2009/10/14/writethisnotthat-com/#comments</comments>
		<pubDate>Wed, 14 Oct 2009 20:08:53 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://caseywatson.com/?p=276</guid>
		<description><![CDATA[Have you checked out WriteThisNotThat.com yet?  You haven&#8217;t?!  Alright.  I see how it is.  I thought we were friends.
WriteThisNotThat.com is a community-based site dedicated to building a library of good development practices by profiling the really ugly ones.  By really ugly practices I mean that 700-line-long method that makes you vomit in your mouth a [...]]]></description>
			<content:encoded><![CDATA[<p>Have you checked out <a href="http://writethisnotthat.com/">WriteThisNotThat.com</a> yet?  You haven&#8217;t?!  Alright.  I see how it is.  I thought we were friends.</p>
<p><a href="http://writethisnotthat.com/">WriteThisNotThat.com</a> is a community-based site dedicated to building a library of good development practices by profiling the really ugly ones.  By really ugly practices I mean that 700-line-long method that makes you vomit in your mouth a little everytime you think about it.  How about that old class that&#8217;s 90% unreachable code because it&#8217;s covered in hacked-together bandages?  That&#8217;s what we want to see!  This site is welcome to all developers regardless of language (even VB) or experience level.  Seasoned architect?  Great!  Straight out of college?  Even better! </p>
<p>We&#8217;re in the process of courting some sponsors so that we can spin up a monthly contest based on your votes.  Post your ugly source code and there might be a little something in it for you. </p>
<p>Drop by when you get chance.  If you don&#8217;t learn anything the first time around it will atleast be good for a chuckle or two. Next time you run across some especially gnarly source code, share it with us!  We&#8217;d love to see it! </p>
<p>If you like the site, please don&#8217;t keep it a secret.</p>
]]></content:encoded>
			<wfw:commentRss>http://caseywatson.com/2009/10/14/writethisnotthat-com/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fun with Fluent Interfaces</title>
		<link>http://caseywatson.com/2009/10/14/fun-with-fluent-interfaces/</link>
		<comments>http://caseywatson.com/2009/10/14/fun-with-fluent-interfaces/#comments</comments>
		<pubDate>Wed, 14 Oct 2009 19:42:19 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://caseywatson.com/?p=255</guid>
		<description><![CDATA[I&#8217;ve been working on an application recently that sleeps until a specific time then checks for the existence of a particular file.  While writing the application it dawned on me that I&#8217;ve written very similar code before for other clients.  I hate to solve the same problem twice so I decided to create a simple API [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on an application recently that sleeps until a specific time then checks for the existence of a particular file.  While writing the application it dawned on me that I&#8217;ve written very similar code before for other clients.  I hate to solve the same problem twice so I decided to create a simple API that allows me to create a new thread, have it sleep for or until a specific time, then execute a block of code.  I decided that my API would also implement a fluent interface.</p>
<p>Fluent interfaces allow developers to work with objects in a more natural and readable fashion by chaining methods together.  By building a fluent interface I can make my API not only more concise but much easier to use.  Take a look at the following code:</p>
<pre class="brush: csharp;">
Wait.Until(&quot;1:45 PM&quot;).Then(() =&gt; DoSomethingImportant());
</pre>
<p>By chaining methods together we&#8217;re forming a sentence describing exactly what we want to happen. We want to wait until 1:45 PM and then do something important. But how do we implement this interface?  <strong>Wait</strong> is actually a static class that defines the <strong>For</strong> and <strong>Until</strong> methods. Let&#8217;s take a closer look to see what&#8217;s going on under the covers:</p>
<pre class="brush: csharp;">
public static class Wait
{
  public static WaitContext For(TimeSpan waitFor_)
  {
    if (waitFor_ &lt;= TimeSpan.Zero)
        throw new ArgumentOutOfRangeException(&quot;waitFor&quot;, &quot;The supplied time span is negative&quot;);

    return new WaitContext(waitFor_);
  }

  public static WaitContext For(string waitFor_)
  {
    TimeSpan waitFor = default(TimeSpan);

    if (!(TimeSpan.TryParse(waitFor, out waitFor)))
        throw new ArgumentOutOfRangeException(&quot;waitFor&quot;, &quot;The supplied time span is invalid.&quot;);

    return For(waitFor);
  }

  public static WaitContext Until(DateTime waitUntil_)
  {
    if (waitUntil_ &lt;= DateTime.Now)
        throw new ArgumentOutOfRangeException(&quot;waitUntil_&quot;, &quot;The supplied date is in the past.&quot;);

    return new WaitContext(waitUntil_);
  }

  public static WaitContext Until(string waitUntil_)
  {
    DateTime waitUntil = default(DateTime);

    if (!(DateTime.TryParse(waitUntil_, out waitUntil)))
        throw new ArgumentOutOfRangeException(&quot;waitUntil_&quot;, &quot;The supplied date is invalid.&quot;);

    return Until(waitUntil);
  }
}
</pre>
<p>Let&#8217;s take a second to examine this class.  As you can see, we are defining overloaded versions of the <strong>Wait</strong> and <strong>For</strong> methods allowing us to supply a specific <strong>DateTime</strong> or <strong>TimeSpan</strong> or a string that can be parsed into the appropriate structure.  By overloading the two key methods to allow strings we can make our interface more natural and easier to read.  Each method first performs some validation logic then returns a <strong>WaitContext</strong> that defines how long we are going to wait before executing a given block of code.  Let&#8217;s take a look at <strong>WaitContext</strong> so we can complete the full picture of how this is all going to work:</p>
<pre class="brush: csharp;">
public class WaitContext
{
  internal WaitContext(DateTime waitUntil_)
  {
    _waitUntil = waitUntil_;
  }

  internal WaitContext(TimeSpan waitFor_)
  {
    _waitFor = waitFor_;
  }

  private DateTime? _waitUntil;
  private TimeSpan? _waitFor;

  public void Then(Action toDo_)
  {
    if (toDo_ == null)
        throw new ArgumentNullException(&quot;toDo_&quot;);

    ThreadPool.QueueUserWorkItem(new WaitCallback(
        new Action&lt;object&gt;(o =&gt;
            {
                Thread.Sleep(
                    _waitUntil.HasValue ?
                    _waitUntil.Value.Subtract(DateTime.Now) : _waitFor.Value);

                toDo_();
            })));
  }
}
</pre>
<p>The <strong>WaitContext</strong> can only be initialized within the <strong>Wait</strong> class defined earlier with a <strong>DateTime</strong> or <strong>TimeSpan</strong> structure.  The <strong>Then</strong> method is the one that actually does all of the heavy lifting.  After checking that the provided <strong>Action</strong> delegate is valid we then spin up a new thread.  Within the thread we&#8217;re going to wait for or until the specified time then invoke the provided delegate.  Since we&#8217;re potentially working with multiple threads here be sure to make the delegate that you provide thread-safe.  If you&#8217;d like, it would be pretty simple to include some sort of callback mechanism within the delegate that you provide. </p>
<p>That&#8217;s pretty much all there is to it.  Keep in mind that there is no one tool for every situation.  Fluent interfaces just seemed to be a particularly good fit this time around.  I&#8217;d like to add some additional functionality in the near future that would allow me to continuously invoke the delegate at a given interval.  I don&#8217;t need that right now but I&#8217;ll probably add it later.</p>
<p>This source code is free to modify and use for whatever purpose.  All that I ask is that you give a little credit where credit is due and let me know how you&#8217;re using it.</p>
<p>Happy hacking!</p>
]]></content:encoded>
			<wfw:commentRss>http://caseywatson.com/2009/10/14/fun-with-fluent-interfaces/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Log4Net + Twitter = Awesome</title>
		<link>http://caseywatson.com/2009/07/07/log4net-twitter-awesome/</link>
		<comments>http://caseywatson.com/2009/07/07/log4net-twitter-awesome/#comments</comments>
		<pubDate>Tue, 07 Jul 2009 17:03:15 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://caseywatson.com/?p=227</guid>
		<description><![CDATA[Unfortunately, application logging tends to be one of those things that doesn&#8217;t become a priority until something goes horribly wrong. Once you decide to implement logging, the next question becomes where you want to log your events to. You might decide that you should log events to the database. You might decide that you should [...]]]></description>
			<content:encoded><![CDATA[<p>Unfortunately, application logging tends to be one of those things that doesn&#8217;t become a priority until something goes horribly wrong. Once you decide to implement logging, the next question becomes where you want to log your events to. You might decide that you should log events to the database. You might decide that you should notify a select set of users by e-mail whenever there is an application error. While both of these are great options, there is no silver bullet. Logging events to a database is a great idea since it basically guarantees persistence, but how often will it really be checked? Ideally, this option should be used in conjunction with another mechanism that provides more immediate feedback when something important has happened. While the most common choice is to automatically send out e-mail notifications, this can often become annoying very quickly to those that are receiving the e-mails.</p>
<p>Twitter is a wildly popular social networking service that allows users to share what they&#8217;re up to, in 140 characters or less, by posting &#8220;tweets&#8221;.  I have been using Twitter for years and find it to be not only addictive, but a great way to keep updated on what those in my social circle are working on in an unobtrusive fashion.  I wondered if it would be possible to leverage this platform to allow my applications to share their status in an equally unobtrusive way.  Fortunately, <a href="http://apiwiki.twitter.com/Twitter-API-Documentation">Twitter exposes almost all of it&#8217;s functionality through an easy-to-use REST-ful API</a>.</p>
<p>Originally, I thought that I would roll my own logging framework to support this new model, however, I eventually decided agasint reinventing the wheel.  I have been using <a href="http://logging.apache.org/log4net/index.html">Log4Net</a>, a .NET port of the popular Java Log4J platform, for years.  Log4Net is not only incredibly flexible, allowing you to customize nearly every facet of your logging strategy via XML configuration, but it is also very extensible.  The Log4Net platform uses &#8220;appenders&#8221; to post logging events to a variety of destinations, including databases, files and even e-mail recipients.  Fortunately, Log4Net makes it simple to create your own custom appenders.</p>
<p>Log4Net recommends that when building a custom appender, you inherit from the abstract AppenderSkeleton class, located within the log4net.Appender namespace.  The AppenderSkeleton class exposes some useful functionality via protected methods and requires that your custom appender override the abstract Append method.  This method is the primary entry point for the Log4Net platform and is where you should implement your custom logic for handling a Log4Net event, represented internally by the LoggingEvent class.</p>
<p>I&#8217;ve posted the code for my TwitterAppender class below.</p>
<pre class="brush: csharp;">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;

using log4net.Appender;
using log4net.Core;

namespace TwitterAppender
{
public class TwitterAppender : AppenderSkeleton
{
#region Private Members

private const string REQUEST_CONTENT_TYPE = &quot;application/x-www-form-urlencoded&quot;;
private const string REQUEST_METHOD = &quot;POST&quot;;

// The source attribute has been removed from the Twitter API,
// unless you're using OAuth.
// Even if you are using OAuth, there's still an approval process.
// Not worth it; &quot;API&quot; will work for now!
// private const string TWITTER_SOURCE_NAME = &quot;Log4Net&quot;;

private const string TWITTER_UPDATE_URL_FORMAT = &quot;http://twitter.com/statuses/update.xml?status={0}&quot;;

private string _twitterUserName;
private string _twitterPassword;

/// &lt;summary&gt;
/// This is where we're posting the actual event as a tweet.
/// I was originally thinking of using REST-ful WCF, but, to keep things simple
/// and to reduce dependencies on other technologies, I decided to keep it simple.
/// &lt;/summary&gt;
/// &lt;param name=&quot;eventToPost_&quot;&gt;The event to post.&lt;/param&gt;
private void PostLoggingEvent(LoggingEvent eventToPost_)
{
// The base RenderLoggingEvent method converts the event to a string
// based on the layout specified in the configuration file.
// It's important to encode the tweet so that the request URL remains valid.

var updateRequest = HttpWebRequest.Create(String.Format(TWITTER_UPDATE_URL_FORMAT,
HttpUtility.UrlEncode(RenderLoggingEvent(eventToPost_).ToTweet()))) as HttpWebRequest;

updateRequest.ContentLength = 0;
updateRequest.ContentType = REQUEST_CONTENT_TYPE;
updateRequest.Credentials = new NetworkCredential(TwitterUserName, TwitterPassword);
updateRequest.Method = REQUEST_METHOD;

// This is in idiosyncracy with the Twitter API.
updateRequest.ServicePoint.Expect100Continue = true;

var updateResponse = updateRequest.GetResponse() as HttpWebResponse;

if (updateResponse.StatusCode != HttpStatusCode.OK &amp;&amp; updateResponse.StatusCode != HttpStatusCode.Continue)
throw new ApplicationException(String.Format(&quot;An error occured while invoking the Twitter REST API [Response Code: {0}]; unable to proceed.&quot;, updateResponse.StatusCode));
}

#endregion

#region Public Members

/// &lt;summary&gt;
/// This is the password for the Twitter account that is to be used.
/// Fortunately, the Log4Net framework automatically populates
/// this property for us based on the configuration.
/// &lt;/summary&gt;
public string TwitterPassword
{
get
{
// We need a password.
if (String.IsNullOrEmpty(_twitterPassword))
throw new ApplicationException(&quot;Twitter account password not specified; unable to proceed.&quot;);

return _twitterPassword;
}
set
{
_twitterPassword = value;
}
}

/// &lt;summary&gt;
/// This is the user name for the Twitter account that is to be used.
/// Fortunately, the Log4Net framework automatically populates
/// this property for us based on the configuration.
/// &lt;/summary&gt;
public string TwitterUserName
{
get
{
// We need a user name.
if (String.IsNullOrEmpty(_twitterUserName))
throw new ApplicationException(&quot;Twitter account user name not specified; unable to proceed.&quot;);

return _twitterUserName;
}
set
{
_twitterUserName = value;
}
}

#endregion

#region Protected Members

/// &lt;summary&gt;
/// This is the main entry point for the Log4Net framework.
/// &lt;/summary&gt;
/// &lt;param name=&quot;loggingEvent_&quot;&gt;The event to append.&lt;/param&gt;
protected override void Append(LoggingEvent loggingEvent_)
{
try
{
if (loggingEvent_ == null)
throw new ArgumentNullException(&quot;loggingEvent_&quot;);

PostLoggingEvent(loggingEvent_);
}
catch (Exception ex_)
{
// Since we're already inside the event logging framework,
// let Log4Net handle this one.
// We don't want to get stuck in a loop!
ErrorHandler.Error(&quot;An error occured while posting the provided event; unable to proceed.&quot;, ex_);
}
}

#endregion
}
}</pre>
<p>Line 44 of the above code uses the custom ToTweet extension method that chops the output of the RenderLoggingEvent to 140 characters (the maximum allowable length for a tweet) and adds an ellipsis if necessary.  That extension method is provided below.</p>
<pre class="brush: csharp;">
private const int MAXIMUM_TWEET_LENGTH = 140;

public static string ToTweet(this string fromString_)
{
if (fromString_ == null || fromString_.Length &lt; MAXIMUM_TWEET_LENGTH)
return fromString_;

return (fromString_.Substring(0, MAXIMUM_TWEET_LENGTH - 3) + &quot;...&quot;);
}
</pre>
<p>Configuring the appender is also pretty straight-forward.  I won&#8217;t go into all of the details of Log4Net configuration, but, if you do need more information, <a href="http://logging.apache.org/log4net/release/manual/configuration.html">take a look at the configuration documentation</a>.  My configuration is posted below.</p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
&lt;configuration&gt;

&lt;configSections&gt;
&lt;section name=&quot;log4net&quot; type=&quot;log4net.Config.Log4NetConfigurationSectionHandler, log4net&quot;/&gt;
&lt;/configSections&gt;

&lt;log4net&gt;
&lt;appender name=&quot;TwitterAppender&quot; type=&quot;TwitterAppender.TwitterAppender, TwitterAppender&quot;&gt;
&lt;!-- This property will be automatically populated by the Log4Net framework. --&gt;
&lt;twitterUserName value=&quot;yourTwitterUserName&quot; /&gt;
&lt;!-- This property will be automatically populated by the Log4Net framework. --&gt;
&lt;twitterPassword value=&quot;yourTwitterPassword&quot; /&gt;
&lt;!--
The layout pattern specified here is used by the RenderLoggingEvent method of
the base AppenderSkeleton class.  This element is optional.
--&gt;
&lt;layout type=&quot;log4net.Layout.PatternLayout&quot;&gt;
&lt;conversionPattern value=&quot;#%level - %message&quot; /&gt;
&lt;/layout&gt;
&lt;/appender&gt;
&lt;root&gt;
&lt;level value=&quot;ALL&quot; /&gt;
&lt;appender-ref ref=&quot;TwitterAppender&quot; /&gt;
&lt;/root&gt;
&lt;/log4net&gt;

&lt;/configuration&gt;
</pre>
<p>That&#8217;s pretty much all there is to it.  This class has made my life so much simpler.  Instead of checking the application log thirty times a day or having to set up special filtering rules in Outlook (I already don&#8217;t care for the Outlook client as it is), I can keep an eye on basically all of my applications in <a href="http://www.tweetdeck.com/">TweetDeck</a>.  The cool thing is that since Twitter is so ubiquitous, you can receive notifications on practically any desktop or mobile platform, including the iPhone.  The solution itself is only limited in scale by the underlying Twitter service.</p>
<p>I, personally, set up an account for each of the applications that I&#8217;m monitoring.  I would also highly recommend that you protect your tweets, so that the internal workings of your applications aren&#8217;t visible to everyone.</p>
<p>I realize that some may consider it a security risk to expose your application events to a public service like Twitter.  It&#8217;s a good idea to keep these updates short and to the point in order to not expose too much information.  I usually combine this method with a more detailed and secure database or file-based solution, using Twitter as a basic notification platform.  Log4Net makes it simple to configure this type of model.</p>
<p>Something I just realized a few days ago is that by channeling your events through a Twitter account, you automatically get an RSS feed as well.  Each Twitter account exposes status updates through an RSS feed.  I don&#8217;t personally use this functionality, but there are certainly situations where it could be handy.</p>
<p>I mentioned before that I use TweetDeck.  You can set up &#8220;search columns&#8221; within TweetDeck (which is now available on the iPhone), to organize your applications events by severity, source, type or pretty much anything else you want.  I find this to be tremendously helpful.  I&#8217;m not sure which other Twitter clients support this functionality, but I&#8217;m sure there are a handful out there.</p>
<p>For more information on using Log4Net, I recommend that you check out <a href="http://www.beefycode.com/post/Log4Net-Tutorial-pt-1-Getting-Started.aspx">this excellent tutorial on beefycode.com</a>.  The official Log4Net documentation from Apache can get a little dry, so I recommend that you start here if you want to get up and running quickly.</p>
<p>I look forward to hearing your feedback.</p>
<p><strong>UPDATE: TwitterAppender is now available on CodePlex at <a href="http://twitterappender.codeplex.com/">http://twitterappender.codeplex.com</a>.  Enjoy!<br />
</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://caseywatson.com/2009/07/07/log4net-twitter-awesome/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>In Defense of the _Underscore</title>
		<link>http://caseywatson.com/2009/06/28/in-defense-of-the-underscore/</link>
		<comments>http://caseywatson.com/2009/06/28/in-defense-of-the-underscore/#comments</comments>
		<pubDate>Sun, 28 Jun 2009 19:57:01 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://caseywatson.com/?p=206</guid>
		<description><![CDATA[There it sits near the top of your keyboard, just to the right of the zero and to the left of the plus sign.  In the last year of my professional life, that one innocuous character, the older brother of the hyphen, has sparked more debate among my peers than any other development practice.
I am [...]]]></description>
			<content:encoded><![CDATA[<p>There it sits near the top of your keyboard, just to the right of the zero and to the left of the plus sign.  In the last year of my professional life, that one innocuous character, the older brother of the hyphen, has sparked more debate among my peers than any other development practice.</p>
<p>I am a proponent of the underscore.  There, I said it.  The use of the underscore is a polarizing topic in most software development circles, with both sides often citing arbitrary arguments for or against its use.  I, personally, have finally had enough.  Today, I am presenting my defense of the underscore in a public forum and oficially inviting you, the reader, to reply with your argument for or against its use.  The only thing that I ask is that you be objective (I don&#8217;t want to hear &#8220;it&#8217;s ugly&#8221;, &#8220;you shouldn&#8217;t do it&#8221; or &#8220;it&#8217;s bad practice&#8221;) and that you present it here, publicly, for all to read.</p>
<p>As with any development convention, I only use the underscore under a very specific set of conditions.  As a matter of fact, I only use it under two very specific conditions: prefixed to a private member variable or postfixed to a function argument.  But, why do I use it?  Do I use it because I think that it looks nice?  No.  Do I use it because other people use it?  No.  This is why I use it:</p>
<ul>
<li>By prefixing all private member variables with underscores, you are automatically creating a valuable shortcut.  Now, whenever you enter the underscore character anywhere within the class, Intellisense will automatically provide you with a list of all private member variables within scope.  Tell me that&#8217;s a bad thing.</li>
<li>A quick review of the class reveals all function arguments and private member variables.  While reading a block of code, I can quickly identify the nature of any variable without having to use the tooltip.  Why is this important?  Being able to quickly identify the nature of these variables makes code, in my opinion, more readable and easier to debug.  I can already hear you crying, &#8220;Well, if you&#8217;re going that far, why don&#8217;t you just use Hungarian notation?&#8221;  With Hungarian notation, I have to decode the first three characters of each variable to glean its type.  Since this notation seems to vary in convention from developer to developer, it tends to make code less readable.  The underscore doesn&#8217;t attempt to share this much information, making it simpler and less ambiguous.</li>
<li>Although the introduction of automatic properties in C# 3.0 has certainly made life easier, there are still times when traditional properties are necessary.  More often than not, these traditional properties implement some type of private backing variable.  Naturally, this backing variable typically shares the same name with the property itself.  Since C# is case-sensitive, technically this doesn&#8217;t present a problem.  However,  if you slip up and don&#8217;t enter the name of the backing variable or property using the exact casing, Intellisense will guess for you and it doesn&#8217;t always guess correctly.  This can cause a compile-time error, or, more likely, a more painful runtime error.  Yes, I know, you can always give the member variable a different name, but this often forces you to come up with an arbitrary name in order to compile, making your code even less readable.  By prefixing the backing variable with an underscore, you can kill two birds with one stone.  I find this to be a rather graceful solution in most cases.</li>
</ul>
<p>Now, it&#8217;s your turn.  Do you agree with me?  Fantastic.  Do you disagree with me?  Fair enough.  Tell me why you disagree with me.  Remember, be objective.  Don&#8217;t tell me that it&#8217;s ugly and don&#8217;t tell me that it&#8217;s bad practice without justifying your position.  If you do, however, have a valid, objective argument against its use, please share.</p>
]]></content:encoded>
			<wfw:commentRss>http://caseywatson.com/2009/06/28/in-defense-of-the-underscore/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Dallas TechFest (#dtf09)</title>
		<link>http://caseywatson.com/2009/06/21/dallas-techfest-dtf09/</link>
		<comments>http://caseywatson.com/2009/06/21/dallas-techfest-dtf09/#comments</comments>
		<pubDate>Mon, 22 Jun 2009 04:51:32 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://caseywatson.com/?p=196</guid>
		<description><![CDATA[As promised, I&#8217;m making the source for the Jeopardy application available for download here.  This application is 100% open source and I invite you to do with it what you wish.  The only thing I ask is that you let me know how you&#8217;re using it.
In order to compile the application, you&#8217;re going to need to grab [...]]]></description>
			<content:encoded><![CDATA[<p>As promised, I&#8217;m making the source for the Jeopardy application available for download <a href="http://cid-97e2cef30d089548.skydrive.live.com/self.aspx/Code%20Samples%20and%20Presentations/Jeopardy.zip">here</a>.  This application is 100% open source and I invite you to do with it what you wish.  The only thing I ask is that you let me know how you&#8217;re using it.</p>
<p>In order to compile the application, <a href="http://fluidkit.codeplex.com/SourceControl/ListDownloadableCommits.aspx">you&#8217;re going to need to grab the FluidKit API</a> and have the .NET Framework 3.5 SP1 installed.  If you want to create your own custom questions (answers?), you can do so by modifying the GameCategories.xml file, provided with the project.  I think the schema is pretty self-explanatory, but if you do have any questions, feel free to hit me up via e-mail at <strong>casey[dot]watson[at]improvingenterprises[dot]com</strong> or, preferably, send me a Twitter DM at <strong>@_caseywatson.</strong></p>
<p>I had a great time this year at Dallas TechFest and I hope that you did as well.</p>
<p>I want to extend a special thanks to Improving Enterprises (<a href="http://www.improvingenterprises.com">http://www.improvingenterprises.com</a>) who generously provided some great prizes for our C# Jeopardy session.  For those of you that didn&#8217;t get a chance to attend, each contestant left with either a $5 Starbucks gift card or a $50 Amazon gift card, all courtesy of Improving.</p>
<p>Finally, I have to thank Tim Rayburn (<a href="http://www.timrayburn.net">http://www.timrayburn.net</a>) who put on this incredible event.  Great job, Tim.</p>
<p>I&#8217;ll see you all next year.</p>
]]></content:encoded>
			<wfw:commentRss>http://caseywatson.com/2009/06/21/dallas-techfest-dtf09/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>So, I know it&#039;s been a while&#8230;</title>
		<link>http://caseywatson.com/2009/06/02/so-i-know-its-been-a-while/</link>
		<comments>http://caseywatson.com/2009/06/02/so-i-know-its-been-a-while/#comments</comments>
		<pubDate>Wed, 03 Jun 2009 05:00:51 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://caseywatson.wordpress.com/?p=146</guid>
		<description><![CDATA[Just thought I should let all of my readers know (both of you), that, yes, I am still around but have been extremely busy.  Rest assured, however, that I am currently working on a new code-intensive blog series that you should look for in the next couple of weeks.  Also, although I know [...]]]></description>
			<content:encoded><![CDATA[<p>Just thought I should let all of my readers know (both of you), that, yes, I am still around but have been extremely busy.  Rest assured, however, that I am currently working on a new code-intensive blog series that you should look for in the next couple of weeks.  Also, although I know that you&#8217;ve already signed up since, you know, you take your career seriously and value respect among your peers, you should trot over and check out <a href="http://www.dallastechfest.com/">http://www.dallastechfest.com/</a>.  If you haven&#8217;t already signed up, drop me a line by either leaving a comment on this post, or hitting me up on &#8220;the Twitter&#8221; at <a href="http://www.twitter.com/_caseywatson">@_caseywatson</a>.  As you can see, the agenda is now full and sports eight power-packed tracks, spanning everything from .NET to Ruby to ColdFusion.  If you have time, please stop by for some C# Jeopardy action, co-hosted by myself and Mr. Wil Bloodworth (a.k.a Big Wil) to put your C# knowledge to the test.  That is, of course, unless your chicken.  Anyway, we look forward to seeing all of you guys there.</p>
<p>More to come soon&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://caseywatson.com/2009/06/02/so-i-know-its-been-a-while/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dear TFS</title>
		<link>http://caseywatson.com/2009/02/22/dear-tfs/</link>
		<comments>http://caseywatson.com/2009/02/22/dear-tfs/#comments</comments>
		<pubDate>Sun, 22 Feb 2009 07:03:39 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://caseywatson.wordpress.com/?p=124</guid>
		<description><![CDATA[Dear TFS,
This isn&#8217;t really easy to do, so I&#8217;m just going to come out and say it.  I think we should break up.
First off, it&#8217;s not you, it&#8217;s me.  I mean, I&#8217;m the one who wants a reliable, easy-to-use source control system. In a lot of ways you&#8217;re a lot better than my [...]]]></description>
			<content:encoded><![CDATA[<p>Dear TFS,</p>
<p>This isn&#8217;t really easy to do, so I&#8217;m just going to come out and say it.  I think we should break up.</p>
<p>First off, it&#8217;s not you, it&#8217;s me.  I mean, I&#8217;m the one who wants a reliable, easy-to-use source control system. In a lot of ways you&#8217;re a lot better than my last source control system.  I mean, in some ways, you&#8217;re great at communicating.  It&#8217;s nice to know that my code builds every time that I check it in.  In some ways, however, you&#8217;re a little much.  It seems like there&#8217;s always conflicts to resolve.  At first, when things were simpler, you would always give me a hand in resolving these conflicts, but, now that things are a little more complicated, it seems like you don&#8217;t want to help at all.  I feel like I&#8217;m constantly resolving these conflicts all by myself.  So, thanks for that.</p>
<p>Also, you never listen to me anymore.  When I&#8217;m trying to check something in and you and I have a conflict, once it&#8217;s resolved, I still want to check it in.  Do you honestly think I&#8217;ve changed my mind?  Why would I change my mind?  I feel like you always want me to go that extra mile even when you know exactly what I&#8217;m trying to do.  Are you purposefully trying to make my life difficult?  Sometimes it feels like it.  The last source control system that I used never did that.  I only had to say things once.  It seems like you don&#8217;t really care.  I mean, when I ask you for the latest version of my code, you often refuse to give it to me just because you think that I already have it.  Well, you&#8217;ve given it to me before, I must still have it, right?  Do you even bother to check?  No, no, no.  I have to ask just the right way to get what I want or you refuse to budge.</p>
<p>Sometimes I just want to check in some code.  I could live without the nagging.</p>
<p>&#8220;Why are you checking this in? Which task is this associated with? Blah, blah, blah.&#8221;  You know what?  Can we just skip the conversation every once in a while and get to the point?  Again, I feel like you&#8217;re doing it on purpose.</p>
<p>I&#8217;m really sorry that it&#8217;s ending this way, TFS.  I never really expected it to come to this.  All of my friends told me that you were the best and I believed them, but, I just feel like it&#8217;s too much work and I&#8217;m not really getting anything out of this relationship.  I&#8217;d appreciate it if you&#8217;d stop by and pick up your stuff from my laptop.  It&#8217;s taking up a lot of space and I really don&#8217;t have any use for it.  Also, I think you still have some of my code.  I can pick it up from you or you can just drop it off.  Either way, let&#8217;s try to be civil about this.</p>
<p>I was thinking maybe I would make one last check in, but I think it&#8217;s best if we just make a clean break.  I&#8217;ll never forget about you, TFS, and I know that there&#8217;s some masochistic, self-hating developer out there that would love to be with a source control system like yourself, but I&#8217;m afraid that&#8217;s not me.  I guess I&#8217;ve seen this coming for a while, but I didn&#8217;t really want to accept it.  Project after project, I&#8217;ve tried to look past these problems, but I think it&#8217;s time that we both just admit that this isn&#8217;t going to work anymore.</p>
<p>I&#8217;m sorry,<br />
Casey.</p>
<p>PS: What&#8217;s your friend Subversion up to this weekend?  I&#8217;m just asking because a friend wants to know, but, I mean, if you&#8217;re not comfortable with it, just let me know. Can you give me her e-mail address, though?  I&#8217;d like to give it to my friend so he can&#8230; You know what?  Nevermind. It&#8217;s too soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://caseywatson.com/2009/02/22/dear-tfs/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Thoughts on Agility</title>
		<link>http://caseywatson.com/2009/02/22/thoughts-on-agility/</link>
		<comments>http://caseywatson.com/2009/02/22/thoughts-on-agility/#comments</comments>
		<pubDate>Sun, 22 Feb 2009 06:26:02 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://caseywatson.wordpress.com/?p=118</guid>
		<description><![CDATA[I&#8217;ve been thinking a lot about agility lately and what it means to &#8220;be agile&#8221;.  As usual, my thoughts are pretty much all over the place, but I thought I&#8217;d share a few with you.
One thing that I&#8217;ve noticed recently is that everyone wants to &#8220;be agile&#8221;, but very few people actually understand what [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been thinking a lot about agility lately and what it means to &#8220;be agile&#8221;.  As usual, my thoughts are pretty much all over the place, but I thought I&#8217;d share a few with you.</p>
<p>One thing that I&#8217;ve noticed recently is that everyone wants to &#8220;be agile&#8221;, but very few people actually understand what it means.  To most people, agile is nothing more than a buzzword.  They understand that it can potentially deliver value and that everyone&#8217;s doing it but, beyond that, they really don&#8217;t have a clue. <a href="http://www.youtube.com/watch?v=D2mOsNojyvM">Just check out this video from my pal Caleb Jenkins to get an idea of what I&#8217;m talking about.</a></p>
<p>There&#8217;s another group that believes that agility equates to a specific method, such as Scrum.  While I&#8217;m certainly not bad-mouthing Scrum (I&#8217;ve seen the value that it can deliver firsthand) or any other method, I don&#8217;t believe that agility can be directly attributed to any one practice.  These methods can help to set you down the right path, but in reality they&#8217;re just tools.  That isn&#8217;t to say that they&#8217;re not valuable tools, but agility is, for the lack of a better term, a lifestyle.  I think that may be why, initially, it&#8217;s so hard to fully grasp.</p>
<p>The funny thing is, you never really get there, because there is no definite &#8220;there&#8221;.  Agility is not a destination, but a journey. The biggest part is simply coming to the realization that most aspects of any development project, be it requirements, human resources, schedules&#8230; are constantly changing.  That&#8217;s reality and there&#8217;s not much that you can do about it.  All that you can do is learn to accept it.  Once you accept it, and even welcome it, you&#8217;re in the right frame of mind. You can begin to actively prepare for and respond to this reality and that is what makes you agile.</p>
<p>In my opinion, agility is simply the ability to react appropriately to reality.  That&#8217;s a rather broad definition, but rightly so.  If you&#8217;re practicing the classic waterfall method and you find that your requirements are in a constant state of flux and that you&#8217;re always trying to &#8220;hit a moving target&#8221;, then you&#8217;re not reacting appropriately to reality, are you?  On a more broad level, if you keep doing the same thing over and over again expecting different results each time, you&#8217;re not being agile.  The funny thing is that, with experience, this is common sense.  The problem is that we&#8217;ve been conditioned our entire career to think to the contrary.  There is no magic recipe for agility since agility depends on your context.</p>
<p>So, what do you think?  Do you agree with me?  Great.  Do you disagree with me?  Even better&#8230; tell me why so we can strike up a conversation.</p>
]]></content:encoded>
			<wfw:commentRss>http://caseywatson.com/2009/02/22/thoughts-on-agility/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
