<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>David Lynch</title>
 <link href="http://davidlynch.org/atom.xml" rel="self"/>
 <link href="http://davidlynch.org/"/>
 <updated>2012-05-11T09:36:25-05:00</updated>
 <id>http://davidlynch.org/</id>
 <author>
   <name>David Lynch</name>
   <email>kemayo@gmail.com</email>
 </author>

 
 <entry>
   <title>Losing Weight</title>
   <link href="http://davidlynch.org/blog/2012/01/losing-weight/"/>
   <updated>2012-01-14T17:49:33-06:00</updated>
   <id>http://davidlynch.org/blog/2012/01/losing-weight</id>
   <content type="html">&lt;p&gt;This is a slight departure from my normal choice of topics, I'll admit.&lt;/p&gt;

&lt;p&gt;Last year I decided that I wasn't happy about my weight. I'd been slowly gaining weight for the last few years, as a fairly predictable consequence of a sedentary lifestyle and liking for food. I topped out at 240 pounds, which left me rather... &lt;a href=&quot;/blog/images/2012/01/chunky.jpg&quot;&gt;chunky&lt;/a&gt;. Realising that I hadn't seen a picture of myself I felt happy about for some time wasn't fun.&lt;/p&gt;

&lt;p&gt;Despite all the social features built into the apps I've been using, and my relatively active twitter use, I believe this is the first time I've mentioned anything about this to other people online. So now you know!&lt;/p&gt;

&lt;p&gt;In September I started out by counting calories, using &lt;a href=&quot;http://loseit.com/&quot; title=&quot;Convenient screenshot from the Lose It! website&quot;&gt;Lose It!&lt;/a&gt;. I tried a few such apps, but that was the one that felt like the best fit for me, giving me easy data entry and a convenient &quot;given your height/weight, eat X calories to lose Y lbs per week&quot; which updated itself as I updated my weight.&lt;/p&gt;

&lt;p&gt;Why counting calories? I like data, and I like how tracking data tricks you into changing your behavior. The simple act of having to write down everything I ate made me conscious of where my calorie intake was coming from, and I thus made changes in my diet to avoid having to write down something horrible.&lt;/p&gt;

&lt;p&gt;Note that I didn't really start eating &lt;em&gt;better&lt;/em&gt;... my diet is almost exactly what it was before, I'm just eating less of it. I particularly didn't try following any sort of fad diet (low carb, shangri-la, paleo, whatever).&lt;/p&gt;

&lt;p&gt;This worked out quite well. After one month I'd lost 13 pounds, which was encouraging. So at the start of October I joined a gym with my wife, who talked me into it because she wanted some company while she worked out.&lt;/p&gt;

&lt;p&gt;I mostly used the gym for running, with minor amounts of weights. For my whole life I've been someone who couldn't run for more than a minute or two, even at times when I've otherwise been relatively fit. But again an app helped me out; in this case the &lt;a href=&quot;http://sites.google.com/site/c25kapp/&quot;&gt;couch to 5k&lt;/a&gt; app. It managed to provide a sequence of running workouts that took me from running 90 seconds at a time to running for a solid half-hour.&lt;/p&gt;

&lt;p&gt;This probably doesn't sound like a lot to many of you, but I find it incredibly weird to know that I can run for a half hour at a stretch. That is seriously at odds with my self-image. In a good sort of way, admittedly.&lt;/p&gt;

&lt;p&gt;How has it gone since then?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2012/01/weight-loss-graph.png&quot; alt=&quot;Graph of weight loss from September 2011 to January 2012&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Pretty well! December held steady because I spent almost the entire month out of town, eating more at holiday parties, with very few opportunities to exercise. But that plateau has ended now I'm home again, which is encouraging.&lt;/p&gt;

&lt;p&gt;As you might note from that graph, I set myself a fairly arbitrary goal of 200 pounds, on the theory that after I lost 40 pounds I would stop and evaluate myself and see how I wanted to proceed from there. I'm getting quite close to that now, and I'm &lt;a href=&quot;/blog/images/2012/01/jenga.jpg&quot; title=&quot;This is a very unfair comparison shot, but you can see the change in the face at least...&quot;&gt;happier about how I look&lt;/a&gt;, but have pretty much decided to set another goal of 180 pounds and then again stop to see how I feel. Given how it's gone so far I'm optimistic that I'll get there before too long. :D&lt;/p&gt;

&lt;p&gt;It turns out that the secret to losing weight is diet and exercise. Who knew, right?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Vulnerable</title>
   <link href="http://davidlynch.org/blog/2011/12/vulnerable/"/>
   <updated>2011-12-09T00:15:41-06:00</updated>
   <id>http://davidlynch.org/blog/2011/12/vulnerable</id>
   <content type="html">&lt;p&gt;One of my sites got hacked. How?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;My wife tried out a number of WordPress themes while setting up her blog a year or two ago.&lt;/li&gt;
&lt;li&gt;One of them contained something called timthumb.php, which &lt;a href=&quot;http://blog.sucuri.net/2011/08/timthumb-php-security-vulnerability-just-the-tip-of-the-iceberg.html&quot;&gt;just this August was found to have a great big security vulnerability&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Someone exploited this vulnerability, probably by &lt;a href=&quot;http://www.planetmike.com/2011/09/09/timthumb-php-vulnerability-scans/&quot;&gt;scanning for every possible theme that contained it&lt;/a&gt; and put a cracker console in the cache directory of that theme.&lt;/li&gt;
&lt;li&gt;They used this console to find and edit every .htaccess on that user account to include a some malicious code. (This was several sites, because I was lazy.)&lt;/li&gt;
&lt;li&gt;It redirected to a quite nasty URL whenever a referrer from a longish list of search engines was seen.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;So that's not terribly nice. I take some small comfort in knowing that &lt;a href=&quot;http://blog.sucuri.net/2011/10/timthumb-php-mass-infection-aftermath-part-i.html&quot;&gt;at least I have a lot of company&lt;/a&gt;. Also, I feel validated in &lt;a href=&quot;http://davidlynch.org/blog/2011/10/jekyll/&quot;&gt;moving off WordPress&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The cracker console was actually quite interesting. If you're curious, you can &lt;a href=&quot;https://gist.github.com/1450516&quot;&gt;see it on this gist, slightly expanded for readability&lt;/a&gt; (or &lt;a href=&quot;http://fc03.deviantart.net/fs71/f/2011/342/8/a/haxxor_by_kemayo-d4iki5x.png&quot;&gt;just a screenshot&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;It was obfuscated by being a big string that ran through &lt;code&gt;preg_replace&lt;/code&gt; using the &lt;code&gt;e&lt;/code&gt; flag, which executes the result. Yes, this is a genuinely &lt;em&gt;insane&lt;/em&gt; feature. That turned some unicode-escaped characters at the beginning into &lt;code&gt;eval(gzinflate(base64_decode('&lt;/code&gt;, which revealed the rest of the huge string to be a base64 encoded gzipped blob of source code.&lt;/p&gt;

&lt;p&gt;The lesson I'm taking from this is: security is hard to enforce when themes that non-technical people are expected to use can contain executable code. Or even technical people... I wouldn't have caught that if I'd been looking for a WordPress theme.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Google Reader... Plus?</title>
   <link href="http://davidlynch.org/blog/2011/11/google-reader-plus/"/>
   <updated>2011-11-01T01:05:44-05:00</updated>
   <id>http://davidlynch.org/blog/2011/11/google-reader-plus</id>
   <content type="html">&lt;p&gt;Google &lt;a href=&quot;http://googlereader.blogspot.com/2011/10/new-in-reader-fresh-design-and-google.html&quot;&gt;released their Google Reader revamp&lt;/a&gt;. Certainly prettier, though I'm not entirely convinced right now by the increased vertical space used by the list view.&lt;/p&gt;

&lt;p&gt;Puzzling oversight is not importing my existing Reader friends into a Google Plus circle. Seems like a really obvious thing to do, and yet they're giving everyone a chance to decide to jump platforms instead of following a painless migration path.&lt;/p&gt;

&lt;p&gt;I suppose that Google is in a privacy bind here. Google Plus has that nice, easy option to post things that are visible to &quot;your circles&quot;... so creating a new circle means they're exposing private information. But not creating a new circle means excluding existing relationships from their new network. Tricky.&lt;/p&gt;

&lt;p&gt;Anyway, the rather painful migration path actually provided is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to the &lt;a href=&quot;http://www.google.com/reader/settings?display=import&quot;&gt;import/export&lt;/a&gt; page on Google Reader&lt;/li&gt;
&lt;li&gt;Export the &quot;List of people that you follow&quot;&lt;/li&gt;
&lt;li&gt;Read JSON enough to extract identifying characteristics and try to track these people down (importantly, it doesn't include email addresses)&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;I rather doubt this will be widely employed.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Raking Jekyll</title>
   <link href="http://davidlynch.org/blog/2011/10/raking-jekyll/"/>
   <updated>2011-10-27T01:11:43-05:00</updated>
   <id>http://davidlynch.org/blog/2011/10/raking-jekyll</id>
   <content type="html">&lt;p&gt;I've never really touched &lt;code&gt;rake&lt;/code&gt; before, but since &lt;a href=&quot;http://davidlynch.org/blog/2011/10/jekyll/&quot;&gt;switching to Jekyll&lt;/a&gt; I'm finding that it's becoming an essential part of my workflow. In the limited area of blogging, at least.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rake&lt;/code&gt; is a version of &lt;code&gt;make&lt;/code&gt; in which you define all your targets in Ruby. Because practically anything would be an improvement over &lt;a href=&quot;http://locklessinc.com/articles/makefile_tricks/&quot; title=&quot;this is sort of cheating as a bad example&quot;&gt;&lt;code&gt;Makefile&lt;/code&gt; syntax&lt;/a&gt;, this is pretty easy to work with. I'm not a huge fan of shell scripting at the best of times, so mixing it in with something else is... not desirable. I still find Ruby less intuitive than Python, but that's my prejudices talking.&lt;/p&gt;

&lt;p&gt;To elaborate... what does posting a new entry look like for me?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;rake server&lt;/code&gt; to start up an automatically-rebuilding local webserver copy of my blog&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rake post[raking-jekyll]&lt;/code&gt; to make a new post with the YAML front matter boilerplate&lt;/li&gt;
&lt;li&gt;Actually edit the newly created post in an editor&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rake deploy&lt;/code&gt; to rsync the local copy to my hosting over ssh&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Any part of my routine which looks like it might be scriptable has been replaced with a &lt;code&gt;rake&lt;/code&gt; target. For example, the &lt;code&gt;post&lt;/code&gt; target:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Copies a template file&lt;/li&gt;
&lt;li&gt;Names it according to the current date and provided title&lt;/li&gt;
&lt;li&gt;Adds an expanded version of the current date into its YAML front matter so sorting will work correctly if I post multiple times a day&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Since I rarely know the current date without having to look it up, that certainly saves me some effort.&lt;/p&gt;

&lt;p&gt;Here's &lt;a href=&quot;https://github.com/kemayo/davidlynch.org/blob/master/Rakefile&quot;&gt;my Rakefile&lt;/a&gt;, if you want to use anything from it. It's probably not properly idiomatic Ruby, but it does at least work.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>XSS is fun!</title>
   <link href="http://davidlynch.org/blog/2011/10/xss-is-fun/"/>
   <updated>2011-10-20T15:54:45-05:00</updated>
   <id>http://davidlynch.org/blog/2011/10/xss-is-fun</id>
   <content type="html">&lt;p&gt;Pretending innocence, I ask why all these high profile websites have their homepages covered in spinning images?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://edition.cnn.com/eyewonder/interim.html?src=http://davidlynch.org/projects/xss/eyewonder.js&quot;&gt;CNN&lt;/a&gt; (&lt;a href=&quot;http://dl.dropbox.com/u/1372532/Screenshots/Screen%20Shot%202011-10-20%20at%203.33.28%20PM.png&quot;&gt;screenshot&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://nytimes.com/eyewonder/interim.html?src=http://davidlynch.org/projects/xss/eyewonder.js&quot;&gt;The New York Times&lt;/a&gt; (&lt;a href=&quot;http://dl.dropbox.com/u/1372532/Screenshots/Screen%20Shot%202011-10-20%20at%204.40.34%20PM.png&quot;&gt;screenshot&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://mashable.com/eyewonder/interim.html?src=http://davidlynch.org/projects/xss/eyewonder.js&quot;&gt;Mashable&lt;/a&gt; (&lt;a href=&quot;http://dl.dropbox.com/u/1372532/Screenshots/Screen%20Shot%202011-10-20%20at%205.49.09%20PM.png&quot;&gt;screenshot&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.foxnews.com/eyewonder/interim.html?src=http://davidlynch.org/projects/xss/eyewonder.js&quot;&gt;Fox News&lt;/a&gt; (&lt;a href=&quot;http://dl.dropbox.com/u/1372532/Screenshots/Screen%20Shot%202011-10-20%20at%205.47.08%20PM.png&quot;&gt;screenshot&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Okay, obviously enough, I'm messing with them. But how can I do that?&lt;/p&gt;

&lt;p&gt;The answer is cross site scripting (&quot;XSS&quot;).&lt;/p&gt;

&lt;p&gt;XSS is surprisingly common, and nigh-universally is caused by poorly escaped user inputs. Even user inputs which, as in this case, they obviously don't think of as user inputs. It happens when content is injected into a page, which results in the loading of arbitrary JavaScript onto that page.&lt;/p&gt;

&lt;p&gt;As such, I &lt;em&gt;own&lt;/em&gt; your interaction with those sites. If I was malicious I could be harvesting your cookies from them, redirecting you to phishing sites, recording everything you type, or just snooping on everything you view. As an example of why someone might want to do this... in the case of these particular sites, stealing your cookies (&lt;code&gt;document.cookie&lt;/code&gt;) would let me post comments as you. I could thus spam those sites using legitimate accounts that I don't have to go through the hassle of creating myself.&lt;/p&gt;

&lt;p&gt;I'm not doing this, because that wouldn't be nice. All I'm doing is reversing links and spinning images, because I think that's cute.&lt;/p&gt;

&lt;p&gt;In this case, all these sites have screwed up by including a little bit of HTML from an ad network (&lt;a href=&quot;http://www.eyewonder.com/&quot;&gt;EyeWonder&lt;/a&gt;) on their site. This HTML accepts an arbitrary URL as a parameter, and loads it in a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag. This is quite a common way for ad networks to ruin your day, often in the name of &quot;frame busting&quot;.&lt;/p&gt;

&lt;p&gt;If you're wondering who might be vulnerable to this exact hole from this exact ad network, &lt;a href=&quot;http://www.google.com/#q=inurl:eyewonder/interim.html&quot;&gt;Google can help you with that&lt;/a&gt;. Hint: it's a lot of sites. I just grabbed the first three big names to demonstrate with.&lt;/p&gt;

&lt;p&gt;Here's the offending HTML:&lt;/p&gt;

&lt;div&gt;&lt;script src='https://gist.github.com/1302421.js?file=interim.html'&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;script language=&amp;quot;JavaScript&amp;quot;&amp;gt;
    var cnnDocDomain = '';
    if(location.hostname.indexOf('cnn.com')&amp;gt;0) {cnnDocDomain='cnn.com';}
    if(location.hostname.indexOf('turner.com')&amp;gt;0) {if(document.layers){cnnDocDomain='turner.com:'+location.port;}else{cnnDocDomain='turner.com';}}
    if(cnnDocDomain) {document.domain = cnnDocDomain;}

    var query = window.location.search;
    var adUrl = query.substring(5, query.length);
    var clickthru;
    var failclickthru;  
    document.write('&amp;lt;s'+'cript language=&amp;quot;JavaScript&amp;quot; src=&amp;quot;');
    document.write(adUrl+'&amp;quot;&amp;gt;&amp;lt;/s'+'cript&amp;gt;');
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;


&lt;p&gt;This would actually be pretty easy to fix, note. A little bit of checking of the input, to restrict it to scripts hosted only on known-trusted domains would be enough to make exploiting it almost impossible. (I say &quot;almost&quot; because someone sufficiently resourceful might find one of these &quot;trusted&quot; domains isn't as secure as they hoped and slip a script onto it. But it at least raises the bar.)&lt;/p&gt;

&lt;p&gt;If you're curious what I'm doing to make these pages spin, check out &lt;a href=&quot;https://gist.github.com/1302421&quot;&gt;this gist&lt;/a&gt; which includes the spinner script. Essentially it's just making an iframe which shows the root of the domain, and then manipulates the contents of that iframe, which it's allowed to do because the script is running on the same domain.&lt;/p&gt;

&lt;p&gt;In short: &lt;em&gt;never&lt;/em&gt; trust user input. Also, don't trust your ad networks to know/care about security.&lt;/p&gt;

&lt;p&gt;This post brought to you by &lt;a href=&quot;http://blog.banksdesigns.co.uk/&quot;&gt;my coworker Paul Banks&lt;/a&gt; pointing out the existence of this fun little hole on CNN. I then added the spinning myself, because it looks nice and spectacular.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Jekyll</title>
   <link href="http://davidlynch.org/blog/2011/10/jekyll/"/>
   <updated>2011-10-18T23:04:49-05:00</updated>
   <id>http://davidlynch.org/blog/2011/10/jekyll</id>
   <content type="html">&lt;p&gt;I've just redone my website using &lt;a href=&quot;http://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt;. It is now completely static. No PHP, no database, nothing like that.&lt;/p&gt;

&lt;p&gt;Why did I do this?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's quite soothing knowing that all my content is version controlled.&lt;/li&gt;
&lt;li&gt;I am now nigh-immune to traffic spikes. I was using caching with WordPress before, so it had never been an issue even when I was on the HN frontpage, but there's some peace of mind in it.&lt;/li&gt;
&lt;li&gt;WordPress had a history of security bugs which wasn't comforting. Since nothing on this new site is executable I feel pretty secure now.&lt;/li&gt;
&lt;li&gt;My site is now ridiculously flexible. Jekyll forces almost no structure on you, leaving you free to change things around as you please.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;I'm happy with the end result, but the process of getting there was not without pain.&lt;/p&gt;

&lt;p&gt;The initial difficulty came from Jekyll's &lt;a href=&quot;https://github.com/mojombo/jekyll/wiki/Usage&quot;&gt;documentation&lt;/a&gt; being somewhat lacking. I found myself somewhat confused about minor details like &quot;how does a layout work?&quot;. After I'd cribbed that together by examining other sites posted with Jekyll, I discovered that the &lt;a href=&quot;https://github.com/mojombo/jekyll/wiki/Template-Data&quot;&gt;template data docs&lt;/a&gt; were inaccurate / misleading, implying the presence of a &lt;code&gt;post&lt;/code&gt; variable which failed to exist. It turned out to be something that's merged into &lt;code&gt;page&lt;/code&gt; if you're viewing a post.&lt;/p&gt;

&lt;p&gt;I don't completely blame Jekyll for this being opaque. Jekyll uses Liquid for its templating language, which claims to be aimed at designers... and I feel it would benefit from some sort of debugging mode that dumps the current scope for examination.&lt;/p&gt;

&lt;p&gt;I resorted to reading Jekyll's source, which cleared up a number of things. However, I view it as a bad sign that I felt I had to do this. Not that a command-line driven static website generator is ever likely to be a mainstream product, but still, it's the principle of the thing.&lt;/p&gt;

&lt;p&gt;Pagination worked, but was completely lacking in configuration. Since part of my goal was to have my URLs remain the same as they were in WordPress, I had to change this. I did so with a horrible monkey-patching hack of a plugin. Specifically, I made a copy of the pagination module from Jekyll's core into my &lt;code&gt;_plugins&lt;/code&gt; directory and selectively edited it to change the pagination urls.&lt;/p&gt;

&lt;p&gt;In the process I noticed a bug in the core code, and &lt;a href=&quot;https://github.com/mojombo/jekyll/pull/415&quot;&gt;submitted a pull request to fix it&lt;/a&gt;. So horrible monkey patching might at least pay off this time.&lt;/p&gt;

&lt;p&gt;Also utterly broken was the related posts feature. No matter what, it always seems to think the most recent posts are the most related to anything. It's possible that running with &lt;code&gt;--lsi&lt;/code&gt; would have helped with this, via complex semantic analysis, but that takes forever and I've seen others complain that it doesn't really help. So there's more monkey patching going on via &lt;a href=&quot;https://github.com/LawrenceWoodman/related_posts-jekyll_plugin&quot;&gt;Lawrence Woodman's related posts plugin&lt;/a&gt;, which I took and edited so it worked based on tags instead of categories.&lt;/p&gt;

&lt;p&gt;One thing I haven't fixed, which I'd like to, is making the automatic regeneration of your site during development / writing a lot smarter. Right now it notices a file has changed and so it regenerates every single bit of content on your site. This &lt;em&gt;does&lt;/em&gt; mean that the live generated site always has recent/related posts up to date everywhere... but it'd be nice to have some sort of &lt;code&gt;--quick&lt;/code&gt; option that ignored that stuff in favor of a faster development cycle.&lt;/p&gt;

&lt;p&gt;Because of the utter staticness, I naturally cannot have my own comment system in use any more. So I've switched to &lt;a href=&quot;http://disqus.com&quot;&gt;Disqus&lt;/a&gt;, which adds commenting to the site via JavaScript. It feels sort of weird to be outsourcing a component of my user experience like this... but they seem to be trustable. Widely used, and their monetization plan is fairly transparent.&lt;/p&gt;

&lt;p&gt;If you're interested you can see the &lt;a href=&quot;https://github.com/kemayo/davidlynch.org&quot;&gt;repo for my website on github&lt;/a&gt;. It contains, in its default / post templates, markup that's compatible with any WordPress theme that's based on Toolbox, which might be of use to some.&lt;/p&gt;

&lt;p&gt;Like I said, I'm happy with how it turned out. I wouldn't recommend this &lt;em&gt;at all&lt;/em&gt; for a non-technical person, but if you want to dig in and get your hands dirty then Jekyll is quite workable.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>To replace PHP you need</title>
   <link href="http://davidlynch.org/blog/2011/10/to-replace-php-you-need/"/>
   <updated>2011-10-05T16:20:17-05:00</updated>
   <id>http://davidlynch.org/blog/2011/10/to-replace-php-you-need</id>
   <content type="html">&lt;p&gt;(Expanding slightly on my response to &lt;a href=&quot;http://news.ycombinator.com/item?id=3077031&quot;&gt;this HN thread&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;First: to be on all shared hosting everywhere. I.e. you need to be really easy to install, and preferably not involve long-running processes that shared hosts might choke on.&lt;/p&gt;

&lt;p&gt;Second: to be beginner friendly. No requirement of understanding MVC, or running commands in a shell (hi RoR!). Pure instant gratification. Someone's first step into using PHP is likely going to be &quot;I want the current date in the footer of my page&quot;, or &quot;I want a random image on my homepage&quot;, or something like that. Anything like that you can handle by taking your existing page and dropping a tiny snippet in where you want the change to happen. &lt;code&gt;&amp;lt;?=date('Y')?&amp;gt;&lt;/code&gt; is a potent thing to someone who has never programmed before.&lt;/p&gt;

&lt;p&gt;Note: For point 2 many of the things serious programmers hate about PHP are actually advantages. All the functions in one big namespace? That's great! A newbie doesn't have to try to understand &lt;code&gt;&amp;lt;? import datetime; print datetime.date('Y'); ?&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It's easy to replace PHP for serious developers. We like advanced features, and care about a sane default library. We're willing to use complex tools to get a payoff.&lt;/p&gt;

&lt;p&gt;It's hard to replace PHP for non-programmers who just want to tweak their static page in notepad so it has one cool new feature, or install a blogging package on their cheapo shared hosting.&lt;/p&gt;

&lt;p&gt;To sum up: if you don't address both of these points then you haven't killed PHP. You're competing with Python or Ruby or whatever. PHP will carry right on ignoring you, because you're not addressing its fundamental use case.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Inane, random, and opinionated</title>
   <link href="http://davidlynch.org/blog/2011/10/inane-random-and-opinionated/"/>
   <updated>2011-10-01T04:30:37-05:00</updated>
   <id>http://davidlynch.org/blog/2011/10/inane-random-and-opinionated</id>
   <content type="html">&lt;p&gt;I need to bear in mind that the threshold for the &lt;a href=&quot;http://news.ycombinator.com/&quot;&gt;Hacker News&lt;/a&gt; front page is a bit lower late at night on Friday, and perhaps only submit my less inane, random, and opinionated stuff in that timeframe.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2011/09/Screen-Shot-2011-10-01-at-4.17.42-AM.png&quot;&gt;&lt;/p&gt;

&lt;p&gt;Oh, who am I kidding? It's great for getting views.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Why not just use an IDE if you want IDE features?</title>
   <link href="http://davidlynch.org/blog/2011/09/why-not-just-use-an-ide-if-you-want-ide-features/"/>
   <updated>2011-09-30T22:34:35-05:00</updated>
   <id>http://davidlynch.org/blog/2011/09/why-not-just-use-an-ide-if-you-want-ide-features</id>
   <content type="html">&lt;p&gt;After I &lt;a href=&quot;http://davidlynch.org/blog/2011/09/sublime-text-2-git-plugin/&quot;&gt;posted&lt;/a&gt; about my &lt;a href=&quot;https://github.com/kemayo/sublime-text-2-git/wiki&quot;&gt;Sublime Text 2 git plugin&lt;/a&gt; I got one response which I thought was worth responding to.&lt;/p&gt;

&lt;blockquote cite=&quot;http://www.reddit.com/r/programming/comments/ktmh5/a_git_plugin_for_sublime_text_2/c2nbsth&quot;&gt;That looks helpful, but I often wonder why not just use an IDE if you want IDE features.&lt;/blockquote&gt;


&lt;p&gt;Obviously I have a bias here, but I'll try to be fair to IDEs...&lt;/p&gt;

&lt;p&gt;An IDE is an editor that does a lot of things, many of them well. If there's something you want to do it'll almost certainly let you do it, but if you're not happy with some basic element of how it works then you're stuck having to find a new IDE. (Yes, I know, many IDEs have plugins available, but I've never had that much luck with them.)&lt;/p&gt;

&lt;p&gt;IDEs also tend to be built with a workflow in mind. If you conform to that workflow then they'll be good to you, but you want to deviate from it you may have to fight with your tools.&lt;/p&gt;

&lt;p&gt;A lightweight-but-extensible editor (e.g. Sublime, TextMate, vi, and so on) tends to focus on having a &lt;em&gt;really good&lt;/em&gt; editing experience. So you start with good editing, and then you pick and choose the &quot;IDE features&quot; that you want to mix in. If part of the editor doesn't work how you want you might have to find a new plugin for it, but since it's not a massive and complicated system it's likely to be easier to find that plugin.&lt;/p&gt;

&lt;p&gt;Neither is necessarily better, but they do tend to appeal to different types of developer. Web developers, needing to work with a number of different file types, and not generally having complicated build system requirements, gravitate towards the lightweight editors.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;UPDATE:&lt;/b&gt; To be clear, I'm not saying either is better. It's a matter of personal choice and situation. As someone who mostly does web development in dynamic languages, I like using a fairly lightweight editing environment. If I wrote in Java I'm sure I'd be singing the praises of IntelliJ/Eclipse/whatever, because I understand that Java is almost impossible to write well &lt;em&gt;without&lt;/em&gt; an IDE.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Sublime Text 2 git plugin</title>
   <link href="http://davidlynch.org/blog/2011/09/sublime-text-2-git-plugin/"/>
   <updated>2011-09-27T22:34:06-05:00</updated>
   <id>http://davidlynch.org/blog/2011/09/sublime-text-2-git-plugin</id>
   <content type="html">&lt;p&gt;I wrote &lt;a href=&quot;https://github.com/kemayo/sublime-text-2-git/wiki&quot;&gt;a git plugin&lt;/a&gt; for &lt;a href=&quot;http://www.sublimetext.com/&quot;&gt;Sublime Text 2&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'd decided to try Sublime out for work to see how it compared to TextMate... and thus some degree of git integration was required. Given that it's been out since January, I was surprised that there wasn't already a solid git plugin.&lt;/p&gt;

&lt;p&gt;I did find &lt;a href=&quot;https://github.com/notanumber/gitst2&quot;&gt;this one&lt;/a&gt;, admittedly, but I decided that I didn't like how it fit in with Sublime. It's built around menus and keybinds, whereas I felt that setting everything up as commands in the palette and hooking as much stuff as I could into the fuzzy search was the way to go.&lt;/p&gt;

&lt;p&gt;Working on the plugin was a good exercise in getting me used to Sublime. I'm fairly sold on it as a result. It's philosophically somewhat similar to TextMate, but with some of TextMate's rough edges smoothed out.&lt;/p&gt;

&lt;p&gt;(Short rant: if the &lt;a href=&quot;http://blog.macromates.com/2011/whats-next/&quot;&gt;recently announced TextMate2 alpha&lt;/a&gt; doesn't get rid of the single-character undo buffer... I don't know what I'll do. It's certainly the biggest single complaint I have about TextMate nowadays.)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>A shadow is upon us</title>
   <link href="http://davidlynch.org/blog/2011/09/a-shadow-is-upon-us/"/>
   <updated>2011-09-02T19:16:52-05:00</updated>
   <id>http://davidlynch.org/blog/2011/09/a-shadow-is-upon-us</id>
   <content type="html">&lt;p&gt;Other people contributing to my projects is often the cause of my improving them. This is because people tend to contribute something that works for the case they care about, without necessarily testing how it combines with the rest of the product. There's nothing wrong with this. They did some work and wanted to give it back; that's how open source should work.&lt;/p&gt;

&lt;p&gt;A case in point here is how shadows just got added to &lt;a href=&quot;https://github.com/kemayo/maphilight&quot;&gt;maphilight&lt;/a&gt;. A &lt;a href=&quot;https://github.com/kemayo/maphilight/pull/10&quot;&gt;pull request&lt;/a&gt; was submitted for a commit that added shadow support for rectangles in canvas only. I accepted the request because, hey, that's a nice improvement, and it seemed to work. But I wasn't really happy with rectangles-only.&lt;/p&gt;

&lt;p&gt;So, I started fiddling with it. I had, for whatever reason, never touched shadows in canvas before. In fact, it's been quite a while since I did the research into canvas that was involved in writing maphilight in the first place.&lt;/p&gt;

&lt;p&gt;Looking at &lt;a href=&quot;https://github.com/Raven24/maphilight/commit/ee12efe020e1dcb6c3a6a9cc337ac9c59c6cca08&quot;&gt;the commit&lt;/a&gt; I see that the shadows have been implemented with a combination of clipping regions and redrawing the shape with some shadow options on the path.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// [Regular shape drawing happens here]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Clip regions&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;beginPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;canvas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;canvas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;closePath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;clip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Shadow drawing&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;beginPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;closePath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;shadowColor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;rgba(0,0,0,1)&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;stroke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now, I'm confused by the clipping being done, since I've never seen it work quite like that before. It's drawing a rectangle around the whole canvas, then another around the rectangle we're shadowing, and telling it to clip. So I do a bit of testing, and I find that this isn't doing what I think the submitter meant it to.&lt;/p&gt;

&lt;p&gt;I think they wanted it to set up a clip region only outside the shape, so that the shadows they drew wouldn't appear inside it. However, in practice it seems that it's just adding the two rectangles together and leaving us with a clip region the size of the whole canvas. It's possible that this &lt;em&gt;did&lt;/em&gt; work in another browser, but not in Chrome where I was testing...&lt;/p&gt;

&lt;p&gt;Since subtractive clipping obviously wasn't the answer, I looked into &lt;code&gt;globalCompositeOperation&lt;/code&gt; to clean up after the fill. It turned out that &lt;code&gt;destination-out&lt;/code&gt; was the operation I needed to empty my shape. Also, because the shadow-drawing had been added after the regular shape, I had to move it to be before that, otherwise the shadow was being drawn on top of the stroke and cleaning it up would wipe out the fill.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// So we now have...&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Shadow drawing&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;beginPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;closePath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;shadowColor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;rgba(0,0,0,1)&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;stroke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;globalCompositeOperation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;destination-out&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;beginPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;closePath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fillStyle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;rgba(0,0,0,1);&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;restore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// [Regular shape drawing happens here]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Okay! Now we have outline shadows.&lt;/p&gt;

&lt;p&gt;But, another issue with this method: it'd fill and stroke on the shape, regardless of the settings you were using. If you had no fill / stroke it'd use the default (flat black) settings, which are ugly. Also, it harmed your opacity settings -- the stroke and fill were being done twice. So when I added a shadow to a strokeless mostly-transparent rectangle I noticed that it gained a thin black outline, and was darker than it should have been.&lt;/p&gt;

&lt;p&gt;I messed around a little bit with trying to erase the fill or stroke, but eventually decided that this was more hassle than it was worth. What wound up being the simplest option was drawing the shape massively off the edge of the canvas, and using shadow offsets to cast the shadow into the right spot.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// Just the shadow part this time&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;beginPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9001&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9001&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;closePath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;shadowOffsetX&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9001&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;shadowOffsetY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9001&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;shadowColor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;rgba(0,0,0,1)&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;stroke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now we had a shadow that didn't involve drawing anything stroking or filling onto the canvas near our existing shape. At this point I had &lt;a href=&quot;https://github.com/kemayo/maphilight/commit/eeeff8ade3262e49585a36ba63b5159e5fb9eaa6&quot;&gt;completely rewritten the code I'd merged in&lt;/a&gt;. About the only thing remaining was the option names Raven24 had chosen.&lt;/p&gt;

&lt;p&gt;I went ahead and added some options for whether the shadow was cast inside or outside the shape, since I could see reasons for both, and added some overrides for whether it'd be casting from the fill or the stroke, since the varying possible configurations made it difficult to reliably guess which would look better.&lt;/p&gt;

&lt;p&gt;I still didn't add it to non-canvas. Largely because now that IE has finally given in and implemented canvas I view that as being a dead branch. Needs to keep working, and any major changes have to be ported over... but minor display differences are somewhat acceptable. Also, I don't have access to IE right now, since I'm away from home. If I ever have reason to look into shadows in VML I'm sure I'll add it in then, for the heck of it.&lt;/p&gt;

&lt;p&gt;You can &lt;a href=&quot;http://davidlynch.org/js/maphilight/docs/demo_features.html&quot;&gt;see all this in action on the demo page&lt;/a&gt; if you're interested.&lt;/p&gt;

&lt;p&gt;And that's how community involvement improves things. :D&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Hiring developers</title>
   <link href="http://davidlynch.org/blog/2011/07/hiring-developers/"/>
   <updated>2011-07-05T23:53:31-05:00</updated>
   <id>http://davidlynch.org/blog/2011/07/hiring-developers</id>
   <content type="html">&lt;p&gt;It turns out to be quite difficult to hire good developers. I'm involved in the hiring process at &lt;a href=&quot;http://www.deviantart.com&quot;&gt;deviantART&lt;/a&gt;, and it has opened my eyes to just how unqualified the majority of applicants to these jobs are.&lt;/p&gt;

&lt;p&gt;To give an example of this, I estimate that we hire perhaps 0.2% of the people who apply for a job with us. I haven't gone back and tallied this up, so all figures in this example are ballpark at best... but I've tried to err on the generous side.&lt;/p&gt;

&lt;p&gt;First, we collect resumes. We advertise on all sorts of job sites, we post things to &lt;a href=&quot;http://news.ycombinator.com&quot;&gt;Hacker News&lt;/a&gt;, and generally we try to get the word out. Filtering the resumes eliminates about 95% of them, depending on where we've been advertising. This is simultaneously the step where unqualified applicants are most expected, and the step that's most likely to be rejecting perfectly qualified people because of some random quirk of their resume.&lt;/p&gt;

&lt;p&gt;Then we ask promising applicants to do a simple exercise. &lt;a href=&quot;http://dt.deviantart.com/blog/32882682/&quot;&gt;This one, in fact&lt;/a&gt;. It really is fairly simple... not FizzBuzz, but still trivial. This gets reviewed by the entire hiring team. Passing it is somewhat subjective; there's a list of things we look for, along with an ineffable &quot;code style&quot; component. This weeds out about 90% of submissions.&lt;/p&gt;

&lt;p&gt;Next comes a phone interview with those who passed the test. Again, with the entire hiring team on the line. Since you've made it this far we're pretty positive about you, and strongly suspect that you can code competently, but we'll still try to dig into your past experiences and quiz you on the reasons for things you did on our exercise. Ideally you'll have left a small bug in the exercise that we can get you to debug while we're on the call. It's not uncommon for us to be underwhelmed here, and we tend to turn down maybe 60% of candidates on this step.&lt;/p&gt;

&lt;p&gt;Finally comes a three month trial period. Which we take &lt;em&gt;seriously&lt;/em&gt;. I'd worked places with a trial period before, but it was always just a matter of not showing up to work drunk and you'd make it. We evaluate performance, work style, and general team fit... and we seem to lose perhaps 20% of hires here.&lt;/p&gt;

&lt;p&gt;Adding all that up, &lt;code&gt;P(we hire you)&lt;/code&gt; would seem to be 0.0016. Or 0.16% if you prefer.&lt;/p&gt;

&lt;p&gt;The step that seems the most telling is the exercise, because it goes out to people who are generally already making a living as a developer. And, like I said, it's not difficult. So we get to see how many professional developers apparently can't perform their job function. For that matter, a hefty chunk of the people who fail that step just plain didn't complete the listed requirements.&lt;/p&gt;

&lt;p&gt;Despite all that, feel free &lt;a href=&quot;http://deviantart.theresumator.com/apply/eR4wR2/Web-Application-Developer.html?source=david&quot;&gt;to apply&lt;/a&gt;! :D&lt;/p&gt;

&lt;p&gt;&lt;b&gt;UPDATE 2011-10-01:&lt;/b&gt; Some people have mentioned that PHP is keeping them from applying. Can't blame them there; it's not cool and modern, and it has some ugly warts. But we're an old website (11 years now), and back in the day it's what was picked. Rewriting into something cool and modern is technically possible, but would also be a genuinely ridiculous amount of work.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;UPDATE 2011-10-02:&lt;/b&gt; It was pointed out to me that I may not have conveyed my point correctly. I mean to say &quot;hiring good people is hard&quot;, not &quot;we are too awesome for you&quot;. The numbers are intended to indicate our low success rate more than our exclusivity.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Random recommendation: Virgin Mobile</title>
   <link href="http://davidlynch.org/blog/2011/06/random-recommendation-virgin-mobile/"/>
   <updated>2011-06-09T15:43:06-05:00</updated>
   <id>http://davidlynch.org/blog/2011/06/random-recommendation-virgin-mobile</id>
   <content type="html">&lt;p&gt;After resisting smartphones for many years, I got one a few months ago, just before I moved. It turns out that they're pretty nifty. Who knew, right?&lt;/p&gt;

&lt;p&gt;I got an &lt;a href=&quot;http://www.virginmobileusa.com/cell-phones/lg-optimus-v-phone.jsp&quot;&gt;LG Optimus V&lt;/a&gt; on Virgin Mobile. One of the big things that had been stopping me from getting one before was that I couldn't quite bring myself to pay as much as you have to for a phone plan with data. Virgin Mobile gets around this objection by offering phone + unlimited data for $25/month... which is frankly insanely cheap compared to everyone else that I looked at.&lt;/p&gt;

&lt;p&gt;It runs Android, and is pretty easy to root and flash to a newer version, which I have done. I held off on it for ages, but then my wife did it and I was impressed enough by CyanogenMOD to want to do it myself.&lt;/p&gt;

&lt;p&gt;It's not a fancy phone; it has a smallish screen, and not a terribly powerful processor. But sufficient for my needs.&lt;/p&gt;

&lt;p&gt;So, consider this recommended. If you're cheap like me. :)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Signs of adulthood</title>
   <link href="http://davidlynch.org/blog/2011/06/signs-of-adulthood/"/>
   <updated>2011-06-09T15:16:31-05:00</updated>
   <id>http://davidlynch.org/blog/2011/06/signs-of-adulthood</id>
   <content type="html">&lt;p&gt;I bought a house.&lt;/p&gt;

&lt;p&gt;Strangely, this makes me feel like more of a &quot;grown up&quot; than producing a daughter did. Possibly because health insurance meant that producing the daughter cost appreciably less. Actually, according to the explanation of benefits letters I got from my insurance company, childbirth was almost exactly one third the cost of a house. America is crazy.&lt;/p&gt;

&lt;p&gt;This lets me add a little bit of extra context into my post, though. Here's where I'm sitting right now:&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;https://lh3.googleusercontent.com/-VoV1Ojy9qtw/TeZc_rd2CiI/AAAAAAAAAeg/XsTkpM0BW8o/s640/IMG_2590.JPG&quot; title=&quot;Workspace&quot; class=&quot;aligncenter&quot; width=&quot;640&quot; height=&quot;427&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Unmentionable</title>
   <link href="http://davidlynch.org/blog/2011/06/unmentionable/"/>
   <updated>2011-06-09T15:11:15-05:00</updated>
   <id>http://davidlynch.org/blog/2011/06/unmentionable</id>
   <content type="html">&lt;p&gt;So, funny thing, I realized that an important life event occurred when I wasn't paying much attention to this blog, and I never got around to mentioning it.&lt;/p&gt;

&lt;p&gt;I have a daughter now, and have for a bit over two years now.&lt;/p&gt;

&lt;p&gt;She's pretty cute.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;https://lh3.googleusercontent.com/-xifsP7i0Tqg/Te03L1Eu6nI/AAAAAAAAAfU/uaSoJuWSKVQ/s800/IMG_20110606_152212.jpg&quot; title=&quot;Danielle&quot; width=&quot;800&quot; height=&quot;600&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 

</feed>

