<?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>chrishowie.com</title>
	<atom:link href="http://www.chrishowie.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.chrishowie.com</link>
	<description>The best laid plans are in my other pants</description>
	<lastBuildDate>Tue, 15 Nov 2011 20:20:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>VPS.NET experiences</title>
		<link>http://www.chrishowie.com/2011/11/15/vps-net-experiences/</link>
		<comments>http://www.chrishowie.com/2011/11/15/vps-net-experiences/#comments</comments>
		<pubDate>Tue, 15 Nov 2011 19:54:32 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Computer]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://www.chrishowie.com/?p=492</guid>
		<description><![CDATA[I&#8217;ve been using VPS.NET as my hosting provider for two years now (since October 2009). Here&#8217;s my experience, the good and the bad. The building block of the VPS offering is a node: a discrete unit of CPU time, RAM, storage, and bandwidth. These nodes can be deployed as separate servers, or combined together to [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been using <a href="http://bit.ly/-vps-net">VPS.NET</a> as my hosting provider for two years now (since October 2009).  Here&#8217;s my experience, the good and the bad.</p>
<p>The building block of the VPS offering is a node: a discrete unit of CPU time, RAM, storage, and bandwidth.  These nodes can be deployed as separate servers, or combined together to create a more powerful server.  Servers can be upgraded or downgraded by attaching and detaching nodes from them.  The CPU/bandwidth changes can be applied without rebooting, but to apply RAM and storage changes, the VPS needs to be rebooted so that the RAM reassignment can happen and so the VPS root volume can be rebuilt.  You can bill nodes per month or per day.  The daily option is more expensive, but allows you to throw an extra node or two at a server that&#8217;s being slashdotted until the traffic subsides &#8212; much cheaper in the long haul then monthly nodes.  Daily nodes are also a good choice for a throwaway server you&#8217;re going to test something on and then scrap.  The math suggests that if you&#8217;re going to be using the server for longer than two or three weeks, monthly nodes are a better deal.</p>
<p>To further sweeten the deal, nodes are portable across any of their data centers.  While you can&#8217;t easily migrate deployed VPSes, you can destroy a server in one data center and create a new one in another using the same node.  I look forward to the day when we&#8217;ll be able to live-migrate running VPSes across the country.  Hopefully someone at VPS.NET is working on that&#8230;</p>
<p>Initially I had one node and this blog was about the only thing running on the server.  Since then, I&#8217;ve expanded the services I host to my personal email server (hosting a few domains for friends too), a Git-based personal software forge, some services for Wikimedia, and a few odds and ends.  While not a feature unique to VPS.NET, having root on your own server is really nice.  Need some software?  Install it.  Want to tweak the firewall?  Go ahead.  I&#8217;m a hacker, so it&#8217;s nice to be able to use my server to just try stuff out and see what works.</p>
<p>Each VPS has CPU and network usage graphs so you can pinpoint busy times and optimize accordingly.  There&#8217;s also a console for each VPS that connects directly to the offline OS terminal, allowing you to recover from a botched network or ssh config without involving support.  While I&#8217;d like to claim that I&#8217;ve never had to make use of this feature, that would be a lie.  I don&#8217;t often need it, but it&#8217;s there when I do.</p>
<p>Uptime has been pretty good all-around.  I&#8217;ve had a few outages here and there: a SAN failure that the staff were not properly prepared for, causing a few hours of downtime; a bootloader issue with Debian caused by upgrading to squeeze (arguably not VPS.NET&#8217;s fault, as Debian decided to change the boot volume path); and most recently, volume corruption caused by upgrading my node, which the support staff remedied within minutes, but ideally should have never happened.  (This makes me a bit reluctant to upgrade again without someone over there babysitting the box to make sure it boots up correctly.)  However, these occurrences were not frequent.  That&#8217;s three distinct issues I can recall since late 2009, two if you attribute the bootloader problem to Debian.  This isn&#8217;t 100% uptime, but it&#8217;s pretty darn close to it, and support is usually quick to respond when problems happen.</p>
<p>I resell a few nodes to some friends and former business partners, and they&#8217;ve had very little issues getting started.  It takes about 10 minutes to go from purchasing a node to having a running server.  When a friend wants another server, I can deliver them their login credentials to a running server within about 15 minutes.  That&#8217;s pretty cool.</p>
<p>There are a few network-level filtering things one should be aware of.  VPS.NET monitors outgoing SMTP (port 25) connections and applies their own spam filtering, rejecting mail if it&#8217;s too spammy.  Some people might like this since it can protect them from being listed on a spam blacklist if their server gets compromised.  Since I run my own mail server and do my own filtering, I wasn&#8217;t pleased when this was deployed, especially since it was done so without any communication on their part.  Once I figured out what was going on, I was able to opt-out of this filtering by filing a support ticket.  I would have preferred more transparency about this change.  Finally, as with most hosts, IRC ports are filtered bidirectionally.  As I was wanting to use my VPS to run a service that collects data from Wikimedia&#8217;s real-time change notification IRC server (essentially just a data stream delivered via IRC) this was a bit of a bummer.  They will not budge on this policy, which is disappointing.</p>
<p>Overall, I am a happy customer.  Things don&#8217;t go wrong often, and when they do support is quick to respond.  I&#8217;d suggest trying a daily node or two if you want to see if they are a good fit for your hosting needs; they&#8217;re only a dollar per day.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.chrishowie.com/2011/11/15/vps-net-experiences/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What I dislike about C++, part 1: References</title>
		<link>http://www.chrishowie.com/2011/09/27/what-i-dislike-about-c-plus-plus-part-1-references/</link>
		<comments>http://www.chrishowie.com/2011/09/27/what-i-dislike-about-c-plus-plus-part-1-references/#comments</comments>
		<pubDate>Tue, 27 Sep 2011 17:46:18 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://www.chrishowie.com/?p=468</guid>
		<description><![CDATA[I&#8217;ve started a new job, for those of you who didn&#8217;t know. I&#8217;m now coding C++ daily. My relationship with C++ has been distant, simply because I haven&#8217;t really ever had a need to use it. However, C and C# are both strong languages of mine, and C++ sits somewhere in the middle: C with [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve started a new job, for those of you who didn&#8217;t know.  I&#8217;m now coding C++ daily.  My relationship with C++ has been distant, simply because I haven&#8217;t really ever had a need to use it.  However, C and C# are both strong languages of mine, and C++ sits somewhere in the middle: C with classes, C# without garbage collection.  (These are rough approximations, and not without caveats.)</p>
<p>There are bound to be things in every programming language that get in the way of productivity.  In this post I&#8217;ll highlight one of those things in C++: references.  References are obfuscating and mostly useless.  But first, why would you use a reference?</p>
<p>A reference is effectively a pointer, but this is hidden by the language.  You use it like it&#8217;s <i>not</i> a pointer, and the compiler turns direct accesses into indirect accesses.  For example:</p>
<pre>#include &lt;iostream&gt;

int main() {
	int a = 5;
	int &amp;b = a;

	std::cout &lt;&lt; "a is " &lt;&lt; a &lt;&lt; std::endl;

	b = 6;

	std::cout &lt;&lt; "a is " &lt;&lt; a &lt;&lt; std::endl;
}</pre>
<p>The output will be:</p>
<pre>a is 5
a is 6</pre>
<p>Note that I did not say <code>*b = 6;</code>.  The reference is treated as though it were not a pointer.  Cool&#8230; but what&#8217;s the benefit?</p>
<p>The solitary benefit I&#8217;ve heard from others is that references cannot be null.  When you declare a function/method that accepts an argument typed as a reference, it&#8217;s not possible to make that reference equivalent to a null pointer.</p>
<p>Ok, so we trade a bit of clarity for a compile-time guarantee that we won&#8217;t be dereferencing a null pointer.  That&#8217;s a good trade, right?</p>
<p>Maybe.  Consider this excerpt:</p>
<pre>class Foo;

void do_something() {
    Foo *foo = new Foo();
    use_foo(*foo);
    delete foo;
}</pre>
<p>This is contrived, yes, and there&#8217;s a better way to write this code.  But I&#8217;m illustrating something here.  I&#8217;ve told you that <code>Foo</code> is a class, but I haven&#8217;t told you the prototype for <code>use_foo()</code>.  That&#8217;s on purpose.  Now, you tell me if the <code>Foo</code> instance is going to be copied.  I&#8217;ll even tell you that <code>Foo</code> doesn&#8217;t overload <code>operator*</code>.</p>
<p>Do you have your answer yet?  If you said yes &#8212; the logical choice &#8212; you&#8217;re wrong.  If you said no, you&#8217;re also wrong.  Well, actually, if you said yes or no, you <i>might</i> be wrong.  It&#8217;s impossible to tell.  If <code>use_foo()</code>&#8216;s declaration is <code>use_foo(Foo foo)</code> then a copy will be made using <code>Foo</code>&#8216;s copy constructor (if possible, otherwise it will be a compile-time error).  But if the function&#8217;s prototype is <code>use_foo(Foo &amp;foo)</code> then we are actually passing in the value stored in the <code>foo</code> variable &#8212; a memory address.  The object will not be copied.  In other words, while it looks like we are dereferencing <code>foo</code>, we are actually doing no such thing.</p>
<p>In C, you can tell pretty much everything you need to know from a call site.  In C++, you must know how the function you&#8217;re calling is defined too, simply because you have to know when things are references and when they are not.  The treatment of what is fundamentally a pointer type as a value type (at the language level) is what causes the uncertainty.  You use value-type grammar around references, even though they are not really a value type.</p>
<p>If it weren&#8217;t for the existence references, the code above would be perfectly clear.  (Well, unless you didn&#8217;t have me to tell you that <code>Foo</code> doesn&#8217;t implement <code>operator*</code>&#8230;)</p>
<p>Don&#8217;t get me wrong, C++ still has a lot of good features.  It&#8217;s just a bit irritating that because of a bad feature (and some other features too, such as some forms of operator overloading), I must know the details of every type and function on a line of code to be absolutely sure what it&#8217;s doing.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.chrishowie.com/2011/09/27/what-i-dislike-about-c-plus-plus-part-1-references/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Bitcoin for Humans series</title>
		<link>http://www.chrishowie.com/2011/06/09/bitcoin-for-humans-series/</link>
		<comments>http://www.chrishowie.com/2011/06/09/bitcoin-for-humans-series/#comments</comments>
		<pubDate>Thu, 09 Jun 2011 20:58:59 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Bitcoin]]></category>
		<category><![CDATA[Computer]]></category>

		<guid isPermaLink="false">http://www.chrishowie.com/?p=449</guid>
		<description><![CDATA[Anyone who&#8217;s been around me recently knows that I love Bitcoin. It&#8217;s a really neat idea, but it&#8217;s also a very complicated thing. Most people that I talk to don&#8217;t really understand how it works and why it was designed the way it was, and therefore have some incorrect ideas and criticisms of Bitcoin. So [...]]]></description>
			<content:encoded><![CDATA[<p>Anyone who&#8217;s been around me recently knows that I love <a href="http://www.bitcoin.org">Bitcoin</a>.  It&#8217;s a really neat idea, but it&#8217;s also a very complicated thing.  Most people that I talk to don&#8217;t really understand how it works and why it was designed the way it was, and therefore have some incorrect ideas and criticisms of Bitcoin.  So I am going to do a series of blog posts about it that attempt to reduce its very intricate design to simple analogies and concepts that might not be <i>completely</i> accurate, but that will help the non-technical person understand it a bit more.</p>
<p>If you don&#8217;t even know what Bitcoin is, it is a distributed and decentralized currency that operates over the Internet.  There is no central bank or issuer; there are no regulators.  The network as a whole decides what the rules are, and the source code for the official Bitcoin client is open.  You can transfer Bitcoins to anyone, anywhere in the world, in about 10 minutes &#8212; and usually for free.</p>
<p>The topics I will cover in my series are:</p>
<ul>
<li>Basic overview: How to send and receive coins.</li>
<li>Addresses: What an address actually is, and why you should care.</li>
<li>The block chain: What the block chain is, and how this keeps the network secure.</li>
<li>Mining: How Bitcoins are created, and why this is not &#8220;generating free money.&#8221;</li>
</ul>
<p>If you can think of any other topics you would like me to cover, let me know and I will extend the series.  If you want a bit more information right now, this video is a pretty good summary of the project:</p>
<p><object width="560" height="349"><param name="movie" value="http://www.youtube-nocookie.com/v/Um63OQz3bjo?version=3&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube-nocookie.com/v/Um63OQz3bjo?version=3&amp;hl=en_US" type="application/x-shockwave-flash" width="560" height="349" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://www.chrishowie.com/2011/06/09/bitcoin-for-humans-series/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mutable strings in Mono</title>
		<link>http://www.chrishowie.com/2010/11/24/mutable-strings-in-mono/</link>
		<comments>http://www.chrishowie.com/2010/11/24/mutable-strings-in-mono/#comments</comments>
		<pubDate>Wed, 24 Nov 2010 19:50:57 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://www.chrishowie.com/?p=434</guid>
		<description><![CDATA[Update 2010-12-17: Those of you who saw this post appear and then vanish were not seeing things. The Mono community identified the contents of this blog post as a serious security vulnerability in Moonlight that, through violation of the type system, allows the CoreCLR security layer to be bypassed. Attackers could potentially run arbitrary code [...]]]></description>
			<content:encoded><![CDATA[<p style="border-bottom: 1px solid #fff"><b>Update 2010-12-17:</b> Those of you who saw this post appear and then vanish were not seeing things.  The Mono community identified the contents of this blog post as a serious security vulnerability in Moonlight that, through violation of the type system, allows the CoreCLR security layer to be bypassed.  Attackers could potentially run arbitrary code with the permissions of the user running Moonlight.  This entry was therefore temporarily removed until a patch was made available.  See <a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-4254">CVE-2010-4254</a> and <a href="http://secunia.com/advisories/42373">SA42373</a>.  If you are using Moonlight, <a href="http://www.go-mono.com/moonlight/download.aspx">update to 2.3.0.1 or later</a> ASAP.  The original and unedited blog post follows:</p>
<p>So I was messing around with generic methods and discovered that <a href="https://bugzilla.novell.com/show_bug.cgi?id=654136">generic constraints can be bypassed on Mono 2.6.7 and 2.8 using reflection</a> (with the exception of the <code>new()</code> constraint).  One of the fun results of this bug is that the <code>String</code> class can be made mutable <i>without using reflection to set private members!</i></p>
<p>The following code demonstrates this; it is legal and will run on Mono up to and including version 2.8:</p>
<pre>using System;
using System.Reflection;

public class FakeString {
    public int length;
    public char start_char;
}

public class TestCase {
    private static FakeString UnsafeConversion&lt;T&gt;(T thing)
        where T : FakeString
    {
        return thing;
    }

    public static void Main() {
        var a = "foo";
        var b = MakeMutable(a);

        Console.WriteLine(a);
        b.start_char = 'b';
        Console.WriteLine(a);
    }

    private static FakeString MakeMutable(string s)
    {
        var m = typeof(TestCase).GetMethod("UnsafeConversion", BindingFlags.NonPublic | BindingFlags.Static);
        var m2 = m.MakeGenericMethod(typeof(string));

        var d = (Func&lt;string, FakeString&gt;)Delegate.CreateDelegate(typeof(Func&lt;string, FakeString&gt;), null, m2);

        return d(s);
    }
}</pre>
<p>This code outputs:</p>
<pre>foo
boo</pre>
<p>Smells like some fun exploits could be written taking advantage of this.  Should Moonlight users be afraid?  I&#8217;m not absolutely certain, but I think there might just be a way to do some damage.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.chrishowie.com/2010/11/24/mutable-strings-in-mono/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OpenVP has landed</title>
		<link>http://www.chrishowie.com/2010/08/20/openvp-has-landed/</link>
		<comments>http://www.chrishowie.com/2010/08/20/openvp-has-landed/#comments</comments>
		<pubDate>Fri, 20 Aug 2010 17:53:26 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Banshee]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[OpenVP]]></category>

		<guid isPermaLink="false">http://www.chrishowie.com/?p=430</guid>
		<description><![CDATA[Well, if you&#8217;ve been waiting for some kind of stable release of OpenVP for Banshee, you will love this. OpenVP is part of the Banshee Community Extensions 1.7.4 release! Go get it, and be sure to file any bugs you come across.]]></description>
			<content:encoded><![CDATA[<p>Well, if you&#8217;ve been waiting for some kind of stable release of OpenVP for Banshee, you will love this.  <a href="http://mail.gnome.org/archives/banshee-list/2010-August/msg00072.html">OpenVP is part of the Banshee Community Extensions 1.7.4 release!</a>  <a href="http://download.banshee.fm/banshee-community-extensions/1.7.4/">Go get it</a>, and be sure to <a href="http://code.google.com/p/openvisualizationplatform/issues/list">file any bugs</a> you come across.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.chrishowie.com/2010/08/20/openvp-has-landed/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>New email address, new mail system</title>
		<link>http://www.chrishowie.com/2010/05/14/new-email-address-new-mail-system/</link>
		<comments>http://www.chrishowie.com/2010/05/14/new-email-address-new-mail-system/#comments</comments>
		<pubDate>Fri, 14 May 2010 18:16:06 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Computer]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Meta]]></category>

		<guid isPermaLink="false">http://www.chrishowie.com/?p=404</guid>
		<description><![CDATA[I&#8217;ve already sent out a message to those I contact frequently, but for the rest of you, my email address has changed from cdh&#65279;owie&#64;gmail&#46;com to me&#64;chris&#65279;howie&#46;com. I have decided to migrate away from Gmail for a variety of reasons. I figured I&#8217;d use my domain so that I have flexibility in my provider choice. For [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve already sent out a message to those I contact frequently, but for the rest of you, my email address has changed from cdh&#65279;owie&#64;gmail&#46;com to <a href="mailto:me&#64;chris&#65279;howie&#46;com">me&#64;chris&#65279;howie&#46;com</a>.</p>
<p>I have decided to migrate away from Gmail for a variety of reasons.  I figured I&#8217;d use my domain so that I have flexibility in my provider choice.  For example, if I decide to change my mail provider I don&#8217;t have to get a new address.  So this change should be permanent.</p>
<p>Now, being a tinkerer, I figured I&#8217;d set up a mail system for myself that retains the features I like from Gmail while doing away with the downsides of using Gmail.  My final system is complicated, but effective.  And it was a fun four days setting it up!  (No, that wasn&#8217;t sarcasm.  This is the kind of thing I enjoy.)</p>
<p>My MTA is Postfix, running on mail.chrishowie.com.  It accepts mail for me and delivers mail from me.  The standard security features are in place: SPF/blacklist checking and no unauthenticated relaying.  I also established SPF records for my domain.  I do not have a spam filter, but I might set up SpamAssassin later if I actually start seeing spam in my inbox; no spam has made it past the sender blacklist check yet.</p>
<p>For downloading mail, I set up Courier as a POP3 server.  The observant will note that this would nullify one of the most useful aspects of Gmail: access to your email from anywhere.  Once you download from a POP3 server and delete, your mail is gone from the server and lives in your mail client.</p>
<p>That&#8217;s where the rest of the rig comes into play.  On my home LAN server I have a multi-piece system that provides me with this anywhere-access.  I have a getmail4 cron job that fetches mail from my POP3 server, as well as from my Gmail account (so people can still reach me using my Gmail address), and some of my other mail accounts, and delivers the mail to my maildir using Dovecot&#8217;s delivery agent.  From there, the agent processes my sieve rules, sorting my mail into various folders.  (It&#8217;s like your favorite mail program&#8217;s &#8220;filters&#8221; only it runs on my server instead of my mail clients, so the configuration is centralized.)</p>
<p>For reading all this mail, I run Dovecot, an IMAP server.  All my mail clients fetch mail from this server, and since it is IMAP, changes to messages (like moving a message between folders, or adding tags, or whatever) are actually pushed back to the server.  So I can use several mail clients at once and they all have a consistent view of my mailbox.</p>
<p>The only major piece I have yet to set up is an LDAP server for centralization of my address book.  The rest has been working quite well.  I can use Thunderbird at home, or my mobile phone&#8217;s email client when I&#8217;m out of the house.  No limiting or inconvenient web interfaces required.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.chrishowie.com/2010/05/14/new-email-address-new-mail-system/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Why I hate IM contact groups</title>
		<link>http://www.chrishowie.com/2010/04/21/why-i-hate-im-contact-groups/</link>
		<comments>http://www.chrishowie.com/2010/04/21/why-i-hate-im-contact-groups/#comments</comments>
		<pubDate>Wed, 21 Apr 2010 16:53:31 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Computer]]></category>
		<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://www.chrishowie.com/?p=382</guid>
		<description><![CDATA[Or at least as they are currently implemented. (Rambling rant alert!) Almost every IM client on the planet has the concept of a group. You create a group, give it a name, and populate it with your contacts. At first glance, this is useful. Having used IM clients since the latter years of AIM&#8217;s domination, [...]]]></description>
			<content:encoded><![CDATA[<p>Or at least as they are currently implemented.  (Rambling rant alert!)</p>
<p>Almost every IM client on the planet has the concept of a group.  You create a group, give it a name, and populate it with your contacts.  At first glance, this is useful.</p>
<p>Having used IM clients since the latter years of AIM&#8217;s domination, I have consistently struggled with the best way to group my contacts.  To this day I have no solution.  Why?</p>
<p>Because the group model is inherently broken in that <b>every major IM client out there allows one group per contact.</b>  This assumes that each person I know has exactly one type of relationship to me.  A contact cannot be a friend, coworker, family member, and developer.  You must pick one.</p>
<p>This problem is exacerbated by multi-protocol clients.  Not through any specific fault of their own, but when they support connecting to many different services, you suddenly wind up with an overwhelming number of groups with no coherent purpose.  If you didn&#8217;t name your groups exactly the same, or you used a different grouping paradigm, you are SOL and must merge the groups somehow.  This becomes an impossible mess when the service on the other end (Facebook, for example) allows contacts to be in multiple groups.  Which group they wind up in on your IM client may as well be random, and may not even be the same each time you connect.  (<i><b>Edit:</b> Since writing this I have discovered that the XMPP server operated by Facebook does actually indicate to clients when contacts are in more than one group.  Pidgin honors this.</i>)</p>
<p>What we need is a cross-service &#8220;tagging&#8221; mechanism that lets me say &#8220;this person is a coworker at X company, and worked with me on Y open-source project.&#8221;  Then, whether I am looking for coworkers at X or codevelopers on Y, this person shows up.  Rules could be established so that &#8220;coworker at X company&#8221; membership implies &#8220;coworker&#8221; membership.  This may at first glance seem like nested groups, but it is very different.  It is completely free-form, and allows me to model my contact structure after how I interact with people in real life.  Not some bizarre mutually-exclusive set of too-shallow or too-specific relationships.</p>
<p>Multi-protocol clients should then support tag equivalency, so that service-mandated groups can be rolled into a differently-named tag.  Or ignore one account&#8217;s groups entirely, with everyone being rolled into one tag, with the possibility of local memorization of extra tags.</p>
<p>But the way things stand now, having groups at all is actually a hindrance to my communication.  &#8220;Did I put that person in friends or coworkers?  Or are they still in the service-specific default friends/buddies/oxygen-converters group?&#8221;</p>
<p>In lieu of a real solution to this problem, I want to disable groups entirely.  Except&#8230; whoops&#8230; Pidgin doesn&#8217;t even let me do that.</p>
<p>I welcome everyone&#8217;s thoughts on this issue.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.chrishowie.com/2010/04/21/why-i-hate-im-contact-groups/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>PGP key transition</title>
		<link>http://www.chrishowie.com/2010/04/14/pgp-key-transition/</link>
		<comments>http://www.chrishowie.com/2010/04/14/pgp-key-transition/#comments</comments>
		<pubDate>Wed, 14 Apr 2010 18:20:28 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Computer]]></category>

		<guid isPermaLink="false">http://www.chrishowie.com/?p=377</guid>
		<description><![CDATA[I am migrating to a new OpenPGP key. If this concerns you, or if you are interested, please read my key transition statement and take appropriate action. Please verify that the transition is signed by both my old and new keys.]]></description>
			<content:encoded><![CDATA[<p>I am migrating to a new OpenPGP key.  If this concerns you, or if you are interested, please read <a href="http://www.chrishowie.com/files/key-transition-2010-04-14.txt">my key transition statement</a> and take appropriate action.  Please verify that the transition is signed by both my old and new keys.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.chrishowie.com/2010/04/14/pgp-key-transition/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>git-svn in the workplace</title>
		<link>http://www.chrishowie.com/2010/04/01/git-svn-in-the-workplace/</link>
		<comments>http://www.chrishowie.com/2010/04/01/git-svn-in-the-workplace/#comments</comments>
		<pubDate>Thu, 01 Apr 2010 16:42:22 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Git]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.chrishowie.com/?p=365</guid>
		<description><![CDATA[At work, we use Subversion for source control. This is quite the popular VCS, but I&#8217;ve grown accustomed to (and much prefer) Git. Don&#8217;t get me wrong, SVN has its advantages, but since using Git my workflow has changed quite radically, and it&#8217;s difficult to revert to the rather inflexible and tedious SVN workflow. Anyway, [...]]]></description>
			<content:encoded><![CDATA[<p>At work, we use Subversion for source control.  This is quite the popular VCS, but I&#8217;ve grown accustomed to (and much prefer) Git.  Don&#8217;t get me wrong, SVN has its advantages, but since using Git my workflow has changed quite radically, and it&#8217;s difficult to revert to the rather inflexible and tedious SVN workflow.  Anyway, I&#8217;ve been using git-svn for the past month or so, and thought I&#8217;d share some of my practices.</p>
<p>In my clone, master is my &#8220;local&#8221; storage branch.  I use it to version things like my .gitignore, and my commit message template.  I would also use it for my dcommit/rebase scripts too, but since this is on Windows, Git becomes angry when it attempts to remove scripts that are executing.</p>
<p>Master is then the common root for my topic branches.  I&#8217;ll do some work and commit, then do more work, as the usual Git workflow goes.  The ability to create local branches and commits is great for several reasons:</p>
<p>First, I can commit much more often, without fearing that I will break somebody else&#8217;s working copy &#8212; I do frequently commit broken code now, because the commits don&#8217;t get sent to SVN automatically.</p>
<p>Second, and a side effect of the above, I am much more agile.  Sometimes I&#8217;ll be working on two projects at once, and keeping separate branches for them means that the broken state of one branch does not affect my ability to build/debug another.  This means I can even drop everything (after a commit or stash) and help out with an urgent QA or support issue, without either having lots of uncommitted work interfering or committing broken code to a production repository first.</p>
<p>Third, I can version changes I make to code that might make my life easier, but that would require approval to commit.  I have not yet done this, but thanks to my local repository, it&#8217;s an option.</p>
<p>Fourth, I can develop against a stable codebase.  If I need a specific fix from SVN to work, I can cherry-pick it into my topic branch &#8212; fetching commits from SVN does not mandate that my code must be merged with them.  Along the same lines, I also have the ability to rebase all my topic branches against a specific SVN commit, which is great when somebody commits broken code that causes build errors or incorrect runtime behavior.  If I were using SVN, I would either have to fix it myself, wait for the owner of the code to fix it, or revert to an earlier commit.  And since commits are linear, that might mean I would lose some of <i>my</i> code.  Git allows me to retain my commits while backing out changes made by others.  And if I <i>did</i> already commit some of my changes after the broken code, I can still rebase master and cherry-pick my subsequent commits onto a new branch and continue my work.</p>
<p>And finally, I can review all my commits before pushing them out.  I&#8217;ve had several occasions to fix up commit messages already.</p>
<p>Of course, I do eventually need to commit to SVN.  I have a few scripts to help here.  Obviously I don&#8217;t want to commit my local-only stuff in master.  So I have one script that simply does <code>git svn fetch &#038;&#038; git rebase --onto git-svn master</code>.  For the Git-impaired, this fetches any new commits from SVN and adds corresponding Git commits on the git-svn branch.  The rebase command then takes all the commits on the current branch since master&#8217;s latest commit, and applies them as patches to the tip of the git-svn branch, creating a new commit for each.  This effectively removes the local changes I&#8217;ve made in master from the commits, as well as merges the changes in SVN into my commits.  (If one of my commits fails to apply as a patch, then I have to resolve the conflicts manually, just like an SVN update.  But in this case, I still retain all my individual commits.)</p>
<p>After running this script, I then <code>git svn dcommit</code>, which commits my local commits to SVN, one by one.</p>
<p>At this point, I usually run my post-commit script, which rebases master on to git-svn, then rebases all my other branches on top of master.  I might not do this if I don&#8217;t want to rebase some of my other topic branches yet.</p>
<p>In closing, I leave you with my trick for changing commit messages.  I used to use git filter-branch for this, which is like using a sledgehammer for surgery.  (My similes are awesome, I know.)  Now I use this process:</p>
<p><code>git checkout -b temp $COMMIT_TO_CHANGE</code> (Create a new branch called &#8220;temp&#8221; at the commit I&#8217;m changing, and switch to it.)</p>
<p><code>git commit --amend</code> (Open an editor to amend my commit.  I change to message here, then save and quit.  The temp branch now has the new commit, whose parent commit is the same as it was before being amended.)</p>
<p><code>git checkout $ORIGINAL_BRANCH</code> (Switch back to the branch we are amending.)</p>
<p><code>git rebase temp</code> (Rebase the branch on top of the amended commit.  Since the original commit will be applied on top of the amended commit, it is dropped during the rebase.  The other commits will apply with no conflicts.  The history is now corrected.)</p>
<p><code>git branch -d temp</code> (Remove our temporary branch.)</p>
<p>And there you have it.  In a history with many thousands of commits, this is much faster than git filter-branch, and for those relatively fluent in Git, is also easier to remember how to do.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.chrishowie.com/2010/04/01/git-svn-in-the-workplace/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>When FarmVille == Productivity</title>
		<link>http://www.chrishowie.com/2010/01/27/when-farmville-productivity/</link>
		<comments>http://www.chrishowie.com/2010/01/27/when-farmville-productivity/#comments</comments>
		<pubDate>Thu, 28 Jan 2010 00:27:11 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Computer]]></category>

		<guid isPermaLink="false">http://www.chrishowie.com/?p=348</guid>
		<description><![CDATA[Update 2010-02-08: Jonathan Pryor has merged many of my extension methods into Cadenza. I&#8217;d strongly suggest checking it out. It&#8217;s no secret to my friends that I love to program&#8230; even more so as I&#8217;ve been developing a FarmVille client in C# and having them test it. (As much as you might hate FarmVille, you [...]]]></description>
			<content:encoded><![CDATA[<p><b>Update 2010-02-08:</b> Jonathan Pryor has merged many of my extension methods into <a href="http://gitorious.org/cadenza">Cadenza</a>.  I&#8217;d strongly suggest checking it out.</p>
<p>It&#8217;s no secret to my friends that I love to program&#8230; even more so as I&#8217;ve been developing a <a href="http://www.farmville.com">FarmVille</a> client in C# and having them test it.  (As much as you might hate FarmVille, you must agree that there&#8217;s a certain awesome factor in LINQ-to-FarmVille: <code>service.Plow(from i in service.World.Objects.OfType&lt;Plot&gt;() where i.State == "fallow" || i.State == "withered" select i</code>)</p>
<p>Well, among this project and others I consistently find myself writing the same code over and over.  I know of many programmers who have developed personal toolkits for the languages they use frequently, but for some reason I&#8217;ve been programming for about 13-15 years now and haven&#8217;t ever built my own library.  This application gave me an excuse to do so, and so I&#8217;ve started on the Cdh.Toolkit suite of libraries.</p>
<p>Here is a summary of the classes available:</p>
<ul>
<li><b>Cdh.Toolkit.Collections</b>: Some useful collection types, all designed to be derived.
<ul>
<li><b>ReadOnlyCollection&lt;T&gt;</b>, <b>ReadOnlyDictionary&lt;TKey, TValue&gt;</b>, and <b>ReadOnlyList&lt;T&gt;</b>: Wrappers around the corresponding interface types ICollection&lt;T&gt;, IDictionary&lt;TKey, TValue&gt;, and IList&lt;T&gt;, throwing exceptions on all write attempts.  While there is a ReadOnlyCollection&lt;T&gt; as part of the .NET framework, it is not designed to be derived, and the other two classes do not have a counterpart at all.</li>
<li><b>SynchronizedCollection&lt;T&gt;</b>, <b>SynchronizedDictionary&lt;TKey, TValue&gt;</b>, and <b>SynchronizedList&lt;T&gt;</b>: Wrappers around the corresponding interfaces.  All accesses are synchronized against a ReaderWriterLockSlim, allowing for multiple concurrent read operations.  The enumeration behavior can be specified as either lock, which holds a read lock for the duration of the enumeration, or copy, which creates a copy of the collection and enumerates it instead.</li>
<li><b>ObservableCollection&lt;T&gt;</b>: A collection that fires events when modified.  ObservableDictionary and ObservableList are currently not provided, due to some implementation complexities.  However, the interfaces <b>IObservableCollection&lt;T&gt;</b>, <b>IObservableDictionary&lt;TKey, TValue&gt;</b>, and <b>IObservableList&lt;T&gt;</b> and some EventArgs classes are provided to allow developers to implement their own observable collections easily.</li>
<li><b>ObservableHashSet&lt;T&gt;</b>: An observable and API-compatible wrapper around HashSet&lt;T&gt;.</li>
<li><b>ReadOnlyObservableCollection&lt;T&gt;</b>, <b>ReadOnlyObservableDictionary&lt;TKey, TValue&gt;</b>, and <b>ReadOnlyObservableList&lt;T&gt;</b>: Wrappers around the IObservable* interfaces mentioned above.  Events from the wrapped collections are forwarded.  This allows one to have a read only observable collection without sacrificing the IObservable* interface, which would happen if such a collection were wrapped in one of the normal read only classes listed above.</li>
</ul>
</li>
<li><b>Cdh.Toolkit.Extensions</b>: Extension libraries designed to ease the use of many classes in the .NET framework.
<ul>
<li><b>Collections</b>: Extensions specific to collection classes.
<ul>
<li><b>TValue IDictionary&lt;TKey, TValue&gt;.GetOrDefault(TKey key)</b>: Returns default(TValue) if the key is not present in the dictionary.</li>
<li><b>TValue IDictionary&lt;TKey, TValue&gt;.GetOrValue(TKey key, TValue fallback)</b>: Returns fallback if the key is not present in the dictionary.</li>
</ul>
</li>
<li><b>ComponentModel</b>: Extensions specific to the System.ComponentModel namespace.
<ul>
<li><b>void ISynchronizeInvoke.AutoInvoke(Action action)</b>: Executes the action delegate on the ISynchronizeInvoke object if required, otherwise does so on the current thread.</li>
<li><b>object ISynchronizeInvoke.AutoInvoke(Delegate method, params object[] args)</b>: Executes the delegate on the ISynchronizeInvoke object if required, otherwise does so on the current thread, and returns the return value of that method in either case.</li>
<li><b>AsyncCallback AsyncCallback.Invoked(ISynchronizeInvoke obj)</b>: Returns a wrapper around the AsyncCallback delegate that will invoke it using the AutoInvoke extension above.  Useful for async callbacks that need to operate on a Winforms GUI.</li>
</ul>
</li>
<li><b>Enumerable</b>: Extensions to enumerable objects.
<ul>
<li><b>IEnumerable&lt;T&gt; IEnumerable&lt;T?&gt;.NotNull() where T : struct</b>: Returns all values from the non-null nullable objects in the sequence.</li>
<li><b>void IEnumerable&lt;T&gt;.Walk()</b>: Enumerates the sequence, discarding all values obtained.  Useful as an alternative to .ToList() when you need to make sure that a query executes, but do not need to use the result.</li>
<li><b>void IEnumerable&lt;T&gt;.CopyInto(IList&lt;T&gt; list)</b>: Copies a sequence into a list.</li>
</ul>
</li>
<li><b>Events</b>: Extensions that make writing event logic easier.  All of these extensions return if the event handler in question is null, making event-firing code simpler and easier to read.
<ul>
<li><b>void EventHandler.Fire(object sender)</b>: Uses EventArgs.Empty as the event arguments.</li>
<li><b>void EventHandler.Fire(object sender, EventArgs args)</b></li>
<li><b>void EventHandler.Fire(object sender, Func&lt;EventArgs&gt; argsFactory)</b>: Calls the factory function only if the event handler is not null.  Useful when construction of the event arguments can take a long time.</li>
<li><b>void EventHandler&lt;T&gt;.Fire(object sender, T args)</b></li>
<li><b>void EventHandler&lt;T&gt;.Fire(object sender, Func&lt;T&gt; argsFactory)</b>: Calls the factory function only if the event handler is not null.  Useful when construction of the event arguments can take a long time.</li>
</ul>
</li>
<li><b>ReaderWriterLockSlim</b>: Allows these kind of locks to be used in a using() block, which makes code easier to read and maintain.  They will also return a no-op IDisposable if a compatible lock is already held by the current thread, which makes non-recursive lock objects simpler to code with.  (The return type is actually a value type that implements IDisposable, which means that usage of these methods does not incur any object allocation overhead.)
<ul>
<li><b>IDisposable ReaderWriterLockSlim.Read()</b>: Returns an IDisposable that will release the read lock when disposed.  This method returns a no-op IDisposable instead if the current thread already holds a read, upgradeable read, or write lock.</li>
<li><b>IDisposable ReaderWriterLockSlim.UpgradeableRead()</b>: Returns an IDisposable that will release the upgradeable read lock when disposed.  This method returns a no-op IDisposable instead if the current thread already holds an upgradeable read or write lock.</li>
<li><b>IDisposable ReaderWriterLockSlim.Write()</b>: Returns an IDisposable that will release the write lock when disposed.  This method returns a no-op IDisposable instead if the current thread already holds a write lock.</li>
</ul>
</li>
<li><b>Reflection</b>
<ul>
<li><b>T ICustomAttributeProvider.GetCustomAttribute&lt;T&gt;(bool inherit) where T : Attribute</b>: Returns a typed attribute, or null if there is no attribute of type T.</li>
<li><b>IEnumerable&lt;T&gt; ICustomAttributeProvider.GetCustomAttributes&lt;T&gt;(bool inherit) where T : Attribute</b>: Returns a sequence of attributes of type T present on the attribute provider.</li>
</ul>
</li>
<li><b>Reflection.Emit</b>
<ul>
<li><b>void ILGenerator.EmitTypeOf(Type type)</b>: Emits the IL sequence that will leave the same Type object on the execution stack.</li>
</ul>
</li>
</ul>
<p>The amount of code is slim, but I&#8217;ve found at least one of the classes or extensions invaluable in every project I&#8217;ve worked on since starting the toolkit.  It&#8217;s an interesting case where coding for a game actually winds up improving my productivity working on other software too.</p>
<p>Eventually these libraries will be released under the MIT license, so stay tuned for another blog post with a link to the Git repository.</p>
<p>(And yes, the above list will be converted into real documentation.  Someday.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.chrishowie.com/2010/01/27/when-farmville-productivity/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>

