<?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>Bill Shupp &#187; PEAR</title>
	<atom:link href="http://blog.shupp.org/category/pear/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.shupp.org</link>
	<description>Software engineer, musician, space enthusiast</description>
	<lastBuildDate>Fri, 03 Feb 2012 22:00:58 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>		<item>
		<title>GitHub Pages + Pirum = Easy PEAR Channel</title>
		<link>http://blog.shupp.org/2010/12/24/github-pages-pirum-easy-pear-channel/</link>
		<comments>http://blog.shupp.org/2010/12/24/github-pages-pirum-easy-pear-channel/#comments</comments>
		<pubDate>Sat, 25 Dec 2010 06:00:07 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[GitHub]]></category>
		<category><![CDATA[PEAR]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=6895</guid>
		<description><![CDATA[I prefer managing my non-PEAR PHP dependencies (such as Zend Framework and PHPUnit) through PEAR channels when possible.  It's much easier to manage component installation, upgrades, etc..  Managing and hosting a PEAR channel (using the Chiara_PEAR_Server) is not always that simple, and can add too much overhead for small projects.  I like how Zend Framework [...]]]></description>
			<content:encoded><![CDATA[<p>I prefer managing my non-<a title="PEAR" href="http://pear.php.net">PEAR</a> PHP dependencies (such as <a title="Zend Framework" href="http://framework.zend.com">Zend Framework</a> and <a title="PHPUnit" href="http://phpunit.de">PHPUnit</a>) through PEAR channels when possible.  It's much easier to manage component installation, upgrades, etc..  Managing and hosting a PEAR channel (using the <a title="Chiara PEAR Server" href="http://pear.chiaraquartet.net/index.php?package=Chiara_PEAR_Server">Chiara_PEAR_Server</a>) is not always that simple, and can add too much overhead for small projects.  I like how Zend Framework leveraged google code to host its PEAR channel, and was able to update it simply through pushing to SVN, avoiding a web interface.  Since I've been accumulating some components recently that really don't fit into pear.php.net, I figured it was time set up a PEAR channel for distributing them, but didn't want to host it myself or have to use a web interface.   Turns out, it's really easy to do now.<span id="more-6895"></span></p>
<p><strong>Hosting using GitHub Pages</strong></p>
<p>Since I prefer <a href="http://github.com">GitHub</a> to <a href="http://code.google.com">Google Code</a> for hosting my open source repositories, I decided to take a look at their new <a title="GitHub Pages" href="http://pages.github.com">Pages</a> feature for project web hosting.  It's <em>super</em> easy to set up.  You can host content at <em>http://username.github.com</em> by creating a repository <em>username.github.com</em> (master branch), and can also host project related content at <em>http://username.github.com/project</em> by creating a top level <em>gh-pages</em> branch in the project.  I was up and running in minutes.  See <a title="GitHub Pages" href="http://pages.github.com">here</a> for specific instructions on setting it up.</p>
<p><strong>PEAR Channel Serving with Pirum</strong></p>
<p>I wasn't sure what the ZF guys were using to manage their channel, so I started by looking at <a title="PEAR2" href="http://pear2.php.net">PEAR2</a>'s <a title="SimpleChannelServer" href="http://pear2.php.net/PEAR2_SimpleChannelServer">SimpleChannelServer</a>.  While it looks promising, and you can even manage it directly from pyrus, I ran into enough errors that I thought I'd take a look <a title="Pirum" href="http://pirum-project.org">Pirum</a>, another simple channel server written by the <a title="Symfony" href="http://symfony-project.org">Symfony</a> project maintainer.  It worked for me right out of the box.  Setup was as simple as:</p>
<p><code><br />
pear channel-discover pear.pirum-project.org<br />
pear install pirum/Pirum<br />
cd ~/git/pirum<br />
# create pirum.xml file<br />
pirum build .<br />
# commit changes and push to github<br />
</code></p>
<p>So now releases through my PEAR channel look like this:</p>
<p><code><br />
# update PEAR package.xml, then run:<br />
pear package<br />
cd ~/git/pirum<br />
pirum add . ~/git/deneb/Deneb-0.3.0.tgz<br />
# commit changes and push to github<br />
</code></p>
<p>Now I've got an easily managed PEAR Channel that I don't have to host:  <a title="Bill Shupp's PEAR Channel" href="http://shupp.github.com/pirum">http://shupp.github.com/pirum</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2010/12/24/github-pages-pirum-easy-pear-channel/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Pragmatic tips for unit testing in PHP</title>
		<link>http://blog.shupp.org/2010/02/21/pragmatic-tips-for-unit-testing-in-php/</link>
		<comments>http://blog.shupp.org/2010/02/21/pragmatic-tips-for-unit-testing-in-php/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 23:38:32 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Digg]]></category>
		<category><![CDATA[PEAR]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHPUnit]]></category>
		<category><![CDATA[Unit Testing]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=51</guid>
		<description><![CDATA[Recently I've been hearing a lot of differing opinions about unit testing.  Some people just don't believe in it at all, others think the value it provides is only part of the picture, and that its cost should be weighed accordingly.  Some think that 100% test coverage should be the goal for high quality software.  [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I've been hearing a lot of differing opinions about unit testing.  Some people just don't believe in it at all, others think the value it provides is only part of the picture, and that its cost should be weighed accordingly.  Some think that 100% test coverage should be the goal for high quality software.  I personally think the cost of unit testing 100% of your code is worth it, but <strong>only</strong> if you can do it efficiently.  And that's the catch; there's a learning curve to become proficient at unit testing, especially with <a title="PHPUnit" href="http://phpunit.de">PHPUnit</a>, the most prominent unit testing framework for PHP.  Unit testing should never take more than 20-30% of your overall coding time, if you do it right.<span id="more-51"></span></p>
<p>Below are some things I keep in mind when coding and testing.  I thought I'd share them here in case anyone else finds them useful.</p>
<p><strong>Think about testability when you write code, not when you write the test<br />
</strong></p>
<p>This may not be new to you, especially if you're familiar with <a title="dependency injection" href="http://en.wikipedia.org/wiki/Dependency_injection">dependency injection</a> or <a title="TDD" href="http://en.wikipedia.org/wiki/Test-driven_development">test driven development</a>.  Your unit tests should be able to run in a vacuum:  No database access, no memcache access, no headers can be sent, etc.  (Sure those things can be tested separately, but should be a small subset of your code, not the overall application logic.)  To do this, make sure you abstract those dependencies.  For example, instead of instantiating a cache driver in the middle of your method, make a getter for it which you can mock:</p>
<p><script src="http://gist.github.com/310433.js?file=gistfile1.php"></script></p>
<p>If you do this abstraction when you code, there's less refactoring to be done when writing your tests.  Also, if your dependency doesn't make a network call upon instantiation, you can still test the getter using <a title="assertType() documentation" href="http://www.phpunit.de/manual/3.4/en/api.html#api.assert.assertType">assertType()</a>.  <a title="Memcached::addServer() documentation" href="http://www.php.net/manual/en/memcached.addserver.php">Memcached's addServer()</a> is an example of such a dependency - no connection is made until you do an operation.  If this is not the case, and you can't properly test the getter, you probably want wrap the getter in <code>@codeCoverageIgnore</code> annotations like so:</p>
<p><script src="http://gist.github.com/310488.js?file=gistfile1.php"></script></p>
<p>It doesn't make sense for code you never intend to test to count against your coverage percentage.</p>
<p><strong>Keep documentation handy</strong></p>
<p>PHPUnit is a big framework.  There are a lot of things to remember, including all the assertion methods available, data providers, and mocking objects, among other things.  Rather than always copying some other example, or bugging your co-worker, spend an hour or two, and <a title="PHPUnit Documentation" href="http://www.phpunit.de/wiki/Documentation">RTFM</a>.  You'll be better off for it.  A co-worker of mine kept a printout of the <a title="TestCase docs" href="http://www.phpunit.de/manual/3.4/en/api.html#api.testcase.tables.api">PHPUnit_Framework_TestCase::getMock()</a> documentation (probably the hardest to remember) taped to his monitor.  I prefer <a title="Delicious" href="http://delicious.com/">delicious</a> bookmarking, but to each his own.  Though I've been using PHPUnit for a couple of years now, I still refer to the documentation regularly.</p>
<p><strong>Don't worry about test code re-usability</strong></p>
<p>As good OOP programmers, we are often pre-occupied with writing elegant, re-usable code, even in tests.  I have recently given up on this in my unit tests, mostly due to scope issues in PHPUnit which I'll describe later.  Rather than try consolidate re-usable code, I'm more likely to copy and paste chunks throughout my test and <strong>know</strong> that they will work.  I think the goal of tests is to write useful assertions, not necessarily elegant, re-usable components.  Why do I care how many lines are in my test code?  You might be thinking "Doesn't that make your tests harder to maintain?"  Maybe so, but in the big picture, I don't think it adds much time, and once you've fixed something in one test, then you can quickly find it elsewhere.  It might not be pretty, but it is faster, and more pragmatic, at least until the tools are better.</p>
<p><strong>Mocking scope issues</strong></p>
<p>As I mentioned above, I've found (and reported) some strange behavior I've seen with scope and mocked objects.  One pattern I see people use is a <code>getMocks()</code> helper in a test, which returns an array of commonly used objects, pre-mocked with the most used defaults already set.  Sounds like a reasonable approach to testing a large class with lots of dependency needs, right?  <strong>Wrong</strong>.  What I've found is that many times (and my test results have been inconsistent, unfortunately), you cannot modify the return value of a mocked method after its expectation has already been set.  No warning or error is thrown when you do this, but the original mocked value is returned instead of the second value you assigned.  Re-mocking return values <strong>does</strong> seem to work when it's used for throwing exceptions, though.  It appears to be a scope issue, but again, my tests have not always been consistent.  The usual result is that you spent an hour pulling your hear out trying to figure out why your test is failing.  I eventually said <em>screw it</em>, and just never set default behaviour for my mocked methods.</p>
<p>I now use a pattern where I have getters in my test for each mocked dependency, which mock each method I may need, but don't set any initial expectations yet.  I'll then pass them all into the getter for the main class I'm trying to test, which attaches them for me.  This way, on a per test basis, I set the expectations of each dependency as needed.  This seems to work much more reliably:</p>
<p><script src="http://gist.github.com/310459.js?file=gistfile1.php"></script></p>
<p><strong>Meaningful assertions</strong></p>
<p>Another complaint I hear is that, especially when enforcing code coverage rules in your development shop, developers focus more on the required coverage than on the quality of the tests.  It's important to think about what it is you're testing.  If you just call a method to make sure you get your code coverage, you're doing it wrong.  There are lots of assertions you can do:  assert the type of the response, assert the content of the response, assert the message of the exception  thrown, the exception code, the type of exception, how many times a mocked method was called, etc.  But you want to be smart about it as well.  We had one case where the original test for a Form framework was testing the exact template output.  Since there was markup and JS in the ouput, every time a designer or JS developer modified it, the test would break.  After a few breaks, I modified the test to use <a title="DomDocument documentation" href="http://www.php.net/manual/en/class.domdocument.php">DomDocument</a> parsing, and make sure the relevant form ids and attributes were present, which is really what we wanted to assert.  <strong>If you don't write meaningful tests, don't bother writing them at all.</strong></p>
<p><strong>Useful tools</strong></p>
<p>Make sure it's easy to write and run your tests.  PHPUnit has options for generating skeletons, for example, to get you started quickly.  You can use --skeleton-class to generate a class from your test (if you're practicing TDD), or the reverse, --skeleton-test, to generate a test from your class.</p>
<p>Running tests should be easy too.  One thing to keep in mind is that your include path must be correct.  For example, when I'm developing a <a title="PEAR" href="http://pear.php.net">PEAR</a> package, I may have a previous version already installed, but am developing in my repository checkout.  I need to make sure my local files are not only in my include path, but that they are at the beginning.  A handy wrapper like this should allow you to always run your development code easily:      <script src="http://gist.github.com/310504.js?file=runTests.php"></script></p>
<p>If I put this in the root of my repository, I can then call it like so:</p>
<p><code>php runTests.php --coverage-html coverage OpenID_AllTests</code></p>
<p>(If this is a PEAR package, you'll want to ignore <code>runTests.php</code> when generating your package.xml file.)</p>
<p>At Digg, our development environment tools are based on <a href="http://en.wikipedia.org/wiki/Make_%28software%29">make</a>, and it's super easy to run not only your PHPUnit tests and coverage, but also chain together running <a title="PHP_CodeSniffer" href="http://pear.php.net/package/PHP_CodeSniffer">PHP_CodeSniffer</a> for coding standards compliance:</p>
<p><code>make coverage phpcs</code></p>
<p>Facebook has a good <a title="Facebook Post on Hiring and Tools" href="http://www.facebook.com/note.php?note_id=158285241831">post</a> about hiring in general, which includes a section on <a title="Writing Tools" href="http://www.facebook.com/note.php?note_id=171746501831">writing good tools</a> for your team.  This idea certainly applies to your testing tools.  The easier you make it for your team to write good unit tests, the better.</p>
<p><strong>Conclusion</strong></p>
<p>Unit testing in PHP is not that easy, in my opinion (compared to python, anyway).  Until you get good at it, that is, and learn to work around quirks in the tools.  Then it's really not that hard.  But everyone  values unit testing differently.  If you choose to invest in testing your code, perhaps you'll find some of the above useful.   I used to not think much about unit testing, until I had a few experiences where unit tests caught problems in my code <strong>before</strong> I had run into them myself.  At this point, I think unit testing my PHP code 100% is worth it, especially now that I can do it quickly and efficiently.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2010/02/21/pragmatic-tips-for-unit-testing-in-php/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>MogileFS, Zend Framework, Boobs, and Kittens</title>
		<link>http://blog.shupp.org/2010/02/10/mogilefs-zend-framework-boobs-and-kittens/</link>
		<comments>http://blog.shupp.org/2010/02/10/mogilefs-zend-framework-boobs-and-kittens/#comments</comments>
		<pubDate>Thu, 11 Feb 2010 06:37:24 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[Boobs]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Kittens]]></category>
		<category><![CDATA[MogileFS]]></category>
		<category><![CDATA[PEAR]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=25</guid>
		<description><![CDATA[An upcoming side project of mine requires the use of MogileFS and Zend Framework.  MogileFS is an open source distributed file system, meant to scale up to many millions of files without a single point of failure.  It's currently used by the likes of Digg and last.fm. Though I was already familiar with using MogileFS [...]]]></description>
			<content:encoded><![CDATA[<p>An upcoming side project of mine requires the use of <a title="MogileFS" href="http://www.danga.com/mogilefs/">MogileFS</a> and <a title="Zend Framework" href="http://framework.zend.com">Zend Framework</a>.  MogileFS is an open source distributed file system, meant to scale up to many millions of files without a single point of failure.  It's currently used by the likes of <a title="Digg" href="http://digg.com">Digg</a> and <a title="last.fm" href="http://last.fm">last.fm</a>.</p>
<p>Though I was already familiar with using MogileFS clients in <a title="File_Mogile" href="http://pear.php.net/package/file_mogile/redirected">php</a> and <a href="http://www.albany.edu/~ja6447/mogilefs.py">python</a> at work, the operations team actually runs the servers.   I wanted to get some experience with managing MogileFS itself (trackers, mogstored, mysql), and hopefully have a better understanding of how it all worked together.  While I was already familiar with Zend Framework, I'd never used it to serve images.  So, I figured I should build a quick prototype using both.  But what to build?  I decided to take inspiration from the notorious <a title="Explosions and Boobs" href="http://explosionsandboobs.com">http://explosionsandboobs.com</a>, but put my own spin on it.  The result?</p>
<p><a href="http://boobsandkittens.com">http://boobsandkittens.com</a><span id="more-25"></span></p>
<p>Bear in mind that the above URL is on my inexpensive <a title="Slicehost" href="http://slicehost.com">Slicehost</a> VPS, and can be slow at times.  This is a really simple application that allowed me to do a few things:</p>
<ul>
<li>scrape some content from google images search</li>
<li>store them in MogileFS</li>
<li>render the stored images through ZF</li>
</ul>
<p>The source is available <a title="Boobs and Kittens Source" href="http://github.com/shupp/bandk">here</a>.  The <a title="google images scraper" href="http://github.com/shupp/bandk/blob/master/application/cli/scrape.php">scraper</a> is pretty straight forward.  I just called it from the command line to save images to a directory.  Once saved to disk, I used the <a title="mogrify" href="http://www.imagemagick.org/script/mogrify.php">mogrify</a> tool from Imagemagick to scale the images down to a height of 400 px max, and visually removed the worst of the images (it's relatively SFW).  Next, I inserted those images into MogileFS with <a title="insertImage.php" href="http://github.com/shupp/bandk/blob/master/application/cli/insertImage.php">insertImage.php</a>.  There are only two real action controllers, the <a href="http://github.com/shupp/bandk/blob/master/application/controllers/IndexController.php">index page</a> and <a href="http://github.com/shupp/bandk/blob/master/application/controllers/ImageController.php">image renderer</a>.  The latter was really the only thing to learn on the php side of this project.  The key there was disabling the layout and view rendering, as well as setting the appropriate image information in the response object (content-type, content-length, and the content itself).  Since most of the logic is in the <a href="http://github.com/shupp/bandk/blob/master/application/models/Model/Images.php">model</a>, the action controllers are pretty skinny.  I used memcache to store db queries and the images from MogileFS to help offset the performance of a cheap VPS.  Since Zend Framework doesn't ship with a MogileFS client, I used the <a href="http://pear.php.net/package/file_mogile/redirected">PEAR</a> one.</p>
<p>That's it.  Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2010/02/10/mogilefs-zend-framework-boobs-and-kittens/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>2009 Year in Review</title>
		<link>http://blog.shupp.org/2010/01/16/2009-year-in-review/</link>
		<comments>http://blog.shupp.org/2010/01/16/2009-year-in-review/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 07:15:47 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Digg]]></category>
		<category><![CDATA[PEAR]]></category>
		<category><![CDATA[Travel]]></category>
		<category><![CDATA[Year In Review]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=8</guid>
		<description><![CDATA[I've been thinking about starting a blog for a while, and since it's the beginning of a new year, I thought I'd start out with a list of highlights from last year.  So here's my 2009 Year in Review: In the beginning of the year I officially became a manager at Digg, though I still [...]]]></description>
			<content:encoded><![CDATA[<p>I've been thinking about starting a blog for a while, and since it's the beginning of a new year, I thought I'd start out with a list of highlights from last year.  So here's my 2009 Year in Review:<span id="more-8"></span></p>
<ul>
<li>In the beginning of the year I officially became a manager at <a title="Digg, Inc." href="http://digg.com" target="_self">Digg</a>, though I still spend a majority of my time there coding.</li>
<li>In March I became an uncle again with the birth of my brother Mike's first child, Nina Taylor Shupp.</li>
<li>April 26th I ran my first 10.6 mile race as part of the <a title="Big Sur International Marathon" href="http://www.bsim.org" target="_self">Big Sur International Marathon</a>.  I finished in around 2 hours 40 minutes.  The course, on CA 1 along the Pacific ocean, has a lot of hills, but is amazingly beautiful.  I hope to do the full marathon next time.</li>
<li>In early May, Digg launched its <a title="Facebook Connect Blog Post" href="http://about.digg.com/blog/facebook-connect-launches-today" target="_self">Facebook Connect</a> integration.  This was a long project which for which I led the technical implementation.  It went really well, and saw an initial increase in registrations upwards of 50%.  It was also covered on <a title="Tech Crunch" href="http://www.techcrunch.com/2009/05/06/digg-to-launch-facebook-connect-today/" target="_self">Tech Crunch</a>.</li>
<li>Later that month I gave an internal "Brown Bag Tech Talk" on <a title="OpenID" href="http://openid.net" target="_self">OpenID</a>.  The slides are available <a title="Slideshare" href="http://www.slideshare.net/billshupp/openid-an-in-depth-look-at-what-it-is-and-what-it-can-do-for-you" target="_self">here</a>.</li>
<li>In June, Peggy and I celebrated our second wedding anniversary just before heading out for a 16 day vacation in Europe.  We visited Paris, Copenhagen, Lunde, Tallinn, Kiel, Hamburg, St. Petersburg, Helsinki, and Stockholm.</li>
<li>In July, myself and a few colleagues at Digg handed in our contribution to a forthcoming <a href="http://qualityassuranceinphpprojects.com/">book</a> on PHP unit testing.  The book is a case study on using <a title="PHP Unit" href="http://phpunit.de" target="_self">PHPUnit</a> and continuous integration by <a title="Sebastian Bergmann" href="http://sebastian-bergmann.de/" target="_self">Sebastian Bergmann</a>.  It's currently being translated into German, and should be out this year in both German and English.</li>
<li>Later that month I spoke at OSCAMP 2009 on contributing to the <a title="PEAR" href="http://pear.php.net" target="_self">PEAR</a> project (the PHP Extension and Application Repository).  The slides are available <a title="Slideshare" href="http://www.slideshare.net/billshupp/contributing-to-pear-dos-and-donts" target="_self">here</a>.</li>
<li>In August, I ran for and was <a title="PEAR Group Election Blog Post" href="http://blog.pear.php.net/2009/08/10/the-new-group-has-been-elected/" target="_self">elected</a> to The PEAR Group, the governing body of PEAR.</li>
<li>That same month, I played drums on a new album with <a title="The Whitehalls" href="http://thewhitehalls.com" target="_self">The Whitehalls</a> (formerly Heathrow), a band I've been playing with since shortly after moving up to San Francisco.  The record is almost done, and should be out soon.</li>
<li>In October I attended my first high school reunion.  It was entertaining, and I really enjoyed seeing a few people, but for the most part it was pretty much exactly what I expected.</li>
<li>We spent Thanksgiving up in Kohler, WI on lake Michigan where some of Peg's family was gathering.  One highlight of the trip was taking a <a title="Peggy on a Segway" href="http://twitpic.com/rhq89" target="_self">segway tour</a> of Chicago's waterfront on the way back.</li>
<li>December 1st I closed down my long running web hosting service, <a title="MerchBox" href="http://merchbox.com/" target="_self">MerchBox</a>, which I started back in 2000.</li>
<li>Just after that saw the <a title="Digg Blog" href="http://about.digg.com/blog/creating-writable-apps-new-digg-api" target="_self">release</a> of Digg's second generation API, another long project which I led initially, and contributed a good amount to.  We also knocked out a fun reference application on a Sunday afternoon to help developers get up and running, which you can see <a title="Digg Lite" href="http://digglite.com" target="_self">here</a>.</li>
<li>Also in December, The Whitehalls participated in <a title="Silicon Valley Rocks 2009" href="http://svrocks.com/" target="_self">Silicon Valley Rocks 2009</a>, a benefit for <a title="MuST" href="http://www.mustcreate.org/">Music in Schools Today</a> that raised $27,000.</li>
<li>We spent Christmas and New Year's Eve back in northern Virginia, and were able to get in a fair amount of time at the Smithsonian.  I wish I had appreciated it when I lived there.</li>
<li>Closing out the month saw the acceptance into PEAR of two libraries I wrote, <a title="PEAR OpenID Proposal" href="http://pear.php.net/pepr/pepr-proposal-show.php?id=603" target="_self">OpenID</a> and <a title="PEAR Services_Digg2 proposal" href="http://pear.php.net/pepr/pepr-proposal-show.php?id=622" target="_self">Services_Digg2.</a></li>
</ul>
<p>Cheers,</p>
<p>Bill Shupp</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2010/01/16/2009-year-in-review/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

