<?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>Jay Paroline - Grooveshark Dev &#187; Coding</title>
	<atom:link href="http://wanderr.com/jay/category/coding/feed/" rel="self" type="application/rss+xml" />
	<link>http://wanderr.com/jay</link>
	<description>Rantings of a Grooveshark Developer</description>
	<lastBuildDate>Fri, 30 Jul 2010 18:31:45 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Why You Should Always Wrap Your Package</title>
		<link>http://wanderr.com/jay/why-you-should-always-wrap-your-package/2010/07/30/</link>
		<comments>http://wanderr.com/jay/why-you-should-always-wrap-your-package/2010/07/30/#comments</comments>
		<pubDate>Fri, 30 Jul 2010 18:31:45 +0000</pubDate>
		<dc:creator>Jay</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[grooveshark]]></category>
		<category><![CDATA[software engineering]]></category>

		<guid isPermaLink="false">http://wanderr.com/jay/?p=388</guid>
		<description><![CDATA[Ok, the title is a bit of a stretch, but it&#8217;s a good one isn&#8217;t it? What I really want to talk about is an example of why it&#8217;s a good idea to make wrappers for PHP extensions instead of just using them directly. When Grooveshark started using memcached ever-so-long-ago, with the memcache pecl extension, [...]]]></description>
			<content:encoded><![CDATA[<p>Ok, the title is a bit of a stretch, but it&#8217;s a good one isn&#8217;t it?</p>
<p>What I really want to talk about is an example of why it&#8217;s a good idea to make wrappers for PHP extensions instead of just using them directly.</p>
<p>When Grooveshark started using memcached ever-so-long-ago, with the memcache pecl extension, we decided to create a GMemcache class which extends memcache. Our main reason for doing this was to add some convenience (like having the constructor register all the servers) and to add some features that the extension was missing (like key prefixes). We recently decided that it&#8217;s time to move from the stagnant memcache extension to the pecl memcached extension, which is based on libmemcached, which supports many nifty features we&#8217;ve been longing for, such as:</p>
<ul>
<li>Binary protocol</li>
<li>Timeouts in milliseconds, not seconds</li>
<li>getByKey</li>
<li>CAS</li>
<li>Efficient consistent hashing</li>
<li>Buffered writes</li>
<li>Asyncronous I/O</li>
</ul>
<p>Normally such a transition would be a nightmare. Our codebase talks to memcached in a million different places. But since we&#8217;ve been using a wrapper from day 1, I was able to make a new version of GMemcache with the same interface as the old one, that extends memcached. It handles all the minor differences between how the two work, so all the thousands of other lines in the app that talk to memcached do not have to change. That made the conversion a &lt;1 day project, when it probably would have otherwise been a month long project. It also has the advantage that if we decide for some reason to go back to using pecl memcache, we only have to revert one file.</p>
]]></content:encoded>
			<wfw:commentRss>http://wanderr.com/jay/why-you-should-always-wrap-your-package/2010/07/30/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP Order of Operations Gotcha</title>
		<link>http://wanderr.com/jay/php_order_of_operation/2009/09/04/</link>
		<comments>http://wanderr.com/jay/php_order_of_operation/2009/09/04/#comments</comments>
		<pubDate>Fri, 04 Sep 2009 15:59:35 +0000</pubDate>
		<dc:creator>Jay</dc:creator>
				<category><![CDATA[Coding]]></category>

		<guid isPermaLink="false">http://wanderr.com/jay/?p=252</guid>
		<description><![CDATA[PHP&#8217;s decision to give addition, subtraction and string concatenation equal precedence has caused some difficult to track down bugs on several occasions. It&#8217;s so non-intuitive I have difficulty remembering this one, and hence keep writing wrong code. Example: $tacos = "Robots: " . 1 + 2 . " for the win!"; I think a normal [...]]]></description>
			<content:encoded><![CDATA[<p>PHP&#8217;s decision to give addition, subtraction and string concatenation equal precedence has caused some difficult to track down bugs on several occasions. It&#8217;s so non-intuitive I have difficulty remembering this one, and hence keep writing wrong code.</p>
<p>Example:</p>
<p><code>$tacos = "Robots: " . 1 + 2 . " for the win!";</code></p>
<p>I think a normal human would expect $tacos to be equal to &#8220;Robots: 3 for the win!&#8221;. But the result is actually &#8220;2 for the win!&#8221;</p>
<p>What gives? Well, the PHP docs say that plus, minus and string concatenation all get equal precedence, with left associativity. So going from left to right, it says:<br />
&#8220;Robots: &#8221; . 1 | &#8220;Robots: 1&#8243; so far, so good.<br />
&#8220;Robots: 1&#8243; + 2 => (int)&#8221;Robots: 1&#8243; + 2; | &#8220;Robots: 1&#8243; converts to 0, so 0 + 2<br />
2 . &#8221; for the win!&#8221; | &#8220;2 for the win!&#8221; D&#8217;oh!</p>
<p>I think it would make a lot more sense for string concatenation to take a lower precedence than any arithmetic. </p>
<p>The correct way to write the above code is:</p>
<p><code>$tacos = "Robots: " . (1 + 2) . " for the win!";</code></p>
]]></content:encoded>
			<wfw:commentRss>http://wanderr.com/jay/php_order_of_operation/2009/09/04/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Bypassing Magic</title>
		<link>http://wanderr.com/jay/bypassing-magic/2009/08/18/</link>
		<comments>http://wanderr.com/jay/bypassing-magic/2009/08/18/#comments</comments>
		<pubDate>Tue, 18 Aug 2009 12:00:46 +0000</pubDate>
		<dc:creator>Jay</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[grooveshark]]></category>

		<guid isPermaLink="false">http://wanderr.com/jay/?p=217</guid>
		<description><![CDATA[In my post about how we are adding client-side caching to Grooveshark 2.0, I mentioned one of the ways we are taking advantage of the fact that thanks to using Flash, we have a full-blown stateful application. As Grooveshark evolves and the application becomes more sophisticated, the PHP layer is more and more becoming just [...]]]></description>
			<content:encoded><![CDATA[<p>In my post about how we are adding <a href="http://wanderr.com/jay/client-side-caching/2009/08/15/">client-side caching</a> to Grooveshark 2.0, I mentioned one of the ways we are taking advantage of the fact that thanks to using Flash, we have a full-blown stateful application.</p>
<p>As Grooveshark evolves and the application becomes more sophisticated, the PHP layer is more and more becoming just an interface to the DB. The application just needs the data; it knows exactly what to do with it from there. It also only needs to ask for one type of data at a time, whereas a traditional webpage would need to load dozens of different pieces of information at the same time. So for our type of application, magic methods and ORM can really just get in the way when all we really need is to run a query, fill up an array with the results of that query, and return it.</p>
<p>Our old libraries employing ORM, magic methods and collections, were designed to meet the needs of a typical website and don&#8217;t necessarily make sense for a full-fledged application. On a webpage, you might only show 20 results at a time, so the overhead of having a bunch of getters and setters automatically fire whenever you load up your data is probably not noticeable. But in an application, you often load far more results than can be displayed, and allow the user to interact with them more richly. When you&#8217;re loading 500, or 5000 results as opposed to 20, the overhead of ORM and magic can start to really bog you down. I first noticed the overhead issue when testing new method calls for lite2, when in some cases fetching the data would take over 30 seconds, triggering my locally defined maximum execution time, <b>even when the data was already cached</b>.</p>
<p>Like any responsible developer considering making changes to code for performance reasons, I profiled our collections code using XDebug and KCachegrind, and then I rewrote the code to bypass collections, magic and all that stuff, loading data from the DB (or memcache) into an array and returning it. The difference? In the worst case, bypassing magic was an order of magnitude less work, often times far better than that. My > 30 second example took less than 1 second in the new code.</p>
<p>For Grooveshark 2.0 code, wherever makes sense, we are bypassing magic, ORM and collections and loading data directly. This of course means that Grooveshark is faster, but it also means that we can load more data at once. In most cases we can now afford to load up entire lists of songs without having to paginate the results, which in turn means fewer calls to the backend *and* much less work for the database. Whenever you must LIMIT results, you must also ORDER BY the results so they come back in an order that makes sense. Not having to ORDER results means in many cases we save an expensive filesort which often requires a temporary table in MySQL. Returning the full data set also allows the client to do more with the data, like decide how the results should actually be sorted and displayed to the user. But that&#8217;s another post&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://wanderr.com/jay/bypassing-magic/2009/08/18/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Detect crawlers with PHP faster</title>
		<link>http://wanderr.com/jay/detect-crawlers-with-php-faster/2009/04/08/</link>
		<comments>http://wanderr.com/jay/detect-crawlers-with-php-faster/2009/04/08/#comments</comments>
		<pubDate>Wed, 08 Apr 2009 13:03:30 +0000</pubDate>
		<dc:creator>Jay</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[grooveshark]]></category>

		<guid isPermaLink="false">http://wanderr.com/jay/?p=166</guid>
		<description><![CDATA[At Grooveshark we use DB-based php sessions so they can be accessed across multiple front-end nodes. As you would expect, the sessions table is very &#8220;hot,&#8221; as just about every request to do anything, ever, requires using a session. We noticed that web crawlers like google end up creating tens of thousands of sessions every [...]]]></description>
			<content:encoded><![CDATA[<p>At Grooveshark we use DB-based php sessions so they can be accessed across multiple front-end nodes. As you would expect, the sessions table is very &#8220;hot,&#8221; as just about every request to do anything, ever, requires using a session. We noticed that web crawlers like google end up creating tens of thousands of sessions every day, because they of course do not carry cookies around with them.</p>
<p>The solution? Add a way to detect crawlers, and don&#8217;t give them sessions. Most of the solutions I&#8217;ve seen online look something <a href="http://www.cult-f.net/2008/05/07/detect-crawlers-with-php/">like this</a>:</p>
<p><code>function crawlerDetect($USER_AGENT)<br />
{<br />
    $crawlers = array(<br />
    array('Google', 'Google'),<br />
    array('msnbot', 'MSN'),<br />
    array('Rambler', 'Rambler'),<br />
    array('Yahoo', 'Yahoo'),<br />
    array('AbachoBOT', 'AbachoBOT'),<br />
    array('accoona', 'Accoona'),<br />
    array('AcoiRobot', 'AcoiRobot'),<br />
    array('ASPSeek', 'ASPSeek'),<br />
    array('CrocCrawler', 'CrocCrawler'),<br />
    array('Dumbot', 'Dumbot'),<br />
    array('FAST-WebCrawler', 'FAST-WebCrawler'),<br />
    array('GeonaBot', 'GeonaBot'),<br />
    array('Gigabot', 'Gigabot'),<br />
    array('Lycos', 'Lycos spider'),<br />
    array('MSRBOT', 'MSRBOT'),<br />
    array('Scooter', 'Altavista robot'),<br />
    array('AltaVista', 'Altavista robot'),<br />
    array('IDBot', 'ID-Search Bot'),<br />
    array('eStyle', 'eStyle Bot'),<br />
    array('Scrubby', 'Scrubby robot')<br />
    );<br />
    foreach ($crawler as $c) {<br />
        if (stristr($USER_AGENT, $c[0])) {<br />
            return($c[1]);<br />
        }<br />
    }<br />
    return false;<br />
}<br />
</code><br />
Essentially, doing a for loop over the entire list of possible clients, and searching the user agent string for each one, one at a time. This seems way too slow and inefficient for something that is going to have to run on essentially every call on a high volume website, so I rewrote it to look like this:<br />
<code>public static function getIsCrawler($userAgent)<br />
    {<br />
        $crawlers = 'Google|msnbot|Rambler|Yahoo|AbachoBOT|accoona|' .<br />
                    'AcioRobot|ASPSeek|CocoCrawler|Dumbot|FAST-WebCrawler|' .<br />
                    'GeonaBot|Gigabot|Lycos|MSRBOT|Scooter|AltaVista|IDBot|eStyle|Scrubby';<br />
        $isCrawler = (preg_match("/$crawlers/", $userAgent) > 0);<br />
        return $isCrawler;<br />
    }</code></p>
<p>In my not-very-scientific testing, running on my local box my version takes 11 seconds to do 1 million comparisons, whereas looping through an array of crawlers to do 1 million comparisons takes 70 seconds. So there you have it, using a single regex for string matching rather than looping over an array can be 7 times faster. I suspect, but have not tested, that the performance gap gets bigger the more strings you are testing against.</p>
]]></content:encoded>
			<wfw:commentRss>http://wanderr.com/jay/detect-crawlers-with-php-faster/2009/04/08/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>The Art of Elegant Code: Eliminating special cases that aren&#8217;t</title>
		<link>http://wanderr.com/jay/the-art-of-elegant-code-eliminating-special-cases-that-arent/2009/02/18/</link>
		<comments>http://wanderr.com/jay/the-art-of-elegant-code-eliminating-special-cases-that-arent/2009/02/18/#comments</comments>
		<pubDate>Wed, 18 Feb 2009 07:53:47 +0000</pubDate>
		<dc:creator>Jay</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[grooveshark]]></category>

		<guid isPermaLink="false">http://wanderr.com/jay/?p=157</guid>
		<description><![CDATA[One of my personal pet peeves is code that contains a bunch of conditional logic to handle seemingly special cases that really aren&#8217;t. For example, let&#8217;s say we have a page that shows a user their playlists if they are logged in, but this page also has other useful information on it, and users aren&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>One of my personal pet peeves is code that contains a bunch of conditional logic to handle seemingly special cases that really aren&#8217;t.</p>
<p>For example, let&#8217;s say we have a page that shows a user their playlists if they are logged in, but this page also has other useful information on it, and users aren&#8217;t required to log in. In our original design for our authentication class, if authentication &#8220;failed&#8221; (i.e. the user was not logged in), a call to Auth::getUserID() would return an empty string.</p>
<p>With that implementation, every piece that might have something to display to a logged in user has to have a bunch of conditional logic checking to see if the user is logged in, doing one thing i they are and another if they are not, adding unnecessary complexity and, of course, more potential for bugs to crop up.</p>
<p>This type of logic is completely unnecessary. I changed Auth to return a userID of 0 if the user is not logged in, and now it is not necessary to have any special handling for that case. If the user is logged in, they get playlists. If the user is not logged in, userID 0 does not have any playlists so they do not get playlists. I estimate that this simple change made over 100 lines of code obsolete. Not a whole lot of code in the grand scheme of things, but how many bugs can hide in 100 lines of code?</p>
<p>Another example of the same principle involves exceptions (which, as regular readers of Raymond Chen know, <a href="http://blogs.msdn.com/oldnewthing/archive/2005/01/14/352949.aspx">are hard to deal with</a>). Under certain circumstances, recommendations from an external source can be included with our normal set of recommendations. The author of the recommendation-supplementing code originally had it throwing exceptions whenever it had problems. Of course, the case of not having supplemental recommendations because of an error is not really a special case. As far as my code is concerned, you just don&#8217;t have supplemental recommendations. In this case modifying the original code eliminates unnecessary handling for a special case and eliminates the potential for an uncaught exception to slip through.</p>
<p>A general rule of thumb to help avoid unnecessary special cases, at least with PHP, is to always return what you say you are going to return (and don&#8217;t throw exceptions). If your method processes some data which results in an array, return an array even if the processing has no results. This is the way most native methods in PHP already work, if you think about it. count(array()) doesn&#8217;t return an empty string or null or raise an exception, nor does count(null). Really, neither of these are special cases. In either case, the number of elements is zero, and developers are not required to care about the differences.</p>
]]></content:encoded>
			<wfw:commentRss>http://wanderr.com/jay/the-art-of-elegant-code-eliminating-special-cases-that-arent/2009/02/18/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How I Broke Grooveshark Lite &#8211; update</title>
		<link>http://wanderr.com/jay/how-i-broke-lite-update/2008/12/10/</link>
		<comments>http://wanderr.com/jay/how-i-broke-lite-update/2008/12/10/#comments</comments>
		<pubDate>Thu, 11 Dec 2008 03:17:36 +0000</pubDate>
		<dc:creator>Jay</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[grooveshark]]></category>

		<guid isPermaLink="false">http://wanderr.com/jay/?p=131</guid>
		<description><![CDATA[After some poking around and scratching our heads a bit, Katy and I were able to discover the source of the problem. Turns out what I hit is a compiler/language/optimization bug. Katy has more about it here, including the generic code we were able to distill it down to in order to cause the breakage. [...]]]></description>
			<content:encoded><![CDATA[<p>After some poking around and scratching our heads a bit, Katy and I were able to discover the source of the problem. Turns out what I hit is a compiler/language/optimization bug. <a href="http://thingsthatwork.net/index.php/2008/12/09/obscure-as3-for-switch-if-false-verify-erro/">Katy has more about it here</a>, including the generic code we were able to distill it down to in order to cause the breakage.</p>
<p>We thought it was a permutation of <a href="http://bugs.adobe.com/jira/browse/ASC-1798">this bug</a> which is fixed, but apparently this is a new one, so we are going to file it.</p>
<p>I find it a bit disturbing that the related bug was brought to their attention in 2006 and the limited fix was only released to the general public 2 months ago. Over two years to release a fix to a language bug?!? From the comments on the bug, they do not seem to take it very seriously:</p>
<blockquote><p>Fixed in the avmplus mainline. I&#8217;d suggest a 10.0 target date, since the change will need soaking time, there is a work-around and it is rare to encounter this problem.</p>
<p>Change 243008 by rreitmai@rickr-dev on 2006/09/08 12:37:23</p>
<p>Severity: important<br />
Summary: Verifier error bugfix</p>
<p>Detailed Description:</p>
<p>An optimization in the verifier allows us to avoid checking for null in various circumstances. Unfortunately, we were being a little too aggressive and we missed a case. If a block is a target of a backwards branch then we need to assume upon entry of the block that no check has been performed.</p>
<p>The other way to fix this would be to emit null checks just prior to the branch for any values that have notNull true, but this could also create a bunch of unnecessary checks.</p></blockquote>
<p>Aren&#8217;t obscure language bugs the absolute worst kind to have? In my case, it first went undetected because it didn&#8217;t trigger any errors/warnings with the debug version of flash (although our sample condensed code does), and then it was extremely difficult to track down because THE CODE WAS CORRECT, and when the production version of flash fails, it does so silently.</p>
]]></content:encoded>
			<wfw:commentRss>http://wanderr.com/jay/how-i-broke-lite-update/2008/12/10/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How I broke Grooveshark Lite</title>
		<link>http://wanderr.com/jay/how-i-broke-grooveshark-lite/2008/12/07/</link>
		<comments>http://wanderr.com/jay/how-i-broke-grooveshark-lite/2008/12/07/#comments</comments>
		<pubDate>Sun, 07 Dec 2008 06:18:43 +0000</pubDate>
		<dc:creator>Jay</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[grooveshark]]></category>

		<guid isPermaLink="false">http://wanderr.com/jay/?p=128</guid>
		<description><![CDATA[I am a PHP and MySQL developer, primarily, and my main responsibility is the server-side Grooveshark Lite components. A couple of days ago I got to write my first ever Actionscript for the Grooveshark Lite front end; an ad rotator to handle ads more statefully and therefore more intelligently. First I ran into a horrible [...]]]></description>
			<content:encoded><![CDATA[<p>I am a PHP and MySQL developer, primarily, and my main responsibility is the server-side Grooveshark Lite components. A couple of days ago I got to write my first ever Actionscript for the Grooveshark Lite front end; an ad rotator to handle ads more statefully and therefore more intelligently.</p>
<p>First I ran into a horrible language bug that causes a nasty runtime crash wherein Flash complains that it can&#8217;t resolve a class with itself. I wasn&#8217;t doing any weird voodoo with class definitions and Katy, our primary Flex developer, couldn&#8217;t find anything wrong with my code, but rewrote some of it anyway. Poof, problem fixed.</p>
<p>Everything looked fine so we thought we were ready to launch. So we did last night. Skyler complained that album art wasn&#8217;t loading for him, but he had just reinstalled 64 bit flash on 64 bit Linux, and he&#8217;s had weird problems with that before. We were unable to reproduce, attributed it to Flash+Linux weirdness and ignored the issue. Today, more people complained about it. We were not able to reproduce. Eventually I figured out that the bug was only affecting non-debug versions of Flash, but I couldn&#8217;t imagine what would be causing album art to not display: my code has nothing to do with displaying images, and I could see in Firebug that the art was being fetched properly, nothing was wrong with the headers, etc.. But it definitely worked fine in the debug version of Flash. Katy looked at it, and through process of elimination was able to determine that the problem was somewhere in my code, but couldn&#8217;t tell where exactly. Everything looked valid, and from the perspective of the debug version of Flash, it was, but my code wasn&#8217;t very &#8220;actionscripty&#8221; &#8211; because I&#8217;m used to writing PHP and haven&#8217;t had any sort of training on actionscript beyond looking at existing code and occasionally looking at a language reference book. Katy couldn&#8217;t figure out what was wrong with my code, so she rewrote it, and now everything is back to normal again. </p>
<p>I don&#8217;t yet know what part of my code was causing the problem, so on Monday I plan to reinstate my code, downgrade to the non-debug version of flash, and figure out what the heck is causing the bug. My instinct tells me that it&#8217;s probably a combination of an optimization setting in non-debug Flash combined with my use of Actionscript in a way that is technically valid but that no Actionscript coder would ever normally use it. For example, Katy says I was using a generic Object as a Dictionary, because I was actually trying to replicate associative arrays in PHP, I didn&#8217;t know about the Dictionary object, and when I had asked previously how to do that, I was told to use an Object. :P</p>
<p>The good news is that I don&#8217;t think many people outside the company paid much attention to this bug. They were too busy being excited about the new features that Katy introduced: broadcast to twitter, broadcast to facebook, and deep linking support: When you &#8220;byte&#8221; a song (open the info panel), your URL bar changes. You can simply copy the URL to share with a friend, *and* clicking back and forward work, so if you want to go from the song you opened back to the playlist you found it on, just click back in your browser. Freaky, but it works.</p>
]]></content:encoded>
			<wfw:commentRss>http://wanderr.com/jay/how-i-broke-grooveshark-lite/2008/12/07/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Leaky Abstractions</title>
		<link>http://wanderr.com/jay/leaky-abstractions/2008/09/12/</link>
		<comments>http://wanderr.com/jay/leaky-abstractions/2008/09/12/#comments</comments>
		<pubDate>Fri, 12 Sep 2008 09:30:02 +0000</pubDate>
		<dc:creator>Jay</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[grooveshark]]></category>
		<category><![CDATA[software engineering]]></category>

		<guid isPermaLink="false">http://wanderr.com/jay/?p=109</guid>
		<description><![CDATA[As with nearly every issue in Software Engineering worth thinking about, Joel Spolsky has written an article about leaky abstractions that is very relevant to some problems I ran into tonight. Abstractions do not really simplify our lives as much as they were meant to. [...] all abstractions leak, and the only way to deal [...]]]></description>
			<content:encoded><![CDATA[<p>As with nearly every issue in Software Engineering worth thinking about, Joel Spolsky has written an article about <a href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html">leaky abstractions</a> that is very relevant to some problems I ran into tonight.</p>
<blockquote><p>Abstractions do not really simplify our lives as much as they were meant to. [...] all abstractions leak, and the only way to deal with the leaks competently is to learn about how the abstractions work and what they are abstracting. So the abstractions save us time working, but they don&#8217;t save us time learning [...] and all this means that paradoxically, even as we have higher and higher level programming tools with better and better abstractions, becoming a proficient programmer is getting harder and harder</p></blockquote>
<p>In my case, I was not working with programming tools per se, more of an abstraction of an abstraction built into the Grooveshark framework that is meant to make life as a programmer easier. And normally it does. But in this case, that abstraction was wrapped in a couple more layers of abstraction away from where my code needed the information, and somewhere in there the information was, for lack of a better description, being mangled. The particular form of mangling is actually due to a lower level abstraction at the DB layer, but is not handled in the higher level of abstraction because for most uses it doesn&#8217;t matter.</p>
<p>From the level of abstraction where <i>my</i> code was sitting, the information needed in order to un-mangle the data was simply not available. I went through the various layers to find a convenient place to put the un-mangling, but by the time I found a place, everything was so abstract that I couldn&#8217;t confidently modify that code and see all potential ramifications, so I just did an end-run around many of the layers of abstraction. This is certainly not ideal, but it works. The point is, an abstraction intended to make life as a programmer slightly easier most of the time, can easily make life as a programmer significantly more difficult on edge cases. Unfortunately, once a code base has been established, most cases are edge cases: feature additions, new products built on top of the old infrastructure, etc., all or most unforeseen, and therefore unaccounted for during the original design process.</p>
]]></content:encoded>
			<wfw:commentRss>http://wanderr.com/jay/leaky-abstractions/2008/09/12/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Who will monitor the monitors?</title>
		<link>http://wanderr.com/jay/who-will-monitor-the-monitors/2008/08/21/</link>
		<comments>http://wanderr.com/jay/who-will-monitor-the-monitors/2008/08/21/#comments</comments>
		<pubDate>Thu, 21 Aug 2008 19:39:15 +0000</pubDate>
		<dc:creator>Jay</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[software engineering]]></category>

		<guid isPermaLink="false">http://wanderr.com/jay/?p=102</guid>
		<description><![CDATA[This is the second time that an error in a monitoring/testing tool that we use has caused me to waste a good deal of time trying to solve a non-problem. The first was when we were using a tool to test the scaling performance of a new feature. According to this tool the performance was [...]]]></description>
			<content:encoded><![CDATA[<p>This is the second time that an error in a monitoring/testing tool that we use has caused me to waste a good deal of time trying to solve a non-problem.</p>
<p>The first was when we were using a tool to test the scaling performance of a new feature. According to this tool the performance was absolutely abysmal with only 50 virtual clients, and I spent a couple of days writing alternative algorithms and trying to test them with this tool. The scalability was horrible no matter what I did, so I added some logging to see if something was going on that wasn&#8217;t supposed to be. It was. The testing tool was sending completely wrong information, creating completely unrealistic scenarios. The testing implementation was done by another developer who was sure that he had set it up right, and I was not familiar with the tool so I assumed that it was a problem with my code. Having another developer write the tests was supposed to <i>save</i> me time.</p>
<p>The latest monitoring snag was caused by a monitoring tool that, for our convenience, tails the php error log and sends the last couple hundred lines to us whenever there is an error. We kept getting the same error periodically and could not track down the source; everything seemed to be working perfectly, but we still got the error. Usage of the site every day is breaking new records so we assumed that it had something to do with the unprecedented load on servers, but could never pinpoint the source of the errors. Today I looked a bit more closely at the error log only to discover that the log was from 3 days ago!</p>
<p>So the question is, when your testing or monitoring tools report an error, how do you ensure that the error is real and not just in the tool itself?</p>
]]></content:encoded>
			<wfw:commentRss>http://wanderr.com/jay/who-will-monitor-the-monitors/2008/08/21/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>On being a DJ</title>
		<link>http://wanderr.com/jay/on-being-a-dj/2008/08/18/</link>
		<comments>http://wanderr.com/jay/on-being-a-dj/2008/08/18/#comments</comments>
		<pubDate>Mon, 18 Aug 2008 17:55:28 +0000</pubDate>
		<dc:creator>Jay</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[grooveshark]]></category>
		<category><![CDATA[life]]></category>
		<category><![CDATA[music]]></category>

		<guid isPermaLink="false">http://wanderr.com/jay/?p=99</guid>
		<description><![CDATA[When I was in college (oh so long ago&#8230;) I was a DJ for our radio station, and then I was a music director. I loved being a DJ: having lots of new, interesting and unreleased music on tap, from Smashing Pumpkins to Underwater Boxer; having a channel to share that music with other people; [...]]]></description>
			<content:encoded><![CDATA[<p>When I was in college (oh so long ago&#8230;) I was a DJ for our radio station, and then I was a music director. I loved being a DJ: having lots of new, interesting and unreleased music on tap, from Smashing Pumpkins to Underwater Boxer; having a channel to share that music with other people; being able to make a small band&#8217;s day by playing their stuff and reporting it to CMJ. Well, there was one part I didn&#8217;t care for so much: talking on the radio. I&#8217;m a bit shy, which is why although I loved being a DJ and music director at Eckerd College, I knew it wasn&#8217;t ever going to be a career path for me.</p>
<p>It&#8217;s interesting, then, that I work at Grooveshark where much of that dream is being fulfilled by participating in this movement. The one piece that is missing is having a channel to share music with other people and subsequently helping small bands by making them more discoverable. Well, now with the release of Autoplay in Grooveshark Lite, it&#8217;s kind of like I get to be everybody&#8217;s DJ. Of course a computer scientist would write a DJing program rather than doing the manual labor of DJing.</p>
<p>As Professor Fishman, the best professor who ever lived, was fond of saying in our classes, a computer scientist isn&#8217;t satisfied with just using computers to put other people out of a job, they won&#8217;t settle until they manage to put themselves out of a job too. To be fair, he usually talked about that in the context of AI and specifically programming languages such as LISP, where the program can rewrite itself, but I think it applies here as well.</p>
<p>Now I get to be everyone&#8217;s DJ, but with everyone&#8217;s help too. If the system is currently a bad DJ, keep giving it feedback and it will learn. Imagine if you got to call up your local radio station and yell at them every time they played something you didn&#8217;t like, and congratulate them every time they played something you liked. If they didn&#8217;t block your phone number, you&#8217;d end up with the ultimate radio station for you, and that&#8217;s what Grooveshark aims to be, although we admit it will take some time to get there.</p>
<p><a href="http://listen.grooveshark.com/">Check out Autoplay</a>, and let me know what you think.</p>
]]></content:encoded>
			<wfw:commentRss>http://wanderr.com/jay/on-being-a-dj/2008/08/18/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk
Page Caching using disk (user agent is rejected)

Served from: wanderr.com @ 2010-07-30 22:03:21 -->