<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[House of Rosania]]></title>
  
  <link href="http://paul.rosania.org/writings/" />
  <updated>2012-07-06T11:48:29-05:00</updated>
  <id>http://paul.rosania.org/writings/</id>
  <author>
    <name><![CDATA[Paul Rosania]]></name>
    <email><![CDATA[paul@rosania.org]]></email>
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/paulrosania" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="paulrosania" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
    <title type="html"><![CDATA[Quora: What's the right time to create a growth team?]]></title>
    <link href="http://paul.rosania.org/writings/2012/06/30/quora-whats-the-right-time-to-create-a-growth-team/" />
    <updated>2012-06-30T20:20:00-05:00</updated>
    <id>http://paul.rosania.org/writings/2012/06/30/quora-whats-the-right-time-to-create-a-growth-team</id>
    <content type="html"><![CDATA[<p>My answer:</p>

<blockquote><p>[&#8230;]
Growth engineering is about consistent small gains, with some big wins mixed in
for good effect.  To achieve this is a matter of patience, discipline and a keen
(but flexible) understanding of your product and market.  When you&#8217;ve achieved
product/market fit, you know why, and you have a stream of data to work with,
you&#8217;re ready.</p></blockquote>

<p>More at
<a href="http://www.quora.com/Facebook-1/What-is-the-right-time-in-a-companys-lifecycle-to-create-a-growth-team/answer/Paul-Rosania">Facebook: What is the &#8220;right&#8221; time in a company&#8217;s lifecycle to create a growth team?</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Tackling Hard Problems]]></title>
    <link href="http://paul.rosania.org/writings/2012/03/27/tackling-hard-problems/" />
    <updated>2012-03-27T15:59:00-05:00</updated>
    <id>http://paul.rosania.org/writings/2012/03/27/tackling-hard-problems</id>
    <content type="html"><![CDATA[<blockquote><p>The point is to be aware. If you find yourself resisting an obvious step due to
an irrational fear, step back and force yourself to push onward. You only need
to be right 1% of the time.</p></blockquote>

<p><a href="http://davidvaldman.com/post/20027940591/psychofhardproblems">The Psychology of Tackling Hard Problems</a>,
by David Valdman</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[A shell one-liner]]></title>
    <link href="http://paul.rosania.org/writings/2012/02/21/a-shell-one-liner/" />
    <updated>2012-02-21T15:38:00-06:00</updated>
    <id>http://paul.rosania.org/writings/2012/02/21/a-shell-one-liner</id>
    <content type="html"><![CDATA[<pre><code>git log --grep [query] | sed -n '/^commit/p' | cut -d\  -f 2 | xargs git show
</code></pre>

<p>Show all changesets matching <em>query</em>. Useful for reviewing a series of related
changes over time. (Assuming consistent commit message habits.)</p>

<p>Don&#8217;t fear the shell.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Will Facebook Kill Google in 2012?]]></title>
    <link href="http://paul.rosania.org/writings/2012/02/17/will-facebook-kill-google-in-2012/" />
    <updated>2012-02-17T11:23:00-06:00</updated>
    <id>http://paul.rosania.org/writings/2012/02/17/will-facebook-kill-google-in-2012</id>
    <content type="html"><![CDATA[<p>As Facebook gears up for the biggest IPO in history, it faces unprecedented
challenges to future growth. With expansion rates in the US and Europe stabilizing,
Facebook relies more and more on emerging markets for growth.  And yet, there is
a big black hole in Facebook&#8217;s social graph, right where China should be. The
Senate and FTC are eyeing Facebook as keenly as ever. To top things off,
Facebook&#8217;s largest competitor has made an open declaration of war.</p>

<p>Of all these things, competition with Google is perhaps the area over which
Facebook has the most control. Make no mistake, Google is putting everything on
the line to gain a foothold against Facebook. For this reason alone, Google is
the competitor to watch in 2012.  Apple&#8217;s recent announcement that OS X 10.8
Mountain Lion will have deep Twitter integration is perhaps a cause for concern,
but Apple&#8217;s userbase is dwarfed by the billion-plus people that visit a Google
property each month. Add Google&#8217;s deep talent pool, healthy balance sheet and
insane profitability ($3.5B in Q4), and you have a company with a tremendous
amount of stamina. Google is gearing up for a long war.</p>

<p>Anyone who doubts Google&#8217;s intention of dominating the social space need look no
farther than Google+.  Its deep integration across all Google properties was a
clear indication that it&#8217;s here to stay. Now, with &#8220;Search Plus Your World&#8221;,
Google is upping the ante. Search is Google&#8217;s golden goose, historically
unmarred by the complexity that seems inexorable in other Google products. Now
all of that is at risk as Google+ integration threatens its simplicity and result
quality.</p>

<p>Whether Google+ will be a success remains to be seen.  According to Google, 90mm
users are on Plus already. How many are active? Google has a huge incentive to
mask the true DAU and MAU numbers until they reach a menacing level.  If Plus
performs like a more typical social site (not Facebook) it&#8217;s safe to say MAU is
in the 20mm range, and DAU is well under 10mm. (Excluding interaction with the
omnipresent Google+ notification menu, which seems unavoidable.)</p>

<p>If Google can make using Google+ a natural part of using Gmail, it can cut
pretty deeply into the reasons for people to use Facebook, at least in theory.
For most of us, a Gmail tab is at least as likely to be open as Facebook at a
given moment, if not moreso. For many demographics, Gmail chat is more popular
than Facebook chat. And yet, we open Facebook compulsively to see what our
friends are doing, and to share and view photos. If Google can make these
behaviors a fluid part of the Gmail experience they could prove to be quite a
menacing figure.</p>

<p>Data from Google+ benefits Google search as well. Picking a dinner venue and
inviting friends could be done at once. A search for &#8216;skiing&#8217; could show photos
of friends&#8217; recent trips, as well as ski conditions for local resorts. (And
maybe even when your ski buddies have free weekends, leveraging Google Calendar.)
None of these niceties is enough on its own, but the combined utility of
everything in one place will be tough to beat.</p>

<p>At this point, as long as the masses are using a Google product (Gmail and
search in particular) Facebook is at a severe competitive risk to Google+.
Google has shown before that they don&#8217;t necessarily have what it takes to get
products done right. Their engineering culture may be too academic; their
obsession with complex problems may be too much of a negative influence on user
experience design. But with Google betting the business on social, Facebook can
hardly rest easy.</p>

<p>Creating an alternative to Gmail and Google search should be an
urgent strategic priority for Facebook. The timing has never been better:
Google&#8217;s &#8220;Search Plus Your World&#8221; initiative has temporarily shifted the privacy
spotlight from Facebook to Google. At the same time, the much maligned redesign
of Gmail (along with other Google products) presents a window for Facebook to
introduce a winning email experience. Last year&#8217;s Facebook messaging redesign
means many Facebook users already have @facebook.com email addresses.</p>

<p>If Facebook can steal a big minority share of email away from Google, they take
a massive amount of momentum away from Google. As mentioned, Gmail is Google&#8217;s
primary portal platform. Without it, they would be forced to rely on search
&mdash; and while many people search each day, they aren&#8217;t in the social mindset
while doing so, like they are when they use Gmail.</p>

<p>Once a Facebook email service is in the market, a Facebook Search product would
be a killing blow. In 2012, the core concepts behind search relevance that
Google pioneered are largely public and widely understood. What&#8217;s missing is
social relevance, and Facebook already has all the social relevance data it
needs: nearly 3 billion likes and comments are added each day.</p>

<p>Perhaps most important are the behavior changes Google or Facebook would require
in order to win the war. Google+ requires us to reframe our conception of what
Google is about and simultaneously migrate there with all of our friends. On the
other hand, Gmail and search are utilities. If a better version exists, users
will switch &mdash; and they can switch one-at-a-time, whereas switching social
networks requires critical mass.</p>

<p>With all of these considerations, it seems inevitable that Facebook will make
moves to kill Google in 2012.  The first move will be a Gmail replacement, and
search will come shortly thereafter.  We may view Google as socially inept, but
they are a multi-billion dollar company and they employing some of the smartest
people in the world. There is too much at stake for Facebook to wait.</p>

<p><em>What do you think? Let me know <a href="http://twitter.com/paulrosania">@paulrosania</a> or
<a href="mailto:paul@rosania.org">paul@rosania.org</a>.</em></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Don't overload #nil?]]></title>
    <link href="http://paul.rosania.org/writings/2011/11/09/dont-overload-nil/" />
    <updated>2011-11-09T21:46:00-06:00</updated>
    <id>http://paul.rosania.org/writings/2011/11/09/dont-overload-nil</id>
    <content type="html"><![CDATA[<p>There&#8217;s a popular post on Hacker News about writing confident code by, among
other things, overloading <code>Object#nil?</code> and returning &#8220;null objects&#8221; instead of
nil itself.</p>

<p><strong>DO NOT DO THIS.</strong></p>

<p>In Ruby, all objects (except nil itself) coerce to the boolean value <code>true</code>. Your object will be nil
and true at the same time. Bad things will happen. Your coworkers will cry. Sad
people from around the world will ask bewildering questions on your mailing
list.</p>

<p>Here&#8217;s what happens:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">NullObject</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">nil?</span>
</span><span class='line'>    <span class="kp">true</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="n">o</span> <span class="o">=</span> <span class="no">NullObject</span><span class="o">.</span><span class="n">new</span>
</span><span class='line'>
</span><span class='line'><span class="n">o</span><span class="o">.</span><span class="n">nil?</span>             <span class="c1">#=&gt; true, great.</span>
</span><span class='line'><span class="o">!!</span><span class="n">o</span>                <span class="c1">#=&gt; true. not so great.</span>
</span><span class='line'><span class="nb">puts</span> <span class="s2">&quot;exists&quot;</span> <span class="k">if</span> <span class="n">o</span> <span class="c1">#=&gt; &quot;exists&quot;. ut oh.</span>
</span></code></pre></td></tr></table></div></figure>


<p>Do you write all your guards using <code>if o.nil?</code>  Neither do I.</p>

<p>If you overload <code>#nil?</code>, <em>you will get burned.</em> Please don&#8217;t.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Giles Bowkett, Swearing and the Greatest Ruby Talk Ever]]></title>
    <link href="http://paul.rosania.org/writings/2011/11/09/giles-bowkett/" />
    <updated>2011-11-09T14:33:00-06:00</updated>
    <id>http://paul.rosania.org/writings/2011/11/09/giles-bowkett</id>
    <content type="html"><![CDATA[<p>At RubyFringe &#8216;08, Giles Bowkett went on a metaprogramming romp about Ruby,
music, the evils of Venture Capital and the virtues of lightweight, ubiquitous
protocols.  He starts with an impressive demo, but it really gets going about 7
minutes in. Giles takes the crowd on a crazy, lightning-speed tour through 496
slides about Leonardo da Vinci, cougars, LSD and weasel-brained muppet fuckers.</p>

<p>He swears 10 times in 40 minutes, including 7 <em>fuck</em>s. They&#8217;re like flourishes
in an epic fireworks display.</p>

<p>Profanity is like rock music. The f-bomb is electric guitar. You might think it
sounds sophmorish, but if you think it doesn&#8217;t add energy to a presentation,
you&#8217;re lying to yourself.</p>

<p>Watch it.</p>

<p><a href="http://www.infoq.com/presentations/archaeopteryx-bowkett">http://www.infoq.com/presentations/archaeopteryx-bowkett</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Buyer Beware: Firebug 1.6 + Firefox 4 Beta]]></title>
    <link href="http://paul.rosania.org/writings/2010/11/09/buyer-beware-firebug-1-6-and-firefox-4-beta/" />
    <updated>2010-11-09T12:00:00-06:00</updated>
    <id>http://paul.rosania.org/writings/2010/11/09/buyer-beware-firebug-1-6-and-firefox-4-beta</id>
    <content type="html"><![CDATA[<p>There is a bug in Firefox 4 beta 6 (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=557791">#557791</a>)
that interferes with Firebug’s &#8220;XHR Spy&#8221; feature (Firebug issue <a href="http://code.google.com/p/fbug/issues/detail?id=3223">#3223</a>).
The net effect is that XmlHttpRequest onReadyStateChange events don&#8217;t fire.</p>

<p>With JQuery, this manifests through $.ajax calls: success and error handlers don’t fire.</p>

<p>The workaround is to uncheck the &#8220;Show XmlHttpRequests&#8221; option in the Console panel.</p>

<p>For more details, see <a href="http://getfirebug.com/knownissues">Firebug&#8217;s Known Issues</a> page.</p>

<p>Hopefully this short post saves someone more time than I lost dealing with this bug today.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The Death of GOOG-411]]></title>
    <link href="http://paul.rosania.org/writings/2010/10/08/the-death-of-goog-411/" />
    <updated>2010-10-08T12:00:00-05:00</updated>
    <id>http://paul.rosania.org/writings/2010/10/08/the-death-of-goog-411</id>
    <content type="html"><![CDATA[<blockquote><p>Back in 2007 we launched 1-800-GOOG-411, a voice-powered directory assistance service that connects you quickly to businesses
across the U.S. and Canada. On November 12, 2010, we will shut down the service.</p>

<p><a href="http://googleblog.blogspot.com/2010/10/goodbye-to-old-friend-1-800-goog-411.html">&#8220;Goodbye to an old friend: 1-800-GOOG-411&#8221; on The Original Google Blog</a></p></blockquote>

<p>That sucks.  I confess that I usually use Google Maps, Yelp or other apps to do my phone number lookups these days.
But sometimes I&#8217;m driving, or walking in a busy area and don&#8217;t want to be staring down at my phone.
I know, no one calls each other anymore.  But when a call is necessary, GOOG-411 was the best 411 resource out there.
(Not to mention, free.)</p>

<p>R.I.P GOOG-411.  At least one of us will miss you.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[On Luck, and Entrepreneurship]]></title>
    <link href="http://paul.rosania.org/writings/2010/09/16/on-luck-and-entrepreneurship/" />
    <updated>2010-09-16T12:00:00-05:00</updated>
    <id>http://paul.rosania.org/writings/2010/09/16/on-luck-and-entrepreneurship</id>
    <content type="html"><![CDATA[<blockquote><p>&#8230; the second big thing is luck.  And it&#8217;s not relying on luck, or relying on fortune.
It&#8217;s being able to recognize when it&#8217;s happening around you, and being able to recognize
a situation that encourages buildout and execution of an idea.</p>

<p><a href="http://www.vimeo.com/11712774">Jack Dorsey at NYT’s 99% Conference</a></p></blockquote>

<p>Startups fail.  If I got paid for every time I heard the 5-year small business success rate quoted, I&#8217;d have my fuck you money already.
My dad, ever the scientist, likes to remind me that despite blood, sweat and tears, if my startup succeeds it will be because I was &#8220;one of the lucky ones.&#8221;</p>

<p>It&#8217;s true.  And yet, the type of luck we seek as entrepreneurs is not blind luck, like finding a $100 bill on the sidewalk.
The type of luck we are after is situational luck.  Nailing a pitch.  &#8220;Clicking&#8221; with a client prospect or investor.
Hiring a kickass team, and watching them hit home runs for your company.  Yes, the outcome of each singular event is lucky.
But the sum of it all, the net outcome, is not luck.</p>

<p>We make our own luck, and it is a blend of situational awareness and tenacity.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Creating a "TheFunded" for Angel Investors]]></title>
    <link href="http://paul.rosania.org/writings/2010/08/25/creating-a-thefunded-for-angel-investors/" />
    <updated>2010-08-25T12:00:00-05:00</updated>
    <id>http://paul.rosania.org/writings/2010/08/25/creating-a-thefunded-for-angel-investors</id>
    <content type="html"><![CDATA[<p>Adam Smith has a great post with many <a href="http://blog.adamsmith.cc/2010/08/thoughts-after-y-combinator-demo-day.html">interesting observations about Y Combinator&#8217;s most recent demo day</a>.  I latched onto one:</p>

<blockquote><p>Do we need a TheFunded for angel investors?</p></blockquote>

<p>I think the answer is yes, for three reasons:</p>

<ul>
<li>Angel investors come at a critical time for the company</li>
<li>Angels’ reputations are not always well known</li>
<li>The role of the angel is on the rise</li>
</ul>


<h2>Angel investors come at a critical time for the company</h2>

<p>The right investor can bring critical momentum to a fledgling startup.  For the &#8220;mega-angels&#8221; this can be clout, but it can also be key introductions to potential clients and business partners.  Experienced angel investors also know how to manage their relationship with the company in a way that increases the company’s likelihood of success, without getting in the way.</p>

<p>On the other hand, the wrong angel investor can pose a serious risk.  Inexperienced or overly aggressive investors can be a huge distraction during the fundraising process, and putting the deal at risk.  The pain can continue once they&#8217;re in, as they chew up valuable time and energy.</p>

<h2>Angels’ reputations are not always well known</h2>

<p>VC firms’ reputations tend to be public.  TheFunded is a valuable asset in this regard, but firms like Union Square Ventures and Sequoia are preceded by their reputations as well as the reputations of their partners.  While the same is true for prolific angels like Ron Conway and Peter Thiel, it is not true for the many thousands of other angel investors clamoring for access to events like YC Demo Day.</p>

<h2>The role of the angel is on the rise</h2>

<p>More startups are trying to achieve profitability with less fundraising.  Sometimes a seed round is all a company needs to get there.  The financial climate is one factor, but movements like Lean Startup indicate a broader trend that will outlast the crisis, and pose a serious threat to the current VC model.</p>

<p>What this means for angels is they play a bigger overall role over the lifetime of the company.  Instead of getting crammed down across Series A, B and C rounds, where VCs take control via equity and board seats, angels can expect to hold significant equity positions for a long period of a startup’s growth.  As a result, startups need to be increasingly focused on identifying angels that can help move their company forward through introductions, rather than purely through investment.</p>

<h2>Sidebar: &#8230; but is it legal?</h2>

<p>Defamation laws in the United States might pose a challenge to a &#8220;TheFunded for Angels.&#8221;  TheFunded is safe since it deals with organizations, but a review site for angels would by necessity contain reviews of individuals.  While angel investors like Mark Cuban probably constitute &#8220;public figures&#8221;, many lesser known angel investors would not.</p>

<p>The authors of negative reviews of angel investors might be exposed to libel suits, regardless of the reviews’ accuracy.  The types of angel investors that receive low ratings are likely the same types of people who wield lawyers to deal with their problems, and this could torpedo the concept.</p>

<p>But otherwise, I love the idea.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Apartment Hunting Is Not Core to Your Business]]></title>
    <link href="http://paul.rosania.org/writings/2010/08/04/apartment-hunting-is-not-core-to-your-business/" />
    <updated>2010-08-04T12:00:00-05:00</updated>
    <id>http://paul.rosania.org/writings/2010/08/04/apartment-hunting-is-not-core-to-your-business</id>
    <content type="html"><![CDATA[<p>I just wrapped up an apartment search.  In total, my girlfriend and I met with 5 brokers and viewed almost 15 apartments over 4 separate days.  I’m guessing we invested at least 50 hours of time in the process, between phone calls, emails, research, traveling around town and just generally dealing with the annoyance that apartment hunting represents.</p>

<p>After all that, we settled on a unit <em>in the building I already live in</em>.</p>

<p>Why?  Simplicity.  When I began my apartment search, I was determined to cut my monthly rent by at least $200.  By moving within my building, I am saving $150 a month (not quite $200).  At the same time, I’m recovering a full month’s rent that would have been lost to our apartment broker.  Amortized over the full year, that’s easily another $150 a month.</p>

<p>Had I made that choice from the beginning I could have saved myself and my girlfriend  100 combined hours of searching Craigslist, making phone calls and viewing apartments.</p>

<p>Moving would have involved:</p>

<ul>
<li>A U-Haul ($50-100)</li>
<li>A full month’s rent as a broker’s fee in most cases ($1500+)</li>
<li>Several lost days of productivity packing, hauling and unpacking everything</li>
</ul>


<h2>What’s the point?</h2>

<p>In my excitement to cut costs, I discarded the easiest option (stay in the building) without considering the opportunity cost.  I wasted valuable hours (and nearly a lot of money) trying to optimize.</p>

<p>I can make a lot more by investing those hours into my startup.  The potential cost savings I gain by shaving some monthly expenses off my budget are far outweighed by the value my business gains from having the hours invested in it.</p>

<p>I think there’s a lesson there for businesses:  Focus on your core.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Quote: "We are so seduced by...]]></title>
    <link href="http://paul.rosania.org/writings/2010/07/23/quote-we-are-so-seduced-by/" />
    <updated>2010-07-23T12:00:00-05:00</updated>
    <id>http://paul.rosania.org/writings/2010/07/23/quote-we-are-so-seduced-by</id>
    <content type="html"><![CDATA[<blockquote><p>We are so seduced by the thought of a guaranteed paycheck every month that
we completely ignore the fact that it&#8217;s actually never too late to pursue our dreams.
The reason as I can understand is probably &#8220;fear of failure&#8221;.  We fear we might fail
and that fear leads us to cook up stories about why you can’t have what you want.
Alibis like &#8220;I don&#8217;t have time, I have family, I&#8217;ll do it when I have more money etc&#8221;.
Stories that convince us that it&#8217;s ok not to follow up on our dreams, that it’s ok
not to do what you love, that it&#8217;s ok to just keep doing the everyday drill.</p></blockquote>

<p>And guess what.  That paycheck ain&#8217;t guaranteed, either.</p>

<p>From the fantastic post, <a href="http://blog.rootein.com/2010/04/for-gods-sake-follow-your-dreams.html">For God&#8217;s sake, follow your dreams</a>
over at <a href="http://blog.rootein.com/">Rootein Blog</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Point-and-Click Install of MongoDB on OS X 10.5+]]></title>
    <link href="http://paul.rosania.org/writings/2010/06/01/point-and-click-install-of-mongodb-on-os-x/" />
    <updated>2010-06-01T12:00:00-05:00</updated>
    <id>http://paul.rosania.org/writings/2010/06/01/point-and-click-install-of-mongodb-on-os-x</id>
    <content type="html"><![CDATA[<p>Update: v1.4.4 is now available!  See download links below.</p>

<p>Our skunk-works project at <a href="http://collegejobconnect.com/">CollegeJobConnect</a> uses <a href="http://mongodb.org/">MongoDB</a> extensively for persistence.
(Through the excellent <a href="http://mongoid.org/">Mongoid</a> ODM.)  MongoDB is fantastic, but setup on my MacBook Pro is still a manual process with each new version,
so I&#8217;ve packaged up a simple installer that should get you up and running in no time.</p>

<h2>The Old Way</h2>

<ol>
<li>Download the MongoDB binary distribution from the matrix at MongoDB.org</li>
<li>Extract</li>
<li>Move to /usr/local</li>
<li>Symlink mongodb-osx-x86_64-1.4.4 -> mongodb</li>
<li>Create a .plist file in /Library/LaunchDaemons</li>
<li>Load the .plist file into launchd using launchctl</li>
<li>Create data and log directories in /var</li>
<li>Add Mongo to the path (/etc/paths.d/mongodb)</li>
</ol>


<h2>The New Way</h2>

<ol>
<li>Download the MongoDB installer from Github (<a href="http://github.com/paulrosania/mongo-installer/downloads">click here</a>)</li>
<li>Run the installer</li>
</ol>


<p>You can check to see if it’s working properly by visiting <a href="http://localhost:28017/">http://localhost:28017/</a> after installation has completed.</p>

<h2>Requirements</h2>

<p>The installer uses launchd and the x86_64 release of MongoDB v.1.4.4.  It requires:</p>

<ul>
<li>Mac OS X 10.5 (Leopard) or 10.6 (Snow Leopard)</li>
<li>A 64-bit CPU (Core 2 Duo or newer)</li>
</ul>


<p>Steps to get it working on 10.4 (Tiger) are probably minimal but are left as an exercise for the reader.  I don&#8217;t use Tiger anymore&#8230; YMMV.</p>

<p>Feel free to leave feedback in the comments.  Issues should be lodged at <a href="http://github.com/paulrosania/mongo-installer/issues">Github</a>.</p>

<h3>Disclaimer</h3>

<p>The installer is provided as a community service to people like me who are looking for an easier way to install MongoDB and keep it up to date.  It comes with no warranty.  I am not responsible for any damage caused by the installer.  The project is freely available on Github.  Feel free to <a href="http://github.com/paulrosania/mongo-installer">peruse the source</a> if you like.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[JRuby Deployment with Glassfish and Capistrano]]></title>
    <link href="http://paul.rosania.org/writings/2010/05/15/jruby-deployment-with-glassfish-and-capistrano/" />
    <updated>2010-05-15T12:00:00-05:00</updated>
    <id>http://paul.rosania.org/writings/2010/05/15/jruby-deployment-with-glassfish-and-capistrano</id>
    <content type="html"><![CDATA[<p>At <a href="http://collegejobconnect.com/">CollegeJobConnect</a>, we need to process Word and PDF-format resumes that we receive from our members.
In order to carefully curate our initial candidate pool, we have done a lot of this work by hand.
However, as we grow we need to automate as much of the registration process as we can.
This involves using automated text extraction to retrieve some basic attributes from these files.
Fortunately, there are some great <a href="http://poi.apache.org/">open</a> <a href="http://pdfbox.apache.org/">source</a> tools out there
that wrangle Word and PDF documents into raw text. Unfortunately, they are written in Java.  Enter <a href="http://jruby.org/">JRuby</a>.</p>

<p>JRuby makes our job drop-dead simple.  We can tap into the Java libraries we need, while keeping our code in the language we love.
Unfortunately, the state-of-the-art in JRuby deployment is in a bit of disarray.
Charles Nutter does a good job of guiding the decision in his <a href="http://blog.headius.com/2009/08/which-deployment-for-jruby-on-rails.html">August 2009 blog post</a>.
We settled on his recommended approach for simple apps — GlassFish gem.  However, things fell apart in the details.
A <a href="http://blogs.sun.com/Jacobkessler/entry/capistrano_and_glassfish_now_with">post on Jacob Kessler’s blog</a> at Sun provided some guidance,
but we had trouble getting his deployment script working properly.
We also wanted something that we could administer with initscripts, to DRY out process control.
After a few hours of head-scratching frustration, we got things running.  Here’s how:</p>

<h2>Prerequisites</h2>

<ul>
<li>Java 6 JRE (sun-java6-jre on Ubuntu)</li>
<li>JRuby 1.5</li>
<li>Git</li>
</ul>


<p>(Our server is running Ubuntu 10.04 LTS &#8220;Lucid Lynx&#8221;, but this should work in 9.10 and 8.04, and with minor adjustments in any similar Unix environment.)</p>

<h2>Getting It Done</h2>

<p>1. Install GlassFish gem: <code>sudo jruby -S gem install glassfish</code></p>

<p>2. Capify your JRuby application. From your application’s root directory, run <code>capify .</code></p>

<p>3. Customize <code>config/deploy.rb</code> for GlassFish.  (Change the ”example_app” references to match your app.) <div><script src='https://gist.github.com/402402.js?file='></script>
<noscript><pre><code>set :application, &quot;example_app&quot;
set :domain, &quot;example-app.com&quot;</p>

<h2>IMPORTANT: &quot;true&quot; prevents the server from booting properly</h2>

<h2>This line is sometimes recommended in other Capistrano configurations,</h2>

<h2>but do not use it for GlassFish.</h2>

<h1>default_run_options[:pty] = true</h1>

<p>set :scm,        :git
set :repository, &quot;git@github.com:paulrosania/example_app.git&quot;
set :user,       &quot;deploy&quot;
set :branch,     &quot;master&quot;
set :deploy_via, :remote_cache
set :deploy_to,  &quot;/home/deploy/sites/#{application}&quot;
set :use_sudo,   false</p>

<p>role :web, domain                          # Your HTTP server, Apache/etc
role :app, domain                          # This may be the same as your <code>Web</code> server
role :db,  domain, :primary =&gt; true # This is where Rails migrations will run</p>

<h1>role :db,  &quot;your slave db-server here&quot;</h1>

<p>namespace :deploy do
  desc &quot;Start Glassfish Gem from a shutdown state&quot;
  task :cold do</p>

<pre><code>start
</code></pre>

<p>  end</p>

<p>  desc &quot;Stop a server running GlassFish gem&quot;
  task :stop do</p>

<pre><code>run &amp;quot;/usr/sbin/service glassfish-example_app stop&amp;quot;
</code></pre>

<p>  end</p>

<p>  desc &quot;Starts a server running GlassFish gem&quot;
  task :start do</p>

<pre><code>run &amp;quot;/usr/sbin/service glassfish-example_app start&amp;quot;
</code></pre>

<p>  end</p>

<p>  desc &quot;Restarts a server running GlassFish gem&quot;
  task :restart do</p>

<pre><code>stop
start
</code></pre>

<p>  end
end
</code></pre></noscript></div></p>

<p>4. Install the glassfish-example_app initscript in /etc/init.d.  (Change the “example_app” references and customize the GlassFish arguments to suit your fancy.) <div><script src='https://gist.github.com/402405.js?file='></script>
<noscript><pre><code>#!/bin/sh</p>

<h3>BEGIN INIT INFO</h3>

<h1>Provides:          example_app</h1>

<h1>Required-Start:    $local_fs $remote_fs $network $syslog</h1>

<h1>Required-Stop:     $local_fs $remote_fs $network $syslog</h1>

<h1>Default-Start:     2 3 4 5</h1>

<h1>Default-Stop:      0 1 6</h1>

<h1>Short-Description: starts the example_app app server</h1>

<h1>Description:       starts the example_app app server</h1>

<h3>END INIT INFO</h3>

<p>set -u
set -e</p>

<h1>Feel free to change any of the following variables for your app:</h1>

<p>APP_ROOT=/home/deploy/sites/example_app/current
PID=$APP_ROOT/tmp/pids/glassfish.pid
ENV=production
CMD=&quot;/usr/local/jruby/bin/jruby -S glassfish --contextroot / --port 3000 --environment production --runtimes 1 --runtimes-min 1 --runtimes-max 2 -P /home/deploy/sites/example_app/current/tmp/pids/glassfish.pid --daemon /home/deploy/sites/example_app/current&quot;</p>

<p>cd $APP_ROOT || exit 1</p>

<p>sig () {</p>

<pre><code>    test -s &amp;quot;$PID&amp;quot; &amp;amp;&amp;amp; kill -$1 `cat $PID`
</code></pre>

<p>}</p>

<p>case $1 in
start)</p>

<pre><code>    sig 0 &amp;amp;&amp;amp; echo &amp;gt;&amp;amp;2 &amp;quot;Already running&amp;quot; &amp;amp;&amp;amp; exit 0
    $CMD
    ;;
</code></pre>

<p>stop)</p>

<pre><code>    sig INT &amp;amp;&amp;amp; exit 0
    echo &amp;gt;&amp;amp;2 &amp;quot;Not running&amp;quot;
    ;;
</code></pre>

<p>force-stop)</p>

<pre><code>    sig TERM &amp;amp;&amp;amp; exit 0
    echo &amp;gt;&amp;amp;2 &amp;quot;Not running&amp;quot;
    ;;
</code></pre>

<p>restart|reload)</p>

<pre><code>    sig INT || sig TERM
    $CMD
    ;;
</code></pre>

<p>*)</p>

<pre><code>    echo &amp;gt;&amp;amp;2 &amp;quot;Usage: $0 &amp;lt;start|stop|restart|force-stop&amp;gt;&amp;quot;
    exit 1
    ;;
</code></pre>

<p>esac
</code></pre></noscript></div></p>

<p>5. Install the initscript in rc.d (this will only work on Ubuntu/Debian):</p>

<pre><code>   sudo update-rc.d glassfish-example_app defaults
</code></pre>

<p>6. Deploy your app with cap deploy.</p>

<p>&#8230; and you’re done! Post in the comments if you have any comments or questions.  If this saves you time, let me know!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[On Privacy (or: What Buzz failed to learn from Newsfeed)]]></title>
    <link href="http://paul.rosania.org/writings/2010/02/12/on-privacy-or-what-buzz-failed-to-learn-from-newsfeed/" />
    <updated>2010-02-12T12:00:00-06:00</updated>
    <id>http://paul.rosania.org/writings/2010/02/12/on-privacy-or-what-buzz-failed-to-learn-from-newsfeed</id>
    <content type="html"><![CDATA[<p>On Friday, September 8, 2006, Mark Zuckerberg <a href="http://blog.facebook.com/blog.php?post=2208562130">published an apology</a>
for the <a href="http://www.wired.com/science/discoveries/news/2006/09/71739">botched</a> <a href="http://www.theregister.co.uk/2006/09/07/facebook_update_controversy/">launch</a>
of Facebook Newsfeed. The gist of his open letter was:</p>

<ul>
<li>We did a poor job explaining the new features</li>
<li>We did not provide anywhere near enough privacy control</li>
<li>We are launching better privacy controls today, after a marathon 48 hour coding session</li>
</ul>


<p>A public apology from the CEO of a major company is commendable.
But contrast this with his <a href="http://blog.facebook.com/blog.php?post=2208197130">post on Tuesday night</a>, just 3 days beforehand:</p>

<ul>
<li>Newsfeed is great and you need to give it a chance</li>
<li>Your privacy settings have not changed</li>
<li>Things that were private are still private</li>
<li>Your friends can see the exact same things they could see before</li>
</ul>


<p>What changed?  Why the sudden change in tone?  Mark was coming to grips with a fundamental issue facing social software:</p>

<h2>Companies don’t understand privacy!</h2>

<p>&#8230; and as a result, they make the same mistakes, over and over again.</p>

<p>We live in public.  And we always have.  <a href="http://www.youtube.com/watch?v=_XSTwfdFwIY">Moreso now</a>, perhaps.
But if you have ever had your picture taken, eaten at a restaurant, or had an argument in a public place,
a little bit of your self has been copied into the ether.  Yet, just because we do these things does not mean we want them to be public.
That argument with your significant other would drop dead if a film crew showed up and pointed a camera in your direction.</p>

<p>In a declarative sense, one can think about privacy as action and context.
What we do, and where and with whom we do it.
Indeed, the Googles and Facebooks of the world have gotten pretty sophisticated about this kind of privacy.
&#8220;Share my vacation photos with my close friends.&#8221;  &#8220;Invite my coworkers to my housewarming.&#8221;</p>

<p>However, (as is typical with computers) things break down when you start to make inferences.
She wrote on someone’s public wall, therefore she intended for everyone to read.
She posted the pictures on her public blog, therefore she wants her coworkers to see them.
It’s pretty easy to see where the wheels come off.  That public argument we were discussing earlier?
It happened in the middle of Faneuil Hall with thousands of people around.  Let’s podcast it automatically!</p>

<p>Action: audio conversation; context: extraordinarily public place.  Privacy setting: Everyone.</p>

<h2>What’s missing is intent.</h2>

<p>Just because something is public does not mean it is intended to be seen.
We do things in public all the time that would be <a href="http://www.people.com/people/article/0,,20323528,00.html">humiliating</a>
or <a href="http://www.ivygateblog.com/2008/12/dartmouth-religion-professor-apparently-clueless-about-the-perils-of-facebook/">destructive</a> if broadcasted.
We are so used to doing these things that sometimes we don’t even notice the context in which we are acting!
Relying on the context of an action to determine intent is a recipe for failure.</p>

<h2>Privacy and the human mind.</h2>

<p>As we use software, we map its features to our intentions.  We learn how to perform actions, and we learn to control context using privacy settings.
But that map is not perfect.  We can be confused or misled by the abundance of options or by our interpretation of instructions.  We can be downright lazy.
Or, like the public argument, we can simply forget (or ignore) context.  When those things happen, we rely on software to understand our intent,
and shield us from mistakes caused by our imperfect mental map.  And unfortunately, when it comes to understanding intent, computers fail.
(<a href="http://gadgetwise.blogs.nytimes.com/2009/06/29/pushing-the-limits-of-googles-speech-recognition/">Sorry</a>, <a href="http://gvscrewups.blogspot.com/">Google</a>.)</p>

<h2>What about Buzz?</h2>

<p>Back to Buzz.  The controversy over privacy is not stemming from the design of Buzz.  It stems from default settings.
The Google Buzz team is attempting to make Buzz useful right out of the gate by guessing your preferred list of followers and followees.
But computers fail at intent, and despite thoughtful design of privacy settings,
Buzz is a <a href="http://fugitivus.wordpress.com/2010/02/11/fuck-you-google/">privacy</a>
<a href="http://www.businessinsider.com/googles-nice-improvements-to-buzz-dont-correct-major-privacy-flaw-2010-2">failure</a>.</p>

<h2>A path forward?</h2>

<p>Failed launches like Newsfeed and Buzz can teach us something about how people think about privacy, and how to design software to be understood and accepted by its users.  Facebook taught us that declarative privacy settings can work.  However, both of these failures highlight two more key issues:
Computers suck at intent.  Inferring privacy preferences for new software, based on prior actions in old software, is a recipe for failure, and a PR nightmare.
People assume computers are great at intent.  We publish things to much wider contexts than we intend, and don’t notice or care until new products and features make incorrect inferences based on that.
The good news is that smart people are working on these problems.  Let’s just hope they are learning from each other.</p>

<h2>In summary</h2>

<ul>
<li>Shockingly, these mistakes have been made before</li>
<li>Companies like Facebook and Google are only just beginning to understand privacy</li>
<li>Explicit, declarative privacy settings are good</li>
<li>Users are loose with their settings, and trust software to “do the right thing”</li>
<li>When it comes to social software, computers suck at figuring out what the right thing is</li>
<li>Products can improve if competitors can learn from each other</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Installing Redis on CentOS 4]]></title>
    <link href="http://paul.rosania.org/writings/2009/12/16/installing-redis-on-centos-4/" />
    <updated>2009-12-16T12:00:00-06:00</updated>
    <id>http://paul.rosania.org/writings/2009/12/16/installing-redis-on-centos-4</id>
    <content type="html"><![CDATA[<p>TL;DR: CentOS 4 initscript for Redis at: http://gist.github.com/257849</p>

<h2>Vanity Is Nice</h2>

<p>I am a huge fan of Vanity, Assaf Arkin’s “Experiment Driven Development” framework.  (A/B testing and metric tracking.)
&#8220;Gem install&#8221; to &#8220;cap deploy&#8221; in under an hour.  Talk about reducing the time investment required to get going with data-driven development!
It Just Makes Life Easier.</p>

<p>Vanity uses Redis as its backing store.  Redis is fast and lightweight — no problem there.  It builds on CentOS right out of the gate.
However, I want to use Redis with Vanity on a production site.  If Redis is down, Vanity crashes and takes my app with it.
I need it installed at runlevels 345, so it always starts at boot time. (We need adequate monitoring, too, but that’s a topic for another post.)</p>

<h2>CentOS Needs a Friend</h2>

<p>There is a Ubuntu initscript floating around, but building dpkg to get the start-stop-service binary is a little heavyweight for my taste.
Instead, I’ve gutted an old Nginx initscript, and it works handily.</p>

<p>You can find it at: http://gist.github.com/257849</p>

<h2>If You Came for the Show</h2>

<p>How to install Redis on CentOS 4, in 13 easy steps:</p>

<ol>
<li>curl http://redis.googlecode.com/files/redis-1.02.tar.gz | tar zx</li>
<li>cd redis-1.02</li>
<li>make</li>
<li>sudo cp redis-server /usr/local/sbin</li>
<li>sudo cp redis-cli /usr/local/bin</li>
<li>sudo mkdir /var/lib/redis /etc/redis</li>
<li>sudo sed -e “s/<sup>daemonize</sup> no$/daemonize yes/” -e “s/<sup>dir</sup> .//dir /var/lib/redis//” -e “s/<sup>loglevel</sup> debug$/loglevel notice/” -e “s/<sup>logfile</sup> stdout$/logfile /var/log/redis.log/” redis.conf > /etc/redis/redis.conf</li>
<li>curl http://gist.github.com/gists/257849/download | tar -zxO > redis-server</li>
<li>chmod u+x redis-server</li>
<li>mv redis-server /etc/init.d</li>
<li>sudo /sbin/chkconfig –add redis-server</li>
<li>sudo /sbin/chkconfig –level 345 redis-server on</li>
<li>sudo /sbin/service redis-server start</li>
</ol>


<p>Congratulations, you have a complete Redis installation!</p>

<ul>
<li>Config: /etc/redis/redis.conf</li>
<li>Data: /var/lib/redis</li>
<li>Logfile: /var/log/redis.log</li>
<li>PID: /var/run/redis.pid</li>
</ul>


<p>If you tweak the paths, you’ll need to edit redis.conf and/or the redis-server initscript accordingly.</p>
]]></content>
  </entry>
  
</feed>
