<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
    <channel>
        <title>Chris Shiflett</title>
        <link>http://shiflett.org/</link>
        <language>en-us</language>
        <description>Blog</description>
        <feedburner:info uri="shiflett" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><geo:lat>40.677249</geo:lat><geo:long>-73.969747</geo:long><image><link>http://shiflett.org/</link><url>http://shiflett.org/img/profile_pic.jpg</url><title>Chris Shiflett</title></image><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://shiflett.org/rss" /><feedburner:emailServiceId>shiflett</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><feedburner:browserFriendly>This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site, subject to copyright and fair use.</feedburner:browserFriendly><item>
            <title>Auto Increment with MongoDB</title>
            <link>http://shiflett.org/blog/2010/jul/auto-increment-with-mongodb</link>
            <guid>http://shiflett.org/blog/2010/jul/auto-increment-with-mongodb</guid>
            <description><![CDATA[We are currently working on an app that uses a number of technologies, including PHP, Python, and MongoDB. Recently, a need arose to use sequential identifiers for users, similar to an auto_increment column in MySQL.

If you've used MongoDB, you migh...]]></description>
            <content:encoded><![CDATA[<p><a href="http://analog.coop/">We</a> are currently working on an app that uses a number of technologies, including PHP, Python, and <a href="http://mongodb.org/">MongoDB</a>. Recently, a need arose to use sequential identifiers for users, similar to an <code>auto_increment</code> column in MySQL.</p>

<div class="note"><p>If you've used MongoDB, you might be familiar with the default behavior of using a <a href="http://en.wikipedia.org/wiki/Universally_unique_identifier"><abbr title="universally unique identifier">UUID</abbr></a> as the primary key. This is convenient, especially if you partition your database across servers, because you don't have to coordinate the primary key in any way. If you use sequential identifiers (as I demonstrate in this post), you can use multiple servers and interleave identifiers by advancing each server's sequence by the total number of servers. (For example, with two servers, advance each sequence by two, so one server generates even identifiers, and the other generates odd.)</p>
<p>I'd rather not discuss the advantages and disadvantages of either approach, because it's exactly this debate that makes it very difficult to find any useful information on using sequential identifiers with MongoDB. Instead, I'm just going to explain how I did it, and hope this is helpful to someone. :-)</p></div>

<p>First, create a sequence collection that you can use to determine the next identifier in the sequence. The following creates a collection called <code>seq</code> that has a single sequence in it (for <code>users</code>), but you can add as many as you need:</p>

<pre class="code">
<code>db.seq.insert({"_id":"users", "seq":new NumberLong(1)});</code>
</pre>

<div class="note"><p>If you assign <code>seq</code> to <code>1</code> instead of <code>new NumberLong(1)</code>, it will be interpreted as a float due to a JavaScript quirk.</p></div>

<p>Before adding a new user, you need to increment the sequence by one and fetch the next identifier. Fortunately, the <a href="http://mongodb.org/display/DOCS/findandmodify+Command">findandmodify() command</a> provides an atomic way to do this. Using the MongoDB shell, the command would look something like this:</p>

<pre class="code">
<code>db.seq.findAndModify({</code>
<code>    query: {"_id":"users"},</code>
<code>    update: {$inc: {"seq":1}},</code>
<code>    new: true</code>
<code>});</code>
</pre>

<p>Because I'm using <a href="http://lithify.me/">Lithium</a>, I added a method for fetching the next identifier to my <code>User</code> model:</p>

<pre class="code">
<code><span class="default">&lt;?php</span></code>
<code><span class="default">&#160;</span></code>
<code><span class="keyword">namespace </span><span class="default">app</span><span class="keyword">\</span><span class="default">models</span><span class="keyword">;</span></code>
<code><span class="keyword">&#160;</span></code>
<code><span class="keyword">class </span><span class="default">User </span><span class="keyword">extends \</span><span class="default">lithium</span><span class="keyword">\</span><span class="default">data</span><span class="keyword">\</span><span class="default">Model </span><span class="keyword">{</span></code>
<code><span class="keyword">&#160;</span></code>
<code><span class="keyword">    static public function </span><span class="default">seq</span><span class="keyword">() {</span></code>
<code><span class="keyword">        </span><span class="default">$seq </span><span class="keyword">= static::</span><span class="default">_connection</span><span class="keyword">()-&gt;</span><span class="default">connection</span><span class="keyword">-&gt;</span><span class="default">command</span><span class="keyword">(</span></code>
<code><span class="keyword">            array(</span><span class="string">'findandmodify' </span><span class="keyword">=&gt; </span><span class="string">'seq'</span><span class="keyword">,</span></code>
<code><span class="keyword">                  </span><span class="string">'query' </span><span class="keyword">=&gt; array(</span><span class="string">'_id' </span><span class="keyword">=&gt; </span><span class="string">'users'</span><span class="keyword">),</span></code>
<code><span class="keyword">                  </span><span class="string">'update' </span><span class="keyword">=&gt; array(</span><span class="string">'$inc' </span><span class="keyword">=&gt; array(</span><span class="string">'seq' </span><span class="keyword">=&gt; </span><span class="default">1</span><span class="keyword">)),</span></code>
<code><span class="keyword">                  </span><span class="string">'new' </span><span class="keyword">=&gt; </span><span class="default">TRUE</span></code>
<code><span class="default">            </span><span class="keyword">)</span></code>
<code><span class="keyword">        );</span></code>
<code><span class="keyword">&#160;</span></code>
<code><span class="keyword">        return </span><span class="default">$seq</span><span class="keyword">[</span><span class="string">'value'</span><span class="keyword">][</span><span class="string">'seq'</span><span class="keyword">];</span></code>
<code><span class="keyword">    }</span></code>
<code><span class="keyword">&#160;</span></code>
<code><span class="keyword">}</span></code>
<code><span class="keyword">&#160;</span></code>
<code><span class="default">?&gt;</span></code>
</pre>

<p>If you're not using Lithium, you can use the <a href="http://php.net/manual/en/class.mongodb.php">MongoDB class</a> to execute a <a href="http://php.net/manual/en/mongodb.command.php"><code>command()</code></a>.</p>

<p>With this in place, adding a new user is a simple process. I create an array called <code>$data</code> with everything I want to store for a user, and then do the following:</p>

<pre class="code">
<code><span class="default">&lt;?php</span></code>
<code><span class="default">&#160;</span></code>
<code><span class="default">$user </span><span class="keyword">= </span><span class="default">User</span><span class="keyword">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">$data</span><span class="keyword">);</span></code>
<code><span class="default">$user</span><span class="keyword">-&gt;</span><span class="default">_id </span><span class="keyword">= </span><span class="default">User</span><span class="keyword">::</span><span class="default">seq</span><span class="keyword">();</span></code>
<code><span class="default">$success </span><span class="keyword">= </span><span class="default">$user</span><span class="keyword">-&gt;</span><span class="default">save</span><span class="keyword">();</span></code>
<code><span class="keyword">&#160;</span></code>
<code><span class="default">?&gt;</span></code>
</pre>

<p>This example should be easy to adapt to any environment. Once you have the next identifier in the sequence, you simply store it as you would any other data.</p>

<p>I hope to blog more about both MongoDB and Lithium. As these technologies are still pretty new to me, please feel free to point out any improvements. I'll update the post accordingly.</p><p style="background-color:#D60;background-image:url(http://shiflett.org/img/bg_syndicate.gif);background-repeat:repeat-x;background-position:50% 0;font:12px arial,monaco,sans-serif;max-width:40em;margin:1em 0;padding:0;"><span style="display:block;background-color:transparent;background-image:url(http://shiflett.org/img/bg_syndicate_ul.gif);background-repeat:no-repeat;background-position:100% 0;color:#fff;font-size:1em;margin:0;padding:0.66em 1em;">Thu, 29 Jul 2010 19:52 GMT&#8201;&#8212;&#8201;<a style="color:#fff;font-size:1em;font-weight:900;" href="http://shiflett.org/">Chris Shiflett&#8217;s Blog</a> <a href="http://shiflett.org/feeds/blog"><img style="margin:0;padding:0;border:0;vertical-align:bottom;" src="http://shiflett.org/img/icon_feed_standard.gif" alt="Chris Shiflett&#8217;s Feed"></a></span></p>]]></content:encoded>
            <pubDate>Thu, 29 Jul 2010 19:52:18 GMT</pubDate>
        </item>
        <item>
            <title>Change Blindness and Zooming Out</title>
            <link>http://shiflett.org/blog/2010/jun/change-blindness-and-zooming-out</link>
            <guid>http://shiflett.org/blog/2010/jun/change-blindness-and-zooming-out</guid>
            <description><![CDATA[

Two weeks ago, I had the great honor of giving a keynote at the Dutch PHP Conference. Because I had never been to Amsterdam or to the Dutch PHP Conference, I was really excited to have a chance to speak there. It was also an opportunity to give my ...]]></description>
            <content:encoded><![CDATA[<p class="blockimg"><a href="http://flickr.com/photos/shiflett/4693037840"><img src="http://shiflett.org/img/dpc10.jpg" alt="Change Blindness Experiment at the Dutch PHP Conference" /></a></p>

<p>Two weeks ago, I had the great honor of giving a keynote at the <a href="http://phpconference.nl/">Dutch PHP Conference</a>. Because I had never been to Amsterdam or to the Dutch PHP Conference, I was really excited to have a chance to speak there. It was also an opportunity to give my favorite talk to a new audience.</p>

<p>On the morning of the keynote, I followed along with conference organizer <a href="http://lornajane.net/">Lorna Mitchell</a> to the RAI Center where the conference was being held. As soon as I saw the stage, I smiled. Not only would I be able to stand on a stage unobstructed by a podium or any other obstacle, the seats were arranged <a href="http://en.wikipedia.org/wiki/Stadium_seating">like a theater</a>, making it easier to connect with the audience. (Conference organizers, please take note.)</p>

<div class="note"><p>It was lucky that I arrived early to test the video and audio. If you own a MacBook Pro, you may or may not know that it puts the sound card to sleep if it has been unused for a few minutes. (If you use headphones, you can hear when it sleeps and awakes.) When you're connected to a massive sound system for a theater, this behavior creates a really horrible noise. The solution I came up with was to play iTunes the entire time with the iTunes volume control turned all the way down. Hopefully this trick will save someone else a lot of trouble. :-)</p></div>

<p>As I began speaking, I noted that PHP had just turned 15 years old. Years ago, the community was energized by all of the misinformation being spread about PHP. It doesn't scale. It's insecure. It's not maintainable. When I began speaking about security, it was partly in response to some of this. I wanted to educate developers, so that we would not only take responsibility for the security of our apps, but also so that we could avoid the most common and dangerous security problems.</p>

<p>These days, petty insults probably continue in the comments on <a href="http://digg.com/">Digg</a> or <a href="http://news.ycombinator.com/">Hacker News</a>, but no one takes them too seriously. Can PHP scale? Well, the biggest and most popular sites on the Web all use PHP, so I guess so. With no misinformation to energize us, it can easily seem like the PHP community has lost its luster. Not so.</p>

<p>In my talk, <a href="http://slideshare.net/shiflett/securitycentered-design">Security-Centered Design</a>, I suggest we take a lesson from the design community, where user experience takes priority. We must evolve, or as <a href="http://aralbalkan.com/">Aral Balkan</a> puts it:</p>

<blockquote><p>The age of features is dead; welcome to the age of user experience.</p></blockquote>

<p>My talk revolves loosely around security, but it's really a call to arms for my developer peers to take a step back and consider the bigger picture. We need to zoom out. Sometimes, even with a subject as technical as security, the social elements of the problems we face are just as important as the technical. If we can't empathize with users, we can't be great developers.</p>

<p>I want to thank everyone who took the time to say <a href="http://joind.in/talk/view/1550">nice things</a> about my talk. Hearing it described as the "best keynote I have ever seen" and the "highlight of the event" is really encouraging and makes it all worthwhile. I can't possibly thank you enough.</p>

<p>I'll leave you with a little taste of the talk where I invite everyone to participate in a change blindness experiment. I may discuss <a href="http://en.wikipedia.org/wiki/Change_blindness">change blindness</a> and how it applies to the Web in more detail later, but for now, see if you can spot the difference in the two photos I used in the <a href="http://vimeo.com/12995367">change blindness video</a> I created for this talk.</p>

<p class="blockimg"><object width="450" height="338" type="application/x-shockwave-flash" data="http://vimeo.com/moogaloop.swf?clip_id=12995367&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=1&amp;color=dd4499&amp;fullscreen=1&amp;loop=1">
	<param name="allowfullscreen" value="true" />
	<param name="allowscriptaccess" value="always" />
	<param name="movie" value="uri" />
</object></p>

<p>Thanks again to everyone who woke up early after a late night at the conference social to see me speak, and I hope to see you again sometime. :-)</p><p style="background-color:#D60;background-image:url(http://shiflett.org/img/bg_syndicate.gif);background-repeat:repeat-x;background-position:50% 0;font:12px arial,monaco,sans-serif;max-width:40em;margin:1em 0;padding:0;"><span style="display:block;background-color:transparent;background-image:url(http://shiflett.org/img/bg_syndicate_ul.gif);background-repeat:no-repeat;background-position:100% 0;color:#fff;font-size:1em;margin:0;padding:0.66em 1em;">Wed, 30 Jun 2010 22:12 GMT&#8201;&#8212;&#8201;<a style="color:#fff;font-size:1em;font-weight:900;" href="http://shiflett.org/">Chris Shiflett&#8217;s Blog</a> <a href="http://shiflett.org/feeds/blog"><img style="margin:0;padding:0;border:0;vertical-align:bottom;" src="http://shiflett.org/img/icon_feed_standard.gif" alt="Chris Shiflett&#8217;s Feed"></a></span></p>]]></content:encoded>
            <pubDate>Wed, 30 Jun 2010 22:12:40 GMT</pubDate>
        </item>
        <item>
            <title>URL Sentences</title>
            <link>http://shiflett.org/blog/2010/may/url-sentences</link>
            <guid>http://shiflett.org/blog/2010/may/url-sentences</guid>
            <description><![CDATA[Two and a half years ago, I was helping Jon Tan redesign a web site. We share an affinity for organization and structure, but we also like to experiment with new ideas.

One morning via Skype, I shared a crazy idea that I wasn't entirely sure of yet,...]]></description>
            <content:encoded><![CDATA[<p>Two and a half years ago, I was helping <a href="http://jontangerine.com/">Jon Tan</a> redesign a web site. We share an affinity for organization and structure, but we also like to experiment with new ideas.</p>

<p>One morning via <a href="http://skype.com/">Skype</a>, I shared a crazy idea that I wasn't entirely sure of yet, trusting Jon to tell me if it was a bad idea.</p>

<blockquote><p>What if we make every URL a sentence?</p></blockquote>

<p>Before he could respond, I pasted in some examples I had been playing with to help clarify what I meant:</p>

<ul>
    <li>
    <code>/is</code> (About)
        <ul>
        <li><code>/is/here</code> (Contact)</li>
        <li><code>/is/hiring</code></li>
        <li><code>/is/chris-shiflett</code></li>
        </ul>
    </li>
    <li>
    <code>/does</code> (Work)
        <ul>
        <li><code>/does/web-design</code></li>
        </ul>
    </li>
    <li>
    <code>/helps</code> (Clients)
        <ul>
        <li><code>/helps/digg</code></li>
        </ul>
    </li>
    <li>
    <code>/thinks</code> (Planet)
        <ul>
        <li><code>/thinks/about</code> (Tags)</li>
        <li><code>/thinks/about/oscon</code></li>
        </ul>
    </li>
    <li>
    <code>/remembers</code> (Timeline)
        <ul>
        <li><code>/remembers/2008</code> (Archive)</li>
        </ul>
    </li>
    <li>
    <code>/writes</code> (Books)
        <ul>
        <li><code>/writes/essential-php-security</code></li>
        <li><code>/writes/http-developers-handbook</code></li>
        </ul>
    </li>
    <li>
    <code>/has</code> (Site Map / Search)
        <ul>
        <li><code>/has?php</code></li>
        <li><code>/has/colophon</code></li>
        <li><code>/has/accessibility</code></li>
        </ul>
    </li>
    <li>
    <code>/shares</code> (Feeds)
        <ul>
        <li><code>/shares/news</code></li>
        <li><code>/shares/planet</code></li>
        <li><code>/shares/everything</code></li>
        </ul>
    </li>
    <li>
    <code>/presents</code> (Talks)
    </li>
</ul>

<p>These URLs still adhere to a basic&#8201;&#8212;&#8201;albeit shallow&#8201;&#8212;&#8201;hierarchy to help keep things organized, but instead of the usual <em>about</em>, <em>work</em>, and <em>clients</em>, I used verbs like <em>is</em>, <em>does</em>, and <em>helps</em>. I was pleasantly surprised to hear Jon liked the idea. He noted some limitations, like the challenge of avoiding awkward wording when the hierarchy was deep, but he thought it was worth trying to map out the entire site to see if we could make it work.</p>
<p>Because <a href="http://omniti.com/">the site</a> was fairly small, it turned out well. As I <a href="http://shiflett.org/blog/2008/mar/urls-can-be-beautiful">noted previously</a>, this approach isn't appropriate for all sites, but it can give URLs a voice of their own. (I don't use URL sentences on <a href="http://shiflett.org/">shiflett.org</a>.) It can also help you organize your pages. For example, if a page can't fit neatly into a sentence that starts with <em>example.org is...</em>, then it probably doesn't belong in the about section of the <em>example.org</em> site.</p>

<p>There are other ways to make sentences with URLs, especially if your domain name <a href="http://google.com/">can be used as a verb</a>. And you don't mind. :-) Using verbs (present tense) as the top-level hierarchy is just one example.</p>

<p>There have been other uses of URL sentences over the years:</p>

<ul>
    <li>Jon collaborated with <a href="http://accessibility.co.uk/">Jon Gibbins</a> on a really neat site for <a href="http://accessibility.co.uk/">Denna Jones</a> that uses URL sentences and other interesting <a href="http://dennajones.com/colophon">innovations</a>. (Pages like the colophon do not, but the primary ones do.)</li>
    <li><a href="http://clearleft.com/">Clearleft</a> use URL sentences in their latest redesign. Paul Lloyd discusses this and more in a <a href="http://paulrobertlloyd.com/2009/12/urls_matter">related post about URLs</a>.</li>
    <li><a href="http://pixeldiva.co.uk/">Ann McMeekin</a> cleverly uses URL sentences to indicate categories for her blog. Some posts she <em>considers</em>; others she <em>shares</em>. A full list of categories is available in the sidebar.</li>
    <li><a href="http://fictivecameron.com/">Cameron Koczon</a> used URL sentences when redesigning <a href="http://jessicahische.com/">Jessica Hische</a>'s site. She chose verbs like <em>typographizes</em> and <em>designifies</em> to add a bit of her personality to the mix.</li>
    <li><a href="http://martin-geber.com/">Martin Geber</a> used past tense verbs as his top-level hierarchy, creating URLs that align with the idea that his site is a personal archive of thoughts, memories, and the like. He <a href="http://martin-geber.com/thought/2008/11/23/new-website/#inspiration">writes more about the inspiration for the site</a>. Thanks for the nod, Martin!</li>
    <li><a href="http://kernpunkt.de/">Kernpunkt</a> gives a German interpretation of URL sentences. This is the only non-English example I've seen.</li>
    <li>There are some examples of URL sentences being used to add a bit of flavor to an existing site without reorganizing everything. Adrian Sevitz pointed me to <a href="http://vzaar.com/is/adrian_sevitz">his company's site</a> as one such example.</li>
</ul>

<p>I'm really happy to see other people embracing URL sentences and adding their own creativity, personality, and style. If the idea makes sense for a site you're making, please let me know, and I'll add your example as an update or comment to this post.</p>

<p>If making sentences out of your URLs makes you smile or makes your work more fun, you should definitely do it. The best sites are the ones we make while having fun. :-)</p><p style="background-color:#D60;background-image:url(http://shiflett.org/img/bg_syndicate.gif);background-repeat:repeat-x;background-position:50% 0;font:12px arial,monaco,sans-serif;max-width:40em;margin:1em 0;padding:0;"><span style="display:block;background-color:transparent;background-image:url(http://shiflett.org/img/bg_syndicate_ul.gif);background-repeat:no-repeat;background-position:100% 0;color:#fff;font-size:1em;margin:0;padding:0.66em 1em;">Mon, 31 May 2010 20:14 GMT&#8201;&#8212;&#8201;<a style="color:#fff;font-size:1em;font-weight:900;" href="http://shiflett.org/">Chris Shiflett&#8217;s Blog</a> <a href="http://shiflett.org/feeds/blog"><img style="margin:0;padding:0;border:0;vertical-align:bottom;" src="http://shiflett.org/img/icon_feed_standard.gif" alt="Chris Shiflett&#8217;s Feed"></a></span></p>]]></content:encoded>
            <pubDate>Mon, 31 May 2010 20:14:06 GMT</pubDate>
        </item>
    </channel>
</rss>
