<?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>Laughing Meme &#187; Longer</title>
	<atom:link href="http://laughingmeme.org/tag/longer/feed/" rel="self" type="application/rss+xml" />
	<link>http://laughingmeme.org</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Tue, 09 Mar 2010 01:35:11 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Looking at PHP5&#8217;s DateTime and DateTimeZone</title>
		<link>http://laughingmeme.org/2007/02/27/looking-at-php5s-datetime-and-datetimezone/</link>
		<comments>http://laughingmeme.org/2007/02/27/looking-at-php5s-datetime-and-datetimezone/#comments</comments>
		<pubDate>Wed, 28 Feb 2007 00:47:09 +0000</pubDate>
		<dc:creator>Kellan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[calendaring]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[datetime]]></category>
		<category><![CDATA[Longer]]></category>
		<category><![CDATA[olson]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[php5]]></category>
		<category><![CDATA[timezone]]></category>

		<guid isPermaLink="false">http://laughingmeme.org/2007/02/27/looking-at-php5s-datetime-and-datetimezone/</guid>
		<description><![CDATA[Looking over the PHP5.2 changelog I noticed that somewhere along the way PHP5 seems to have picked up a provocatively named pair of classes, DateTime and DateTimeZone.  

There is something fundamentally brash, brazen even, to releasing a class named DateTime.  As a calendar geek I imagine upon seeing &#8220;new DateTime()&#8221; I feel something [...]]]></description>
			<content:encoded><![CDATA[<p>Looking over the <a href="http://www.php.net/ChangeLog-5.php">PHP5.2 changelog</a> I noticed that somewhere along the way PHP5 seems to have picked up a provocatively named pair of classes, DateTime and DateTimeZone.  </p>

<p>There is something fundamentally brash, brazen even, to releasing a class named DateTime.  As a calendar geek I imagine upon seeing &#8220;new DateTime()&#8221; I feel something akin to what an old thespian feels when they see a company putting on a production of the Scottish play &#8212; it&#8217;s a decidedly mixed emotion.  But I&#8217;m going to bump my way through learning how to use this new DateTime lib, bringing <strong>all my preconceptions</strong> about how it should work.  The odds of this being interesting to you is probably nil unless you&#8217;re in one or two very small cliques, feel free to read on, or browse away.</p>

<p>I&#8217;m primarily working in PHP4 right now, so my first step was to grab a copy of <a href="http://www.mamp.info/en/home.php">MAMP 1.5b</a> getting me a nice PHP5.2 sandbox to play with.</p>

<p>The new objects are <a href="http://www.php.net/manual/en/ref.datetime.php">documented here</a>, apparently there are functional equivalents for each of the object methods, and they use the <a href="http://pecl.php.net/package/timezonedb/">PECL timezomedb</a>.  </p>

<p>Hey!  timezonedb!  First fence cleared!  A timezone database compiled into a native format based on Olson is the <em>one true solution</em>, and I can update it independently, the most recent release being based on 2007b.  Sweet.  </p>

<p><a href="http://php.net/manual/en/function.date-create.php">Constructor</a> takes an initialization string that it passes to <a href="http://php.net/manual/en/function.strtotime.php">strtotime()</a>, and an optional DateTimeZone obj.  Defaults to &#8220;now&#8221;</p>

<pre><code>$date = new DateTime();
echo $date . "\n";
&gt; Object of class DateTime could not be converted to string 
</code></pre>

<p>Oops, no <code>__toString()</code> method defined.  You&#8217;ll need to use the <code>format()</code> instance method.  If you end up using the DateTime objects, you&#8217;ll be seeing a lot of <code>format()</code>, more on that in a bit.  </p>

<p><code>format()</code> uses the <a href="http://php.net/manual/en/function.date.php">date() formatting strings</a> (not the <code>strftime</code> format strings).  Also takes a number of useful constants, most usefully your pal and mine RFC3339 (aka W3CDTF aka Dublin Core/Atom date format).</p>

<pre><code>echo $date-&gt;format(DATE_RFC3339) . "\n";
&gt; 2007-02-22T15:23:47-05:00
</code></pre>

<p>Note: thats a constant, if you pass in the string &#8216;DATE_RFC3339&#8242;, and you&#8217;ll get odd looking results.</p>

<p>Here we can see the default constructor sets both the time and a timezone &#8212; correctly, for the moment, identifying my timezone as <code>America/New_York</code>.   That&#8217;s somewhat contentious behaviour, some people will tell you that dates with unspecified timezones should either be in UTC or be &#8220;floating&#8221;, divorced from any timezone.  Why?  At least in part because across platforms and boxes timezone guessing is going to be non-deterministic &#8212; the script that worked when you ran it locally on your Mac laptop in New York, might fail on your ISP&#8217;s servers.  You get a hint of this reading over the timezone guessing rules on <a href="http://php.net/date_default_timezone_get"><code>date_default_timezone_get</code></a>.  There is also the fact that I&#8217;m currently moving at about 400mph and will be in a different timezone real soon now.  However you can set the default to something reasonable in a script, or in the php.ini.  (consider this my recommendation)</p>

<pre><code>date_default_timezone_set('UTC');
$date = new DateTime();
echo $date-&gt;format(DATE_RFC3339);
&gt; 2007-02-22T20:44:49+00:00
</code></pre>

<p>Yay, that worked.  Okay, but lets display that datetime in the local timezone.  (after all the <em>point</em> of this entire exercise will be the ability to work painlessly in multiple timezones).</p>

<pre><code>$date-&gt;setTimezone('America/New_York');
&gt; DateTime::setTimezone() expects parameter 1 to be DateTimeZone
</code></pre>

<p>Siiiigh.  Not smart enough to cast strings into TimeZone objects (holds true for the constructor as well, so no <code>new DateTime('now', 'UTC'))</code>.  Now its time to learn how to use DateTimeZone.</p>

<h3>Working with DateTimeZone, All Hail Olson</h3>

<p>I mentioned briefly earlier that PHP is now shipping with an extension timezonedb, which is a compiled version of the <a href="http://en.wikipedia.org/wiki/Zoneinfo">Olson database</a>.  The Olson database is a massive, largely volunteer effort to catalog the various timezones both in use, and those that have been in the past.  Time is a political issue, <a href="http://laughingmeme.org/2005/04/04/daylight-saving-sucks-war-time/">particularly day light savings</a>, and as such the rules governing it are arbitrary, whimsical, and subject to frequent change.  (p.s. gotten a panicked memo yet about new daylight savings compliance for March 11th?  No?  Where did you say you worked?)</p>

<p>Note: Olson also uses a longer form of the zone names then we usually see in the U.S., this is to combat ambiguity.  See <a href="http://www.php.net/manual/en/timezones.php">Appendix H</a> for a list of timezone names, including some <a href="http://www.php.net/manual/en/timezones.others.php">handy shortcuts</a>.</p>

<pre><code>$tz = new DateTimeZone('America/New_York');
$date-&gt;setTimezone($tz);
echo $date-&gt;format(DATE_RFC3339) . "\n";
&gt; 2007-02-22T16:02:55-05:00
</code></pre>

<p>This is starting to get long winded, but, hey, PHP5 supports object dereferencing on returns.  Maybe this will work.</p>

<pre><code>echo $date-&gt;setTimezone($tz)-&gt;format(DATE_RFC3339) . "\n";
&gt;  Call to a member function format() on a non-object
</code></pre>

<p>Nope. Oh well.</p>

<h3>Date vs Datetime?</h3>

<p>Say I&#8217;ve got a nice platonic date, say November 11th.  There is no time element associated with this, so timezones are kind of irrelevant.  I mean Nov. 11th <em>starts</em> at different times through out the world, but Nov. 11th is universal. (as long as you&#8217;re using the same version of Gregorian as most of the rest of us)  Ideally this date would float above timezone issues, but that isn&#8217;t how PHP does it, 2007-11-11 is treated internally as midnight on the 11th, which is certainly simpler, but disappointing.  You can prove this like so:</p>

<pre><code>$date = new DateTime('2007-11-11');
$date-&gt;setTimeZone($tz);
echo $date-&gt;format(DATE_RFC3339) . "\n";
&gt; 2007-11-10T19:00:00-05:00
</code></pre>

<p>The other useful DateTimeZone method is getOffest() </p>

<pre><code>echo $tz-&gt;getOffset($date); 
&gt; -18000
</code></pre>

<h3>Daylight Saving, March 11th, and Why Programmers Are a Grouchy Lot</h3>

<p>Note: <code>getOffset</code>, which returns a timezone&#8217;s offset in seconds from UTC, takes a DateTime obj because offsets can be date sensitive due to daylight savings.  Really without daylight saving this stuff would all be pretty straightforward.    Let&#8217;s test to make sure the offsets are correct at the boundary.</p>

<pre><code>echo $tz_nyc-&gt;getOffset(new DateTime('2007-03-11 1:00')) . "\n";
echo $tz_nyc-&gt;getOffset(new DateTime('2007-03-11 2:00')) . "\n";
&gt; -18000
&gt; -14400

(-18000/(60*60) == -5 hours) 
(-14400/(60*60) == -4 hours) 
</code></pre>

<p><strong>Yay!</strong> They got the memo about <a href="http://en.wikipedia.org/wiki/Energy_Policy_Act_of_2005">U.S. Energy Policy Act of 2005</a>.</p>

<h3>The Basics:  Accessors and Mutators</h3>

<p>So what are some other basic desires?</p>

<p>Get epoch seconds!  Except for their kind of limited range epoch seconds are great, and have helped a generation of programmers put off worrying about timezones as long as possible.  They&#8217;re also the backbone of PHP&#8217;s traditional date/time methods.</p>

<p>Alas, there isn&#8217;t an accessor method for getting epoch seconds, you&#8217;ll have to use <code>format()</code>. </p>

<p>In fact DateTime doesn&#8217;t expose <strong>any</strong> of the accessors you&#8217;d expect, so you&#8217;ll be using <code>format</code> a <strong>lot</strong> if you want to access pieces of your date. (for you know, display purposes, or manipulation, or building queries, or pretty much doing anything you&#8217;d want to do with a date)</p>

<p>examples of the <code>format()</code> as all purpose accessor pattern:</p>

<pre><code>epoch:  $date-&gt;format('U'); // 1173596400
year:   $date-&gt;format('Y'); // 2007
month:  $date-&gt;format('n'); // 3
day:    $date-&gt;format('j'); // 11
dow:    $date-&gt;format('l'); // Sunday
</code></pre>

<p>&#8230; etc &#8230;</p>

<p>So now you have accessors for the full range of <a href="http://php.net/manual/en/function.date.php">date() formatting strings</a>.  You just have to jump through a hope.</p>

<p>Pretty much the only accessor is <code>getTimezone()</code></p>

<pre><code>echo $date-&gt;getTimeZone();   // hope springs eternal!
&gt; Object of class DateTimeZone could not be converted to string
echo $date-&gt;getTimeZone()-&gt;getName() . "\n";
&gt; America/New_York
</code></pre>

<h3>Mutators</h3>

<p>Speaking of accessors, DateTime is a little sparse on mutators as well: <code>setTime()</code>, <code>setDate()</code>, and the mysteriously named <code>setISODate()</code>.</p>

<pre><code>$date-&gt;setDate('2007', '1', '1')-&gt;format(DATE_RFC3339);  // who am I kidding?
&gt; Call to a member function format() on a non-object 
$date-&gt; setDate('2007', '1', '1');
echo $date-&gt;format(DATE_RFC3339) . "\n";
&gt; 2007-01-01T02:00:00-05:00
</code></pre>

<p>Now what if I want to set just the day?</p>

<p>Maybe</p>

<pre><code>$date-&gt; setDate(null, null, '11');
echo $date-&gt;format(DATE_RFC3339) . "\n";
&gt; -001-12-11T02:00:00-05:00
</code></pre>

<p>Nope.  </p>

<p>Instead you&#8217;ll need to pull out the year and month (using our <code>format()</code> accessors) and pass those back in just to set the day.</p>

<pre><code>$date-&gt; setDate('2007', '1', '1');   // jan 1.  
$date-&gt;setDate($date-&gt;format('Y'), $date-&gt;format('n'), 11);
echo $date-&gt;format(DATE_RFC3339) . "\n"; 
</code></pre>

<p>Clunky.  </p>

<p><code>setTime()</code> works the same, but for time.  </p>

<p>e.g. Setting just the minutes, 33 minutes past, but keep hours, and seconds constant:</p>

<pre><code>$date-&gt;setTime($date-&gt;format('G'), 33, $date-&gt;format('s'));
echo $date-&gt;format(DATE_RFC3339) . "\n"; 
&gt; 2007-01-11T02:33:00-05:00
</code></pre>

<p>So what is an ISODate?  I&#8217;m unclear, and so is PHP&#8217;s documentation.  The docs show the call signature taking a $year, $week, and optional $day, while the description talks about $year, $month, $day.  Looking at the code looks like $week is the proper call, $month is cut and paste error from <code>setDate()</code>.  So I guess this is a method for setting day by the &#8220;week of the year&#8221; a concept more popular in Europe then in the US.  Not sure what ISO has to do with it.   So what is our current week of the year?</p>

<pre><code>echo $date-&gt;format('N') . "\n";  // 'N' is new in 5.1.0
&gt; 4 
</code></pre>

<p>Jan 11th was in the 4th week of the 2007?  Go figure.  </p>

<pre><code>$date-&gt;setISODate(2007, 4, 5);  // fifth day of the 4th week?
echo $date-&gt;format(DATE_RFC3339) . "\n";
&gt; 2007-01-26T02:33:00-05:00
</code></pre>

<p>Um.  You know what?  You&#8217;re on your own with <code>setISODate</code>, sorry.</p>

<h3>Date Math: Adding and Subtracting Deltas aka $date->modify($str)</h3>

<p>PHP5 for better or worse has very limited operator overloading, so no $dt1 + $dt2 * $dt3 / $dt4.  Instead the primary method for doing math is <code>modify()</code></p>

<p>Thankfully PHP&#8217;s <code>strtotime()</code> method is a gem, and one of the things it handles is relative dates.  <code>strtotime()</code> + relative dates is the secret to doing math with PHP5&#8217;s DateTime.</p>

<p>Lets get a basic date to start with:</p>

<pre><code>$date = new DateTime('today');
echo $date-&gt;format(DATE_RFC3339) . "\n";
&gt; 2007-02-22T00:00:00+00:00
</code></pre>

<p><strong>Note:</strong> <code>modify()</code> is destructive. It changes the original datetime object (as the name suggests).  You&#8217;ll need to jump through some hopes to keep a copy of your original date.  More later.</p>

<p>Add/subtract N days:</p>

<pre><code>foreach (range(1,10) as $n) {
   $date-&gt;modify("+1 days");
   echo $date-&gt;format("Y-m-d") . "\n";
}

&gt; 2007-02-23
&gt; 2007-02-24
&gt; 2007-02-25
&gt; 2007-02-26
&gt; 2007-02-27
&gt; 2007-02-28
&gt; 2007-03-01
&gt; 2007-03-02
&gt; 2007-03-03
&gt; 2007-03-04

$date-&gt;modify("-10 days");
echo $date-&gt;format("Y-m-d") . "\n";

&gt; 2007-02-22

$date-&gt;modify("-1 month");
echo $date-&gt;format("Y-m-d") . "\n";
&gt; 2007-01-22
// or alternately
$date-&gt;modify("1 month ago");
echo $date-&gt;format("Y-m-d") . "\n";
&gt; 2006-12-22
</code></pre>

<h3>Cloning DateTime objects to work around <code>modify</code></h3>

<p>Of course you <strong>usually</strong> want to keep the original when doing date math, so <code>modify()</code>&#8217;s lack of idempotentce is annoying.  Lets say I&#8217;m building a SQL query to select events happening in the next 7 days.</p>

<p>In an <strong>ideal</strong> world the code would like this:</p>

<pre><code>$start = new DateTime('today');
$end = $start + 7;
echo "select between " . $start-&gt;format('Y-m-d') . " and " . $end-&gt;format('Y-m-d') . "\n";
</code></pre>

<p>The above of course is just a pipe dream.  But wouldn&#8217;t it be nice?</p>

<p>I&#8217;d settle for:</p>

<pre><code>$end = $start-&gt;calc("+7 days");
</code></pre>

<p>Or even:</p>

<pre><code>$end = $start-&gt;clone-&gt;modify('+7 days');
</code></pre>

<p>None of the above examples remotely work.  </p>

<p>Instead use:</p>

<pre><code>$start = new DateTime('today');
$end = clone $start;
$end-&gt;modify('7 days 3 minutes 42 seconds ago');
</code></pre>

<p>Now format our SQL query for our example:</p>

<pre><code>echo "select between " . $start-&gt;format(DATE_RFC3339) . " and " . $end-&gt;format(DATE_RFC3339) . "\n";
&gt; select between 2007-02-22T00:00:00+00:00 and 2007-02-14T23:56:18+00:00
</code></pre>

<p>Awkward, but it gets the job done.</p>

<p>At least the relative date format is super flexible and expressive.  As far as I know the closest thing to documentation is from the <a href="http://www.gnu.org/software/tar/manual/html_node/tar_109.html">GNU tar manual on date input formats</a>. (just like CVS)  Btw. if you ever want nightmares, take a look at the <code>scan</code> method in PHP&#8217;s parse_date.c and be thankful that isn&#8217;t your job to maintain <img src='http://laughingmeme.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<h3>Date Math: Comparison and Differences</h3>

<p>Beyond adding deltas (&#8220;+7 days&#8221;), the other common date math is comparing two datetimes, to find out which is more recent, and getting the difference between them.  DateTime supports no methods for comparing two datetimes.  The simplest solution for doing comparison is to compare epoch seconds.</p>

<p><strong>Note:</strong>  This method only works for dates that can be represented by epoch seconds. PHP uses a signed int for epoch seconds, so the range is limited by the size of the max int on your platform.  Generally you get approximately 138 years, 1901 to 2038.  There are other schemes besides epoch seconds for mapping dates to an easily comparable number; <a href="http://en.wikipedia.org/wiki/Julian_day">MJDs</a>, and <a href="http://cr.yp.to/proto/utctai.html">Tai time</a> being two.  See also <em>Rheingold &amp; Dershowitz 1997</em></p>

<pre><code>$d1 = new DateTime("today");
$d2 = new DateTime("tomorrow");
if ($d1-&gt;format('U') &lt; $d2-&gt;format('U')) {
   echo "true\n";
} 
&gt; true
</code></pre>

<p>If you&#8217;re going to be comparing a large number of dates you might consider a memoization technique like the <a href="http://en.wikipedia.org/wiki/Schwartzian_transform">Schwartzian transform</a>.</p>

<p>We can get the difference in seconds using the same hack of casting to epochs.</p>

<pre><code>echo $d2-&gt;format('U') - $d1-&gt;format('U') . "\n";
&gt; 86400
</code></pre>

<p>Ideally we&#8217;d then divide the difference seconds to get the difference in hours, days, weeks, or months.  However the following naive solution <strong>won&#8217;t</strong> work.  </p>

<pre><code>$diff / (60*60*24);  // calculate difference in days, **BADLY**
</code></pre>

<p>Why not?  Because days don&#8217;t always have 24 hours.  Sometimes they have 23 hours, sometimes they have 25.  Daylight saving strikes again.  (If you want to be even more pedantic, minutes are also not 60 seconds long, sometimes they&#8217;re 61 seconds long if we have a leap second)</p>

<p>Basically you need to break yourself of thinking of datetime units as being fungible.  You can&#8217;t simply calculate minutes from seconds, or days from hours.  Just like you can&#8217;t divide days by 30 to get an accurate number of months.  There are solutions, but they&#8217;re a bit beyond this blog post.</p>

<h3>new DateTime from Epoch Seconds</h3>

<p>So, <strong>non-fungible</strong>, remember that.</p>

<p>But sometimes you&#8217;ve cast DateTimes down to epochs to do math.  And then you&#8217;ll want to cast back to a DateTime.  </p>

<p>Alas DateTime doesn&#8217;t have a constructor that takes an epoch, and passing a epoch to the default constructor will throw an exception, rather you want:</p>

<pre><code>$from_epoch = new DateTime(date('c', '-568080000'));
echo $from_epoch-&gt;format('Y-m-d') . "\n";
&gt; 1952-01-01   // expected result
</code></pre>

<h3>Conclusions</h3>

<p>DateTime/DateTimeZone get timezones right, and for solving that hard problem they deserve all possibles accolades.  </p>

<p>The rest of the API however is kind of simplistic, awkward to work with, and verbose.</p>

<p>Single most useful change: have DateTime methods actually return the object making it possible to use a slightly more abbreviated calls.</p>

<p>I had thought about writing up a few more recipes, like nth dow of the month, and such.  But we were coming in for descent, and it was time to be done.  Might happen in the future.  </p>

<p>Also if anyone has any power to <strong>enhance</strong> the DateTime object, I hope some of the above can act as a road map for a more expressive and powerful core library.  Or ping me, happy to chat.</p>
]]></content:encoded>
			<wfw:commentRss>http://laughingmeme.org/2007/02/27/looking-at-php5s-datetime-and-datetimezone/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>On Book Listing Services</title>
		<link>http://laughingmeme.org/2005/11/06/on-book-listing-services/</link>
		<comments>http://laughingmeme.org/2005/11/06/on-book-listing-services/#comments</comments>
		<pubDate>Mon, 07 Nov 2005 03:10:00 +0000</pubDate>
		<dc:creator>Kellan</dc:creator>
				<category><![CDATA[allconsuming]]></category>
		<category><![CDATA[books]]></category>
		<category><![CDATA[community]]></category>
		<category><![CDATA[information]]></category>
		<category><![CDATA[infrastructure]]></category>
		<category><![CDATA[Longer]]></category>
		<category><![CDATA[participation]]></category>
		<category><![CDATA[review]]></category>
		<category><![CDATA[site]]></category>
		<category><![CDATA[social]]></category>
		<category><![CDATA[state.of.the.art]]></category>
		<category><![CDATA[tagging]]></category>
		<category><![CDATA[webservice]]></category>

		<guid isPermaLink="false">http://lm.quxx.info/?p=3092</guid>
		<description><![CDATA[For years I&#8217;ve wanted a decent website where I can manage my relationship with books. (not especially complicated, but voluminous)  

For a while there was largely nothing, then there was Allconsuming which was wonderful, but slowly died, and went dark before being re-incarnated in the mold of a 43x tool.  And I have [...]]]></description>
			<content:encoded><![CDATA[<p>For years I&#8217;ve wanted a decent website where I can manage my relationship with books. (not especially complicated, but voluminous)  </p>

<p>For a while there was largely nothing, then there was <a href="http://laughingmeme.org/tag/allconsuming">Allconsuming</a> which was wonderful, but slowly died, and went dark before being re-incarnated in the mold of a <a href="http://43.allconsuming.net">43x tool</a>.  And I have this memory of there being a nifty little $14/mo tool, back in the days when I didn&#8217;t pay for websites, but I wasn&#8217;t able to find it.</p>

<p>Last Fall, I started sketching down notes towards building my own, and in the intervening year its become an interestingly crowded space. (who knew so many other people felt the pull)  Even in the 6 weeks since I first started jotting down sites for this blog post, the space has evolved with <a href="http://librarything.com">LibraryThing</a> coming out solidly on top as the most active: most actively developed, most actively used, and most <a href="http://www.librarything.com/blog/">actively engaged developer</a>.</p>

<p>That said, in a cursory search (mostly of my del.icio.us links)  I turned up  5 other very similar services</p>

<ul>
<li><a href="http://43.allconsuming.net">Allconsuming</a>: the Next Generation</li>
<li><a href="http://bibliophil.org/default.php">Bibliophil</a></li>
<li><a href="http://bookswelike.net/">Books We Like</a> &#8211; &#8220;activist e-commerce and collective intelligence&#8221;</li>
<li><a href="http://www.listal.com/">Listal</a> &#8211; where &#8220;all&#8221; is defined as DVDs, Books, Music, and Games</li>
<li><a href="http://reader2.com/">Reader2</a> &#8211; repurposing of the <a href="http://myprogs.net/">MyProgs</a> codebase</li>
</ul>

<p>Also the <a href="http://bookshelf.ning.com">Bookshelf</a> example app from <a href="http://ning.com">24L</a>, and the intersting related services <a href="http://whatshouldireadnext.com/">What Should I Read Next?</a>, and <a href="http://www.libraryelf.com/">Library Elf</a></p>

<p>None of them are quite there yet, and I want more, more, <strong>more</strong>!</p>

<p><span id="more-3092"></span></p>

<h3>LibraryThing</h3>

<ul>
<li><p>So like I said, <a href="http://librarything.com">LT</a> is rocking out in terms of development and growth.  When I first found it, it lacked <a href="http://www.librarything.com/blog/2005/10/universal-import-filesand-now-web.php">import</a>, <a href="http://www.librarything.com/blog/2005/10/book-rating-added-no-pencil-required.php">ratings</a>, and <a href="http://www.librarything.com/blog/2005/10/one-rss-feed-made-so-what-rss-do-you.php">feeds</a>.   Wow.</p></li>
<li><p>Additionally the search is amazingly comprehensive, fast, and accurate.  Search is where LibraryThing originally shined, and it blows every other service out of the water.  <a href="http://librarything.com">LT</a> was the only service to successfully come up with <a href="http://www.craphound.com/someone/">&#8220;Someone Comes to Town, Someone Leaves Town&#8221;</a> when I searched for &#8220;someone comes&#8221;.  Which is good, because there is no way I&#8217;m typing in full titles.  (just re-tested, and <a href="http://43.allconsuming.net">Allconsuming</a> which wasn&#8217;t finding <strong>anything</strong> last time I checked, also came up with the correct results)</p></li>
<li><p>Surprisingly zippy.</p></li>
<li><p>One-click export.  Sweet.</p></li>
</ul>

<h3>LibraryThings:  The Downside</h3>

<ul>
<li><p>No per-tag feeds, apparently on the todo list, but I <strong>need</strong> per feed tags.</p></li>
<li><p>No feed of reviews, also on the todo list, but I&#8217;m simply not willing to create content without an RSS feed. (which is why I&#8217;ve <a href="http://laughingmeme.org/articles/2005/01/15/a-few-more-thoughts-on-netflix-friends">stopped writing $0.02 reviews</a> on <a href="http://netflix.com">Netflix</a>)</p></li>
<li><p>Feeds lack anything beyond basic data.  No structured meta-data (authors, isbn/asin, cover art, etc), so very limited usefulness.</p></li>
<li><p>One dimensional tags. (no <a href="http://laughingmeme.org/articles/2005/01/20/tagging-isn-t-classifying-and-other-uses-of-tags">tag combos</a>)</p></li>
<li><p>Ugly, and awkward.  Totally in the eye of the beholder, but I find the interface consistently confusing and awkward to use.  I only have a handful of books in my catalog, but already its feeling unmanageable.  Not a designer, so I can&#8217;t do much more then complain.</p></li>
<li><p>One comment/review per book, meaning you can&#8217;t use it to blog your ongoing experience with a book.  One of my use cases for a book service is that I can use it to power a book blog.</p></li>
<li><p>Uses frames!?!??  In this day and age?  Meaning it can&#8217;t be the that <a href="http://laughingmeme.org/articles/2003/01/04/a-definitive-uri-for-books">&#8220;definitive URI for books&#8221;</a> that I keep looking for.</p></li>
</ul>

<h3>Listal</h3>

<ul>
<li><p>More then just books if you&#8217;re in to that thing.  I&#8217;m not really, and find it kind of frustrating that I sometimes end up searching DVDs.</p></li>
<li><p>Slick, clean, attractive.</p></li>
<li><p>Allows browsing by author! (key missing feature for LibraryThing)</p></li>
<li><p>Per tag feeds, multiple reviews/comments per book.</p></li>
</ul>

<h3>Listal: Cons</h3>

<ul>
<li><p>Feels sluggish, aggravated by a click heavy interface.</p></li>
<li><p>Limited import.</p></li>
<li><p>Not run by a book nut, and in general the site is voiceless failing to expose either the developer, or the user community.  Feels stagnant.</p></li>
<li><p>Search failed the &#8220;Someone Comes&#8221; test.</p></li>
</ul>

<h3>Bookshelf</h3>

<p>I thought I was going to like <a href="http://bookshelf.ning.com">Bookshelf</a>.  I love the concept of the <a href="http://www.ning.com/pivot">Ning &#8220;Pivot&#8221;</a>, if not the implementation.  Unfortunately <a href="http://bookshelf.ning.com">Bookshelf</a> is <strong>very</strong> slow, and buggy.  I dived into the code (I can do that with Ning, whoohoo!!!), and unfortunately rather then the domain specific langauge for building social webapps I expected to find, I just found a messy of PHP code.  <img src='http://laughingmeme.org/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>

<h3>What I Still Want/Need/Dream About</h3>

<p>I wrote down a list of things I wanted a while back, and LT is converging on it very quickly, and for that I&#8217;m inclined to overlook the interface.</p>

<h4>Syndication</h4>

<p>I need more feeds.  Per tag feeds allow for intelligent interaction with the site.  Beyond topical tags, functional tags (e.g. *to:read) allow me to syndicate the information out in useful ways</p>

<p>And richer feeds please.  E.g. if you can&#8217;t syndicate the cover art give me the necessary metadata so I can pull it from <a href="http://www.amazon.com/gp/aws/landing.html">AWS</a>.</p>

<h4>More data and Webservices</h4>

<p>And note, I&#8217;m happy with my primary webservice being a feed, but I need richer way to interact with the data before I can make it work for me. </p>

<p>I&#8217;d like to be able to hook this up to my local library (auto-request books flagged *to:read), <a href="http://upcoming.org">Upcoming</a>, and <a href="http://amazon.com">Amazon</a>.</p>

<p>Plus I should be able to power my involvement in <a href="http://www.whatshouldireadnext.com/">What to Read Next</a>/<a href="http://bookswelike.net/">Books We Like</a>/innovative new service from within <a href="http://librarything.com">LT</a> (or at least with my LT data)</p>

<h4>More Pivots</h4>

<p>I&#8217;d like author, and ratings smooshed down into the tag namespace.  So I can browse by author, and by rating.  Additionally I&#8217;d like to be able to browse tag combos, author plus tag combos, and author plus rating combos.</p>

<h4>Insta-Community</h4>

<p>I love the idea of <a href="http://www.librarything.com/blog/2005/11/how-to-do-librarything-forum.php">integrating a forum into the site</a>.  And really integrating it.  </p>

<ol>
<li>Allow people to start new threads from a book page</li>
<li>Tag those threads with the book</li>
<li>Display only properly tagged threads on the book page</li>
<li>Aggregate all threads in a more standard forum view.</li>
</ol>

<p>(We&#8217;ve discussed doing something similar for Social Source Commons, though haven&#8217;t yet)</p>

<h4>Book Scanning</h4>

<p>Ala <a href="http://www.delicious-monster.com/">Monster&#8217;s Delicious</a></p>

<p>What would be involved I wonder if writing a simple app/Firefox plugin to scan barcodes using something like an iSight or a CueCat, and have it post the data to a URL?  </p>

<h4>Blue Sky:  Peerflix for Books?</h4>

<p>Like <a href="http://www.bookcrossing.com/">Bookcrossing</a> for books you want to get back someday.</p>

<p><strong>update:</strong> Also <a href="http://www.stuffopolis.com/">Stuffopolis</a>, and <a href="http://beta.douban.com/">Douban</a></p>
]]></content:encoded>
			<wfw:commentRss>http://laughingmeme.org/2005/11/06/on-book-listing-services/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Interestingness, Community, Infrastructure, and the Academy</title>
		<link>http://laughingmeme.org/2005/10/28/interestingness-community-infrastructure-and-the-academy/</link>
		<comments>http://laughingmeme.org/2005/10/28/interestingness-community-infrastructure-and-the-academy/#comments</comments>
		<pubDate>Fri, 28 Oct 2005 23:15:00 +0000</pubDate>
		<dc:creator>Kellan</dc:creator>
				<category><![CDATA[centralization]]></category>
		<category><![CDATA[community]]></category>
		<category><![CDATA[decentralization]]></category>
		<category><![CDATA[flickr]]></category>
		<category><![CDATA[infrastructure]]></category>
		<category><![CDATA[Longer]]></category>
		<category><![CDATA[ownership]]></category>
		<category><![CDATA[participation]]></category>
		<category><![CDATA[reputation]]></category>
		<category><![CDATA[service]]></category>
		<category><![CDATA[social]]></category>
		<category><![CDATA[st]]></category>

		<guid isPermaLink="false">http://lm.quxx.info/?p=3069</guid>
		<description><![CDATA[In the &#8220;few thoughts, loosely joined&#8221; school, Anil&#8217;s recent post The Interesting Economy, got me revisiting worn grooves, thinking about community.

Anil posits that [Flickr's] users, creators of value and &#8220;interestingness&#8221; are getting short changed, or at least in the future our understanding of Flickr&#8217;s value proposition will lead us to conclude their users are being [...]]]></description>
			<content:encoded><![CDATA[<p>In the &#8220;few thoughts, loosely joined&#8221; school, Anil&#8217;s recent post <a href="http://www.dashes.com/anil/2005/10/25/the_interesting">The Interesting Economy</a>, got me revisiting worn grooves, thinking about <a href="http://laughingmeme.org/tag/community+service">community</a>.</p>

<p>Anil posits that <a href="http://flickr.com">Flickr&#8217;s</a> users, creators of value and &#8220;interestingness&#8221; are getting short changed, or at least in the future our understanding of Flickr&#8217;s value proposition will lead us to conclude their users are being short changed.  It&#8217;s part of an ongoing struggle to define our norms around participation, community, hosted tools, and ownership.  (On a side note, syndication can mix into this explosively, as with this <a href="http://www.meetup.com/boards/view/viewthread?thread=1451982&amp;pager.offset=0">thread last Summer on Meetup and EVDB</a>)</p>

<p>Actually Anil&#8217;s point was more interesting and more subtle, and worth reading, but as the signal <a href="http://technorati.com/search/dashes.com%2Fanil%2F2005%2F10%2F25%2Fthe_interesting">bounced around the echo chamber</a>, it degraded into &#8220;Hey,  <strong>I</strong> make Flickr interesting, pay <strong>me</strong>!&#8221;.  </p>

<p>I mean as software tends towards commodification (<a href="http://www.toolshed.com/blog/articles/2005/09/15/what-happens-when-t-approaches-0">as t approaches 0</a>), clearly Flickr derives its value from its participants, yes? </p>

<p>No.  Quite the opposite.  </p>

<p>I could replicate Flickr&#8217;s software (call it Flickah, a Boston Flickr derivative), give it away free, and still people would pay to be part of Flickr.  And in fact if I ever managed to grow the community to a fraction of Flickr&#8217;s size I&#8217;d be in trouble.  Flickr isn&#8217;t a photo hosting site, it&#8217;s a salon, and unsurprisingly value accumulates most quickly to the salon owner.  Value arises from the centralization.</p>

<h3>Community Service Models?</h3>

<p>So assuming software, what alternatives models exist for a community to host a service they find useful?  How do communities gain and support the values of centralization without handing over control?  A <a href="http://flickr.com">Flickr</a>, an <a href="http://upcoming.org">Upcoming</a>, or an <a href="http://audioscrobbler.com">Audioscrobbler</a> provide value in direct proportion to the size of the community, while the centralization of a Google Maps (or a Geocoder) makes an expensive resource affordable.  It&#8217;s a question I&#8217;ve been <a href="http://laughingmeme.org/articles/2004/08/31/community-services">wrestling with for a while</a> (<a href="http://laughingmeme.org/tag/community+service">community+service</a>).  And a question I asked at <a href="http://del.icio.us/tag/techdinner">techdinner</a> recently to surprising results.  </p>

<p>I expected to hear about grid computing, alternate economic models, p2p, etc.  Instead it was suggested that maintaining such a resource, or at least some subset of such community resources is the role of the Academy in the 21st century.  (less surprising given the presence of <a href="http://cyber.law.harvard.edu/home/">Berkman-ites</a> in the crowd)  </p>

<p>Perhaps not a Google Maps, or Flickr but maybe Harvard should be hosting the <a href="http://laughingmeme.org/articles/2003/01/04/a-definitive-uri-for-books">definitive URI for books</a>?  I was intrigued. (not to mention a little appalled given my stint doing tech for Higher Ed.)</p>

<p>Last thought, in the multitude responses to Anil, it was pointed out that interestingness can be gamed, as can most deployed reputation systems.  Yet eBay works?  How?  By making buy in into the system cost real cash, something <a href="http://blog.flickr.com/flickrblog/2005/10/your_photos_on_.html">Flickr print</a> is poised to do.  As a print service not terribly exciting, but what a great way to quantify interestingness.</p>
]]></content:encoded>
			<wfw:commentRss>http://laughingmeme.org/2005/10/28/interestingness-community-infrastructure-and-the-academy/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Money, Services, and the Changing Nature of Information Consumption</title>
		<link>http://laughingmeme.org/2004/09/20/money-services-and-the-changing-nature-of-information-consumption/</link>
		<comments>http://laughingmeme.org/2004/09/20/money-services-and-the-changing-nature-of-information-consumption/#comments</comments>
		<pubDate>Tue, 21 Sep 2004 04:54:00 +0000</pubDate>
		<dc:creator>Kellan</dc:creator>
				<category><![CDATA[community]]></category>
		<category><![CDATA[infrastructure]]></category>
		<category><![CDATA[Longer]]></category>
		<category><![CDATA[money]]></category>
		<category><![CDATA[service]]></category>
		<category><![CDATA[web2.0]]></category>

		<guid isPermaLink="false">http://lm.quxx.info/?p=913</guid>
		<description><![CDATA[
Les is wondering how
people are planning to finance and support services like Bloglines, flickr, and del.icio.us.  It&#8217;s a question that can
be addressed from two directions, both interesting.  You can frame the
question as, &#8220;What is the business model?&#8221;, or you can ask &#8220;How does a
community support a resource it finds useful?&#8221;.



One line that jumped [...]]]></description>
			<content:encoded><![CDATA[<p>
<a href="http://www.decafbad.com">Les</a> is wondering <a
href="http://www.decafbad.com/blog/2004/09/20/bootstrapping_out_into_open_space">how
people are planning to finance and support</a> services like <a
href="http://bloglines.com">Bloglines</a>, <a
href="http://flickr.com">flickr</a>, and <a
href="http://del.icio.us">del.icio.us</a>.  It&#8217;s a question that can
be addressed from two directions, both interesting.  You can frame the
question as, &#8220;What is the business model?&#8221;, or you can ask &#8220;How does a
community support a resource it finds useful?&#8221;.
</p>

<p><p>
One line that jumped out at me at me was
<blockquote>
I do appear to shell out at least $50 per month in internet services
beyond my bandwidth bill.
</blockquote></p>

<p>That got me thinking.  A few years ago this would have been an
unprecedentedly large amount. The idea that we were all going to get
rich selling online services was so firmly rejected that it became a
commonly accepted truism that &#8220;people won&#8217;t pay for things online&#8221;,
and yet, quietly, almost under the radar this seems to be changing.
</p>
<span id="more-913"></span>
<p>
Looking at my personal expenses online they can be broken down into:
paid content, online tools, online services, personal hosting, and net
facilitated donations.
</p>
<p>
<h3>Paid content</h3></p>

<p>I maintain a <a href="http://safari.oreilly.com/">Safari</a> account (which after several years of comp I
started paying for last year), I&#8217;m a <a href="http://www.zmag.org/sustainers/">Zmag sustainer</a>, and in the past I&#8217;ve
subscribed to several premium info sources.  90-95% of my daily
information consumption is network mediated &#8212; blogs, online newspapers,
email newsletters, and radio streams.  The bulk of the rest of it
comes from magazines. (which I either subscribe to, or pick up on the
newsstand depending on whether I want to financially support the
publisher).
</p>
<p>
Monthly cost: ~$15
</p>
<p>
<h3>Online tools</h3></p>

<p>I use a large number of online tools in my daily life, from the
ubiquitous Google, to the essential <a href="http://bloglines.com/">Bloglines</a>.  I currently
experimenting with using <a href="http://gmail.com">Gmail</a>, having tried nearly all of the webmail
products at one point or another over the years.  Currently I&#8217;m a light weight user
of <a href="http://usetasks.com/">Use Tasks</a>, for online managed tasks, and used to be a regular user
of the Anyday.com hosted pim service (I also was an Anyday developer)
</p>
<p>
For a while I was using <a href="http://allconsuming.net/">All Consuming</a> to facilitate my book reading
habit, and in its heyday I was a heavy user of <a href="http://www.backflip.com/">BackFlip</a>, a dotcom era
<a href="http://del.icio.us">del.icio.us</a>.  (I feel like I&#8217;m forgetting a handful of key tools here, I&#8217;ll have to back fill them later)
</p>
<p>
Beyond my text editor, most of my work (and most of my day) happens
within the confines of a Firefox window.  Currently the only tool I&#8217;m
paying for is <a href="http://usetasks.com/">Use Tasks</a>.
</p>
<p>
Monthly cost: ~$4
</p>
<p>
<h3>Online services</h3></p>

<p>Hard to split online services from online tools really, but I guess
I&#8217;m thinking of net facilitated services.  <a href="http://netflix.com">Netflix</a> is a good example,
as is the iTunes Music Store.  <a href="http://pobox.com">Pobox</a> mail forwarding is a slightly
murkier one.  Automated clipping services like <a
href="http://pubsub.com">PubSub</a> are largely indistinguishable from
tools.  You could argue that webmail, or a provider like Fastmail
should actually be in this category.
</p>
<p>
A chunk of the my monthly online spending goes to this category,
mostly Netflix, with handful of change going to various more obscure services.
</p>
<p>
Monthly cost: ~$27
</p>
<p>
<h3>Personal Hosting</h3></p>

<p>The cost of maintaining an online presence.  My primary web and email
hosting are covered as a side benefit of some of the tech activism I
do, but I do pay for a hosted dev box (a VLS really), and have been
contemplating setting up a new solution for email.
</p>
<p>
Monthly cost: $10
</p>
<p>
<h3>Donations</h3></p>

<p>I make both regular and irregular donations to a number of online
services.  Some of the donations are towards tech activist
projects like <a href="http://riseup.net">Riseup</a>, or <a href="http://activista.org">Activista</a>.  Some are for
funding drives for web commons projects (e.g. <a href="http://wikipedia.org">Wikipedia</a>, or <a href="http://www.mirrorproject.com/">Mirror Project</a>), or
blogger bailouts (e.g. the <a href="http://daringfireball.net/">Daring Fireball</a> pledge drive)
</p>
<p>
Of all the discussed categories, this is my largest expense.
</p>
<p>
Monthly cost: ~$35
</p>
<p>
<h3>Running the Numbers</h3>
Works out to something like $90/month above basic connectivity. (with
the single largest line item being Netflix, so embarrassing, I really
need to learn how to use Bittorrent)  Might sound like a lot, but if
you calculate that I spend anywhere from 10-14 hours a day online,
thats about $0.25 an hour for a service that provides personal and
work communication, information and professional development, news and
entertainment.  Its significantly less then I spend monthly on food,
rent or transportation, and yet I&#8217;d say its at least as fundamental to
me as any of those.  It&#8217;s about what I spend on books (a bit less), but
given I&#8217;m not in school currently that isn&#8217;t a good indicator.
</p>
<p>
<h3>Some obvious places to be spending more</h3></p>

<p>It is odd to want to spend more, and frankly, I don&#8217;t.  In particular
the problem in spending more on services means you need to either
figure out how to have services swell, and shrink with changing
income, or you get stuck having raised the minimum you can live on,
which is a dangerous relationship to get into with capitalism.
</p>
<p>
Still, I really should be spending another $5-$10/monthly on personal hosting
in order to get a more functional email setup, as a person who lives
largely online spending so little to maintain the presence
seems&#8230;.off.
</p>
<p>
I <b>really</b> should be paying more for online tools.  Another
$5 monthly for Bloglines at least in a no brainer.  Some amount of
money to a meaningful and useful social software/collaboration tool is
burning a hole in my pocket.  And a good hosted pim/tasks/reminders
service still needs to get (re-)built.
</p>
<p>
Noticeably absent from the list are any self supporting community or
discussion spaces.  I&#8217;m not sure I believe in virtual communities,
which doesn&#8217;t seem to stop me from being involved in a ridiculously
large number of them.  Most exist in a nebulous hybrid mailing
list/forum/irc space, none of which ever seems to get paid for, and
none of which ever seem to improve and become more useful.  I know
several people, like <a href="http://sedesdraconis.com">my brother</a>, who participate in incredibly
specialized and erudite online communities.  A way of striking a
balance between getting the right people into the community, and
supporting growth needs to found.
</p>
<p>
Lastly independent media is still doing a lousy job of developing
models to deliver information both locally and globally using the
internet, and doing an even worse job of figuring out how to use the
net to engage meaningful participation and support.  Right now most of
my net mediated media consumption is filtered corporate media, the
filters are important, interesting, and useful, to a self sustaining
alternative it ain&#8217;t.
</p>
<p>
I&#8217;ve totally failed to answer Les&#8217; question, but I thought it might be
worth re-examining our received wisdom about people&#8217;s online spending
habits, or at least mine.
</p>
<p>
Doing some rough calculations based on current income levels, amount of value I&#8217;m deriving or wish to be deriving, and
looking at the above list, I&#8217;d say there is about $150-$250/monthly
that I should be spending in one of these 5 categories that I&#8217;m not
for lack of a meaningful place to spend it.
</p>
<p>
That said, as we move towards more and more hosted/online services and
tools, its going to become increasingly important to develop new models
of engagement, and transparency.  What do the ideals of free software
mean in the context of a hosted service?  How do I fork if I don&#8217;t
like where things are going?  What is the role of collective ownership
in these projects, or is it assumed I&#8217;m simply a consumer?  Thats a whole other essay, and one I&#8217;m too tired to start right now.<br />
</p>
<p>
And TeleDyn has an excellent essay <a href="http://www.teledyn.com/mt/archives/002126.html">Living with Webservices</a>, which seems to be closely related in ways my brain is totally refusing to articulate right now.  Good night.
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://laughingmeme.org/2004/09/20/money-services-and-the-changing-nature-of-information-consumption/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL, and the CASE for Class Table Inheritance</title>
		<link>http://laughingmeme.org/2004/08/14/mysql-and-the-case-for-class-table-inheritance/</link>
		<comments>http://laughingmeme.org/2004/08/14/mysql-and-the-case-for-class-table-inheritance/#comments</comments>
		<pubDate>Sun, 15 Aug 2004 01:08:00 +0000</pubDate>
		<dc:creator>Kellan</dc:creator>
				<category><![CDATA[case]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[eaa]]></category>
		<category><![CDATA[enterprise]]></category>
		<category><![CDATA[Longer]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[oop]]></category>
		<category><![CDATA[patterns]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://lm.quxx.info/?p=883</guid>
		<description><![CDATA[
At work we&#8217;re using Class Table Inheritance to model the core data structures of our as yet nameless open source CRM. (actually it has a code name, but I don&#8217;t like it, so we&#8217;ll pretend it&#8217;s nameless)  



This week as I learned both the name of this pattern, and the SQL to implement it [...]]]></description>
			<content:encoded><![CDATA[<p>
At <a href="http://groundspring.org">work</a> we&#8217;re using <a href="http://martinfowler.com/eaaCatalog/classTableInheritance.html">Class Table Inheritance</a> to model the core data structures of our as yet nameless open source <acronym title="Community Relationship Management">CRM</acronym>. (actually it has a code name, but I don&#8217;t like it, so we&#8217;ll pretend it&#8217;s nameless)  
</p>

<p><p>
This week as I learned both the name of this pattern, and the SQL to implement it efficiently in MySQL I thought I&#8217;d share some notes on what we&#8217;ve come up with.
</p>
<span id="more-883"></span>
<p>
<h3>Class Table Inheritance</h3>
<acronym title="Class Table Inheritance">CTI</acronym> is a pattern where your schema  hews closely to the your class hierarchy &#8212; you have a table for each class, and object attributes are stored as columns in the table for that class.  This is as opposed to <a href="http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html">Single Table Inheritance</a>, which stores all attributes for every member of an inheritance tree in a single table, or <a href="http://www.martinfowler.com/eaaCatalog/concreteTableInheritance.html">Concrete Table Inheritance</a> which duplicates the inherited fields to each table.
</p>
<p>
We&#8217;re using CTI for a number of reasons, some excellent, and some because that is how our brains work.  One key benefit is we get the ability to operate on heterogenous collections of object. (i.e. display a sorted list of contact objects irrespective of whether they are individuals, organizations, etc.)  The fact that something as fundamental as polymorphism can be difficult to accomplish using other O/R techniques hilights the general difficulty and <a href="http://www.google.com/search?q=impedance+mismatch" title="6 of the first 10 results are about O/R">impedance mismatch</a> of object to relational mapping.
</p>
<p>
There are, however a few challenges involved. 
</p>
<p>
<h3>The Model</h3>
But quickly a trivial mock up of the data model to give us something to play with.  In this model we have 3 classes, a base Contact class, and 2 types of contacts Individual and Organization which inherit from Contact.  In the database we model this as a Contact table, with a primary id, and any fields which the Contact the parent class provides.  Individual and Organization each get their own table, with class specific attributes, plus the primary id from Contact which is both the primary id, and a foreign key into Contact.  For every contact stored in the database there is a record in the Contact table, and a record in either Individual or Organization.
</p>
<p>
<img src="http://laughingmeme.org/img/simple_contact_model.gif" />
</p>
<p>
<h3>Challenge 1:</h3>
How do you retrieve your data now that it is broken across multiple tables?  The obvious (and obviously wrong) solution would be to first select against the Contact table, examine the resulting data, and select against the appropriate children tables. (remember this example is a drastically simplified data model)
</p>
<p>
<h3>Solution 1:</h3>
My current solution is to do a 3 way left outer join, and then instantiate the objects out of fields which aren&#8217;t null.  It can look a bit ugly with large numbers of columns, but is actually pretty simple, and initial benchmarks against a test data set of 1.3 million records suggests it scales nicely.</p>

<pre>
SELECT 
  c.id as id, c.contactType,
  i.firstName, i.lastName,
  o.name as orgName
FROM
  Contact as c
LEFT JOIN Individual as i ON i.id = c.id 
LEFT JOIN Organization as o ON o.id = c.id
</pre>

<p>(And it&#8217;s pretty easy to coax the necessary SQL out of our modified version of <a href="http://pear.php.net/package/DB_DataObject">DB_DataObject</a>. I&#8217;ll demonstrate that in a future entry)
</p>
<p>
<h3>Challenge 2:</h3>
One of the good reasons (in fact the only concrete one I&#8217;ve given you) to go with CTI and its potential added complexity is the desire to sort a mixed list of contact types.   But what do you do when you want to sort on an amorphous concept like &#8220;Name&#8221;?  Individual might sort by &#8220;Lastname, Firstname&#8221;, while we just use &#8220;orgName&#8221; for an organization.  Where is our polymorphism now?
</p>
<p>
One solution would be select all known records, and do sorting and slicing at the application level.  (This is so wrong it makes my head hurt)  Another solution would be store a field like &#8220;sortName&#8221; on Contact, which you could calculate and save on inserts and updates.  This is on the right track.
</p>
<p>
<h3>Solution 2:</h3>
The solution (which <a href="http://blogs.onenw.org/carl">Carl</a> clued me into while we waited to get into the zoo), is to use the <a href="http://dev.mysql.com/doc/mysql/en/Control_flow_functions.html">SQL CASE statement</a> to calculate &#8220;sortName&#8221; on the fly.  Below is our SQL from below with the new logic in green.</p>

<pre>
SELECT 
  c.id as id, c.contactType,
  i.firstName, i.lastName,
  o.name as orgName<span style="color:green;">,
CASE 
 WHEN c.contactType = 'Individual' THEN CONCAT(i.lastName, i.firstName)
 WHEN c.contactType = 'Organization' THEN o.name
END as sortName</span>
FROM
  Contact as c
LEFT JOIN Individual as i ON i.id = c.id 
LEFT JOIN Organization as o ON o.id = c.id
<span style="color:green;">ORDER by sortName</span>
</pre>

<p></p>
<p>
This simply adds a switch statement to your field list conditionally setting the value of sortName.
</p>
<p>
There is nothing quite so satisfying as finding the right tool for the right job.  I&#8217;m currently totally in love with the CASE statement, and think everyone should know about it. (hence this bit of evangelism)
</p>
<p>
Tip: don&#8217;t forget that &#8216;,&#8217; after orgName, I keep forgetting it and wondering why my SQL isn&#8217;t working.
</p>
<p>
So concludes today&#8217;s edition of &#8220;Enterprise Development with MySQL&#8221; (&#8220;Kellan Learns SQL&#8221; didn&#8217;t sound as impressive).  In the near future I hope to get a chance to write up some of the PHP libs we&#8217;ve been building/modifying to support object rich web development techniques, completing the picture. (<acronym title="Objects Linux Apache MySQL PHP">OLamp</acronym> anyone?)
</p>
<p>
<h3>Mixing Metaphors</h3>
Single, and Concrete <acronym title="Table Inheritance">TI</acronym> both have their places, and the good news is you can mix these patterns without much difficulty.  Still I&#8217;m happy with both the flexibility and &#8220;OO-ness&#8221; of Concrete Table Inheritance, and once again impressed by the speed, and power of MySQL. (N.B. we&#8217;re targeting 4.1.x, but these above examples all work with 4.0.16 and 4.0.20)
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://laughingmeme.org/2004/08/14/mysql-and-the-case-for-class-table-inheritance/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Maintaining Date/Timezone Sanity with DateTime.pm and Class::DBI</title>
		<link>http://laughingmeme.org/2003/09/25/maintaining-datetimezone-sanity-with-datetimepm-and-classdbi/</link>
		<comments>http://laughingmeme.org/2003/09/25/maintaining-datetimezone-sanity-with-datetimepm-and-classdbi/#comments</comments>
		<pubDate>Thu, 25 Sep 2003 23:33:00 +0000</pubDate>
		<dc:creator>Kellan</dc:creator>
				<category><![CDATA[calendaring]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[datetime]]></category>
		<category><![CDATA[Longer]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[timezone]]></category>

		<guid isPermaLink="false">http://lm.quxx.info/?p=601</guid>
		<description><![CDATA[
Calendaring can be a fraught and tricky business.  Probably doesn&#8217;t compare to building software to do precise robotic control of surgical tools (though I have a friend who worked for a summer putting Windows into operating rooms), or high volume real time transaction management, but its does have its pitfalls and tricks.



The Case of [...]]]></description>
			<content:encoded><![CDATA[<p>
Calendaring can be a fraught and tricky business.  Probably doesn&#8217;t compare to building software to do precise robotic control of surgical tools (though I have a friend who worked for a summer putting Windows into operating rooms), or high volume real time transaction management, but its does have its pitfalls and tricks.
</p>

<p><p>
<h3>The Case of the Missing Timezone</h3></p>

<p>A classic mistake when one sets out to write calendar software, particularly web calendar software, is to ignore timezones.  &#8220;Now&#8221; is treated as the current time on the web server, new events are added to the database without reference to the timezone of their creator.  And amazingly, by and large this will work, for a while.  Often your first set of users will be in your timezone, or thereabouts, perhaps you aren&#8217;t displaying hours, so it&#8217;s just a few hours early in the morning, and late at night when people notice your calendar is displaying the wrong date.
</p>
<p>
Problems start to crop up as your audience becomes more international, or you start trying to add more time sensitive services.  So you try to retro-fit timezones, add them on.  And now you&#8217;re living in a world of pain.
</p>
<span id="more-601"></span>
<p>
<h3>A Not So Hypothetical Example</h3></p>

<p>Say you&#8217;re running a web calendar off a server in your closest in Massachusetts, in a timezone affectionately if rather unprecisely known as Eastern time.  You have a user in Sydney who has been happily adding events, timezone free.  Now if you wanted to display the correct date for a given event to your users in Sydney you need to calculate the offset between the two locations.  Simple enough?  Is MA observing day light savings?  Is Sydney?  How about when the event was added? Any one of those questions can be annoying to answer, getting all 3 right, and collated&#8230; well trust me, it gets ugly quick.
</p>
<p>
<h3>Yet Another Problem</h3></p>

<p>What happens when you move that server out of your closest to a colo off the coast of England?  All of a sudden you&#8217;ve switched from adding events in &#8220;Eastern&#8221; time to some British local time.  How do you know how to calculate the offsets now?  One solution I&#8217;ve seen (when I was working on a website for a certain very large PDA manufacturer who shall rename nameless) was to add a switch into the code:
<pre>
 if (date &lt; kDayWeMovedToColo) { ... } else { ... }
</pre>
</p>
<p>
This problem can bite you even if you were clever enough to get your users setup with timezones from day one.
</p>
<p>
<h3>A Simple Solution</h3></p>

<p>After all that hand wringing, and doom saying, you&#8217;ll be happy to know that the solution is simple.  Store all your dates in UTC (sometimes called GMT, sometimes called Zulu time); a zero offset time that doesn&#8217;t observe day light savings.  As added bonus a number of languages even support converting to GMT time, though many of them are broken. (PHP&#8217;s are, rumor has it so are C#&#8217;s, Java got it wrong for its first 3-4 versions)
</p>
<p>
<h3>Some Code!</h3></p>

<p>As Perl hackers we&#8217;ve got an advantage, we&#8217;ve got the best date/time library in any language I&#8217;ve ever seen, <a href="http://perl-date-time.sf.net">DateTime.pm</a>, which just happens to have the most complete TimeZone implementation you&#8217;ve ever dreamed of. (if you&#8217;re a calendar geek, and dream about this stuff)
</p>
<p>
And we&#8217;ve got Class::DBI, which as much as I&#8217;ve said some nasty things about it, has a few nice features in the db-to-object mapping sphere.
</p>
<p>
I use a simple adapter class to handle my conversions to and from GMT, but a more proficient CDBI wizard could probably replace my class with a couple of code refs.
</p>
<p>
In your Class::DBI definitions you would add some code like:</p>

<pre>

MyEvent->has_a(
   start_date => 'DateAdapater',
   inflate => sub { DateAdapter->inflate(shift) },
   deflate => 'deflate'
);

</pre>

<p>Where DateApapater looks like:</p>

<pre>

package DateAdapater;
use base qw(DateTime);
# this is a DateTime::Format::DBI
# which I haven't figured out how to combine with cdbi
#
use DateTime::Format::MySQL; 

sub inflate {
  my ($class, $value) = @_;
   my $dt = $class->parse($value);
   # starts in 'floating' tz
   $dt->set_time_zone('UTC');
   return bless $dt, $class;
}

sub deflate {
    my $dt = shift;
    # convert to UTC
    $dt->set_time_zone('UTC');
    return DateTime::Format::MySQL->format_datetime($dt);
}

sub parse {
    my ($class, $value) = @_;
    my $dt = eval { return DateTime::Format::MySQL->parse_datetime($value); };
    if ($dt) { return $dt; }
    else {
       return DateTime->new(year => 1970);
    }
}

</pre>

<p></p>
<p>
<h3>A Few Things to Note</h3></p>

<p>MySQL&#8217;s datetime fields don&#8217;t maintain a concept of timezone, so DT creates them with a floating timezone.  Therefore casting them to UTC doesn&#8217;t change their settings for year, month, hour, etc.  DateTime objects coming in will presumably be set in the user&#8217;s timezone, therefore casting them to UTC will change their year, month, hour, etc fields, but the object will still refer to the exact same instant in time.
</p>
<p>
Lastly, you know you&#8217;ve been hacking Unix dates too long when you&#8217;re idea of an error message is to return some day in 1970.
</p>
<p>
(Also it&#8217;s strikingly odd how much longer it takes to write a blog entry about some code, then to just write the code.  Noticed it for both this, and the timezone selector.   Need a code to blog adapter.)
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://laughingmeme.org/2003/09/25/maintaining-datetimezone-sanity-with-datetimepm-and-classdbi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Once more into the Breach:  Calendars, Events, and RSS</title>
		<link>http://laughingmeme.org/2003/09/22/once-more-into-the-breach-calendars-events-and-rss/</link>
		<comments>http://laughingmeme.org/2003/09/22/once-more-into-the-breach-calendars-events-and-rss/#comments</comments>
		<pubDate>Mon, 22 Sep 2003 08:39:00 +0000</pubDate>
		<dc:creator>Kellan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[calendaring]]></category>
		<category><![CDATA[Longer]]></category>
		<category><![CDATA[ozzie]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[state.of.the.art]]></category>
		<category><![CDATA[syndication]]></category>
		<category><![CDATA[udell]]></category>
		<category><![CDATA[upcoming]]></category>

		<guid isPermaLink="false">http://lm.quxx.info/?p=594</guid>
		<description><![CDATA[
The launch of Upcoming.org seems to have rekindled some interest in calendaring standards, stoked by a post from Ray Ozzie, and the Calendar Fiasco, by Jon Udell. (also see eric&#8217;s collection of upcoming.org links)






Jon is right, the state of calendaring standards is a fiasco.  There are a couple of reasons for that.  I [...]]]></description>
			<content:encoded><![CDATA[<p>
The launch of <a href="http://www.upcoming.org">Upcoming.org</a> seems to have rekindled some interest in calendaring standards, stoked by <a href="http://www.ozzie.net/blog/2003/09/20.html#a109">a post from Ray Ozzie</a>, and <a href="http://weblog.infoworld.com/udell/2003/09/21.html#a801">the Calendar Fiasco, by Jon Udell</a>. (also see eric&#8217;s <a href="http://snowdeal.org/section/ex_machina/archives/2003_09_01_index.html#106415003490015283">collection of upcoming.org links</a>)
</p>

<p><p>
<span id="more-594"></span>
</p>
<p>
Jon is right, the state of calendaring standards is a fiasco.  There are a couple of reasons for that.  I think the two key factors have been:
<ul>
<li>the <a href="http://calsch.org">CALSCH working group</a>, like many people, tried to solve the scheduling problem, with business use as the target use case, versus just building some basic calendar building blocks.  Despite this focus <a href="http://www.ietf.org/rfc/rfc2445.txt">iCalendar</a> still works pretty well as a basic building block.  However the 7 years since it was released have fundamentally changed the landscape (like the standardization on XML), changes CALSCH hasn&#8217;t been able to keep up with or respond to.
</li>
<li>
Microsoft.  Aren&#8217;t they always the problem?  A huge amount of time, energy, effort and tears has been spent trying to build a calendar tools that work with Outlook, and Exchange.  Its a nightmare, even when MS supports standards, they do it brokenly, and the Outlook/Exchange combo has been specifically engineered to look out alternatives.  Anyone who navigates the treacherous waters of MAPI, and Outlook&#8217;s various modes feel entitled to be paid for their efforts, and rightly so.
</li>
</ul>
<p>
<h3>Apple, a Hope Which Fell Short</h3></p>

<p>Apple really did a great job of reviving interesting in the iCalendar spec,  and calendaring, and calendaring standards in general.  They combined a pretty interface with a modern implementation of the standard, and a good enough, worse is better network protocol that worked over HTTP, and integrated with the Web, and web services.
</p>
<p>
However, <a href="http://laughingmeme.org/archives/000162.html#000162">they pulled up short</a>.  Where they could have pushed forward and set a quick and dirty standard for calendar sharing over HTTP that bypassed the byzantine, perpetually under construction CAP, they failed to implement a real, two way, pub-sub protocol.  Presumably to drive people to use their .Mac premium service, and iSync application.  Disappointing really, a very understandable, uninspired, profit driven decision.  I&#8217;m sure Microsoft would be proud.
</p>
<p>
<h3>Ray&#8217;s Questions</h3></p>

<p>Ray asked a few questions in post, probably rhetorical, and designed to draw attention to the daunting absence of good work being done in this field.  However I&#8217;ll take a stab at answersing them. (oh, looks like <a href="http://planb.nicecupoftea.org/archives/000072.html">Libby answered them as well</a>)</p>

<ul>

<li>Has a method to embed iCal into XML ever been approved or agreed upon?  If so, let me refer to it as xCal.
<p>
Yes, xCal existed in <a href="http://www.ietf.org/proceedings/02mar/I-D/draft-ietf-calsch-many-xcal-01.txt">draft form</a>.  Calsch decided to let it die, according to Doug Royer, <a href="http://laughingmeme.org/archives/000091.html#comments">&#8220;because there is no reason to have 2 standards for the same thing.&#8221;</a>  I&#8217;m inclined to also point to an certain hostility towards things web, and XML that I&#8217;ve seen over the years on the Calsch mailing list.  There was even a <a href="http://laughingmeme.org/archives/000238.html#000238">parser for it</a>, for a while. 
</p>
</li>

<li> Has a method to embed xCal events/etc ever been suggested as a viable item type for RSS?
<p>
The <a href="http://www.purl.org/rss/1.0/modules/event/">mod_event</a> module was proposed in May, 2001, and is a simple, straightforward syntax for marking up an RSS feed to indicate event information.  Many peoples&#8217; reaction to seeing mod_event is to start trying to lard in the iCal syntax.  I think this misses the point of an RSS event feed, a need which, in conjunction with other RSS modules, the mod_event serves very well.
</p>
</li>

<li> Has anyone built websites that publish venues&#8217; event calendars in such a format for subscription/aggregation?
<p>
<a href="http://protest.net/about_protest_net.html">Protest.net</a> does, and has for quite a while.  I know a handful of other projects that are in prototype or various stages of completion.
</p>

<li> Has anyone built an Outlook or Notes adapter that publishes personal or team calendars to such a feed, OR</li>
<li>
Has anyone built an RSS aggregator that can aggregate multiple calendar RSS feeds into a desktop or web calendar UI?
<p>
Not that I know of.  But remind me to get back to the question of web calendar UIs.
</p>
<p>
<a href="http://magpierss.sf.net">Magpie</a> does include basic support for  mod_event, and I&#8217;ve built a couple of scripts using <a href="http://search.cpan.org/dist/XML-RSS">XML::RSS</a> and <a href="http://search.cpan.org/dist/DateTime-Format-W3CDTF/">DateTime::Format::W3CDTF</a>.
</p>
</li>
<li>Has anyone built an RSS aggregator that can aggregate multiple calendar RSS feeds into your Outlook or Notes personal calendar?
<p>
See my earlier point about Microsoft being one of the two key factors behind the calendar fiasco.
</p>
</li>
</ul>

<p><p>
<h3>There Are Other Hammers</h3></p>

<p>That said, I don&#8217;t think RSS is a particularly natural fit as transport for <em>all</em> calendaring and scheduling information.  As Jon said, <a href="
http://weblog.infoworld.com/udell/2003/08/08.html#a773">&#8220;Stop punishing RSS for its success&#8221;</a>.  RSS, and an RSS event feed works wonderfully well for public event calendars, and as a notification feed.  It does not, and will not, map well to representing someone&#8217;s personal calendar in all its, repeating, complex, conditional, glory.
</p>
<p>
<a name="webcalui"></a>
<h3>A Brief Note on Web UIs for Calendars</h3>
Close your eyes, visualize a calendar, what do you see?  You see a page with rows and rows of boxes, a wall calendar, a month-at-a-time view.  Paper is wonderful medium, but it does have some limitations.  Its poor at interactivity, especially delivering context sensitive content based on the current date.  The wall calendar is a clever hack to get around this.  On the web we aren&#8217;t strapped with papers limitations, don&#8217;t translate medium specific hacks onto the web, okay?
</p>
<p>
<h3>Next Steps?</h3>
Calendar standards really lost an opportunity when iCal.app didn&#8217;t go far enough, a standards based calendar app would have catapulted the whole problem forward.  Maybe <a href="http://www.osafoundation.org/">Chandler</a> will present another opportunity.  Outlook certainly is never going be where innovation happens, and my understanding is that the iCal.app team are working on other projects, <a href="http://www.mozilla.org/projects/calendar/">the Mozilla calendar project</a> has stalled multiple times, and looks primed for another stall, so in the meantime the Web is our innovation space.
</p>
<p>
<h3>Event Auto-discovery</h3>
I think one of the most useful interesting things we could do would be to start standardizing on an event auto-discovery standard, modeled on the <a href="http://diveintomark.org/archives/2002/06/02/important_change_to_the_link_tag">RSS auto-discovery standard.</a>  I&#8217;ll post more on this soon.
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://laughingmeme.org/2003/09/22/once-more-into-the-breach-calendars-events-and-rss/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Few Tips for Writing Useful Libraries in PHP</title>
		<link>http://laughingmeme.org/2003/08/05/a-few-tips-for-writing-useful-libraries-in-php/</link>
		<comments>http://laughingmeme.org/2003/08/05/a-few-tips-for-writing-useful-libraries-in-php/#comments</comments>
		<pubDate>Wed, 06 Aug 2003 05:30:00 +0000</pubDate>
		<dc:creator>Kellan</dc:creator>
				<category><![CDATA[design]]></category>
		<category><![CDATA[essay]]></category>
		<category><![CDATA[libraries]]></category>
		<category><![CDATA[Longer]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://lm.quxx.info/?p=547</guid>
		<description><![CDATA[
(A month or more ago I started writing a blog entry, which became so long I decided to turn it into an article.  However life has gotten away from me, and I don&#8217;t know when I&#8217;ll get around to doing the clean up to write that article, so here it is.) 



Zend has an [...]]]></description>
			<content:encoded><![CDATA[<p>
(A month or more ago I started writing a blog entry, which became so long I decided to turn it into an article.  However life has gotten away from me, and I don&#8217;t know when I&#8217;ll get around to doing the clean up to write that article, so here it is.) 
</p>

<p><p>
Zend has an article <a href="http://www.zend.com/zend/tut/tutorial_moran.php">Writing Libraries in PHP</a> (you&#8217;ll have to trust me on the title, as their CMS seems to be broken). It is a good article as far as it goes, but I think the title over sells the article. Which is a shame, because of all of PHP&#8217;s many faults and quirks, perhaps it&#8217;s most telling (and most crippling) is a cultural one, PHP programmers write applications, not libraries. I don&#8217;t consider myself a PHP guru, being more comfortable in Perl and Java, but I do consider myself a good software developer, and so I&#8217;ll try to capture a few of the lesson I learned when developing <a href="http://magpierss.sf.net">MagpieRSS</a>, my PHP library for parsing RSS. 
</p>
<p>
    First, lets identify the problem. <h3>PHP, its a cultural thang</h3> Python positions itself as distinct from Perl with the slogan &#8220;batteries included.&#8221; Whether you feel that is accurate is irrelevant, because PHP is the real &#8220;batteries included&#8221; language. PHP bend so far in this direction, you&#8217;ll find functions like <code>pfpro<em>process</code> for talking to the &#8220;Versign Payflow Pro&#8221; service in the core language. Besides the patent of absurdity of this, its also created a culture that sees only 2 forms of PHP, core language extensions, and applications. 
</p>
<p>
<h3>Why is this a problem?</h3> So whats wrong with that? Code written for a particular application is often very difficult to reuse. Code reuse is one of the holy grails of open source, its how you leverage all the vaunted of benefits of &#8220;lots of eyes make bugs shallow&#8221;, and patches, and shared development. Code reuse also reduces development time, and bugs in applications that reuse the code. Unless of course to reuse your code I&#8217;ve had to dig into it, hacking it to suit my purposes, in which case I&#8217;ve probably spent more time, and introduced bugs into code I only half understand. I&#8217;ll be tempted to throw it away and start over, splitting time and development energy over multiple solutions rather then improving just one. 
</p>
<p>
<h3>So what is the difference between an application and a library?</h3> A little over a year ago, I was wanting to syndicate the events from <a href="http://protest.net">Protest.net</a> to a website published with PHP. As we generate <a href="http://protest.net/about_protest_net.html">RSS feeds for our calendars</a> I thought this would be easy. I went looking for a tool to recomend for the website to use, and I came up short. I found many, many, many PHP applications that took an RSS file, and generated HTML, these were applications for displaying RSS as HTML, but they weren&#8217;t libraries, they tried to do it all, and therefore couldn&#8217;t integrate with this website which had its own way of wanting to use RSS and PHP. A key characteristic of an application versus a library is how many problem it tries to solve; solve too many problems in a single layer and you lose flexibility. 
</p>
<p>
<h3>Tips for writing PHP libraries</h3> A few of these tips are theoretical, some are very concrete. Some I&#8217;m not thrilled with but they&#8217;re are the best solution I have to date. If you disagree, or have suggestions, please add them. 
<ol>
    <li>
        Do one thing, do it well 
        <p>
            You aren&#8217;t building a CMS, you aren&#8217;t building an interface, you&#8217;re trying to support other people in those tasks. 
        </p>
    </li>
    <li>
        Don&#8217;t echo or print content, return it! 
        <p>
            This is one of the key problems you see in much PHP code. If you echo out the results of some function directly to the web page, when I&#8217;m trying to use your code to write the output to a file, or run it in a testing environment I&#8217;m going to be frustrated. What if I&#8217;m trying to build an internationalized app, and you&#8217;re echo&#8217;ing out English? Don&#8217;t assume you know in what context your code will be run, return objects, or strings. <b>Don&#8217;t print.</b> 
        </p>
    </li>
    <li>
        Return data, strings, or objects, not HTML.
        <p>
        The corollary to the don&#8217;t print rule, and abused nearly as often, if not more so, is don&#8217;t return formatted  HTML. (unless you are writing an HTML widget, in which case that is all you should be doing)    If you return the results of your function as a formatted table, it might be pretty and easy to use, but I can&#8217;t pass those results to another function to sort them, or integrate it with my pure CSS layout.  It is really common to see code like <code>echo('&lt;font color="red"&gt;$error</em>msg&lt;/font&gt;');</code>.  Don&#8217;t do it. 
        </p>
    </li>
    <li>
        Allow intelligent error handling 
        <p>
            One of the most common reasons a library will print content directly to the web page is on encountering an error. This makes makes it very difficult for the application using your library to figure out what happened and respond accordingly. Don&#8217;t assume your code is the most important part of someone&#8217;s application, maybe they don&#8217;t care if you failed? Or maybe they care a whole bunch, and want to totally change what they were doing? 
        </p>
    </li>
    <li>
        Use an error() function 
        <p>
            I&#8217;m still struggling to come up with the best way to do error handling as a library in PHP. Once PHP5 arrives and we have real exceptions, much of this will be irrelevant. In the meantime. 
        </p>
        <p>
            What I do with Magpie is provide an <code>error()</code> method for each part of the application. 
        </p>
        <p>
            <code>error()</code> takes a message, and an optional error level, appends <code>php<em>errormsg</code> if <code>track</em>errors</code> is on, prepends a string identifying the library that is throwing the error, sets up a package/class variable with the resulting error, and, if debugging is on, triggers an error message. 
        </p>
        <p>
            Why is this good? Code using your library has easy way to check for error conditions (<code>if ($lib->error) { ... do error handling .. } </code> ), error messages are very complete, and consistently formatted, when someone is developing with your app they can easily find out what went wrong based on their <code>php.ini</code> settings, and lastly if someone does need to hack or override your chosen behaviour, they only have to do it once. 
        </p>
    </li>
    <li>
        Allow simple configuration 
        <p>
            If you don&#8217;t provide a way for people to change the behaviour of your library, then you force them to hack on it. If someone has had to go into your code and hack on it, then they&#8217;ll be resistant to upgrading as new versions become available, and any changes they make that you want to roll back into the core will be more difficult to apply. 
        </p>
        <p>
            Configuration can be parameters passed to a class&#8217;s constructor, set/get methods called later, or constants defined at a runtime. (more on this later) 
        </p>
    </li>
    <li>
        Choose intelligent defaults 
        <p>
            This is true with any application, or library in any environment. It is particular true with PHP where a great number of your users aren&#8217;t programmers by profession or choice, but just trying to get something working to support their real work. 
        </p>
    </li>
    <li>
        Break your library into multiple files 
        <p>
            One way to simplify your code, and encourage encapsulation and reuse is to split your library into logically sub pieces, and move these pieces into their own files. 
        </p>
        <p>
            Something I didn&#8217;t do with Magpie, but wish I had was store all the files in a lib/ directory. Having all your files in a single directory makes it much easier for people to install your code. (When it came time to bundle an external library, a modified version of Snoopy, I had learned, and put it in extlib/ ) 
        </p>
        <p>
            This tip is really an excuse for the next tip. 
        </p>
    </li>
    <li>
        Don&#8217;t assume everyone&#8217;s PHP looks like yours.
        <p>
            PHP has a lot of configuration options, runs on dozens of different platforms, and is used in all sorts of different ways.  Keep that in mind when writing a library.
        </p>
    </li>
    <li>
        If you have multiple files, allow your user to define a base dir. (aka don&#8217;t make assumptions #1)
        <p>
            This is trick from Smarty that was pointed out to me. 
        </p>
        <p>
            If you have a core library file (e.g. class.inc) that will be including support files don&#8217;t make assumptions about the PHP include path on the various machines where your library will be installed. 
        </p>
        <p>
            For example assume there is a constant MAGPIE<em>DIR defined then you can include the support libraries with: <pre class="code">
require</em>once( MAGPIE<em>DIR . 'rss</em>parse.inc' );
require<em>once( MAGPIE</em>DIR . 'rss<em>cache.inc' );
</pre> This allows code that uses your library to inform your code about the local environment, rather then forcing your client code into contortion to match your expectation of how a PHP install should work. 
        </p>
        <p>
            MAGPIE</em>DIR (or YOUR<em>LIBRARY</em>DIR) might be set up with code like: <pre class="code">
if (!defined('DIR<em>SEP')) {
    define('DIR</em>SEP', DIRECTORY_SEPARATOR);
}</p>

<p>if (!defined('MAGPIE<em>DIR')) {
    define('MAGPIE</em>DIR', dirname(<strong>FILE</strong>) . DIR_SEP);
}
</pre> </p>

<p>Which fill set the MAGPIE_DIR to the current directory (useful as &#8216;.&#8217; isn&#8217;t always in the include path) unless you override it with a statement like (for example): </p>

<pre class="code">
define('MAGPIE_DIR', '../../magpiefiles');
</pre> 

<pre><code>    &lt;/p&gt;
    &lt;p&gt;
        (More on using constants for configuration later.) 
    &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
    If you're using a semi-obscure PHP extension test that it has been compiled in.  (aka don't make assumptions #2)
    &lt;p&gt;
        This &lt;a href="http://laughingmeme.org/archives/000811.html"&gt;bit me hard&lt;/a&gt; when developing MagpieRSS.  I add supported HTTP gzip encoding, and suddenly for a small number of users Magpie starting failing.  This was a surprisingly difficult bug to track down, I recomend avoiding it all together.  This is what PHP's &lt;code&gt;function_exists()&lt;/code&gt; function is for.
    &lt;/p&gt;
    &lt;p&gt;
    In code that uses gzinflate I might add a conditional like
    &lt;pre class="code"&gt;
</code></pre>

<p>if ( function<em>exists(&#8216;gzinflate&#8217;) ) {
 &#8230;.
}
        </pre>
        Or at the beginning of the Magpie RSS parser I check to make sure PHP has been built with XML support with
<pre class="code">
if (!function</em>exists('xml<em>parser</em>create')) {
 ... trigger error ...
}
</pre>
    </li>
    <li>
    Don't pollute the global namespace
<p>
All functions share a namespace in PHP.  What that means is, if I have a parse<em>file() function in my library, and you have a parse</em>file() function in your library PHP has no way of telling them apart, and we've got a serious problem.  Classes help with this.
</p>
<p>
Another option is to prefix the functions in your library with a common string.  <a href="http://minutillo.com/steve/weblog/">Steve</a> does this with <a href="http://minutillo.com/steve/feedonfeeds/">Feed on Feeds</a>, prefixing all his functions with fof<em>, e.g. parse</em>file() becomes fof<em>parse</em>file().  Cuts down on conflicts, and increases readability.
</p>
</li>
<li>
If you use database tables allow a table prefix. (aka don't pollute the other global namespace)
<p>
Most libraries aren't going to work directly with a database, that is the province of applications usually, but if you are consider allowing the user to configure a table prefix, much like the function prefix from the previous tip.  Many users are on low end hosting platforms with only a single MySQL database, this creates another global namespace.  If my library has a <code>user</code> table, and your library has a <code>user</code> table, and we have different schemas (almost a guarantee) then we've got a problem.
</p>
</li>
    <li>
        Provide a well designed, object oriented interface to your library, that follows the above rules. 
        <p>
            This is outside the scope of these tips, but see the following corollary. 
        </p>
    </li>
    <li>
        Provide a functional, PHP-like interface that builds on your OO interface. 
        <p>
            PHP is not a language for building airy, abstract object hierarchies. It is a quick and dirty language for throwing together webpages with a minimum of fuss. While its important to provide the more elegant interface for your advanced users, and to encourage proper design, the majority of your users are going to want something simpler. 
        </p>
        <p>
            With Magpie I provide an object oriented RSS parsing class. I also provide a simple, <code>rss<em>fetch()</code> one function front-end that is designed to be used directly from within a PHP page. 
        </p>
        <p>
            My design consideration for <code>rss</em>fetch</code> were fetching remote files is time consuming, and parsing an XML file can be resource intensive. In most languages/environments you would setup a cron script to run in the background handling these tasks, and spitting out HTML fragments. This is not very PHP-like, and often beyond the technical ability of many PHP users. (or beyond what is offered in their hosting environment). So <code>rss<em>fetch</code> transparently uses PHP's <code>serialize</code> and <code>unserialize</code> to cache the results of the time/resource intensive calls, and serve subsequent calls quickly. 
        </p>
        <p>
            This makes it very easy for the end users to do the right thing, while writing simple, idiomatic PHP. I think this is very important for writing useful PHP libraries, and is one of the challenges that comes with the territory. 
        </p>
    </li>
    <li>
        Configuring the functional interface using defines. 
        <p>
            (aside: by functional we means as opposed to object-oriented, not as opposed to non-functional or dysfunctional) 
        </p>
        <p>
            Choose intelligent defaults, and provide a simple default means our functional interface should "just work" for many people. But when it doesn't, it should be equally easy to configure without cluttering up the API. 
        </p>
        <p>
            What I've done with Magpie, and its worked well, is extend the technique used in "setting a base dir". 
        </p>
        <p>
            Conditionalize your library behaviour on a set of constants (e.g. MAGPIE</em>USE<em>GZIP, and MAGPIE</em>CACHE<em>ON). Document these constants. People can now change the behaviour of your library with some simple statements at the top of their PHP, like: <pre class="code">
define('MAGPIE</em>CACHE<em>ON', false);  // turn off cacheing
</pre> Then the first thing your function should do is call an <code>init()</code> function which sets up those intelligent default we talked about: <pre class="code">
function init () {
    if ( defined('MAGPIE</em>INITALIZED') ) {
        return;
    }</p>

<pre><code>if ( !defined('MAGPIE_CACHE_ON') ) {
    define('MAGPIE_CACHE_ON', true);
}
... other constants ....
define('MAGPIE_INITALIZED', true);
</code></pre>

<p>}
</pre> 
        </p>
    </li>
    <li>
        Provide examples 
        <p>
            Always a good idea, but particularly important when distributing PHP libraries. Don't assume people will read the documentation, or if they do your programmer-esque understanding of your tool will be meaningful to them. What will make sense is example. 
        </p>
    </li>
    <li>
        Provide examples, carefully 
        <p>
            Be careful what your examples look like because whatever you do in your example is what 90% of your users will do in their scripts. 
        </p>
        <p>
            Test your examples or your support queue will fill up with people who cut and pasted your code and it isn't working for them. 
        </p>
        <p>
            Make your examples as attractive as you can while still being simple, otherwise you'll be forced to look at your ugly HTML all over the web. 
        </p>
        <p>
            Show examples that show proper use of your library, including best practices like error handling. If your examples show how to use a feature it will be used, if they don't, them most people won't use them. 
        </p>
    </li>
    <li>
        Document 
        <p>
            Document document document. Provide inline document. Provide a README. Provide a FAQ. Provide a website. Provide hints of where to go looking for more info. Hints like "this class is used by rss<em>fetch() you can stop reading now if you just want to use the simple interface" can also be useful. (of course don't sound too smug about it, as chances are people are there trying to find one of your bugs) 
        </p>
        <p>
            Running code is good documentation. 
        </p>
        <p>
            If you're going to provide code snippets make them longer then seems necessary as people will often have different instincts about what should come before and after the line in question. This is again the joy and trouble with providing a PHP library. 
        </p>
        <p>
            I personally like "cookbooks", a hybrid of a FAQ and running code samples. 
        </p>
    </li>
    <li>
        Use it Yourself, Use Consistent Names, Plan to Expand 
        <p>
            And just to re-iterate a few of Moran's suggestions 
        </p>
        <p>
            Until you really use your library you'll never know how well you've succeeded. When you write a library you shouldn't conceive of yourself as the only user, but certainly one of the users. Also developing good relationship with people who use your library will cause it to improve dramatically. 
        </p>
        <p>
            If you name half your methods <code>getRSSFile()</code> and the other half <code>get</em>cache_dir()</code> your users (and yourself in a few months) will be confused, and your code will look messy. 
        </p>
        <p>
            Moran says, "Never return a single value when you can return an array. Never return an array when you can return an object." 
        </p>
        <p>
            I think that is overstating the case, often you'll want to return a single value for simplicity sake, but take into account when you might not want to. Often returning an object will make the most sense, as long as your clearly document how to use the object. 
        </p>
    </li>
</ol>
</p>
<p>
<h3>PHP needs libraries</h3> PHP can be a frustrating language to work in, but its also very rewarding. One of the things I find most rewarding about it is the chance to make an impact, and the easiest way to do that if to release well written, well architected libraries. The community is starting pull together and provide some of this in form of PEAR and PECL, but those projects have a long way to go before they are well documented, easy to use and easy to install. In the meantime you can fill a critical need. 
</p>
<p>
<h3>Resisting Temptation, Educating, and Refactoring</h3> Because this lack of libraries is a deep set cultural problem you'll often find users writing you asking you to add feature X, or feature Y to your library to make it work more like they want their application to work. Remember you're doing one thing, and doing it well. This is a chance for education. Explain that you're building a library and the features they've asked for are more suited to an application. If you're feeling like you have the time, or are particularly generous, or if a request comes up over and over consider adding a code sample to your examples to show how to fulfill that particular feature request. Among other things you might find its harder then it should be, and prompt a change in your library. 
</p>
<p>
Thanks to <a href="http://minutillo.com/steve/weblog/">Steve</a>, <a href="http://traumwind.de/blog/">Martin</a>, <a href="http://radio.weblogs.com/0103807/">Scott</a>, and <a href="http://anarchogeek.com">Evan</a> for their feedback and suggestions.
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://laughingmeme.org/2003/08/05/a-few-tips-for-writing-useful-libraries-in-php/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Due Process</title>
		<link>http://laughingmeme.org/2003/07/02/due-process/</link>
		<comments>http://laughingmeme.org/2003/07/02/due-process/#comments</comments>
		<pubDate>Wed, 02 Jul 2003 09:21:00 +0000</pubDate>
		<dc:creator>Kellan</dc:creator>
				<category><![CDATA[atom]]></category>
		<category><![CDATA[collaboration]]></category>
		<category><![CDATA[community]]></category>
		<category><![CDATA[Longer]]></category>
		<category><![CDATA[process]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[wiki]]></category>

		<guid isPermaLink="false">http://lm.quxx.info/?p=501</guid>
		<description><![CDATA[
The Echo project switched gears tonight, and in doing so moved into deep water.  You see tonight was the night when people started producing Echo feeds.  That is the sort of concrete results people like to see, the sort of thing that can trigger a cascade.  And it spotlights the Echo projects [...]]]></description>
			<content:encoded><![CDATA[<p>
The <a href="http://www.intertwingly.net/wiki/pie/">Echo project</a> <a href="http://www.intertwingly.net/blog/1506.html">switched gears tonight</a>, and in doing so moved into deep water.  You see tonight was the night when people <a href="http://www.joelonsoftware.com/echo.xml">started</a> <a href="http://diveintomark.org/xml/necho-prototype-20030701.xml">producing</a> <a href="http://philringnalda.com/feed.xml">Echo</a> feeds.  That is the sort of concrete results people like to see, the sort of thing that can trigger a cascade.  And it spotlights the Echo projects one serious short coming.
</p>

<p><span id="more-501"></span>
<p>
<h3>SocioTechnical</h3>
For me, the promise of a next generation RSS was not a technical one, but a social one.  RSS 1.0&#8217;s failure was not that it included a few arbitrary tags (most XML formats do, and most people ignore them), but that it failed  to create structures that encouraged growth and development.  It had a few things going for it:  a mailing list with public archives, a working group with a published decision making process, and a commitment to viewing the format as a public standard.  What it failed to do was continue to refine its web presence; adding clarifications to the spec, and building easy entry points for new developers.  (the constant feeling of being under siege probably didn&#8217;t help, and eventually discouraged early community leaders)  So Echo was a chance to do what RSS 1.0 did right, while correcting where it went wrong.  An act of social engineering.
</p>
<p>
<h3>Something Different</h3>
However there are a few traits to Echo project to date which are different then RSS 1.0, or almost any other project like it.  Two key ones come to mind.
<ol>
<li> No mailing list</li>
<li> Incredible speed of convergence</li>
</ol>
Instead of a mailing list there is the <a href="http://www.intertwingly.net/wiki/pie/">wiki</a>, but perhaps more importantly there is ongoing conversation scattered over blogspace; a conversational circuit familiar to those who have trudge after what Phil called the 
<a href="http://philringnalda.com/blog/2003/06/mostly_moz_news.php">Semipermanent Floating RSS Argument</a> but totally opaque to most.  Some people find the wiki style of collaboration exhilarating, many find it frustrating.  The very web centric nature of this conversation to date has been fascinating, but it has also acted to be exclude a large swathe of the population.  A population who have been very active in related project, and in the roots of this one.  A number of people have state that they are unable to participate because the conversation is purely web-based, more has simply slipped away.
</p>
<p>
The other factor which has been incredible (and a bit alarming) is how fast it pulled together.  Arguably this is because the work had already been done.  Everybody knew what the new format was supposed to look like, the project was just to clarify a few details, and rename it.  Actually it turned out that there was a fair amount of debate on the wiki about how to do things, even among the small group who showed up, and yet still the convergence has happened blindingly quickly. (Some have suggested there is a story there still to be told, but I wouldn&#8217;t know.)  Progress is good, concrete results are good, the maxim of open source development is &#8220;release early, release often&#8221;, so what is the problem?  Well combine a fevered working pace, with a difficult to penetrate discussion space and the barrier to entry gets pretty high.
</p>
<p>
<h3>Haunting Echoes</h3>
And something else.  This rapid, ad-hoc process reminds me of something, something I had hoped Echo would get away from.  It reminds me of the development process for the Userland branch of RSS. 
</p>
<p>
<h3>Well Formed, and Whither?</h3>
We now have some idea about what a &#8220;Well Formed Weblog&#8221; looks like.  I think the next round of work for the Echo project should not be about nailing down the details of the format, and it certainly shouldn&#8217;t be encouraging a thousand Echo feeds to bloom (not that anyone is [or has to]).  The next round of work should be sitting down and laying out what a well formed working group looks like.<br />
</p>
<p>
Otherwise all that has been accomplished is changing some names, and perhaps changing who has the power, but an opportunity to create something more interesting and more open will have been missed, and the chance to tap the insight of the larger community will be lossed.  In political organizing there is a word for what we have on our hands, we call it a <a href="http://flag.blackened.net/revolt/hist_texts/structurelessness.html">Tyranny of Structurelessness</a>.
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://laughingmeme.org/2003/07/02/due-process/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Weather, RSS, and Thunderstorms</title>
		<link>http://laughingmeme.org/2003/06/22/weather-rss-and-thunderstorms/</link>
		<comments>http://laughingmeme.org/2003/06/22/weather-rss-and-thunderstorms/#comments</comments>
		<pubDate>Mon, 23 Jun 2003 03:28:00 +0000</pubDate>
		<dc:creator>Kellan</dc:creator>
				<category><![CDATA[design]]></category>
		<category><![CDATA[Longer]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[weather]]></category>

		<guid isPermaLink="false">http://lm.quxx.info/?p=488</guid>
		<description><![CDATA[
Tim Bray 
touched lightly on an idea for a business model I had a while back; that of leveraging RSS&#8217;s popularity as a format beyond web syndication.  Information like bank services, sales tracking, traffic alerts, and weather.



Its an idea that occurred to me when I first started playing around with 
delivering events via RSS, [...]]]></description>
			<content:encoded><![CDATA[<p>
Tim Bray 
<a href="http://www.tbray.org/ongoing/When/200x/2003/06/19/RSS4All">touched lightly</a> on an idea for a business model I had a while back; that of leveraging RSS&#8217;s popularity as a format beyond web syndication.  Information like bank services, sales tracking, traffic alerts, and weather.
</p>

<p><p>
Its an idea that occurred to me when I first started playing around with 
<a href="http://laughingmeme.org/archives/000036.html">delivering events via RSS</a>, and realized that RSS wasn&#8217;t an XML file for headlines, but a webservice pipeline I could shove all types of data through.<br />
<a href="http://laughingmeme.org/archives/000533.html">
Sourceforge figured out the same thing</a>, and Technorati has a nice little service (don&#8217;t know how &#8220;successful&#8221; in the business since its been) 
<a href="http://www.technorati.com/watchlists/index.html">selling a personalized RSS feed</a> that can watch Google queries, or keep track of who is linking to you.<br />
</p>
<p>
Tim mentions a few of the same types of feeds I was thinking of, misses a couple, and mentions one I never would have thought of, traffic reports. (being a non-driver and all)  Unfortunately/fortunately most of my entrepreneurial flare was burned out of me during the brief years I was running my own little dotcom, and so like a handful of other business models, it sits collecting dust.
</p>
<p>
<h3>Weather</h3>
Or at least sort of.  I did have a brief go at producing an RSS feed of the weather, and last night, as lightning struck all around, and great thunder claps, pealed and rumbled on and on like bombs detonating, their sound waves rattling my winds, and setting off all the car alarms of the apartment building next door, I revived the project.
</p>
<span id="more-488"></span>
<p>
(long rambling thoughts on RSS weather service [see: insomnia-induced].  <b>includes running code!</b>)
</p>
<p>
<h3>A Quick Spec</h3>
A spec is easy to produce, weather reporting is well understood.<br />
Detailed current info, a forecast, alerts for major changes, storm tracking, maybe some doppler images for when large bodies of precipitation move through your area.  Aren&#8217;t we lucky that this is essentially the form the informations in?  (Quick tangent.  A trick to providing this service, and something you would put some time into if you were providing a large number of different information feed, is deciding how and when a new item gets generated.  What constitutes new info?  What is the threshold triggers a new notification?  This is not as critical as it might be in say, and SMS paging service, as a RSS item is a less aggressive form of notification).
</p>
<p>
<h3>Current State of Things</h3>
Governments around the world do a pretty good of collecting weather statistics.  Then a number of commercial companies are willing to re-package that info for you, and re-sell it at exorbitant prices. (aforementioned dotcom was doing a local pitch, weather is part of that sell)  The US National Weather Service also provides several different forms of raw data: the <a href="http://iwin.nws.noaa.gov/iwin/textversion/main.html">NOAA&#8217;s forecasts</a> and the aviation service <a href="http://weather.noaa.gov/weather/metar.shtml">METAR, for detailed current conditions at airports</a>.  Dozens, perhaps hundreds, of tools exist to parse these formats, as do tools for scraping the big weather sites, <a href="http://wunderground.com">Wunderground</a> and <a href="http://weather.com">Weather.com</a> (which are really just super sophisticated versions of the smaller tools)  CPAN turns up a <a href="http://search.cpan.org/search?query=weather&#038;mode=all">dozen or so</a> of varying approach and quality.  However a quick survey (and some historical knowledge of the options) turns up none of them that are quite flexible to do what I want.
</p>
<p>
<h3>Notes On My Approach</h3>
I&#8217;m doing this as a cure for insomnia, and because weather has rather aggressively shoved itself into my consciousness, something that rarely happened as a child growing up in eternally &#8220;partly cloudy&#8221; Santa Cruz. (truth be told I&#8217;ve been thinking about weather off and on for a while).  I&#8217;m not building a business, and I&#8217;ve never really been a one of those Weather Channel radar imagery addicts.  And while its nice of the government to provide a text format, frankly its easier to scrape HTML then parse their terse, circa 1970s format.(<a href="http://search.cpan.org/dist/HTML-TokeParser">HTML::TokeParser</a> is your friend!)  Also limiting one&#8217;s service to US cities besides being boring, is a dead end, and makes you seen provincial. (the real reason I18N is taking off, so your European counterparts can&#8217;t laugh at you)
</p>
<p>
For national weather, given a city and state, scrape the <a href="http://weather.gov">NWS website</a>.  This gives you anywhere for 3-6 days of forecast.  Formats vary based on locality (there is a certain amount of free form data entry going on at the sources) but thats okay, I don&#8217;t need to understand the data, just classify it, and re-display it.
</p>
<p>
For international weather, given a city and country, scrape <a href="http://wunderground.com">Wunderground</a>.  (Wunderground&#8217;s international info is nice and predictable, while their national coverage tends to be chatty, and harder to interpret)
</p>
<p>
<h3>Interpretation</h3>
Weather forecasts tends to get broken into morning, afternoon, night, and overnight periods.  Ideally a service would collapse this information into a form compact form as the forecast gets farther into the future.  Similarly you sometimes see 4 or 5 days of identical predictions when its clear that what is really going on is a lack of good date, would be nice to run a similar transformation on those.  Maybe in version 2. (they also compose their forecasts from a limited vocabulary like: clear, fair, partly cloud, etc.  Which is not useful to me currently, but might be in the future)  Actually the Wunderground based feeds has a bit of ways to go before it looks quite right.
</p>
<p>
<h3>RSS Design Descisions</h3>
In this version there are no special namespaces used, all the info is packed into your basic RSS elements.  Warnings only provide a link to further details, the warning isn&#8217;t inlined.  Forecast items&#8217; rdf:about attribute points to arbitrary destination, and &lt;link&gt; points to the page where the info was scraped from.(note this requires a recent XML::RSS CVS checkout, or XML::RSS 1.03 when its released)  Each item gets the date of when the scrape took place, and the recommended ordering is that in the RSS feed.  Future versions of the RSS would probably include a weather module, and images.
</p></p>

<p>
<h3>Code?</h3>
The package contains 2 pieces, Weather::RSS, and Weather::RSS::Source.
</p>

<p><p>
<b>Weather::RSS::Source</b> is an interface that determines if your asking for US weather, or weather from somewhere else and then hands off the heavy lifting  (filling out forms, handling redirects, HTML scraping) to Weather::RSS::Source:WeatherGov and Weather::RSS::Source::Wunderground respectively, whom returned detailed current info, the extended forecast, and any weather alerts, or hazard warnings they happened to find. (this piece should probably be re-packaged and released to CPAN as I like it better then any of the existing Weather:: packages, maybe as Weather::Source?  Weather::Forecast? Weather::RainGods?)
</p>
<p>
<b>Weather::RSS</b> on the other hand is merely responsible for taking the resultant weather source object, and spitting out an RSS feed.
</p>
<p>
Also include is a little cgi that steals the logic from 
<a href="http://aaronland.info/weblog">Aaron&#8217;s</a> 
<a href="http://search.cpan.org/dist/Acme-Test-Weather/">Acme::Test::Weather</a> and attempts to guess at a visitors location, and provide the proper RSS feed.
<ul>
<li>Download <a href="http://laughingmeme.org/weather-rss/Weather-RSS-0.01.tar.gz">Weather-RSS-0.01.tar.gz</a>.</li>
<li>Example output:  <a href="http://laughingmeme.org/weather-rss/nyc.rss">New York</a>, <a href="http://laughingmeme.org/weather-rss/paris.rss">Paris</a>, <a href="http://laughingmeme.org/weather-rss/santa_cruz.rss">Santa Cruz</a>, <a href="http://laughingmeme.org/weather-rss/montevideo.rss">Montevideo</a>.</li>
</ul>
</p>
<p>
<h3>Next Steps</h3>
Well the code is all very alpha quality.  With screen scraping, and particularly with weather, you never know you&#8217;ve got your parser just right, you just know it hasn&#8217;t broken yet.  So there are probably a few bugs still lurking.
</p>
<p>
Improvements could come from being more intelligent about when to produce new RSS items, and folding/condensing the forecasts as mentioned above.  Also including doppler, doing a better job of tracking down extreme weather info, and maybe cute little weather icons like everyone seems to have.
</p>
<p>
Also the current version (if its still the current version) will probably brake sometime next Winter, as Winter weather reports just look different.
</p>
<p>
Lastly more and better datasources.  If you know of a better source of info, let me know.  Thanks.
</p>
<p>
<h3>Providing a Service</h3></p>

<p>Right now its just some Perl modules, and few scripts, you&#8217;re welcome to download it.  Like I said I kind of burned out my entrepreneurial side hasn&#8217;t really re-grown.  But <b>IF</b> you really did want to pay me to provide a RSS weather service, something like $8-$12/year probably I might be interested.  I wonder what the legality of re-selling other peoples data is?  There are a number of desktop clients which do it, but they&#8217;re selling clients, not the data. (I guess I&#8217;m just selling a webservice client at that)  In the process of jack hammering my thoughts out of Perl and into English this morning (Trader Joe&#8217;s Moka Java) I think I was hit for the first time what confuses and baffles people about open source.  At commercial development prices this is a $1500-$2000 dollar investment before infrastructure, as open source its something to do until the rain stops.  (hey, or you could hire me, and I&#8217;ll thrown in setting up a customized RSS feed of just about anything as a bonus)
</p>
<p>
In the meantime, expect at least a minimal project page, ala 
<a href="http://laughingmeme.org/cvs2rss/">cvs2rss</a> in the near future.  (and try to resist making it into a wildly successful commericial venture, that would be depressing)
</p>
<p>
ps.  this post almost was titled, &#8220;It was a Dark and Stormy Night&#8221; (after all it was!), this is why people are bad at meta-data.
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://laughingmeme.org/2003/06/22/weather-rss-and-thunderstorms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RSSifying the Mailing List</title>
		<link>http://laughingmeme.org/2002/11/25/rssifying-the-mailing-list/</link>
		<comments>http://laughingmeme.org/2002/11/25/rssifying-the-mailing-list/#comments</comments>
		<pubDate>Mon, 25 Nov 2002 19:59:00 +0000</pubDate>
		<dc:creator>Kellan</dc:creator>
				<category><![CDATA[collaboration]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[Longer]]></category>
		<category><![CDATA[mailinglists]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[state.of.the.art]]></category>

		<guid isPermaLink="false">http://lm.quxx.info/?p=225</guid>
		<description><![CDATA[
Lattice asked me about resources for representing a mailing list as an RSS
feed.  Particularly, he was wanting to put together an alternative(post-email)
interface to a 
Sympa mailing list, with an RSS aggregator for reading the list
traffic, and the Sympa web interface for posting.  I didn&#8217;t have any
suggestions for Sympa, but noted that the script [...]]]></description>
			<content:encoded><![CDATA[<p>
<a href="http://resist.ca/~lattice/">Lattice</a> asked me about resources for representing a mailing list as an RSS
feed.  Particularly, he was wanting to put together an alternative(post-email)
interface to a 
<a href="http://listes.cru.fr/sympa/">Sympa</a> mailing list, with an RSS aggregator for reading the list
traffic, and the Sympa web interface for posting.  I didn&#8217;t have any
suggestions for Sympa, but noted that the script 
<a href="http://taint.org/mmrss/">mmrss</a> turns Mailman
lists into RSS feeds.
</p>

<p><p>
<h3>A Thought</h3>
This inspired me to think about tackling the chronic lack of mail list archiving soltuions as multi-step problem.  Perhaps if we could get the mailing lists into a suitable inbetween format, with all the assumptions exposed, and codified into XML, then perhaps the archivers simply focus on giving a decent presentation of the complex interactions of a mailing list.  And having that format be compatible with the latest crop of desktop clients would allow people to build new and exciting ways of interacting with the lists.
</p>
<p>
So I compiled an overview of the problems, the challeges, and work that has gone before on building an RSS threading standard.
</p>
<span id="more-225"></span>
<p>
<h3>A Quick Review of the State of the Archiver</h3></p>

<p><a href="http://mhonarc.org">MHonarc</a> is something of a standard, but I can&#8217;t standard the archives it
generates, it should be possible to generate something attractive and usable,
but I&#8217;m still waiting.  Current otherings run from the pedestrian 
<a href="http://www.mail-archive.com/modperl%40apache.org/">Mail Archive</a> to
byzantine <a href="http://listes.cru.fr/wws/arc/sympa">Sympa style</a>)
</p>
<p>
<a href="http://list.org">Mailman&#8217;s</a> archives (
<a href="http://www.amk.ca/python/unmaintained/pipermail.html">pipermail</a>) are pleasingly 
<a
href="http://lists.indymedia.org/mailman/public/syndication/2002-November/thread.html">
straightforward and clean</a>, however their
threading algorithm is a little weak, the archives are fragile with slight
changes to the mbox changing URLs, and rebuilding the archives for very active,
old lists can be incredibly slow.  This and pipermail has no clue what to do
with attachments.
</p>
<p>
<a href="http://zest.sf.net">Zest</a> is an intriguing alternative I&#8217;ve mentioned before, however people I&#8217;ve
shown it to find it confusing, and while I think they could learn, I hesitate to
recommend it as a drop in replacement for MHonarc/Pipermail.
</p>
<p>
<h3>The Problem with MMRSS</h3></p>

<p>Unfortunately <a href="http://taint.org/mmrss/">mmrss</a> doesn&#8217;t solve our problems.  It scrapes the existing
Mailman archives, and creates 
<a href="http://taint.org/mmrss/FoRK.rss">very simple RSS 0.91</a>.  Because RSS 0.91 isn&#8217;t
very flexible, there is no way to include most of the interesting information,
including the basic meta-data like creator (<code>From:</code>), and date 
sent (<code>Date:</code>) as
well as more email specific info (like attachments, user agent, and message
id), and the messages threading information (<code>In-Reply-To:</code>)
</p>
<p>
This means that while MMRSS could be useful for watching a list (ie. getting
notified when it updates) it does not provide a meaningful alternative to
reading the list.(this could partially be due to the script started life to
generate RSS feeds for 
<a href="http://xent.com/mailman/listinfo/fork">FoRK</a>, an email based proto-blog with an interesting role
in the history of RSS/Email convergence)
</p>
<p>
<h3>What would we want?</h3></p>

<p>On the &lt;channel&gt; definition we&#8217;ll want the usual suspect, including:
<ul>
<li> the name of the mailing list in the &lt;title&gt;
<li> the URL of either the lists webpage if it has one (as all Mailman and
Sympa lists do), or the link to the web accessible archives (if for some reason
you are using something else, and haven&#8217;t setup a webpage)
<li> the date of the most recent message to the list in &lt;dc:date&gt;
<li> and as much other meta-data as possible including description, and language.
</ul> 
And we&#8217;ll want: 
<ul>
<li> the list, and list admin addresses, perhaps in &lt;dc:creator&gt; and &lt;dc:publisher&gt;?
 or would that be an inappropriate re-use?
</ul></p>

<p>On a particular &lt;item&gt; we&#8217;ll want:
<ul>
<li>  the URL to the web archived email
<li>  the subject of the email in the &lt;title&gt;
<li>  the contents of the From: field in &lt;dc:creator&gt; (or one of the 
<a href="http://groups.yahoo.com/group/rss-dev/message/4481">sha1/foaf based
 email obscuring technologies</a> being discussed on rss-dev)
<li>  the date the email was sent (or received by the mailing list software) in
  &lt;dc:date&gt;
<li>  the full content of the message in the &lt;description&gt; (if you&#8217;re serious about
  providing an alternative interface to the list)
</ul></p>

<p>Ideally we would also have:
<ul>
<li>  information about the messages membership in a thread (see below)
<li>  links to web archives of any attachments that might have been included in the
  email
<li>  a link (or mail address) to reply to this message particular message
 </ul></p>

<p>There might also be reasons to include:
<ul>
<li>    Message-ID (perhaps for constructing replies)
<li>    User-Agent
<li>    Spam Status (or similar Spam flagging header)
<li>    CC information
</ul>
Some of this definitely can&#8217;t be shoe horned into the 3 standard RSS 1.0 modules
(Dublin Core, Syndication, and Content), and demand extensions, but perhaps a
proposed module (or modules) will do.
</p>
<p>
<h3>Examining the Prior Art in Threading</h3></p>

<p>Not surprisingly, displaying email as RSS, displaying mailing lists as RDF, and
building interchange formats for threaded discussion in RSS have all been
discussed before.  No one change up with exactly the same feature set
(surprise!) because everyone had slightly different conceptions of the problem.
</p>
<p>
The first important insight when considering an implementation (and examining
prior art) is to realize that much of what is important to representing a
mailing list is important to representing any form of threaded discussion, like
the comments from a message board or blog, or the posts from a newsgroup.
</p>
<p>
There is the proposed 
<a href="http://purl.org/rss/1.0/modules/threading/">RSS threading module</a>, that adds one tag: &lt;child&gt;. 
Which is nice and simple, but also kind of awkward as email tends to be linked
into threads by referring to a parent.(<code>In-Reply-To:</code>)
</p>
<p></p>

<p><a href="http://www.quicktopic.com/7/H/rhSrjkWgjnvRq?m1=66&#038;mN=66">ThreadML</a>
 was an interesting initiative of 
 <a href="http://www.quicktopic.com/blog/">Steve Yost</a> of 
 <a href="http://www.quicktopic.com">Quicktopic</a>,
partially created in a response to this article on 
<a href="http://www.hyperorg.com/backissues/joho-jun17-01.html">Joho</a>. 
It was a standard composed of RSS 1.0, mod<em>content, mod</em>threading to represent
parent-to-child, and mod<em>annotation to represent child-to-parent relations. 
There was a very active 
<a href="http://www.quicktopic.com/7/H/rhSrjkWgjnvRq">quicktopic
discussing ThreadML</a> for a while, but it seems
to have gone quiet.  An example <a
href="http://www.quicktopic.com/7/H/rhSrjkWgjnvRq.rss">Quicktopic RSS feed</a> to see how it might have
looked.
</p>
<p>
Discussion of 
<a href="http://groups.yahoo.com/group/rss-dev/message/3102">creating an RSS
feed</a> for the W3C&#8217;s mailing lists, prompted the
proposal of a 
<a href="http://groups.yahoo.com/group/rss-dev/message/3121">mod</em>email</a> which might be useful, but doesn&#8217;t seem to focus on
the commonality between different mediums enough for me.
</p>
<p>
The PHP mailing lists are available 
<a href="http://news.php.net/group.php?group=php.dev&#038;format=rss">
as RSS feeds</a>, unfortunately here again, they
aren&#8217;t very useful RSS feeds, with the From information stuck into a &lt;mailto:&gt;
tag in the &lt;description&gt; tag.  Odd.
</p>
<p>
Yahoogroups (formerly eGroups) provides RSS feeds for the lists (e.g.
RSS-DEV[18] they host, see the 
<a href="http://www.xent.com/FoRK-archive/april00/0808.html
">original announcement on FoRK</a>)
</p>
<p>
Mail-archive.com makes a simple RSS 0.9 feed available for each list, for
example <a
href="http://www.mail-archive.com/modperl%40apache.org/maillist.rdf">mod_perl&#8217;s
RSS</a>
</p>
<p>
Lastly, the 
<a href="http://www.eyrie.org/~zednenem/2002/web-threads/">Thread Description
Language</a> is an interesting attempt to build a
rich RDF syntax for talking about all sorts of different threads.  Some of its
concepts like agreesWith and disagreesWith would be very cool to add to a
RSS/RDF feed based on Zest and its inline mark up.
</p>
<p>
<h3>Conclusion, and Concerns</h3></p>

<p>All of that is very interesting, but I don&#8217;t feel like any of the above directly
maps to the features I mentioned above, it might be possible to assemble
something out of the pieces, but a few items (like the url/mailto to respond to
a post) is totally missing from any of this.
</p>
<p>
It might be worth looking at an email&lt;-&gt;NTTP gateway to see what tricks they
play, and what they consider necessary.
</p>
<p>
One problem with marking up email in XML is that it makes it very very easy for
spammers to identify email addresses.  There is a thread on RSS-DEV about ways
to combat this.  It seems like it should be possible with the collusion of the
list archiver to send out &#8220;privatized&#8221; emails, where contact information is
replaced with some sort of smart URI to confuse harvesters without interrupting
communication.  Yahoogroups kind of does this.
</p>
<p>
It would cut down on the complexity immensely to just skip the whole threading
thing, but I think threading is an important feature for facilitating a culture
of discussion, often discourages in spaces that use &#8220;linear threading&#8221; (like the
traditional display of an email client&#8217;s inbox)  Might be suitable for a version
1.0
</p>
<p>
Yet another approach would be to get away from the concept of an individual
post, and syndicate conversations (threads).  This would map <b>very</b> well to
Zest&#8217;s concept of threads, but would work pretty well for normal archives and
threads as well.  The one trick would be figuring out distribute threads in such
as way as to be useful with the most recent post readily accessible.
</p>
<p>
Related Posts:
<ul>
<li><a
href="http://laughingmeme.org/archives/000094.html#000094">Revolutionizing the
Mail Archive</a>
</ul>
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://laughingmeme.org/2002/11/25/rssifying-the-mailing-list/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web Development with Perl.</title>
		<link>http://laughingmeme.org/2002/09/10/web-development-with-perl/</link>
		<comments>http://laughingmeme.org/2002/09/10/web-development-with-perl/#comments</comments>
		<pubDate>Wed, 11 Sep 2002 01:19:00 +0000</pubDate>
		<dc:creator>Kellan</dc:creator>
				<category><![CDATA[Longer]]></category>
		<category><![CDATA[patterns]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[state.of.the.art]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://lm.quxx.info/?p=145</guid>
		<description><![CDATA[
In preparation for doing the Protest.net re-write I&#8217;m doing some research on web
frameworks.  I find myself rewriting the same central dispatcher code, adding
refinements, like a redirect method (similiar to the forward() method in
servlets) and in general missing some of the refinements of Java&#8217;s web
environments (servlets, 
Struts, bundles for i18n) while refusing to give up
Perl, [...]]]></description>
			<content:encoded><![CDATA[<p>
In preparation for doing the Protest.net re-write I&#8217;m doing some research on web
frameworks.  I find myself rewriting the same central dispatcher code, adding
refinements, like a redirect method (similiar to the forward() method in
servlets) and in general missing some of the refinements of Java&#8217;s web
environments (servlets, <a href="http://jakarta.apache.org/struts/index.html">
Struts</a>, bundles for i18n) while refusing to give up
Perl, CPAN, and <a href="http://www.tt2.com">Template Toolkit</a>.
</p>

<p><p></p>

<p>This is my brain dump so far.  Lots of questions, a few answers. The next step will be firing up the text editor
and looking under the hood.
</p>
<p>
<h3>Steal from the Best</h3>
Applications I&#8217;m going to examine for ideas to steal, particularily framework
ideas (error handling, inner loop, etc.)</p>

<ul>
<li><a href="http://moveabletype.org">Moveable Type</a> &#8211; in my few glaces at
the code its seemed intelligent, and well structured.  Runs under mod_perl and
CGI, handles some complex UI demands like pages that use redirects to update
progress bars, and re-entrant forms.</li>
<li><a href="http://bricolage.cc">Bricolage</a> &#8211; based on Mason, I&#8217;ve been
hearing good things about this CMS, particular about its clever <em>Burners</em>
abstraction, hope to find other good things under the hood.  Don&#8217;t really know
much about <a href="http://masonhq.com">Mason</a>, not sure if that is going to
be barrier</li>
<li><a href="http://fsck.com/projects/rt">RT</a> &#8211; popular, mod_perl and Mason,
ticket tracking software. Also supports email, and command line interfaces.</li>
<li><a href="http://scoop.kuro5hin.org">Scoop</a> &#8211; haven&#8217;t looked at Scoop in a
while, but I remember it seemed well done (having just come from looking at
Slashcode 1.0), I wonder if it will stand the test of time.  Not expecting to
find anything all that relevant, but maybe.  Will probably do a quick skim of
the CMS parade: <a href="http://slashcode.com">Slash</a>, <a
href="http://everydevel.com/">Everything2</a>, and maybe <a
href="http://livejournal.com/developer/">LiveJournal</a>.  Definitely want to look at 
<a href="http://www.livejournal.com/developer/embedding.bml">LiveJournal&#8217;s embedding instructions.</a>
<li><b>??</b> Do you any Perl web applications you would consider examples of best
practices<b>??</b></li>
</ul>

<p></p>
<p>
<h3>Perl Frameworks</h3>
<ul>
<li><a href="http://www.openinteract.org">OpenInteract</a> seems popular, and uses
TT2, but leaves me cold, partially because I&#8217;m just not crazy about persistence
layers.  But I should probably spend some time looking at it.  <b>??</b> Any expirences using it <b>??</b>
</li>
<li>
<a href="http://www.masonhq.com">Mason</a> natively uses an embedded, page based
execution model, which seems PHP-like to me, but
<a href="http://masonhq.com/user/autarch/Comps_vs_modules">Design Issues with
Mason:  What are Components For?</a> seems to be simple guidelines for avoiding
the siren calls.  There is an Oreilly book coming out on it, which will be
<a href="http://masonbook.com">available online</a>, but the author says, <a
href="http://use.perl.org/comments.pl?sid=7183&#038;cid=12705">don&#8217;t expect it until
mid-October</a>.
</li>
<li>
<a href="http://wombat.sf.net">Wombat</a> is billed as an implementation of the
Servlet API in Perl, but I can find exactly zero reference to anyone using it,
never a good sign.
</li>
<li>
<a href="http://axkit.org">AxKit</a> is a web framework built along the lines of
Cocoon.  I bet there are seriously cool ideas to steal in there, but I&#8217;ve been
burned pretty badly playing with XSLT and don&#8217;t want to go back into that water
right now.
</li>
<li>
<a href="http://openframe.fotango.com/">OpenFrame</a> also seems interesting. 
It has the request and response objects ala servlets, and <a
href="http://use.perl.org/~acme">acme</a> is being paid to work on it, and it
has a &#8220;Slot&#8221; concept which seems similiar to Brico&#8217;s Burner concept, and
supports TT2.  However it bills itself as an &#8220;open source application framework
for distributed media applications.&#8221;  Which isn&#8217;t really what we are building.
</li>
<li>
A few others are listed at <a
href="http://perl.apache.org/products/app-server.html">Application Servers and
Toolkits based on mod<em>perl</a>.  Also,
<a href="http://perlmonks.org/index.pl?node=Web%20Application%20Frameworks%20and%20their%20Templating%20Engines%20with%20a%20Comparative%20Study%20of%20Template%20and%20HTML%3A%3ATemplate
">Web Frameworks and their Template Engines</a> is interesting.
</li>
<li>
Last time I was looking at this stuff there was 
<a href="http://snafu.wgz.org/chromatic/jellybean.html">JellyBean</a>, which no
longer seems maintained, and Iadio, which no longer exists.
</li>
<li>
I found a <a href="http://perlmonks.org/index.pl?node_id=157946">simple
home-rolled framework</a> that feels simliar to the one I did for <a
href="http://www.rockwoodleadership.org">Rockwood</a>.  It was mentioned in this
<a href="http://perlmonks.org/index.pl?node_id=157582">interesting thread</a>.
</li>
<li>
The book, <a href="http://www.globalspin.com/thebook/">Perl for the Web</a> from
New Riders, is freely available online and seems interesting if out of date.
</li>
</ul>
</p>
<h3>Piecemealing with Modules</h3>
<ul>
<li>
We&#8217;ll definitely be using <a href="http://www.template-toolkit.org">Template
Toolkit</a>.  Read Perrin&#8217;s <a
href="http://perl.apache.org/docs/tutorials/tmpl/comparison/comparison.html">classic
article on Template engines</a>. (the sequel to his classic article on 
<a
href="http://perl.apache.org/docs/tutorials/apps/scale_etoys/etoys.html">building
the eToys website</a>.)
</li>
<li>
 <a href="http://search.cpan.org/dist/Apache-Session/">Apache::Session</a> is a
 given.  Not finding a good webpage on it, but it has great POD.
 </li>
 <li>
 <a href="http://perl-cache.sf.net">Cache::Cache</a> is a given.  The Perl Cache
 project is one of those tools, like TT2, that makes you never want to leave
 Perl.
</li>
<li>
DBI is an of course, and I think we&#8217;ll be avoiding the DBIx namespace in favour
of having a peer layer with hand written SQL.
</li>
<li>
Many people are reccomending <a
href="http://search.cpan.org/dist/CGI-Application/">CGI::Application</a> as an
implementation of the central dispatchers.  An article on <a href="http://www.perl.com/lpt/a/2001/06/05/cgi.html
">using CGI::Application</a>, and on <a href="http://perlmonks.org/index.pl?node_id=142580
">using CGI::Application with Template Toolkit</a>.  I&#8217;ve looked at it before,
and it was simpler to roll my own, but I&#8217;m going to check it out again.  It runs cleanly under Apache::Registry, but isn&#8217;t really a full blown mod</em>perl app.
</li>
<li>
<a href="http://search.cpan.org/author/MARKSTOS/Data-FormValidator-1.11/lib/Data/FormValidator.pm">Data::FormValidator</a> is
recommended, and includes a <a
href="http://search.cpan.org/author/TBONE/Data-FormValidator-Tutorial-1.3/Tutorial.pm">tutorial</a>,
but some people prefer <a
href="http://search.cpan.org/author/FRAJULAC/FormValidator-0.11/HTML/FormValidator.pm">HTML::FormValidator</a>,
but I don&#8217;t really know what the difference is yet.  Hmmm, they look like they might actually be the same module.  <b>??</b> Any idea <b>??</b>
</li>
<li><b>??</b> Did I leave out your favorite module <b>??</b>
</ul>
</p>
<p>
<b>UPDATE</b>: After looking at the available options, and at 
<a href="http://www.theserverside.com/resources/article.jsp?l=Struts1_1">Struts 1.1</a>, I would go with Java if I didn&#8217;t know I would have an insurrection on my hands.
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://laughingmeme.org/2002/09/10/web-development-with-perl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Business Plan for an Online Calendar</title>
		<link>http://laughingmeme.org/2002/08/20/business-plan-for-an-online-calendar/</link>
		<comments>http://laughingmeme.org/2002/08/20/business-plan-for-an-online-calendar/#comments</comments>
		<pubDate>Tue, 20 Aug 2002 23:55:00 +0000</pubDate>
		<dc:creator>Kellan</dc:creator>
				<category><![CDATA[anyday]]></category>
		<category><![CDATA[business]]></category>
		<category><![CDATA[calendaring]]></category>
		<category><![CDATA[Longer]]></category>
		<category><![CDATA[service]]></category>
		<category><![CDATA[services]]></category>

		<guid isPermaLink="false">http://lm.quxx.info/?p=128</guid>
		<description><![CDATA[
The title is something of a joke.  When I sent out this email last November, as it was becoming clear that Anyday was going to be shut down, it was to friends all of whom were working in companies that had a business plan for online calendaring.  The idea was a simple one, [...]]]></description>
			<content:encoded><![CDATA[<p>
The title is something of a joke.  When I sent out this email last November, as it was becoming clear that Anyday was going to be shut down, it was to friends all of whom were working in companies that had a business plan for online calendaring.  The idea was a simple one, (and very un-dotcom) make an online calendar/pim service that provided quality for money, using a simple, and viable mini-payments (like mirco-payments, but bigger).  
</p>

<p><p>
I was reminded of it recently when researching 
<a href="http://fastmail.fm">fastmail.fm</a>, whom I think has done a great job
implementing this exact same business plan, but for email.  Keep prices low, allow
people to upgrade for a small, and well disclosed fee, grow slowly and stably on
the back of income so you&#8217;re around for the long haul, and provide what people
are asking for.  I was also reminded of it by my partner just recently started working as an office
manager at a university and said, &#8220;I finally understand why Anyday was cool.&#8221;  7
months after Palm shut it down unfortunately.
</p>
<p>
Anyday was a web-based PIM, inspired by the Palm pilot, and built largely by
ex-Lotus people (and a few of <a href="http://anarchogeek.com">us</a> with different <a href="http://protest.net">calendar backgrounds</a>).  The primary goal was to get a
functional online PIM that could sync with your desktop PIM, and Palm pilot,
for the purposes of remote access, backup, or act simply as a stand alone product. 
Once people were online, there was the opportunity to use that connectivity to
do things impossible with the traditional applications, scheduling, free/busy
lookup, delegation, etc.
</p>
<p>
A while back I noticed that the <a href="http://horde.org">Horde</a> had almost all the components neccessary to satisfy that primary goal.  And I was tempted to see if it could be used to
build an Anyday clone, just to see how fast it could be done, and how irrelevant
all of us overpaid Java programmers were.  Once Anyday was gone the idea
evolved.
</p>
<p>
Horde provides:  an addressbook with an LDAP backend, webmail with an IMAP
backend, a web calendar, and hooks for integrating them.  So it would be real
simple to throw up something like Anyday, minus groups, scheduling, and sync.
</p>
<p>
<h3>Sync</h3>
Sync was always the coolest idea, and the hardest, most expensive problem
at Anyday.  Funny thing is it doesn&#8217;t seem like it should need to be that
hard.  I think part of the problem was in the conception.
</p>
<p>
They(we) bought into a solution (Extended Connect), that said &#8220;All things
must go through me.&#8221;  Obviously 
<a href="http://www.extendedsystems.com">Extended</a> liked this because it made then
more valuable.
</p>
<p>
But Sync&#8217;ing with the Palm could be really simple.  I think a little desktop
client, that can talk XML-RPC to the server, used pilot-link to the Palm,
and parsed SyncML, would do the trick nicely.  And if it was properly open and
interesting, would take off as its own open source project.
</p>
<p>
(update: not sure now iSync, and OS X fit on the landscape since this was written, might function as an open source alternative to iSync)
</p>
<p>
<h3>Self-Sustaining</h3></p>

<p>Here is where I think the most intersting parts come in.  I&#8217;m inspired by
Yahoo&#8217;s &#8220;sort-of-mirco-payments&#8221; at mail.yahoo.com, where you get 6M free,
and then you get another chunk for $2/month
</p>
<p>
The basic service would be free.  And then you pay for extras.
</p>
<p>
Extras would include
<ul>
<li>Direct access to the LDAP server behind the addressbook for sync&#8217;ing to
Outlook, Evolution and such.</li></p>

<p><li>Direct access to the IMAP server again for access from Outlook, Evolution 
and kin.</li></p>

<p><li>More disk space, not sure if this is just for email, or total.
(update:  I notice that diskspace isn&#8217;t fastmail.fm&#8217;s primary concern, but bandwidth, that makes sense, the collorary to the trusim &#8220;storage is cheap&#8221; is &#8220;bandwidth isn&#8217;t&#8221;)</li></p>

<p><lli>CAP access when CAP becomes more exciting. Reefknot is almost ready! (update: Well Reefknot seems to have slowed down, but iCal.app, Entourage, Evolution,
and Outlook are all becoming serious iCalendar players)</li></p>

<p></ul>
<p>
You would want an account page, that summarizes all expenses, and makes
people feel very aware of how much they are spending.  I think part of
what scares people about mirco-payents is feeling out of control.
</p>
<p>
Another trick would be to only bill when the amount owed gets large enough
to make it worth it.  And to be clear about this.  (sort of the reverse of what Amazon does for affiliate accounts)
(update: And to send a nice email about it the way Safari does)
</p>
<p>
I think the billing system would be the most complicated piece of
development.  Probably 2 weeks work. (+2-3 weeks to debug <img src='http://laughingmeme.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> 
(update: I&#8217;ve sinced learn I <b>badly</b> underestimate the time things take these days)
</p>
<p>
<h3>Further Development</h3></p>

<p>I think Groups is an important concept to really make a service like this
useful.  Both formal groups, and ad-hoc ones.  And of course I would like
to expand the ideas of group scheduling that I was playing with before But
I don&#8217;t think they&#8217;re critical for initial acceptance.
</p>
<p>
update: Since I originally came up with this idea, iCal has been annouced which makes
some noise about the potentials for sharing calendar information, and syncing. 
It will be interesting to see (in a couple of weeks now) what they&#8217;ve come up
with.
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://laughingmeme.org/2002/08/20/business-plan-for-an-online-calendar/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Day at MassMOCA</title>
		<link>http://laughingmeme.org/2002/08/19/a-day-at-massmoca/</link>
		<comments>http://laughingmeme.org/2002/08/19/a-day-at-massmoca/#comments</comments>
		<pubDate>Mon, 19 Aug 2002 16:46:00 +0000</pubDate>
		<dc:creator>Kellan</dc:creator>
				<category><![CDATA[art]]></category>
		<category><![CDATA[boston]]></category>
		<category><![CDATA[Longer]]></category>
		<category><![CDATA[ma]]></category>
		<category><![CDATA[personal]]></category>
		<category><![CDATA[photos]]></category>
		<category><![CDATA[travel]]></category>

		<guid isPermaLink="false">http://lm.quxx.info/?p=122</guid>
		<description><![CDATA[
Jasmine and I ditched Boston and its cement melting temperatures for a weekend
back in Western Mass., where we both went to school.  And we finally cashed in that rain-check to go MassMOCA, the current show,
Contemporary Viennese artists, didn&#8217;t really excite us, but we&#8217;ve been saying we would go for nearly 3 years now.



A long [...]]]></description>
			<content:encoded><![CDATA[<p>
Jasmine and I ditched Boston and its cement melting temperatures for a weekend
back in Western Mass., where we both went to school.  And we finally cashed in that rain-check to go <a href="http://massmoca.org">MassMOCA</a>, the current show,
Contemporary Viennese artists, didn&#8217;t really excite us, but we&#8217;ve been saying we would go for nearly 3 years now.
</p>

<p><p>
<h3>A long road ahead</h3>
First thing you should know about visiting MassMOCA is it is <b>far</b> away.  I
mean everyone says its far, but its just hard to believe <b>how far</b>.  I grew
up in California where we have counties larger then Massachusetts, and the only
explanation I can think of to justify how far out there North Adam is and still
be in Massachusetts is that it exists on some other plane.  So when you call the
museum and they say take 91N to Greenfield, get on Rt. 2W and you&#8217;re almost
there. They are lying!
</p>
<p>
Heading out Rt. 2 we nearly turned back in despair several times, only sustained
by the how beautiful and green that part of Mass can be.  Even after finally
seeing the &#8220;Entering North Adams&#8221; sign, we hadn&#8217;t arrived, it was merely a lure
to reel in the reluctant.  We would pass through 2 more towns, and cross a small
mountain range, before we descended (beautiful view) into the Hoosac river
valley, and the old industrial town of N. Adams.
</p>
<p>
<h3>Doubts</h3>
I&#8217;ve been told with MassMOCA the show is everything, the curating can soar to
heights of brilliance, but apparently maintaining the altitude proves tricky.  So
I was a little worried.  My worries felt confirmed when we walked into the show
and were confronted with sophomoric video art that expressed the artists desire
to &#8220;break free of the conservative and oppressive Viennese art regime&#8221;, and a
painter of abstracts that cheerfully embraced the appellation, &#8220;decorative&#8221;. 
However there were some hilights.
</p>
<p>
<h3>Franz West</h3>
<img src="/img/aad.thumb.jpg"  align="right" width="150" height="75" border="0" />
MassMOCA is in the back of beyond so that they can have a really huge space
cobbled together out of those great abandoned New England factory buildings.  I
vacillate between:  fanatsizing about remodelling them into amazing live/work spaces with steampunk enfused aesthetics, and the dread certainty of a
Californian that one day the Big One will hit, and I would be buried by a city
block worth of red bricks.  Either way, the Franz West exhibit blossomed in the
enormous space.
</p></p>

<p>
Walking into the exhibit room a cheerful note proclaims, &#8220;All Chairs May Be Sat
In.&#8221;  A 30ft tall sculpture of a Pepto Bismol pink intestine, <em>&#8220;Drama
(Model)&#8221;</em> quickly draws the
eye.  As does the 90ft long white table, <em>&#8220;Kantine&#8221;</em>&#8220;, that attempts to
play with Kant&#8217;s 2 ideals of pleasure.  We&#8217;re told at the <a href="http://mak.at">MAK</a> this was a
performance piece, where you ate heavy German peasant food while staring at the
high art intestine so that the lump in your stomach and your growing panic of
not understanding why Austria&#8217;s most influential artist has sculpted a giant
intestine come to symbolize Kant&#8217;s interested and disinterested pleasures.  I
don&#8217;t personally remember Swedish meatballs coming up in our discussions of the
Enlightenment but it was an intriguing piece.
</p>

<p><p>
<h3>Erwin Wurm</h3>
It was this piece that prompted Jazz&#8217;s insight, &#8220;They are going for
Disneyland.  Art that is fun for the whole family.&#8221;  Which is not to say we
didn&#8217;t like it, a lot, but one worried if the curator had sacraficed critique in bringing
it to you.  Still, Wurm&#8217;s center piece was worth seengi
</p>
<p>
A self portrait of the artist in a hot pink button up and tight black pants,
shot from a decidedly unflattering angle, looks down upon a car which sags with heavy curves of flesh.  The hood is chubby; the bumper and skirt, and
mirrors droop with cellulite; the door handle, and key hole are deep dimples. 
The whole car is the unreal pink of a &#8220;Flesh&#8221; crayon, and fat. Unlike West&#8217;s
more conceptual intestine, endless hours have clearly been put into to making
the hard plastic shell of this car look like you would squish into its fleshy
expanses if pushed up against it.  I feel as if we are supposed to be repulsed by its obesity, but to someone like myself who has never embraced the sleek metallic aesthetic of modern cars it is also sexy.
</p>
<p>
As we stand in awe, staring at this contrivance, we are excitedly informed by a
fellow museum goer that underneath all that pink excessive is &#8220;a Ford Escort!
Can you believe that?  A Ford Escort!&#8221;.  I feel deeply alienated from my
fellow citizens.
<img src="/img/aab.thumb.jpg"  align="right" width="150" height="141" border="0" /></p>

<p></p>
<p>
(Update:  Actually the photo behind the car is not the artist, a man, but the curator. 
Suddenly my whole understanding of the piece bucks, and swims before my eyes, as
I reconsider how I feel about it&#8230;)
</p>
<p>
<h3>Lois Weinberger</h3>
<img src="/img/aac.thumb.jpg"  align="left" width="150" height="119" border="0" /></p>

<p>Probably my favorite artist from the show, and probably the  understated. 
His little alcove revolved around a collection of plastic bags, filled with dirt
and plants under a grow light, <em>&#8220;Portable Garden&#8221;</em>.  The plants were weeds transplanted from the
grounds of MassMOCA, the bags I recognized from  Tijuana, but apparently they
are also popular among the Vienna&#8217;s poor immigrants from Eastern Europe, and
Africa.  Hard to capture in words, you could sense Weinberger&#8217;s deep sympathy
with these scrappy, unwelcome transplants.  A message that blended
environmentalisms, and social justice.
</p>
<p>
Against one wall was a large piece of newsprint in which a sprawling fictitious
city plan has been depicted, <em>&#8220;Course/Drift&#8221;</em>.  The city has grown smack up against its encircling
mountains, represented with topo lines, and is now trying to figure out how to
go on growing.  The cityscape is labeled, not with traditional names like Main St., or 6th Ave., but with a powerful and loaded vocabulary. (on which I
did not take notes, unfortunately)  A plaza might be named happiness, taxes,
lost, or ball game.  A concourse I remember was named &#8220;Upper Class Concert&#8221;, a 
little neighborhood block named &#8220;Revolution&#8221;. It conjured up one of Calvino&#8217;s
invisible cities, and I stood and stared for a long time. 
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://laughingmeme.org/2002/08/19/a-day-at-massmoca/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
