<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 <title>Dispatches - Eric Farkas</title>
 <link href="http://ericfarkas.com/atom.xml" rel="self"/>
 <link href="http://ericfarkas.com/"/>
 <updated>2026-03-22T00:34:14+00:00</updated>
 <id>http://ericfarkas.com</id>
 <author>
   <name>Eric Farkas</name>
 </author>

 
 <entry>
   <title>Share By Default</title>
   <link href="http://ericfarkas.com/posts/share-by-default"/>
   <updated>2020-07-15T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/share-by-default</id>
   <content type="html"><![CDATA[
     <p>Information asymmetry is a feature, not a bug, of management. You are in meetings with leaders from
different teams and departments. In these meetings you <em>learn things</em>. Not only that, as a good manager
you seek out information. What are other departments working on? What features are we missing that
cause us to lose potential customers?</p>

<p>As a manager, how should you decide which information to pass along to your
team?</p>

<p>Your bias should be to “share by default”.</p>

<p>Take a step back. Start from a place of “trust by default”. Every person on your team
is a diligent professional, doing the best they can with the information they have. Each
teammate brings their unique personal and professional experiences to bear on their work.</p>

<p>You put in the work to get to know each teammate. You have facilitated the establishment of common
practices within the team. Despite this, you cannot know, much less predict, the effect that a piece of
information will have upon a person’s work. Yes, you have context your team doesn’t have, but they
also have context <em>you</em> don’t have.</p>

<p>“Share by default” is empathetic.  It communicates that you don’t know everything. It demonstrates
that you trust your teammates to make good decisions. You believe that the more informed they are,
the better decisions they will make.</p>

<p>What shouldn’t you share by default?</p>

<ul>
  <li>
    <p>Individual matters, shared in private. This includes things shared  with you by someone, or shared with you <em>about</em> someone.</p>
  </li>
  <li>
    <p>Assume anything shared in a 1:1 is “share with permission”. If you learn something in a 1:1 that you think another person should hear, always ask “Do you mind if I share that?” In my experience, most of the time the answer is yes, but never assume.</p>
  </li>
</ul>

<p>A bias for “share by default” doesn’t mean you will wind up sharing everything
in public. It only means that you’re looking for reasons <em>to not</em> share
information. This is as opposed to looking for explicit reasons <em>to</em> share information. Just
because you, in your limited wisdom, can’t come up with a reason to share
information, doesn’t mean a good reason does not exist.</p>

<p>In the absence of a compelling reason to keep information to yourself, you should share it, even if you’re not sure other people need to know it.</p>

<h3 id="lightbulb-moment">Lightbulb Moment</h3>

<p>I learned this lesson some time ago when I was in a meeting with leaders from
other departments. An executive spoke about how we’d market the feature
my team was working on with features two other teams built, as a package
aimed at a segment of target customers. I gathered that many in the room had known about this marketing effort for weeks, but it was the first time I
had heard of it. I realized that if I didn’t have this context, my
team didn’t either.</p>

<p>At our next standup I said something like, “I was in a meeting yesterday
where I heard the feature we’re working on will be marketed together
with these other features. Here’s how the rest of the company is
viewing our work. Thought you’d all like to know.”</p>

<p>Having that knowledge didn’t help anyone write better code. But it
did renew the team’s sense of purpose in their work. We saw our
effort in the larger context of the company’s goals. We realized other
teams were depending on our work in a way that we hadn’t before.</p>

<p>Since that meeting, as a manager I have become more aggressive in
seeking out information and context. The goal is to then share it
with my team. For example, when in discussions with a PM about a feature, I will
often say, “There should be nothing you know about this feature, that
we don’t. Give us everything.”</p>

<p>Far from overloading your team with information, you will communicate
that you trust them to synthesize new information, and make good decisions
with it.</p>

<p>You are also exemplifying the traits they will need when they are technical leaders.</p>

   ]]></content>
 </entry>
 
 <entry>
   <title>Book Review: The Ride of a Lifetime</title>
   <link href="http://ericfarkas.com/posts/the-ride-of-a-lifetime"/>
   <updated>2020-03-17T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/the-ride-of-a-lifetime</id>
   <content type="html"><![CDATA[
     <h3 id="the-ride-of-a-lifetime-by-robert-iger"><em><a href="https://www.penguinrandomhouse.com/books/556683/the-ride-of-a-lifetime-by-robert-iger/">The Ride of a Lifetime</a></em> by Robert Iger</h3>

<p>
  <img src="/assets/images/ride-of-a-lifetime.jpg" align="left" style="margin-right:
10px; margin-bottom: 10px;" class="img-polaroid" />
  Robert Iger was the CEO of the Walt Disney Company from 2005 to 2020. In <i>The Ride of
  a Lifetime: Lessons Learned From 15 Years as CEO of the Walt Disney Company</i>, Iger recounts his time coming through the ranks
  at ABC, Capital Cities, and eventually, as the title suggests, CEO of Disney after
  Michael Eisner.
</p>

<p>
  This book is mainly a business biography. There is little in the way of personal
  detail about Iger himself, which is fair enough. This was disappointing to me because I personally find the value in these
  kinds of books to not only derive from the business lessons learned, but the thought process
  leading up to decisions.
</p>

<p>
  It's easy in retrospect to see how, for example, Disney
  absolutely had to develop their own streaming platform, even if it meant
  cannibalizing their business in the short-term. Iger talks about seeing the need for
  Disney to "disrupt themselves".
</p>

<p>
  But how did he realize this? What books was he
  reading? Who was he talking to? He often refers to an early business lesson: innovate
  or die. But how did he jump from "innovate or die" to Disney+? To make that kind of
  move inside a huge, historic company like Disney is truly visionary, and had to
  require a kind of courage. I was left wanting more insight into the man himself,
  and didn't get it.
</p>

<p>
  That said, as a fan of Disney, I thoroughly enjoyed the book. The business stories
  are <i>good</i>. My favorite parts are Iger's interactions with Steve Jobs. Anyone
  familiar with Jobs will instantly recognize him: not interested in playing it safe,
  not giving an inch when he has all the leverage, always looking to innovate.
</p>

<p>
  I was emotional as Iger told how Jobs pulled him aside on Pixar's campus in 2006, moments
  before the event to announce Disney's acquisition of Pixar, to tell Iger that his
  cancer had returned. It was a moment of great humanity and vulnerability in the
  middle of a huge business deal, expertly told.
</p>

<h3 id="lessons">Lessons</h3>
<ul>
  <li>
    <p>Business is personal. Many of Disney’s biggest deals under Iger were successful
because Iger built a personal relationship with the main players (Jobs at Pixar,
Lucas at Lucasfilm, Perlmutter at Marvel, Murdoch at Fox). I tend to think of Serious
Business being mostly a matter of numbers and shared interests, but it struck me how
personal it is, at the highest levels.</p>
  </li>
  <li>
    <p>“Innovate or die”. Iger learned this lesson early in his career. He was never
scared of what the future meant to his business. Rather than trying to protect
Disney out of fear, he tried to anticipate the future and position Disney to take
advantage of it, even if that meant short-term financial pain. The more I think about
it, the more I appreciate how bold this approach was for Iger. He must be a great
storyteller.</p>
  </li>
</ul>

   ]]></content>
 </entry>
 
 <entry>
   <title>Questions I Ask During Code Review</title>
   <link href="http://ericfarkas.com/posts/questions-i-ask-during-code-review"/>
   <updated>2020-01-09T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/questions-i-ask-during-code-review</id>
   <content type="html"><![CDATA[
     <p><em>The following is adapted from an internal writeup I did for my team on the topic of
code review. It has been shaped by my experience as a developer and engineering
manager in the particular technical, social, and business contexts of my career. A year ago,
this document would have looked different. A year from now, it will hopefully look
different too. While I think some of these points are applicable in all contexts, I
make no claim that this is how everyone should do code review.</em></p>

<p>What should we look for when doing code review? How should we receive code reviews from others?</p>

<p>thoughbot’s <a href="https://github.com/thoughtbot/guides/blob/master/code-review/README.md">Code Review</a> guide is a
great starting point. It articulates principles for the relational side of code review. This
is especially relevant for us in a remote environment. <em>How</em> we give and receive feedback is
as important as the feedback itself.</p>

<h3 id="things-to-look-for-in-code-review">Things To Look For In Code Review</h3>

<p>The following is a very incomplete list of questions to ask yourself during code review. The
items here are meant to be starting points for a conversation with the code’s author. Always
assume the best intentions.</p>

<ul>
  <li>
    <p>Is the commit message well-formed? See <a href="https://chris.beams.io/posts/git-commit/">How to Write a Git Commit Message</a> and <a href="https://robots.thoughtbot.com/5-useful-tips-for-a-better-commit-message">5 Useful Tips For A Better Commit Message</a>.</p>
  </li>
  <li>
    <p>Given the commit message, do I, as a reviewer, understand the purpose of this code? Do I know how to manually QA it? Do I know how I’d even determine if the code does it what it claims to do?</p>
  </li>
  <li>
    <p>Has anyone outside of the author’s team QA’d the feature or bugfix to verify it?</p>
  </li>
  <li>
    <p>Have all it’s tests passed?</p>
  </li>
  <li>
    <p>Are there any Hound errors? Has ESLint been run on any new JS code?</p>
  </li>
  <li>
    <p>Are there any lines of code that make me scroll horizontally? If so, the line is probably too long.</p>
  </li>
  <li>
    <p>Are there tests? If not, why?</p>
  </li>
  <li>
    <p>Do the tests follow our RSpec conventions? If not, the author should present a case for introducing a new pattern.</p>
  </li>
  <li>
    <p>Are these the right tests? This can be hard to determine.</p>
  </li>
  <li>
    <p>Do the tests prove that the code does what it claims to do? Generally, there should <em>at least</em> be tests at the <a href="https://robots.thoughtbot.com/testing-from-the-outsidein">highest level possible level</a>.</p>
  </li>
  <li>
    <p>Are the tests efficient? Do we need to hit the database <em>that many times</em> to prove our code works? Do we need to reload that object? Are we doing <code class="language-plaintext highlighter-rouge">js: true</code> in feature specs that don’t need JS? There are so many aspects to this question.</p>
  </li>
  <li>
    <p>Is the code readable (well-named variables and methods, etc.)?</p>
  </li>
  <li>
    <p>Is there duplication of <em>business logic</em>? This is not always a bad thing (see <a href="https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction">The Wrong Abstraction</a>). But we should be on the lookout for duplicated business logic nonetheless.</p>
  </li>
  <li>
    <p>Does the code follow the general pattern of other code that does similar things? If not, the author should present a case for introducing a new pattern.</p>
  </li>
  <li>
    <p>Can we achieve any performance boost (however small) from <a href="https://www.justinweiss.com/articles/4-simple-memoization-patterns-in-ruby-and-one-gem/">memoizing</a>?</p>
  </li>
  <li>
    <p>If writing a new background job, has the Operations team taken a look at the code and approved it? What are the things they look at when determining if a background job is efficient or not? Learn those things!</p>
  </li>
  <li>
    <p>If writing an Elasticsearch query, is pagination going to behave the way the author thinks it will?</p>
  </li>
</ul>

<h3 id="ruby-specific">Ruby-Specific</h3>

<p>During code review we want to look for sub-optimal Ruby Standard API usage. Most of
these instances will be related to misuse of <a href="https://ruby-doc.org/core-2.6/Enumerable.html">Enumberable</a> methods. Reading <a href="https://thomasleecopeland.com/2013/09/18/refactor-to-standard-library.html">Refactor to use Ruby standard library</a> will give you a good grounding in ways to make Ruby code more idiomatic.</p>

<p>The most common instances take this shape:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">some_collection_filtering_method</span>
  <span class="n">my_array</span> <span class="o">=</span> <span class="p">[]</span>
  <span class="vi">@collection_from_class_args</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">item</span><span class="o">|</span>
    <span class="k">if</span> <span class="n">item</span><span class="p">.</span><span class="nf">meets_some_condition?</span>
      <span class="n">my_array</span> <span class="o">&lt;&lt;</span> <span class="n">item</span>
    <span class="k">end</span>
  <span class="k">end</span>
  <span class="n">my_array</span>
<span class="k">end</span>
</code></pre></div></div>
<p>A more idiomatic approach would be to use <a href="https://ruby-doc.org/core-2.6/Enumerable.html#method-i-select"><code class="language-plaintext highlighter-rouge">#select</code></a>:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">some_collection_filtering_method</span>
  <span class="vi">@collection_from_class_args</span><span class="p">.</span><span class="nf">select</span><span class="p">(</span><span class="o">&amp;</span><span class="ss">:meets_some_condition?</span><span class="p">)</span>
<span class="k">end</span>
</code></pre></div></div>

<p>Similarly:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">some_collection_transforming_method</span>
  <span class="n">my_array</span> <span class="o">=</span> <span class="p">[]</span>
  <span class="vi">@collection_from_class_args</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">item</span><span class="o">|</span>
    <span class="n">modified_item</span> <span class="o">=</span> <span class="n">widgetize</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
    <span class="n">my_array</span> <span class="o">&lt;&lt;</span> <span class="n">modified_item</span>
  <span class="k">end</span>
  <span class="n">my_array</span>
<span class="k">end</span>
</code></pre></div></div>
<p>A more idiomatic approach would be to use <a href="https://ruby-doc.org/core-2.6/Enumerable.html#method-i-map"><code class="language-plaintext highlighter-rouge">#map</code></a>:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">some_collection_transforming_method</span>
  <span class="vi">@collection_from_class_args</span><span class="p">.</span><span class="nf">map</span> <span class="k">do</span> <span class="o">|</span><span class="n">item</span><span class="o">|</span>
    <span class="n">widgetize</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>
<p>And if the result of <code class="language-plaintext highlighter-rouge">widgetize</code> could be <code class="language-plaintext highlighter-rouge">nil</code>, we could use <a href="https://ruby-doc.org/core-2.6/Array.html#method-i-compact"><code class="language-plaintext highlighter-rouge">#compact</code></a>:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">some_collection_transforming_method</span>
  <span class="vi">@collection_from_class_args</span><span class="p">.</span><span class="nf">map</span> <span class="k">do</span> <span class="o">|</span><span class="n">item</span><span class="o">|</span>
    <span class="n">widgetize</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
  <span class="k">end</span><span class="p">.</span><span class="nf">compact</span>
<span class="k">end</span>
</code></pre></div></div>
<p>One should look for these instances when doing code review.</p>

<h3 id="rails-specific">Rails-Specific</h3>
<p>Some Rails-specific things to look out for in code review:</p>

<ul>
  <li>
    <p>Are there any unnecessary database calls? Are we missing an <a href="https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations">eager-load</a>?</p>
  </li>
  <li>
    <p>Using <code class="language-plaintext highlighter-rouge">where(...).first</code> instead of <code class="language-plaintext highlighter-rouge">find_by(...)</code>.</p>
  </li>
  <li>
    <p>Using <code class="language-plaintext highlighter-rouge">update_attributes</code> instead of <code class="language-plaintext highlighter-rouge">update</code>.</p>
  </li>
  <li>
    <p>Not capturing the output of <code class="language-plaintext highlighter-rouge">save</code> or <code class="language-plaintext highlighter-rouge">update</code>. Why doesn’t the author care if their database call was successful or not? If they don’t care, should the code raise an exception if it’s not successful, via <code class="language-plaintext highlighter-rouge">save!</code> or <code class="language-plaintext highlighter-rouge">update!</code>? Be careful of this in tests: if we are doing an <code class="language-plaintext highlighter-rouge">update</code> in a test but not saving the return value and ensuring it’s <code class="language-plaintext highlighter-rouge">true</code>, how are we sure our test setup is correct?</p>
  </li>
  <li>
    <p>Not using <code class="language-plaintext highlighter-rouge">find_each</code> when iterating over collections of unknown size.</p>
  </li>
  <li>
    <p>Not scoping queries. There are cases where it’s OK to do this, but they are rare.</p>
  </li>
</ul>

<h3 id="further-reading">Further Reading</h3>
<ul>
  <li><a href="https://www.notion.so/How-to-do-Code-Reviews-1c33cbf7597a4d61aeb3905b86844baf">How To Do Code Reviews</a></li>
</ul>

   ]]></content>
 </entry>
 
 <entry>
   <title>The Map Is Not The Territory</title>
   <link href="http://ericfarkas.com/posts/the-map-is-not-the-territory"/>
   <updated>2019-03-04T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/the-map-is-not-the-territory</id>
   <content type="html"><![CDATA[
     <p>I’ve been thinking about how the idea that <a href="https://fs.blog/2015/11/map-and-territory/">“the map is not the territory”</a>
applies to software development.</p>

<p>In software development, we use tools that us help break large tasks into smaller ones. We can represent these sub-tasks as “cards”.</p>

<p>But, if we don’t pay attention, those same tools can lull us into thinking of our application as the smaller units those “cards” represent. We begin to mistake the map for the territory.</p>

<p>In reality, an application is a <em>system</em>. Changes in one area can (and often do) have implications in other areas of the system. Put another way: few changes are actually <em>isolated</em>. This is true not only on the level of actual code, but in the capabilities an application affords.</p>

<p>How many times have you come across a bug you were <em>sure</em> wasn’t related to a recent change, only to discover that it was? Or gave users a new capability, only to discover you now have data in a state that another part of the app cannot handle?</p>

<p>Thus, it’s necessary to step back from your tasks. You have to ask: what are the implications of this change for the whole application? What am I missing? What questions am I not asking?</p>

<p>A good team lead will encourage everyone, regardless of experience level, to think in these terms. Once the team is asking these questions, together, it will become natural for team members to think this way, on their own.</p>

<p>The Trello board is not the iteration.</p>

<h3 id="see-also">See Also</h3>
<p><a href="https://genius.com/Jorge-luis-borges-on-exactitude-in-science-annotated">On Exactitude In Science</a> by Jorge Luis Borges</p>

   ]]></content>
 </entry>
 
 <entry>
   <title>Cleaning Up Old Git Branches</title>
   <link href="http://ericfarkas.com/posts/cleaning-up-old-git-branches"/>
   <updated>2018-10-27T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/cleaning-up-old-git-branches</id>
   <content type="html"><![CDATA[
     <p>At work, we typically delete remote branches after they are merged into <code class="language-plaintext highlighter-rouge">master</code>. This often leaves me in a situation
where I have many <em>local</em> branches whose <em>remote</em> no longer exists.</p>

<p>Some folks like to keep those branches around <em>just in case</em>. Because of the power of <a href="https://git-scm.com/docs/git-reflog">git-reflog</a>,
I don’t think keeping old branches around is necessary.</p>

<p>In a perfect world, I’d <code class="language-plaintext highlighter-rouge">git branch -D</code> everytime a remote branch was deleted. But things often
get too busy to clean up, and who wants to remember <em>which</em> branch was deleted? Can’t I just tell Git to clean up
after itself?</p>

<p>Yes, you can!</p>

<p>We can do so via this function in our shell profile of choice (mine is <code class="language-plaintext highlighter-rouge">.zshrc</code>), which will “delete any local branches whose remote has been deleted”:</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>clean_branches<span class="o">()</span> <span class="o">{</span>
  git remote prune origin
  git branch <span class="nt">-vv</span> | <span class="nb">grep</span> <span class="s2">"origin/.*: gone]"</span> | <span class="nb">awk</span> <span class="s1">'{print $1}'</span> | xargs git branch <span class="nt">-D</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Let’s walk through it.</p>

<h3 id="pruning">Pruning</h3>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git remote prune origin
</code></pre></div></div>

<p>The <a href="https://git-scm.com/docs/git-remote#git-remote-empruneem">docs</a> for this command tell us that it:</p>

<blockquote>
  <p>Deletes stale references associated with <code class="language-plaintext highlighter-rouge">&lt;name&gt;</code></p>
</blockquote>

<p>In this case, we want to delete stale references associated with the remote <code class="language-plaintext highlighter-rouge">origin</code>.</p>

<p>The best way to see what this command does is to compare before/after. Here is what <code class="language-plaintext highlighter-rouge">git branch -vv</code> looks like <em>before</em> pruning:</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span> git branch <span class="nt">-vv</span>
  bin-setup      d135a8d bin/setup
<span class="k">*</span> clean-branches f1fdebb Merge pull request <span class="c">#12 from speric/tweaks</span>
  gitignore      9fe5518 <span class="o">[</span>origin/gitignore] Add jekyll-metadata to gitignore
  master         f1fdebb <span class="o">[</span>origin/master] Merge pull request <span class="c">#12 from speric/tweaks</span>
  tweaks         5de39cc <span class="o">[</span>origin/tweaks] Tweaks
</code></pre></div></div>

<p>This tells me:</p>
<ul>
  <li>I am on the <code class="language-plaintext highlighter-rouge">clean-branches</code> branch right now (writing this post!)</li>
  <li>I have a branch called <code class="language-plaintext highlighter-rouge">bin-setup</code> that is not tracking a remote branch</li>
  <li>Both the <code class="language-plaintext highlighter-rouge">gitignore</code> and <code class="language-plaintext highlighter-rouge">tweaks</code> branches <em>do</em> track remote branches, of the same name (as does <code class="language-plaintext highlighter-rouge">master</code>, obviously)</li>
</ul>

<p>I know that the <code class="language-plaintext highlighter-rouge">gitignore</code> and <code class="language-plaintext highlighter-rouge">tweaks</code> branches’ remotes have been deleted, because I did so via the GitHub UI when I merged them into <code class="language-plaintext highlighter-rouge">master</code>.</p>

<p>Now, I will run <code class="language-plaintext highlighter-rouge">git remote prune origin</code>, and then <code class="language-plaintext highlighter-rouge">git branch -vv</code>:</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span> git remote prune origin
Pruning origin
URL: git@github.com:speric/speric.github.com.git
 <span class="k">*</span> <span class="o">[</span>pruned] origin/gitignore
 <span class="k">*</span> <span class="o">[</span>pruned] origin/tweaks
<span class="o">&gt;</span> git branch <span class="nt">-vv</span>
  bin-setup      d135a8d bin/setup
<span class="k">*</span> clean-branches f1fdebb Merge pull request <span class="c">#12 from speric/tweaks</span>
  gitignore      9fe5518 <span class="o">[</span>origin/gitignore: gone] Add jekyll-metadata to gitignore
  master         f1fdebb <span class="o">[</span>origin/master] Merge pull request <span class="c">#12 from speric/tweaks</span>
  tweaks         5de39cc <span class="o">[</span>origin/tweaks: gone] Tweaks
</code></pre></div></div>

<p>We can see here that <code class="language-plaintext highlighter-rouge">gitignore</code> and <code class="language-plaintext highlighter-rouge">tweaks</code> have been pruned, which makes sense because their remote no longer exists.</p>

<p>Nothing happened to <code class="language-plaintext highlighter-rouge">bin-setup</code> because it never had a remote. Nothing happened to <code class="language-plaintext highlighter-rouge">master</code> either because it still exists at the remote.</p>

<p>Note that whereas, pre-prune, we saw the following for the <code class="language-plaintext highlighter-rouge">gitignore</code> branch:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gitignore      9fe5518 [origin/gitignore] Add jekyll-metadata to gitignore
</code></pre></div></div>

<p>Now we see that it’s <code class="language-plaintext highlighter-rouge">gone</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gitignore      9fe5518 [origin/gitignore: gone] Add jekyll-metadata to gitignore
</code></pre></div></div>

<p>With this information we can now build up our command to delete those remote branches.</p>

<h3 id="deleting">Deleting</h3>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git branch <span class="nt">-vv</span> | <span class="nb">grep</span> <span class="s2">"origin/.*: gone]"</span> | <span class="nb">awk</span> <span class="s1">'{print $1}'</span> | xargs git branch <span class="nt">-D</span>
</code></pre></div></div>

<p>Let’s take this set of commands apart.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git branch -vv
</code></pre></div></div>

<p>This command lists all local branches, <a href="https://git-scm.com/docs/git-branch#git-branch--vv">verbosely</a>. As we saw above,
after we’ve pruned, it will tell us which branches are “gone”.</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">grep</span> <span class="s2">"origin/.*: gone]"</span>
</code></pre></div></div>

<p>The output of <code class="language-plaintext highlighter-rouge">git branch -vv</code> will be piped to the <code class="language-plaintext highlighter-rouge">grep</code> command above. This command will <a href="http://man7.org/linux/man-pages/man1/grep.1.html">grep</a>
that output for any lines which contain <code class="language-plaintext highlighter-rouge">origin/some-branch-name: gone]</code>.</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span> git branch <span class="nt">-vv</span> | <span class="nb">grep</span> <span class="s2">"origin/.*: gone]"</span>
  gitignore      9fe5518 <span class="o">[</span>origin/gitignore: gone] Add jekyll-metadata to gitignore
  tweaks         5de39cc <span class="o">[</span>origin/tweaks: gone] Tweaks
</code></pre></div></div>

<p>So now we have the two branches we want to delete: <code class="language-plaintext highlighter-rouge">gitignore</code> and <code class="language-plaintext highlighter-rouge">tweaks</code>.</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">awk</span> <span class="s1">'{print $1}'</span>
</code></pre></div></div>

<p>The output of our <code class="language-plaintext highlighter-rouge">grep</code>-ing is then piped to the above <code class="language-plaintext highlighter-rouge">awk</code> command. <a href="https://www.gnu.org/software/gawk/manual/gawk.html">awk</a> is neat, and I confess I have
not grasped the full extent of its power.</p>

<p>In this context, we can think of the above code as saying: “For each line, in the piped-in text, print the first string”. We can see what it does:</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span> git branch <span class="nt">-vv</span> | <span class="nb">grep</span> <span class="s2">"origin/.*: gone]"</span> | <span class="nb">awk</span> <span class="s1">'{print $1}'</span>
gitignore
tweaks
</code></pre></div></div>

<p>We have isolated the <em>actual</em> branch names. Nearly there!</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>xargs git branch -D
</code></pre></div></div>

<p>The <a href="http://man7.org/linux/man-pages/man1/xargs.1.html">documentation</a> for <code class="language-plaintext highlighter-rouge">xargs</code> tells us:</p>

<blockquote>
  <p>xargs reads items from the standard input, delimited by blanks (which can be protected with double or
single quotes or a backslash) or newlines, and executes the command (default is /bin/echo) one
or more times with any initial-arguments followed by items read from standard input.</p>
</blockquote>

<p><code class="language-plaintext highlighter-rouge">xargs</code> is awesome, and you should take the time to learn it if you’re not already familiar with it.</p>

<p>Conceptually, we can think of our usage as “pass each item of the piped in text as the first argument to it’s own invocation of <code class="language-plaintext highlighter-rouge">git branch -D</code>”. We
will wind up running <code class="language-plaintext highlighter-rouge">git branch -D</code> twice in this case, once each for the <code class="language-plaintext highlighter-rouge">gitignore</code> and <code class="language-plaintext highlighter-rouge">tweaks</code> branches.</p>

<p>Put it all together, and we get:</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span> git branch <span class="nt">-vv</span> | <span class="nb">grep</span> <span class="s2">"origin/.*: gone]"</span> | <span class="nb">awk</span> <span class="s1">'{print $1}'</span> | xargs git branch <span class="nt">-D</span>
Deleted branch gitignore <span class="o">(</span>was 9fe5518<span class="o">)</span><span class="nb">.</span>
Deleted branch tweaks <span class="o">(</span>was 5de39cc<span class="o">)</span><span class="nb">.</span>
</code></pre></div></div>

<p>Done!</p>

<h3 id="wrap-up">Wrap-up</h3>

<p>Here’s the function again; stick it in your shell profile of choice:</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>clean_branches<span class="o">()</span> <span class="o">{</span>
  git remote prune origin
  git branch <span class="nt">-vv</span> | <span class="nb">grep</span> <span class="s2">"origin/.*: gone]"</span> | <span class="nb">awk</span> <span class="s1">'{print $1}'</span> | xargs git branch <span class="nt">-D</span>
<span class="o">}</span>
</code></pre></div></div>

<p>I should also note that this kind of “workflow” only makes sense where you (or your team) get comfortable
deleting remote branches after they’re merged.</p>

<p>Lastly, a shameless plug for my <a href="https://github.com/speric/dotfiles">dotfiles</a>.</p>

<h3 id="update">UPDATE</h3>
<p>Shortly after this post went live, <a href="https://twitter.com/pengwynn">@pengwynn</a> pointed me to a post he wrote
on <a href="https://wynnnetherland.com/journal/extending-the-command-line/">Extending the Command Line</a>. After digesting
that post, I’ve tweaked my approach here.</p>

<p>The big idea is that any file in your <code class="language-plaintext highlighter-rouge">PATH</code> that follows the <code class="language-plaintext highlighter-rouge">git-</code> convention will become a new Git command. With that knowledge, I added my dotfiles <code class="language-plaintext highlighter-rouge">bin</code> folder to the <code class="language-plaintext highlighter-rouge">PATH</code> in my <code class="language-plaintext highlighter-rouge">.zshrc</code>:</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>path+<span class="o">=(</span>
  <span class="k">${</span><span class="nv">HOME</span><span class="k">}</span>/dev/dotfiles/bin
<span class="o">)</span>
</code></pre></div></div>
<p>(<a href="https://github.com/speric/dotfiles/blob/5a2135c5fafb0dd783c1c81186b2f1e412897caf/zshrc#L14">commit</a>)</p>

<p>Then, I moved the body of <code class="language-plaintext highlighter-rouge">clean_branches</code> to a file called <a href="https://github.com/speric/dotfiles/tree/master/bin">git-cleanup</a> in my dotfiles <code class="language-plaintext highlighter-rouge">bin</code> folder:</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># !/bin/sh</span>
<span class="c"># Usage: git-cleanup</span>
<span class="c"># Delete any local branches whose remote has been deleted</span>
git remote prune origin
git branch <span class="nt">-vv</span> | <span class="nb">grep</span> <span class="s2">"origin/.*: gone]"</span> | <span class="nb">awk</span> <span class="s1">'{print $1}'</span> | xargs git branch <span class="nt">-D</span>
</code></pre></div></div>

<p>I then deleted the <code class="language-plaintext highlighter-rouge">clean_branches</code> function from my <code class="language-plaintext highlighter-rouge">.zshrc</code>.</p>

<p>Now, in any repository, I can do:</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git cleanup
</code></pre></div></div>

<p>And the old branches will be deleted.</p>

   ]]></content>
 </entry>
 
 <entry>
   <title>Working On Large Features</title>
   <link href="http://ericfarkas.com/posts/working-on-large-features"/>
   <updated>2017-07-07T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/working-on-large-features</id>
   <content type="html"><![CDATA[
     <p>I’ve spent most of the last 18 months working on large features at my day job.  For my purposes, a “large feature” will have most of the following characteristics:</p>

<ul>
  <li><p>Needs more than one developer, if the goal is to ship the feature in a reasonable timeframe (a month, a quarter, etc.).</p></li>
  <li><p>Immediately becomes a core aspect of the product offering, from a business perspective.</p></li>
  <li><p>Immediately becomes a core aspect of the application, from a developer perspective. An example of this would be doing a major version upgrade of Rails. Another is switching to a new background processing library.</p></li>
  <li><p>Involves changes to core aspects of the application's data model.</p></li>
  <li><p>Involves changes to core aspects of the application's business logic. A bug here would have negative business impact on customers.</p></li>
  <li><p>If extending an existing feature, then making significant UI changes. This involves bringing in a UI/UX-focused team member.</p></li>
  <li><p>Lots of new code, either reworking existing classes or introducing new ones. LOC is not a great measurement of the impact of a feature. Indeed, it's possible to leverage a small code change into a big win. But most large features that need more than one developer are also going to add a lot of new code.</p></li>
</ul>

<p>Here are some things I’ve learned that have helped the teams I’ve been on to stay organized and ship large projects.</p>

<h2 id="plan-up-front">Plan Up-front</h2>

<p>The worst thing to do when working on a large project is to start coding immediately. Resist the urge to spike. Instead, spend time planning what you will work on. </p>

<p>This will always involve a bit of guesswork. Many times, you will be working with incomplete requirements. You won’t have all the resources you need. And, of course, things change once people start using the actual feature.</p>

<p>What you’re trying to do is articulate what you do know, and how you’ll go about executing on it. I recommend using a tool like Trello to make cards for each distinct task. Even if you are not sure of all that the task entails, write it down.</p>

<p>Doing this accomplishes two things. One, it frees you from having to keep the entire feature in your head. Since you are working with other developers, this is a good thing. Second, it teases out the things you don’t know about the feature. You can then bring those questions to the right people. I create a “Questions” list in Trello for these issues, and ping the people who can help resolve them. In the meantime, I can work on what I do know.</p>

<h2 id="ship-early">Ship Early</h2>

<p>As people a lot smarter than I <a href="https://blog.newrelic.com/2012/11/14/long-running-branches-considered-harmful/">have</a> <a href="https://martinfowler.com/bliki/FeatureBranch.html">argued</a>, long-running feature branches can be painful. But sometimes you can’t avoid them. What I look for in the up-front planning phase are opportunities to get code into master as soon as possible. This way, if we do need a long-running feature branch, it will be as small and easy to review as possible.</p>

<p>With enough planning, database migrations are good candidates for early merging. Code refactoring that makes a path for new behavior is also a good candidate. For a recent feature, we shipped a refactoring of core business logic to production a month before the rest of the feature. In this way, we proved that the changes introduced in the new feature would be “backwards compatible”. It gave the rest of the team a comfort level with the new feature that they would have otherwise not have had. Other candidates are UI changes that are behind a feature flag, and new API endpoints that are not public yet.</p>

<p>An added benefit of going to master as soon as possible with smaller code changes is that team members not working on the feature need less context to review pull requests. Huge pull requests are hard to review, and often become a matter of “if it works, ship it!”. Smaller PRs are easier to review. Teammates don’t need to know the entire scope of the feature to review the change.</p>

<p>The faster you can get into master and deployed to production, the faster non-dev feature stakeholders can start using the feature. Again, I am standing on the shoulders of giants when I say this: the faster you can get to the point where you’re getting real user feedback, the better. My own experience has borne this out.</p>

<p>What I have found is that the more I try to ship things earlier, the better I get at identifying <em>what</em> to ship earlier. There doesn’t seem to be a hard and fast rule here. You’re going to need to experiment. I imagine much of your success in this area will depend on team culture and operational setup.</p>

<h2 id="keep-everything-green">Keep Everything Green</h2>

<p>If you are going to use a feature branch, treat it like master: keep it green all the time. Pull requests into the feature branch should be green themselves. If the feature branch’s tests are failing after a merge, stop what you’re doing and fix them.</p>

<p>It’s a nightmare to fix failing specs on a branch that has had a lot of churn. It feels like trying to hit a moving target. The sooner you fix failing tests, the better.</p>

<h2 id="double-down-on-strengths">Double Down On Strengths</h2>

<p>In chapter 12 of the 1950 edition of <a href="https://www.amazon.com/Armed-Forces-Officer-1950/dp/098836963X"><em>The Armed Forces Officer</em></a>, entitled “Group Nature”, S.L.A. Marshall offers the following:</p>

<blockquote>
  <p>Progress comes of making the most of strengths rather than looking for ways to repair weaknesses. This is true in things both large and small.</p>
</blockquote>

<p>Marshall was speaking in a military context. The stakes there are much higher than shipping software. But the thought is an intriguing one.  I’ve come to understand that quote to mean this: when it comes time for battle, double down on your strengths. The time for self improvement, as an individual or as a group, is not on the battleground. You will learn on the battleground, but that’s not your main purpose.</p>

<p>Applying that idea to teams doing software development requires a delicate balance. Developers always want to work with new things and learn. But when working on large features that have business-impacting scope, the idea seems to be that developers should work on tasks that cater to their strengths. </p>

<p>This is not to say that developers shouldn’t have opportunity to work with new tech. Say you have two developers on a project. They both know Rails well. One knows React well, and enjoys front-end work. One has less React knowledge, and enjoys back-end and API work. They should work on what they are best at and enjoy the most. It doesn’t mean the developer who is front-end focused on this feature can’t work on the back-end, and vice versa. There will be plenty of smaller tasks that are perfect to learn on. But I would argue the bulk of the work each developer does should be in the area they are strongest in. Not all, but most. In this way, morale will stay high, since both developers are doing what they enjoy. Additionally, output stays high, since both are doing what they are comfortable with.</p>

<p>This isn’t a hard and fast rule. Sometimes both developers are good in the same area, and weak in the same area. The work will then be more evenly distributed. Team dynamics will always be at play here. In an environment with a lot of pairing, there will be more cross-pollination of learning. But even without pairing, learning can happen via pull request review as well.</p>

<p>The general idea is to play to your team’s strengths.</p>

<h2 id="stay-organized">Stay Organized</h2>

<p>Process for process sake is a waste of time. Process that gets in the way of shipping code is useless too. But process also gives structure to your work. The constraints of process provide the freedom within which one can stay focused on the task at hand.</p>

<p>We work hard to keep our Trello board up-to-date. If you are working on a card, assign it to yourself and move it to the “Doing” column. Move it to “Done” after merging the pull request. If there’s a discussion going on in Slack which results in a new task, put it in Trello. Keep checklists.</p>

<p>Doing these things allow us to actually focus on writing code. I don’t need to worry about remembering that thing we were talking about on standup because I created a card for it. I don’t need to remember what I am working on next. There are cards already assigned to me, or I can grab the next one from the “To Do” list. If a manager asks me about the status of the project, a glance at Trello will give them all the information they need.</p>

<p>The actual tool you use to organize is not as important as the fact of staying organized. I cannot stress enough how important it is to have an up-to-date task list that is accessible by any team member. I’ve never regretted taking the time to create and maintain such a list. </p>

<h2 id="summary">Summary</h2>

<p>I am still learning about this part of the craft of software development. There’s still more to learn.  But in the meantime, these are some of the things that have helped the teams I’ve been on ship features.</p>

   ]]></content>
 </entry>
 
 <entry>
   <title>A Refactoring Story</title>
   <link href="http://ericfarkas.com/posts/a-refactoring-story"/>
   <updated>2016-11-15T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/a-refactoring-story</id>
   <content type="html"><![CDATA[
     <p>
  Last spring, development started up again on a side business that I'm
  involved in. I'd hardly touched the two apps that run the business in over 3
  years, and they needed some love. Back in May I discussed wrestling with the question of whether to <a href="https://www.briefs.fm/speric/4">Refactor or Rewrite</a> these
  apps. I decided to refactor, and I don't regret the decision.
  What follows is one small refactoring that I did.
</p>

<h3>Context</h3>

<p>
  <a href="https://talentsoup.com">TalentSoup</a> is a marketplace.
  It connects professional and amateur actors, actresses, and models
  with producers and photographers. Talent sign up, upload photos, and
  fill out a basic profile. They are then matched with
  open projects in their area that they are a fit for.
</p>

<p>
  Each talent sees a Talent Dashboard when they first log in. The Dashboard has two main
  components. The first is a listing of all open projects across TalentSoup. The second,
  a listing of projects for which they are under consideration to be cast.
</p>

<p>
  The data driving these two components comes from a separate, internal
  project management app we've written. This app exposes a REST-ful API
  that TalentSoup calls to get the data it needs to display the
  Dashboard.
</p>

<h3>Dashboard Behavior: How It Should Work</h3>

<p>
  If it's the user's first time seeing the Dashboard, we want to display a "welcome message" which has
  tips on how to get the most out of their TalentSoup account. There are
  two cases which are a "first-time view" of the Dashboard. The first is a
  new user signing up and being immediately redirected to the Dashboard. The second case is an
  existing user who is viewing the Dashboard for the first time after we
  had made significant UI changes to the old Dashboard. We want them to
  see the "welcome message" too, since the changes were so radical.  On subsequent visits,
  they'll all see the real dashboard.
</p>

<p>
  To keep track of whether a user had viewed the "welcome message", I
  added a boolean column, <code>wc_view</code>, (default
  <code>false</code>) to the users table (<code>wc</code> stands for
  "Webcomp", which is what we call Talent portfolios). When the welcome message has
  been viewed, <code>wc_view</code> becomes <code>true</code>. Looking
  back, this column is unhelpfully named. Something like
  <code>welcome_message_viewed</code> would have been clearer.
</p>

<h3>Initial Code</h3>

<p>
  Before the refactor, the controller action driving the Dashboard code looked liked this (URLs are not real,
obviously):
</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">TalentController</span> <span class="o">&lt;</span> <span class="no">ApplicationController</span>
  <span class="k">def</span> <span class="nf">dashboard</span>
    <span class="k">if</span> <span class="n">current_talent</span><span class="p">.</span><span class="nf">wc_view</span>
      <span class="k">begin</span>
        <span class="vi">@open_projects</span> <span class="o">=</span> <span class="no">HTTParty</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span>
          <span class="s2">"https://commissary.dev/open-projects"</span><span class="p">,</span>
          <span class="ss">body: </span><span class="s2">""</span><span class="p">,</span>
          <span class="ss">output: </span><span class="s1">'json'</span>
        <span class="p">)</span>
        <span class="vi">@availability_requests</span> <span class="o">=</span> <span class="no">HTTParty</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span>
          <span class="s2">"https://commissary.dev/availability-requests/</span><span class="si">#{</span><span class="n">current_talent</span><span class="p">.</span><span class="nf">id</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span>
          <span class="ss">body: </span><span class="s2">""</span><span class="p">,</span>
          <span class="ss">output: </span><span class="s1">'json'</span>
        <span class="p">)</span>
      <span class="k">rescue</span>
        <span class="vi">@availability_requests</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="vi">@open_projects</span> <span class="o">=</span> <span class="p">[]</span>
      <span class="k">end</span>
    <span class="k">else</span>
      <span class="n">current_talent</span><span class="p">.</span><span class="nf">wc_view</span> <span class="o">=</span> <span class="kp">true</span>
      <span class="n">current_talent</span><span class="p">.</span><span class="nf">save</span>
      <span class="n">render</span> <span class="ss">template: </span><span class="s2">"talent/welcome"</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<h3>Code Review</h3>

<p>
  I cringe looking at this, but it's how I wrote code 4-5 years ago. You have to start somewhere.
</p>

<p>
  If I were reviewing this code in a pull request today, I would make the following comments:
</p>

<ul>
  <li>
    <p>
      The <code>dashboard</code> action is not a REST-ful route, according to Rails idioms. It should extracted to it's own controller .
    </p>
  </li>
  <li>
    <p>
      The controller is updating <code>current_talent</code> (an <code>ActiveRecord</code> object) directly. This means it has to know which columns mean what. The knowledge about how the application should determine whether or not a Talent has viewed the "welcome message" should be pushed down to the Talent class itself (or some other class?), but shouldn't live in the controller.
    </p>
  </li>
  <li>
    <p>
      The knowledge about how to mark a talent as having viewing the "welcome message" should also live in the Talent class
itself (or another class), but not in the controller.
    </p>
  </li>
  <li>
    <p>
      The two <code>HTTParty</code> calls to the external Commissary service means the controller
      knows everything about where the endpoints are, and what to do in case of an error. This isn't the worst approach, but could be improved by moving these calls to a separate class. Doing so would also give us the benefit of being able to use those classes in other places.
    </p>
  </li>
</ul>

<p>
  Generally speaking, this code violates a number of rules that I (now)
  try to abide by:
</p>

<ul>
  <li><p>Violates Rails idioms.</p></li>
  <li><p>Spreads too much knowledge about implementation details.</p></li>
  <li><p>Misses the opportunity to extract interesting functionality
(calls to the external Commissary service) into small classes that can
be reused.</p></li>
  <li><p>Is ugly to look at.</p></li>
</ul>

<h3>The Refactor</h3>

<p>
  The first thing I did was move all the "has Talent viewed their
  welcome message before?" logic out of the controller. I can get around
  how badly the <code>wc_view</code> column is named by wrapping it in an
  intention-revealing method.
</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># app/models/talent.rb</span>
<span class="k">class</span> <span class="nc">Talent</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span>
  <span class="k">def</span> <span class="nf">first_webcomp_view?</span>
    <span class="o">!</span><span class="n">wc_view</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">first_webcomp_viewed</span>
    <span class="n">update_column</span><span class="p">(</span><span class="ss">:wc_view</span><span class="p">,</span> <span class="kp">true</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="c1"># test/models/talent_test.rb</span>
<span class="k">class</span> <span class="nc">TalentTest</span> <span class="o">&lt;</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">TestCase</span>
  <span class="k">def</span> <span class="nf">setup</span>
    <span class="vi">@talent</span> <span class="o">=</span> <span class="n">talents</span><span class="p">(</span><span class="ss">:luke_skywalker</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="nb">test</span> <span class="s2">"#first_webcomp_view? is true when wc_view is true"</span> <span class="k">do</span>
    <span class="vi">@talent</span><span class="p">.</span><span class="nf">update_column</span><span class="p">(</span><span class="ss">:wc_view</span><span class="p">,</span> <span class="kp">true</span><span class="p">)</span>
    <span class="n">assert</span> <span class="vi">@talent</span><span class="p">.</span><span class="nf">wc_view</span>
    <span class="n">refute</span> <span class="vi">@talent</span><span class="p">.</span><span class="nf">first_webcomp_view?</span>
  <span class="k">end</span>

  <span class="nb">test</span> <span class="s2">"#first_webcomp_view? is true when wc_view is false"</span> <span class="k">do</span>
    <span class="vi">@talent</span><span class="p">.</span><span class="nf">update_column</span><span class="p">(</span><span class="ss">:wc_view</span><span class="p">,</span> <span class="kp">false</span><span class="p">)</span>
    <span class="n">refute</span> <span class="vi">@talent</span><span class="p">.</span><span class="nf">wc_view</span>
    <span class="n">assert</span> <span class="vi">@talent</span><span class="p">.</span><span class="nf">first_webcomp_view?</span>
  <span class="k">end</span>

  <span class="nb">test</span> <span class="s2">"#first_webcomp_viewed sets wc_view to true"</span> <span class="k">do</span>
    <span class="vi">@talent</span><span class="p">.</span><span class="nf">update_column</span><span class="p">(</span><span class="ss">:wc_view</span><span class="p">,</span> <span class="kp">false</span><span class="p">)</span>
    <span class="vi">@talent</span><span class="p">.</span><span class="nf">first_webcomp_viewed!</span>

    <span class="n">assert</span> <span class="vi">@talent</span><span class="p">.</span><span class="nf">wc_view</span>
    <span class="n">refute</span> <span class="vi">@talent</span><span class="p">.</span><span class="nf">first_webcomp_view?</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>
  Now I am able to clean the controller up, and rework the logic with
  my new methods. The controller will be a bit easier to read, and the
  implementation details have been effectively hid:
</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">TalentController</span> <span class="o">&lt;</span> <span class="no">ApplicationController</span>
  <span class="k">def</span> <span class="nf">dashboard</span>
    <span class="k">if</span> <span class="n">current_talent</span><span class="p">.</span><span class="nf">first_webcomp_view?</span>
      <span class="n">current_talent</span><span class="p">.</span><span class="nf">first_webcomp_viewed</span>
      <span class="n">render</span> <span class="ss">template: </span><span class="s2">"talent/welcome"</span>
    <span class="k">else</span>
      <span class="k">begin</span>
        <span class="vi">@open_projects</span> <span class="o">=</span> <span class="no">HTTParty</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span>
          <span class="s2">"https://commissary.dev/open-projects"</span><span class="p">,</span>
          <span class="ss">body: </span><span class="s2">""</span><span class="p">,</span>
          <span class="ss">output: </span><span class="s1">'json'</span>
        <span class="p">)</span>
        <span class="vi">@availability_requests</span> <span class="o">=</span> <span class="no">HTTParty</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span>
          <span class="s2">"https://commissary.dev/availability-requests/</span><span class="si">#{</span><span class="n">current_talent</span><span class="p">.</span><span class="nf">id</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span>
          <span class="ss">body: </span><span class="s2">""</span><span class="p">,</span>
          <span class="ss">output: </span><span class="s1">'json'</span>
        <span class="p">)</span>
      <span class="k">rescue</span>
        <span class="vi">@availability_requests</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="vi">@open_projects</span> <span class="o">=</span> <span class="p">[]</span>
      <span class="k">end</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>
  Now, the details about what columns Talent has, and what they mean,
  are pushed down into the Talent class itself. If those columns change,
  or if what it means to have made the initial view of your Dashboard changes,
  we can change the underlying implementation and are less likely to need
  to touch the controller.
</p>

<p>
  Next, I re-worked the two calls to the external Commissary service.
  I'm going to detail the "open projects" path, since it's shorter.
</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># app/services/commissary.rb</span>
<span class="k">module</span> <span class="nn">Commissary</span>
  <span class="no">ENDPOINT</span> <span class="o">=</span> <span class="s2">"https://commissary.dev/"</span>

  <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">endpoint_for</span><span class="p">(</span><span class="n">action</span><span class="p">)</span>
    <span class="s2">"</span><span class="si">#{</span><span class="no">ENDPOINT</span><span class="si">}#{</span><span class="n">action</span><span class="si">}</span><span class="s2">"</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="c1"># app/services/commissary/open_projects.rb</span>
<span class="k">module</span> <span class="nn">Commissary</span>
  <span class="k">class</span> <span class="nc">OpenProjects</span>
    <span class="nb">attr_accessor</span> <span class="ss">:http_client</span>

    <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">fetch</span>
      <span class="nb">self</span><span class="p">.</span><span class="nf">new</span><span class="p">.</span><span class="nf">fetch</span>
    <span class="k">end</span>

    <span class="k">def</span> <span class="nf">initialize</span>
      <span class="vi">@http_client</span> <span class="o">=</span> <span class="no">HTTParty</span>
    <span class="k">end</span>

    <span class="k">def</span> <span class="nf">fetch</span>
      <span class="n">http_client</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span>
        <span class="no">Commissary</span><span class="p">.</span><span class="nf">endpoint_for</span><span class="p">(</span><span class="s2">"open-projects"</span><span class="p">),</span>
        <span class="ss">body: </span><span class="s1">''</span><span class="p">,</span>
        <span class="ss">output: </span><span class="s1">'json'</span>
      <span class="p">).</span><span class="nf">map</span> <span class="p">{</span> <span class="o">|</span><span class="n">project</span><span class="o">|</span> <span class="no">OpenStruct</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">project</span><span class="p">)</span> <span class="p">}</span>
    <span class="k">rescue</span>
      <span class="p">[]</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>
  This is a simple class, but there's more going on that might initially appear. The
  first is that there's an <code>attr_accessor</code> for an <code>http_client</code>. You
  can't initialize the class with a custom <code>http_client</code> (the "default" is
  <code>HTTParty</code>), but you can set one after initialization. I can't take credit
  for this pattern; I learned it (and many other things!) from
  <a href="https://twitter.com/brandonhilkert">Brandon Hilkert</a>. The
motiviation for using this pattern will become apparent in the test
below.
</p>

<p>
  I also convert the response into an array of <code>OpenStruct</code>
  objects. This is purely for the convenience of using dot notation in
  my views.
</p>

<p>
  One of the advantages of this approach is that it makes the
  <code>Commissary::OpenProjects</code> class easier to test. There are of
  course many ways to stub/mock out an HTTP request, but using this
  method, we don't need any external libraries! We can do it all in plain
  Ruby:
</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">require</span> <span class="s1">'test_helper'</span>

<span class="k">class</span> <span class="nc">Commissary::OpenProjectsTest</span> <span class="o">&lt;</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">TestCase</span>
  <span class="nb">test</span> <span class="s2">"#fetch with a good response"</span> <span class="k">do</span>
    <span class="n">client</span> <span class="o">=</span> <span class="no">Commissary</span><span class="o">::</span><span class="no">OpenProjects</span><span class="p">.</span><span class="nf">new</span>
    <span class="n">client</span><span class="p">.</span><span class="nf">http_client</span> <span class="o">=</span> <span class="no">FakeHTTParty</span>
    <span class="n">open_projects</span> <span class="o">=</span> <span class="n">client</span><span class="p">.</span><span class="nf">fetch</span>

    <span class="n">assert_equal</span> <span class="mi">1</span><span class="p">,</span> <span class="n">open_projects</span><span class="p">.</span><span class="nf">count</span>
    <span class="n">project</span> <span class="o">=</span> <span class="n">open_projects</span><span class="p">.</span><span class="nf">first</span>
    <span class="n">assert_equal</span> <span class="s2">"987654321"</span><span class="p">,</span> <span class="n">project</span><span class="p">.</span><span class="nf">id</span>
    <span class="n">assert_equal</span> <span class="s2">"An amazing project"</span><span class="p">,</span> <span class="n">project</span><span class="p">.</span><span class="nf">name</span>
    <span class="c1"># other assertions omitted for brevity</span>
  <span class="k">end</span>

  <span class="nb">test</span> <span class="s2">"#fetch when an exception occurs"</span> <span class="k">do</span>
    <span class="n">client</span> <span class="o">=</span> <span class="no">Commissary</span><span class="o">::</span><span class="no">OpenProjects</span><span class="p">.</span><span class="nf">new</span>
    <span class="n">client</span><span class="p">.</span><span class="nf">http_client</span> <span class="o">=</span> <span class="no">FakeHTTPartyWithException</span>
    <span class="n">open_projects</span> <span class="o">=</span> <span class="n">client</span><span class="p">.</span><span class="nf">fetch</span>

    <span class="n">assert_equal</span> <span class="p">[],</span> <span class="n">open_projects</span>
  <span class="k">end</span>

  <span class="k">class</span> <span class="nc">FakeHTTParty</span>
    <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">get</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
      <span class="p">[</span>
        <span class="p">{</span>
          <span class="ss">id: </span><span class="s2">"987654321"</span><span class="p">,</span>
          <span class="ss">name: </span><span class="s2">"An amazing project"</span><span class="p">,</span>
        <span class="p">}</span>
      <span class="p">]</span>
    <span class="k">end</span>
  <span class="k">end</span>

  <span class="k">class</span> <span class="nc">FakeHTTPartyWithException</span>
    <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">get</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
      <span class="k">raise</span> <span class="s2">"Oops!"</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>
  We've "mocked" an HTTP request to an external service without using
  a gem like VCR or Webmock. The disadvantage to this
  approach is that, if the response from the Commissary service changes, I
  can't just blow away my cassettes, as I could if I were using VCR, regenerate them, and fix my
  tests. I'll have to fix my fake client(s) also. However, weighed against the
  overhead of adding another gem to my app, it's a tradeoff I am willing
  to make. Additionally, in writing a simple mock HTTP client like this,
  you become familiar with the shape of the response coming back from the
  external service in a way you don't when using VCR, for example.
  That's been my experience, having used VCR extensively.
</p>

<p>
  The other interesting thing in <code>Commissary::OpenProjects</code> 
  is the <code>fetch</code> class method, which is just:
</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">fetch</span>
  <span class="nb">self</span><span class="p">.</span><span class="nf">new</span><span class="p">.</span><span class="nf">fetch</span>
<span class="k">end</span>
</code></pre></div></div>

<p>
  This is a pattern I learned from <a href="https://twitter.com/moklett">Michael Klett</a>. It
  can be more work than it's worth sometimes, but in this case, since the constructor for
  <code>Commissary::OpenProjects</code> takes no args, having this class method saves us from doing
  <code>Commissary::OpenProjects.new.fetch</code>, which I find aesthetically objectionable!
</p>

<p>Our refactored controller action now looks like:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">TalentController</span> <span class="o">&lt;</span> <span class="no">ApplicationController</span>
  <span class="k">def</span> <span class="nf">dashboard</span>
    <span class="k">if</span> <span class="n">current_talent</span><span class="p">.</span><span class="nf">first_webcomp_view?</span>
      <span class="n">current_talent</span><span class="p">.</span><span class="nf">first_webcomp_viewed</span>
      <span class="n">render</span> <span class="ss">template: </span><span class="s2">"talent/welcome"</span>
    <span class="k">else</span>
      <span class="vi">@open_projects</span> <span class="o">=</span> <span class="no">Commissary</span><span class="o">::</span><span class="no">OpenProjects</span><span class="p">.</span><span class="nf">fetch</span>
      <span class="c1"># refactoring not shown for this</span>
      <span class="vi">@availability_requests</span> <span class="o">=</span> <span class="no">Commissary</span><span class="o">::</span><span class="no">AvailabilityRequests</span><span class="p">.</span><span class="nf">fetch</span><span class="p">(</span>
        <span class="ss">talent_id: </span><span class="n">current_talent</span><span class="p">.</span><span class="nf">id</span>
      <span class="p">)</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>
  The final step was to move this action (part of a larger controller
  with many other non-RESTful routes) into it's own controller:
</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># config/routes.rb</span>
<span class="n">resource</span> <span class="ss">:talent_dashboard</span><span class="p">,</span> <span class="ss">only: </span><span class="p">[</span><span class="ss">:show</span><span class="p">]</span>

<span class="c1"># app/controllers/talent_dashboards_controller.rb</span>
<span class="k">class</span> <span class="nc">TalentDashboardsController</span> <span class="o">&lt;</span> <span class="no">ApplicationController</span>
  <span class="k">def</span> <span class="nf">show</span>
    <span class="k">if</span> <span class="n">current_talent</span><span class="p">.</span><span class="nf">first_webcomp_view?</span>
      <span class="n">current_talent</span><span class="p">.</span><span class="nf">first_webcomp_viewed</span>
      <span class="n">render</span> <span class="ss">template: </span><span class="s2">"talent/welcome"</span>
    <span class="k">else</span>
      <span class="vi">@open_projects</span> <span class="o">=</span> <span class="no">Commissary</span><span class="o">::</span><span class="no">OpenProjects</span><span class="p">.</span><span class="nf">fetch</span>
      <span class="vi">@availability_requests</span> <span class="o">=</span> <span class="no">Commissary</span><span class="o">::</span><span class="no">AvailabilityRequests</span><span class="p">.</span><span class="nf">fetch</span><span class="p">(</span><span class="ss">talent_id: </span><span class="n">current_talent</span><span class="p">.</span><span class="nf">id</span><span class="p">)</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>
  The motivation here is to adhere to Rails idioms. Additionally,
  smaller controllers are easier to read, and therefore easier to get context
  about. I don't mind an app with a lot of small controllers that do one
  or two things well.
</p>

<h3>Conclusion</h3>

<p>
  This code could be improved even further by extracting the methods on
  the <code>Talent</code> class into a plain Ruby object (a "service"
  object, in the parlance of our times). I decided against this because
  the <code>Talent</code> class, although it represents the main user of
  the app, is not a <a href="https://en.wikipedia.org/wiki/God_object">god object</a>.
  If, in the future, it feels like <code>Talent</code> is growing out of
  control, I could see the value in such an extraction.
</p>

   ]]></content>
 </entry>
 
 <entry>
   <title>Understanding updateIn &amp; keyPath in ImmutableJS</title>
   <link href="http://ericfarkas.com/posts/understanding-keypath-in-immutablejs"/>
   <updated>2016-08-10T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/understanding-keypath-in-immutablejs</id>
   <content type="html"><![CDATA[
     <p><a href="https://facebook.github.io/immutable-js/">ImmutableJS</a> is
a neat library, especially when used in combination with <a href="https://github.com/reactjs/redux">Redux</a>. I’m not ashamed to
admit, though, that I found the docs confusing at first. For example,
look at the method signature for <code class="language-plaintext highlighter-rouge">Map#updateIn()</code>:
<br /><br /></p>

<center><div><img src="/assets/images/keypath.png" class="img-polaroid" /></div></center>

<p><br />
<code class="language-plaintext highlighter-rouge">updateIn()</code> is a useful function to use when you’re interacting with Redux. I had to understand it.  In the end, what helped me become productive with <code class="language-plaintext highlighter-rouge">updateIn()</code> was understanding the <code class="language-plaintext highlighter-rouge">keyPath</code> parameter.</p>

<p>The key (sorry) to understanding <code class="language-plaintext highlighter-rouge">keyPath</code> is to realize it’s just an
array of values that Immutable will call <code class="language-plaintext highlighter-rouge">get</code> with as it works it’s way through whatever data
structure you’re calling <code class="language-plaintext highlighter-rouge">updateIn()</code> on. It doesn’t matter if the value is a <code class="language-plaintext highlighter-rouge">Map</code> key or a <code class="language-plaintext highlighter-rouge">List</code> index. This works because both <code class="language-plaintext highlighter-rouge">Map#get</code>
and <code class="language-plaintext highlighter-rouge">List#get</code> inherit from <code class="language-plaintext highlighter-rouge">Iterable#get</code>
(<a href="https://facebook.github.io/immutable-js/docs/#/Iterable/get">https://facebook.github.io/immutable-js/docs/#/Iterable/get</a>).</p>

<p>Consider the following data structure, which is a <code class="language-plaintext highlighter-rouge">Map</code> of <code class="language-plaintext highlighter-rouge">endpoints</code>, keyed on their <code class="language-plaintext highlighter-rouge">id</code>. The values are a <code class="language-plaintext highlighter-rouge">List</code> of <code class="language-plaintext highlighter-rouge">Maps</code> that represent that endpoint’s “subscriptions” to a
given event (<code class="language-plaintext highlighter-rouge">enabled: true|false</code>):</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">endpoints</span> <span class="o">=</span> <span class="nx">fromJS</span><span class="p">({</span>
  <span class="dl">"</span><span class="s2">abc-123</span><span class="dl">"</span><span class="p">:</span> <span class="p">[</span>
    <span class="p">{</span>
      <span class="na">id</span><span class="p">:</span> <span class="mi">111</span><span class="p">,</span>
      <span class="na">endpoint_id</span><span class="p">:</span> <span class="dl">"</span><span class="s2">abc-123</span><span class="dl">"</span><span class="p">,</span>
      <span class="na">event_key</span><span class="p">:</span> <span class="dl">"</span><span class="s2">signup_success</span><span class="dl">"</span><span class="p">,</span>
      <span class="na">enabled</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
    <span class="p">},</span>
    <span class="p">{</span>
      <span class="na">id</span><span class="p">:</span> <span class="mi">222</span><span class="p">,</span>
      <span class="na">endpoint_id</span><span class="p">:</span> <span class="dl">"</span><span class="s2">abc-123</span><span class="dl">"</span><span class="p">,</span>
      <span class="na">event_key</span><span class="p">:</span> <span class="dl">"</span><span class="s2">signup_failure</span><span class="dl">"</span><span class="p">,</span>
      <span class="na">enabled</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
    <span class="p">},</span>
  <span class="p">],</span>
  <span class="dl">"</span><span class="s2">def-456</span><span class="dl">"</span><span class="p">:</span> <span class="p">[</span>
    <span class="p">{</span>
      <span class="na">id</span><span class="p">:</span> <span class="mi">333</span><span class="p">,</span>
      <span class="na">endpoint_id</span><span class="p">:</span> <span class="dl">"</span><span class="s2">def-456</span><span class="dl">"</span><span class="p">,</span>
      <span class="na">event_key</span><span class="p">:</span> <span class="dl">"</span><span class="s2">signup_success</span><span class="dl">"</span><span class="p">,</span>
      <span class="na">enabled</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
    <span class="p">},</span>
    <span class="p">{</span>
      <span class="na">id</span><span class="p">:</span> <span class="mi">444</span><span class="p">,</span>
      <span class="na">endpoint_id</span><span class="p">:</span> <span class="dl">"</span><span class="s2">def-456</span><span class="dl">"</span><span class="p">,</span>
      <span class="na">event_key</span><span class="p">:</span> <span class="dl">"</span><span class="s2">signup_failure</span><span class="dl">"</span><span class="p">,</span>
      <span class="na">enabled</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
    <span class="p">},</span>
  <span class="p">],</span>
<span class="p">});</span>
</code></pre></div></div>
<p><br />
To get all the subscriptions for a given endpoint, we use <code class="language-plaintext highlighter-rouge">Map#get</code> as
follows:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">subscriptions</span> <span class="o">=</span> <span class="nx">endpoints</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">"</span><span class="s2">abc-123</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">keyPath</span> <span class="o">=</span> <span class="p">[</span><span class="dl">"</span><span class="s2">abc-123</span><span class="dl">"</span><span class="p">]</span>
</code></pre></div></div>

<p>Since <code class="language-plaintext highlighter-rouge">subscriptions</code> is now a <code class="language-plaintext highlighter-rouge">List</code>, we can get the first element using <code class="language-plaintext highlighter-rouge">List#get</code>, passing it the index of the element we want to access:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">subscription</span> <span class="o">=</span> <span class="nx">subscriptions</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="nx">keyPath</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span>
</code></pre></div></div>

<p>We could do this in one shot:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">subscription</span> <span class="o">=</span> <span class="nx">endpoints</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">"</span><span class="s2">abc-123</span><span class="dl">"</span><span class="p">).</span><span class="kd">get</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="nx">keyPath</span> <span class="o">=</span> <span class="p">[</span><span class="dl">"</span><span class="s2">abc-123</span><span class="dl">"</span><span class="p">,</span> <span class="mi">0</span><span class="p">]</span>
</code></pre></div></div>

<p>What’s neat is that we can construct a <code class="language-plaintext highlighter-rouge">keyPath</code> down to an attribute of
an element. Say we wanted to get the <code class="language-plaintext highlighter-rouge">enabled</code> attribute of the above
endpoint:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">enabled</span> <span class="o">=</span> <span class="nx">endpoints</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">"</span><span class="s2">abc-123</span><span class="dl">"</span><span class="p">).</span><span class="kd">get</span><span class="p">(</span><span class="mi">0</span><span class="p">).</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">enabled</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">keyPath</span> <span class="o">=</span> <span class="p">[</span><span class="dl">"</span><span class="s2">abc-123</span><span class="dl">"</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="dl">"</span><span class="s2">enabled</span><span class="dl">"</span><span class="p">]</span>
</code></pre></div></div>

<p>Now that we know how to construct a <code class="language-plaintext highlighter-rouge">keyPath</code> to any point in a deeply
nested data structure, we can move to understanding the <code class="language-plaintext highlighter-rouge">updater</code> parameter of <code class="language-plaintext highlighter-rouge">updateIn</code>.</p>

<p>The simplest way to understand <code class="language-plaintext highlighter-rouge">updater</code> is that it’s a function
that will be passed as it’s parameter the result of calling <code class="language-plaintext highlighter-rouge">get</code> on the
final element in the <code class="language-plaintext highlighter-rouge">keyPath</code> array. It should return the new value for
that…value. It’s easier to show in code.</p>

<p>Let’s say I wanted to flip the <code class="language-plaintext highlighter-rouge">enabled</code> flag for the subscription
represented by element <code class="language-plaintext highlighter-rouge">0</code> for endpoint <code class="language-plaintext highlighter-rouge">abc-123</code>:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">endpoints</span><span class="p">.</span><span class="nx">updateIn</span><span class="p">([</span><span class="dl">"</span><span class="s2">abc-123</span><span class="dl">"</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="dl">'</span><span class="s1">enabled</span><span class="dl">'</span><span class="p">],</span> <span class="nx">isEnabled</span> <span class="o">=&gt;</span> <span class="o">!</span><span class="nx">isEnabled</span><span class="p">);</span>
</code></pre></div></div>

<p>In the above example, I constructed the <code class="language-plaintext highlighter-rouge">keyPath</code> right down to the
<code class="language-plaintext highlighter-rouge">enabled</code> flag (the first parameter), and the second parameter is a
function that will be passed the current value of <code class="language-plaintext highlighter-rouge">enabled</code> as a parameter called <code class="language-plaintext highlighter-rouge">isEnabled</code>, and will simply return opposite boolean value of <code class="language-plaintext highlighter-rouge">isEnabled</code>.</p>

<p>You could back the <code class="language-plaintext highlighter-rouge">keyPath</code> up one level, as <code class="language-plaintext highlighter-rouge">["abc-123", 0]</code>, which
would give you the entire subscription <code class="language-plaintext highlighter-rouge">Map</code> at that index, and then
return a new <code class="language-plaintext highlighter-rouge">Map</code> with the <code class="language-plaintext highlighter-rouge">enabled</code> flag flipped. But in my
(limited) experience, I’ve not updated more than one attribute of a
given object at a time in a reducer. Hope this helps!</p>

   ]]></content>
 </entry>
 
 <entry>
   <title>10 Things I Wish I Knew As A Junior Developer</title>
   <link href="http://ericfarkas.com/posts/10-things-i-wish-i-knew-as-a-jr-dev"/>
   <updated>2016-01-15T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/10-things-i-wish-i-knew-as-a-jr-dev</id>
   <content type="html"><![CDATA[
     <p>Here are some things I wish I knew when I was a junior (and solo) developer trying to "level up":</p>

<ul>
  <li><p>The best way to level up is by pairing with someone more experienced. Books &amp; screencasts are great and should be used, but pairing will help you make the leap more quickly. My "level up hierarchy" is <code>pairing &gt; code review &gt; books/screencasts</code>.</p></li>
  <li><p>Everything is a tradeoff. You need to see the advantages and
disadvantages of different approaches to solving a problem, and then
decide with your team which advantages are most important, and which
disadvantages you can live with. There will rarely be a perfect solution
to a problem, and the framework for deciding which tradeoffs to make
varies from team to team.</p></li>
  <li><p>Design will become an important question. When you see two
classes with similar functionality, should you extract a common base
class? Should you move some methods to a shared module? Why or why not?
Your answers to these questions will change over time, but it's
important to develop reasoned opinions. Remember, everything is a
tradeoff.</p></li>
  <li><p>One of the biggest challenges of working on a large Rails app is code
organization. Questions like "where do non-ActiveRecord classes go?" arise and are trickier to answer than they first appear.</p></li>
  <li><p>There's nothing magical about the code you write for a large
app. There's no secret subset of Ruby (or Rails) that you need to be
initiated into before you can code "at scale". You will find yourself
considering different things when working on a large vs small app
(performance, background jobs, caching, etc.) but those are design issues. Ruby is still
Ruby.</p></li>
  <li><p>Learn to love testing. In most cases, you should be nervous about shipping
code that is not tested.</p></li>
  <li><p>Learn about testing philosophy. More tests are not necessarily
better. It's important to know what to test and why. See
<a href="https://github.com/speric/til/blob/master/ruby/questions-to-ask-when-writing-tests.md">Questions to ask when writing tests</a>.</p></li>
  <li><p>Don't be afraid to ask questions of more senior developers if
something doesn't make sense. You'll either learn something new, or your
questioning will result in a new approach that the other developer
hadn't considered. Everyone wins!</p></li>
  <li><p>If an idea doesn't make sense at the time, come back to it in 6
months. Sometimes we're not ready to absorb a new language or
paradigm, but that doesn't mean we won't be ready at some future point
after growing in another area. I had this experience with functional
programming.</p></li>
  <li><p>Related to the last point, and somewhat contradictory, you need to aggressively find ways
to use new things. The only way to truly learn a new language or
technology is to build something with it. This will often require tinkering with
things on your own time. Some things are hard to learn, and require
persistence.</p></li>
</ul>

   ]]></content>
 </entry>
 
 <entry>
   <title>Remote Work</title>
   <link href="http://ericfarkas.com/posts/remote-work"/>
   <updated>2015-07-08T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/remote-work</id>
   <content type="html"><![CDATA[
     <p>This was posted in Slack a few days ago:</p>

<blockquote>
  <p>Any of the remote folks here have any resources on [building an ideal desk/office // stepping up the communication &amp; collaboration game // building life structure] around remote work?</p>
</blockquote>

<p>I'm coming up on 2 years at Chargify (and therefore 2 years of
full-time remote work), which puts me in a good position to share my experiences as they relate to the above questions.</p>

<h3>Building An Ideal Desk/Office</h3>
<p>My wife and I have four children, and we homeschool, so the house is full all day, everyday. My response is therefore affected by the fact that my house is a hive of activity.</p>

<p>The goal here is to have a space where you can work undistracted. To me that means you'll want a proper office with a door that locks. The understanding among your family has to be that the office is your space to work. When the door is closed, it means no interruptions. The lock is for the times when people forget what the closed door means. And they will forget.</p>

<p>The other thing about a room dedicated to work is that it allows you
to mentally segment home life and work life. I don't always work in my
office when I'm home (more on that in a bit). But even so, I know when I
am done for the day, I leave my office and shut the door, and that's
that.</p>

<p>Working from home gives you the unique opportunity to completely
customize your workspace. An ideal desk and office setup is relative to
what inspires you. What helps you focus and get "in the zone"? For
example, I like to have a view of the outside world when I work. I also try to
keep my desk free of non work-related things like bills and
mail. I find those sorts of things distracting. I'll get to the mail later; for now, I'm
working.</p>

<p>I recommend investing in a good pair of headphones or a headset. I use <a href="http://www.amazon.com/Sony-MDRV6-Studio-Monitor-Headphones/dp/B00001WRSJ">Sony MDRV6 Studio Monitor Headphones</a>. I find that listening to music through headphones helps me focus more than listening through external speakers. YMMV. Here are two playlists I listen to when hacking:</p>
<ul>
  <li><p><a href="https://open.spotify.com/user/speric/playlist/50Pk2JxEQXvGckPb4bbvbN">https://open.spotify.com/user/speric/playlist/50Pk2JxEQXvGckPb4bbvbN</a></p></li>
  <li><p><a href="https://open.spotify.com/user/speric/playlist/6DSBFarhDIkxfzIvZLbHYt">https://open.spotify.com/user/speric/playlist/6DSBFarhDIkxfzIvZLbHYt</a></p></li>
</ul>

<p>I like to switch up my work location. I work in my
office 90% of the time, but sometimes I work in my living room, or at the local Starbucks, or even the pub!</p>

<p>Switching up work locations like this keeps me from getting into a
rut. Working remotely, I don't have face-to-face communication with
co-workers. I miss out on things like going with co-workers to a new place to get lunch, or grabbing a coffee mid-afternoon, things I was accustomed to when working in an office. Changing work
locations approximates this experience, however poorly.</p>

<h3>Stepping Up Communication and Collaboration</h3>
<p>The answer I'd give here would mostly be a summation of his thoughts anyway,
so I will just point you directly to <a href="https://github.com/pengwynn/pingwynn/issues/3">Wynn Netherland's answer</a> when I asked him the
same question.</p>

<p>I will add to that: communicate early, and often; don't be afraid to ask questions. The channels and means you use to communicate (synchronous vs. asynchronous) will be different based on the company, but the general principle applies. The worst thing in a remote job is to be stuck on something and feel alone. It doesn't have to be that way. Just ask!</p>

<h3>Building Life Structure Around Remote Work</h3>
<p>Working remotely has changed my life, and my family's life. We've
been able to travel for long periods of time, and as long as I have a
web connection (tethering FTW!), I can work a full-day and then have the
evenings and weekends to enjoy a new place.</p>

<p>I'd encourage anyone working remotely to try such a "work-cation". Of
course, it's easier for us to do because we homeschool as well, so we
can do school and I can work "on the road". That said, it can still be
done, you just need to be creative. When we travel we mostly stay with
family and friends to keep our costs down, but with Airbnb it's possible
to find long-term (1-2 month) rentals at an affordable cost.</p>

<p>Remote work presents a great opportunity to do interesting things,
but it's important to remember the <i>work</i> part of "remote work". In
everything you do (working at a coffeeshop, doing a "work-cation"), keep
in mind that you're part of a team, and the implicit understanding is
that you're responsible enough to be productive and manage yourself. The
goal is for everything you do to be transparent to your co-workers: no
matter where you're working or what your office looks like, you're still
contributing at a high level to your company. When my family travels out of
town on extended trips, we always drive on weekends or late at night, so
that I can still work a full day/week. If I want to take a day off to
do something fun with my family, I take it, but otherwise, it's a normal
work day, sitting poolside notwithstanding.</p>

<p>Additionally, I think it's important to have a routine when working
remotely. Have a consistent general start time, and general end time. Take a real
lunch break. It's easy to either a) work all the time, since you can
work anywhere, or b) become undisciplined in work habits because no one
is micromanaging you. You're conscientious, and responsible: don't let
that happen to you.</p>

<p>Use the fact that you don't have a commute to your advantage. Spend
the hour that would have been spent in the car or on the train instead on reading a technical
book, or exercising. I've recently started waking up around 6:30am,
making coffee, and just taking the morning easy by reading or going for
a run. The kids are still asleep during that time and I can get out in
front of the day instead of the day's events controlling me. When
working remotely it's easy to sleep until 10 minutes before you're
expected to be online, then rolling out of bed and starting work. Again,
you're not that kind of person; you're going to make the most out of the
the time you have.</p>

<h3>Closing Thoughts</h3>
<p>Remote work is fun, but also challenging. Unfortunately I've seen
people who can't handle the responsibility of working remotely. And
that's very sad to me, because it's such a great opportunity for so many
things. So communicate well, work hard, and enjoy yourself.</p>

<h3>See Also</h3>
<p><a href="http://cultivatenow.com/10-commandments-for-remote-working/">10 Commandments for Remote Working</a></p>

   ]]></content>
 </entry>
 
 <entry>
   <title>Elixir and Phoenix Quickstart Guide</title>
   <link href="http://ericfarkas.com/posts/elixir-and-phoenix-quickstart-guide"/>
   <updated>2015-05-27T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/elixir-and-phoenix-quickstart-guide</id>
   <content type="html"><![CDATA[
     <p>I've begun tinkering with <a href="http://elixir-lang.org/">Elixir</a> and the <a href="http://www.phoenixframework.org/">Phoenix framework</a>. The guides on the Phoenix site seem to be slightly out of date, so I thought it'd be helpful to post a quick start guide. I am running OS X 10.10.3.</p>

<h4>1 - Install Elixir via Homebrew</h4>
<pre>$ brew install elixir</pre>

<p>The latest version as of today is `1.0.4`. Along with Elixir comes <a href="http://elixir-lang.org/docs/stable/mix/">Mix</a>.

<blockquote><p>Mix is a build tool that provides tasks for creating, compiling, testing Elixir projects, as well as handle dependencies, and more.</p></blockquote>

<h4>2 - Install Hex</h4>

<blockquote><p><a href="https://hex.pm">Hex</a> is a package manager for the Erlang ecosystem.</p></blockquote>

<pre>$ mix local.hex</pre>

<h4>3 - Install latest version of Phoenix</h4>
<p>As of today, the latest Phoenix release is `v0.13.1`. Check the project's <a href="https://github.com/phoenixframework/phoenix/releases">Releases page</a> to be sure you're going to install the latest version.</p>

<pre>$ mix archive.install https://github.com/phoenixframework/phoenix/releases/download/v0.13.1/phoenix_new-0.13.1.ez</pre>

<h4>4 - Create your Phoenix app</h4>
<p>By default, your app will be created in the same directory you're in
when you run this command:</p>

<pre>$ mix phoenix.new phoenix_test_app</pre>

<p>Specifying an absolute path also works:</p>

<pre>$ mix phoenix.new /path/to/my/phoenix_test_app</pre>

<p>Be sure to type "Y" when prompted to install all dependencies.</p>

<h4>5 - Start the web server&lt;/h5&gt;

<pre>$ cd phoenix_test_app
$ mix phoenix.server</pre>

<p>Open your browser and visit <a href="http://localhost:4000">http://localhost:4000</a>. You should see the following:</p>

<center><div><img src="/assets/images/phoenix.png" class="img-polaroid" /></div></center>


</h4></p>

   ]]></content>
 </entry>
 
 <entry>
   <title>Inheritance</title>
   <link href="http://ericfarkas.com/posts/inheritance"/>
   <updated>2014-11-06T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/inheritance</id>
   <content type="html"><![CDATA[
     <p>I'm coming to the opinion that, in Ruby, inheritance is never the first tool you should reach for when designing classes. This has been a difficult mental shift for me to make, coming to Ruby as I did from the Java world. Reading <i><a href="http://www.poodr.com/">Practical Object-Oriented Design in Ruby</a></i> earlier this year first put the idea in my head. But recent experience doing post-mortems on production code which made use of inheritance has made the abstract idea concrete.</p>

<p>The major reason for this shift in thinking is that, in my
experience, code which makes
use of inheritance is harder to reason about. This is especially the
case when one is trying to track down a bug during an outage or some
other "support incident". Your experience may be different. But there's
something to be said for having all the methods that a class makes use of all in one place.</p>

<p>It can be argued that composition also introduces the same type of
problem, but it's mitigated for me by the fact that classes
which make use of composition tend to have shallower hierarchies. Most
of the time you're just jumping to one file to look for a method
definition, whereas with inheritance you are potentially jumping into a
complex class hierarchy.</p>

<p>I'm beginning to think that dependency injection is the best way to
make potentially complex model interactions very simple. When you focus
on message-based design, you quickly discover news ways to leverage Ruby's
duck-typing capabilities in the service of writing small classes that do
one thing and are simple to reason about. These types of classes are
easy to change, and in my experience, easier for the person who didn't
write them to someone to come in and understand. And for teams working
on large applications, that's a big win.</p>

   ]]></content>
 </entry>
 
 <entry>
   <title>My git Workflow</title>
   <link href="http://ericfarkas.com/posts/my-git-workflow"/>
   <updated>2014-03-29T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/my-git-workflow</id>
   <content type="html"><![CDATA[
     <p>I've settled into what I think is an effectively simple git workflow that I thought would be helpful to share.</p>

<p>Let's say I am working on a new feature. First thing I want to do is
make sure my local copy of the codebase is up-to-date:</p>

<pre>$ git pull master</pre>

<p>I'll then create a new feature branch. In my experience, 99% of the
time I am branching off of master:</p>

<pre>$ git checkout -b an-awesome-new-feature</pre>

<p>But it’s just as easy to branch off another branch:</p>

<pre>$ git checkout -b an-awesome-new-feature some-other-branch</pre>

<p>Within this new branch, I can spike on the new feature, and if things
get hairy I can blow it away and start over. I'll commit often. Most of
my commits during the spike or early phase of a feature will look
like:</p>

<pre>$ git commit -am "WIP specs"</pre>

<p>If I am
pairing, I will be more descriptive with the commit messages. But when I am
coding alone, these pre-PR commits are for me, and are not meant to be
used for any meaningful code review. When I am satisfied that I the work I've done will eventually become a PR, I'll push my branch to a remote:</p>

<pre>$ git pushr</pre>

<p>The <code>pushr</code> command is a nice little shortcut from the <a href="https://github.com/jeremywrowe/dotfiles/blob/master/dots/gitconfig#L67">dotfiles</a> I use. It creates a remote branch with the same name as my local branch, in this case, <code>an-awesome-new-feature</code>. After the initial <code>git pushr</code>, I can just do <code>git push</code> and it will push to the remote branch.</p>

<p>The "do some work, test, commit, push" loop happens until I am
satisfied that the feature is ready for a pull request. If a new feature
was merged into <code>master</code> that will effect my feature, I'll
pull the changes in, and then do:</p>

<pre>$ git rebase master</pre>

<p>Recently I've gotten into the habit of <a href="http://git-scm.com/book/en/Git-Branching-Rebasing">rebasing</a> my
feature branches whenever anything is merged into <code>master</code>,
even if I don't think they will effect what I am doing. I've done this
mainly because, if there is a conflict, I'd rather be in merge hell in
the middle of working on a feature than at the end of a feature. It's dispiriting when you're about to open a shiny new PR and you realize it won't merge cleanly.</p>

<p>At this point I
will <a href="http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html">rebase
and squash</a> all of my commits on the
<code>an-awesome-new-feature</code> branch into one commit. This commit
message will be as informative (detailed) as possible, since it will become the
basis for the pull request message.</p>

<p>Once that's done, I'll force push to the branch with my new rebased
history:</p>

<pre>$ git push --force</pre>

<p>I'll then open my pull request. I will push new commits to the branch
after the PR is open, based on feedback. Once I get a :shipit:, I like
to re-squash all post-PR commits back into the first PR commit.</p>

<p>There's
been some discussion on our team about the merits and demerits of this
approach.  I like to have one commit per PR when it's possible. It seems
cleaner to me. But there's a good argument for not doing this, since
those post-PR commits were changes made based on feedback, and that
feedback history is important to have. Personally, I feel the comments
in the PR on GitHub are sufficient as far as history goes. Usually if I
want to dig deeper into what went into a new feature and why, I'll go back and re-read
the PR message and subsequent comments, as opposed to reading commit messages in <code>git log</code>. But that's my
own preference. The other way is fine too, in my opinion.</p>

<p>In either case, once the PR is merged, the feature branch is deleted
locally and remotely. The <code>master</code> is updated locally via
<code>git pull</code>, and the cycle repeats.</p>

   ]]></content>
 </entry>
 
 <entry>
   <title>In Praise Of Effort</title>
   <link href="http://ericfarkas.com/posts/in-praise-of-effort"/>
   <updated>2014-02-27T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/in-praise-of-effort</id>
   <content type="html"><![CDATA[
     <p><blockquote>"If a thing is worth doing, it is worth doing badly." -
G.K. Chesterton</blockquote></p>

<p>Newton's first law of motion states that objects in motion
tend to stay in motion, and objects at rest tend to stay at rest, unless
acted on by an external force. This law explains the reason behind an
opinion I've adopted: starting <i>something</i> is difficult. Of course
finishing, and finishing well, are also difficult. But I think that
first leap, from doing <i>nothing</i> to <i>something</i>, is
harder.</p>

<p>Talk is cheap. It costs nothing to say you will do <i>something</i>. And people love to talk about the amazing plans they have. But
there's a price to putting forth an effort. Doing <i>something</i>
means not doing other things. It's a sacrifice of time, sometimes with
family, oftentimes of activities that are themselves enriching. Doing
<i>something</i> means there will an end product, which can be (and
often is) criticized. So there's also the emotional price which must be paid.</p>

<p>Additionally, you have those laws of motion working against you. It
seems to be our nature, that when we're doing nothing, we tend to
continue to do nothing. There's also some <a href="https://vimeo.com/5895898">Lizard Brain</a> stuff going on too. So to go from doing <i>nothing</i> to
<i>something</i>, an outside force is needed. As you mature you realize
that in many cases, you need to be your own outside force. You come
to understand that you're fighting against yourself to get stuff done.
A self-motivated person is one who understands that, and doesn't need
(or wait for) someone to give them a push.</p>

<p>If you're part of an organization, you can see this play out everytime you have some sort of housekeeping meeting. Ask for
feedback on an issue, watch the hands go up. Everyone likes to talk
about how things should change, what they would do if they were in
charge. Ask for volunteers to work on implementing that change, or watch the
follow-up effort by folks who just "do stuff", and it's usually
disappointing.</p>

<p>Therefore, I am one who praises effort, even effort that
results in something of low quality, because I appreciate how hard it is
to do <i>something</i>. Especially when that effort is the beginning of
<i>something</i>. When I see someone attempt to organize an event
and fail, ship a software product that I find ridiculous, start a
workout program, or many other things like that, I will always admire the
effort. At least they are trying. People who offer nothing other than words
shouldn't criticize the people actually doing <i>something</i>.</p>

<p>The only time effort itself should be criticized is if it's sub-par. One should always aim for excellence. But excellence is hard to achieve, especially at the beginning of a thing. So as long as someone is trying as best as they can, and working to improve, their effort should be praised.</p>

<p>Poor outcomes are tolerated on the way to better outcomes. Poor effort is never tolerated. Honest effort is always to be praised.</p>

   ]]></content>
 </entry>
 
 <entry>
   <title>Learning vim</title>
   <link href="http://ericfarkas.com/posts/learning-vim"/>
   <updated>2014-01-28T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/learning-vim</id>
   <content type="html"><![CDATA[
     <p>I've spent the last 6 months all-in with vim. At Chargify, we use vim when doing remote pairing, so it's been necessary to get up to speed for that reason alone. To shorten the learning curve I uninstalled TextMate on my personal laptop and have been using vim for all <a href="https://talentsoup.com">TalentSoup</a> development as well. My vim knowledge was basic when I joined Chargify, and while I am far from expert at this point, I am productive and learning more each day.</p>

<p>Given the experience of needing to go from 0 to productive in a short period, I'd offer that the best way to learn vim is with someone else. Whether you use someone's dotfiles (I use a fork of my colleague Jeremy Rowe's <a href="https://github.com/jeremywrowe/dotfiles">dotfiles</a>) or not is a secondary concern. Nothing will speed up your vim education like having someone watch you attempt to do something, and suggest another, more efficient way. A great set of dotfiles is super helpful, but more important is that you have someone offering guidance.</p>

<p>More and more I am becoming convinced that the pairing model is the best way to get better at software development. If you can find someone to be a mentor to you, you're in a great spot.</p>

<p>P.S. - If you can't find someone to pair with to learn vim, I recommend watching the <a href="http://destroyallsoftware.com">Destroy All Software</a>
screencasts. You'll see Gary do a lot of crazy things, which will lead
you to ask "how did he do [X]", which will start you on the right
path.</p>

   ]]></content>
 </entry>
 
 <entry>
   <title>A Developer&apos;s Daily Checklist</title>
   <link href="http://ericfarkas.com/posts/a-developers-daily-checklist"/>
   <updated>2013-10-23T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/a-developers-daily-checklist</id>
   <content type="html"><![CDATA[
     <p>Below is a list I am going to read everyday before I start working. Some points are repetitive, because I need to hear them over and over. This list is in no particular order.</p>

<ul>
<li><p>Communicate early, and often. Don't be afraid to ask questions.</p></li>
<li><p>If something isn't clear or a proposed solution doesn't seem right, say something. At best you've discovered a blind spot in your team's approach, at worst, you will have learned something. So you win either way.</p></li>
<li><p>Assume nothing. Take the extra time to confirm or refute your assumptions by asking a team member.</p></li>
<li><p>Program defensively. Assume users will break things and enter bad data, or that the worst will happen.</p></li>
<li><p>It's ok joke around and shoot the breeze every so often, but at the end of the day, this is your job. Be serious about it.</p></li>
<li><p>Every moment is a teachable moment. Learn, soak in as much as you can from others. Again, ask questions: "Why are you doing it that way? What does that method do? What are some others ways to do the same thing?" Pair programming offers so many opportunities for this interaction, which is why I think it's the best way to level up.</p></li>
<li><p>Test your code thoroughly. Ask others if there are blind spots in your tests.</p></li>
<li><p>Understand that, even though every PR is reviewed by others, there's a level of trust in you as a developer. Own the code you write, and take pride in it. Make sure it works, don't assume others will catch a mistake.</p></li>
<li><p>Never. Stop. Learning.</p></li>
<li><p>Ask about blind spots: "What other parts of the app might break if I change this? What are some "gotchas" about the process I am working on that are perhaps not apparent? Can you just go over with me what's happening here?"</p></li>
<li><p>Document useful things you discover.</p></li>
<li><p>If something is broken, fix it.</p></li>
</ul>

<p>The biggest takeaway for me, especially as a remote worker, is to just speak up if you have a question or are unsure about something. In my experience, colleagues are very understanding about getting someone up to speed with how the app works, or to just go back and forth talking about the merits and demerits of a particular approach.</p>

   ]]></content>
 </entry>
 
 <entry>
   <title>The Challenges Of Being A Solo Developer</title>
   <link href="http://ericfarkas.com/posts/the-challenges-of-being-a-solo-developer"/>
   <updated>2013-07-24T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/the-challenges-of-being-a-solo-developer</id>
   <content type="html"><![CDATA[
     <p>Since October 2009 I have been the only developer at <a href="https://talentsoup.com">TalentSoup</a>.  In the past, I've been part of large co-located teams, and smaller distributed teams (across continents). TalentSoup is my first experience building an application this large, by myself. I want to briefly talk about my experience as a solo developer, and offer some helpful tips to others in the same situation.</p>

<p>In short, the best part of being a solo developer is that you can do whatever you want. Also, the worst part of being a solo developer is that you can do whatever you want.</p>

<h3>The Best Part</h3>
<p>The best part of being a solo developer is that you can do whatever you want. It turns out that this is a double edged sword, as I'll get to below. But there are times when it's nice to use whatever technologies or frameworks that you are most productive with. No bureaucracy to deal with.</p>

<p>The other great thing is that you learn a lot.  When working on an application with other developers, the tendency is to divide up the work based on the expertise of the team, especially when time is of the essence. It takes a strong lead developer to say, "Jane doesn't have a lot of experience with billing systems, so we're going to let her spend the next few weeks working on some news features for ours, so she can learn." As a solo developer, you get those opportunities by default.  For me, this also involved learning basic sysadmin stuff, like securing a new server, troubleshooing server issues, scaling up the application, things of that nature.</p>

<p>All this, in addition to all the little things you learn as you refactor, gain a deeper understanding of your language and framework, etc.  Not to say I wouldn't have learned as much if I were working with someone else, just that I <b>had</b> to learn. Having worked in the past at places where there were separate teams handing server and database administration, I enjoyed the chance to dig in to new things.</p>

<h3>The Worst Part</h3>
<p>The worst part of being a solo developer is that you can do whatever you want. The longer I am a solo developer, the more I think it's a net negative.  Unless you have an exhaustive knowledge of the technologies available for a given solution, and the experience to know the benefits/limitations of each, the fact is that you will have blindspots in your thinking. I'm not saying that someone with limited experience can't find a good solution to a problem. What I am saying is that it's good to have someone who can suggest a couple of different courses of action, because there might be a solution that fits your problem better than the one you're about to implement.</p>

<p>This principle also affects the learning process.  There have been times when I have wanted to try out a new database for example, but knowing there'd be a learning curve, I avoided it and stuck with what I knew. There's a good business reason for doing this: when stuff breaks, it's better to be working with something you know how to fix. But it would have been nice to be working with someone who had experience with that new database and provided a safety net in terms of knowledge and experience. Even if no one on a team has experience with a new technology, stepping into the unknown with a group is better than stepping in alone.</p>

<p>Another factor is that we all have comfort zones.  I have test frameworks and gems I like to use, and a development process that feels comfortable to me.  But if I want to keep my skills relevant, thinking about opportunities beyond my current position, it would be in my best interest to branch out and learn other things. As a solo dev, unless you are really disciplined, it's hard to step out of that comfort zone.</p>

<p>Also, it can be emotionally difficult to bear the weight of knowing every feature, bug fix and upgrade depends on you. This can lead to burnout.</p>

<p>Finally, when you are a solo developer, there's no one to review your actual code. No one to call you out on a bad implementation, or educate you on the idiomatic way to do a certain thing. No one to raise a flag when untested code goes into production.  I've gotten into some bad habits that have taken much effort to reverse. When you are a solo developer you don't get the positive peer pressure that's needed to grow as a craftsman.</p>

<h3>A Way Forward</h3>
<p>The challenges of being a solo developer aren't insurmountable. If you feel that you're not able to get out of your comfort zone, you have to, in the words of my friend <a href="http://twitter.com/imsnakes">Matt</a>, "Aggressively find ways to use things."  It takes being disciplined and intentional to gain experience with new things when you are on your own. There's no other way. No secret sauce.</p>

<p>I've had the privilege of getting to know some really good Ruby developers.  I'll send an email every once in a while asking how they'd best solve some problem, or if they could recommend a book to help me level up. There are also resources like <a href="http://www.pairprogramwith.me/">pairprogramwith.me</a> if you're looking to pair with another developer.  I got to spend a day pairing with a startup recently, and it was an eye-opening experience, one that I am eager to participate in again. Talking out loud with another developer, while looking at the same code in the same room, exposed so many areas of my craft that I need to improve. It was worth many books and screencasts.</p>

<p>If you are feeling overwhelmed by your workload, might I suggest something counterintuitive: walk away. Take a day or two and don't open the editor, or look at a bug list. Just take some time for yourself. Or, if you are going to work, work on a pet project, something fun. At TalentSoup, a couple of small features that have turned out to be popular were the result of me blowing off a laundry list of things I <b>had</b> to do, to work on something fun, just for my sanity.</p>

<p>These certainly aren't an exhaustive list of solutions, but if you're a solo dev and know you will be for the forseeable future, it's a starting point.</p>

   ]]></content>
 </entry>
 
 <entry>
   <title>Recent Experience With Service Objects In Rails</title>
   <link href="http://ericfarkas.com/posts/recent-experience-with-service-objects-in-rails"/>
   <updated>2013-07-13T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/recent-experience-with-service-objects-in-rails</id>
   <content type="html"><![CDATA[
     <p>I read <a href="https://twitter.com/brynary">Bryan Helmkamp's</a> blog post <a href="http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/">7 Patterns to Refactor Fat ActiveRecord Models</a> when it was originally posted, but it's taken me until recently to implement some of his suggestions in <a href="https://talentsoup.com">TalentSoup</a>. Specifically, I've been writing service objects, using similar criteria to Bryan.</p>

<p>One quick example of how I've used service objects is in the downgrading process. Previously, my code for downgrading an account looked like this:</p>

<p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1">#controller action</span>
<span class="k">def</span> <span class="nf">downgrade</span>
  <span class="vi">@subscription</span> <span class="o">=</span> <span class="no">Chargify</span><span class="o">::</span><span class="no">Subscription</span><span class="p">.</span><span class="nf">find_by_customer_reference</span><span class="p">(</span><span class="vi">@current_user</span><span class="p">.</span><span class="nf">chargify_reference</span><span class="p">)</span>
  <span class="vi">@current_user</span><span class="p">.</span><span class="nf">downgrade_brand_to</span><span class="p">(</span><span class="s2">"new_brand"</span><span class="p">,</span> <span class="vi">@subscription</span><span class="p">)</span>
  <span class="no">AuditLog</span><span class="p">.</span><span class="nf">create</span><span class="p">(</span><span class="ss">user_id: </span><span class="vi">@current_user</span><span class="p">.</span><span class="nf">id</span><span class="p">,</span> <span class="ss">content: </span><span class="n">params</span><span class="p">[</span><span class="ss">:downgrade_reason</span><span class="p">])</span>
  <span class="n">flash</span><span class="p">[</span><span class="ss">:notice</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"Your account has been successfully downgraded."</span>
  <span class="n">redirect_to</span> <span class="ss">:controller</span> <span class="o">=&gt;</span> <span class="ss">:home</span>
<span class="k">end</span></code></pre></figure>

</p>

<p>My <code>user.rb</code> class was responsible for post-downgrade cleanup in the <code>downgrade_brand_to</code> method, like canceling the subscription with Chargify, and resetting some of the features availabile to our Pro users.  The code certainly worked, but there were a number of things wrong the approach (besides how obviously hideous it is!):</p>

<ul>
  <li><p>Spread out the business logic behind canceling across a controller and a model.  I always want to log the reason for a cancellation along with doing the actual canceling, but the previous implementation had those two occuring separately.</p></li>
  <li><p>Since there was no single point of entry that would encapsulate the entire downgrade process, it was hard to test.</p></li>
  <li><p>It was also not portable. We might want to downgrade in other parts of the app too (reconciliation process via Rake task, perhaps) and the current process would necessitate repeating ourselves, and possibly leaving out something important.</p></li>
</ul>

<p>My refactored code now looks like this:</p>

<p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1">#controller action</span>
<span class="k">def</span> <span class="nf">downgrade</span>
  <span class="vi">@subscription</span> <span class="o">=</span> <span class="no">Chargify</span><span class="o">::</span><span class="no">Subscription</span><span class="p">.</span><span class="nf">find_by_customer_reference</span><span class="p">(</span><span class="vi">@current_user</span><span class="p">.</span><span class="nf">chargify_reference</span><span class="p">)</span>
  <span class="no">WebcompDowngrader</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="vi">@current_user</span><span class="p">,</span> <span class="vi">@subscription</span><span class="p">,</span> <span class="n">params</span><span class="p">[</span><span class="ss">:downgrade_reason</span><span class="p">]).</span><span class="nf">downgrade!</span>
  <span class="n">redirect_to</span> <span class="ss">controller: :home</span><span class="p">,</span> <span class="ss">notice: </span><span class="s2">"Your account has been successfully downgraded."</span>
<span class="k">end</span>

<span class="c1">#service object</span>
<span class="k">class</span> <span class="nc">WebcompDowngrader</span>
  <span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">user</span><span class="p">,</span> <span class="n">subscription</span><span class="p">,</span> <span class="n">downgrade_reason</span><span class="p">)</span>
    <span class="vi">@user</span>             <span class="o">=</span> <span class="n">user</span>
    <span class="vi">@subscription</span>     <span class="o">=</span> <span class="n">subscription</span>                       
    <span class="vi">@downgrade_reason</span> <span class="o">=</span> <span class="n">downgrade_reason</span>
  <span class="k">end</span>
  
  <span class="k">def</span> <span class="nf">downgrade!</span>
    <span class="n">reset_subscription_level</span>
    <span class="n">delete_chargify_subscription</span>    
    <span class="n">log_downgrade_reason</span>
  <span class="k">end</span>
  
  <span class="kp">private</span>
  
  <span class="k">def</span> <span class="nf">reset_subscription_level</span>
    <span class="c1">#some downgrading actions on the user's account...</span>
    <span class="vi">@user</span><span class="p">.</span><span class="nf">save</span>
  <span class="k">end</span>
  
  <span class="k">def</span> <span class="nf">log_downgrade_reason</span>
    <span class="no">AuditLog</span><span class="p">.</span><span class="nf">create</span><span class="p">(</span><span class="ss">user_id: </span><span class="vi">@user</span><span class="p">.</span><span class="nf">id</span><span class="p">,</span> <span class="ss">content: </span><span class="vi">@downgrade_reason</span><span class="p">)</span>
  <span class="k">end</span>
  
  <span class="k">def</span> <span class="nf">delete_chargify_subscription</span>
    <span class="no">Chargify</span><span class="o">::</span><span class="no">Subscription</span><span class="p">.</span><span class="nf">delete</span><span class="p">(</span><span class="vi">@subscription</span><span class="p">.</span><span class="nf">id</span><span class="p">)</span>
  <span class="k">end</span>                             
<span class="k">end</span>                                                                        </code></pre></figure>

</p>

<p>I think this is much cleaner, it's reusable, and it's easier to test.</p>

<p>To be quite honest, as great as those things are, the biggest win for me so far has been that I feel better about the application.  I feel more confident going in to change things, because I can focus on much smaller parts of the application, rather than digging into God models. As a solo developer, it becomes harder to keep the whole application in your head as the code base grows.  Therefore, anything that will express business logic in a concise way and make it easier to come back and understand months later ("I just need to look at one small class to see what we do when we downgrade") is huge.</p>

<h3>See Also</h3>
<p><a href="http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/">7 Patterns to Refactor Fat ActiveRecord Models</a></p>
<p><a href="http://rubyrogues.com/083-rr-decomposing-fat-models-with-bryan-helmkamp/">Ruby Rogues - Decomposing Fat Models with Bryan Helmkamp</a></p>

   ]]></content>
 </entry>
 
 <entry>
   <title>How To Create Opportunity</title>
   <link href="http://ericfarkas.com/posts/how-to-create-opportunity"/>
   <updated>2013-04-19T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/how-to-create-opportunity</id>
   <content type="html"><![CDATA[
     <p>A number of related but scattered thoughts on the subject of creating opportunity for yourself.</p>

<h3>Favor Action Over Inaction</h3>
<p>Look at goals you have in terms of actions to be taken.  It's not enough to write down ideas and talk about them. You have to work to implement them.  Recently someone at my church suggested regularly getting together during the summer at a local beach for volleyball.  Everyone was enthusiastic about the idea.  But to make it happen, someone needs to contact the town and see if we need a permit, and if we do, to work at getting that permit. Someone else needs to purchase equipment.  There is action to be taken; who's going to take it?</p>

<p>I think it's helpful to see yourself as a hustler, and I mean that in the sporting sense.  In baseball, someone who's a hustler will run out every ground ball, dive for every line drive, chase every ball hit anywhere in the outfield.  At the end of the game, he comes back to the locker room with a dirty uniform. To a hustler, there are no lost causes.</p>

<p>The way this played out for me is that I spoke to everyone who wanted to work with me, everyone with an idea. I answered emails, met with people, even if I had an inclination that it would be a waste of time.  Because you never know. Every potential opportunity is worth a look. This mindset (at the time I was looking for a project to be involved in long-term) is what caused me to <a href="https://twitter.com/saddington/status/4367475923">answer a random tweet</a>, which led me to Radford Harrell and <a href="https://talentsoup.com">TalentSoup</a>. On the surface it looked like short-term work, but it turned into 3-1/2 years (and going!) of a great partnership. You never know.</p>

<p>The nature of the hustle will change over time.  Now that I am in a situation that I worked hard for many years to find, the types of opportunities I am looking for has changed.  I want to meet people who will help me grow my business, and help me improve as a developer, whereas before I was looking for a project to be a part of. But the bias toward action will always exist.</p>

<h3>Sometimes It's Better To Stay The Course</h3>
<p>All of that said, being biased towards action does not necessarily mean always looking for new things.  If you're in a situation where you are really unsure of what to do, consider the possibility of just carrying on. But hopefully "carrying on" for you means continuing with some action, as opposed to doing nothing.</p>

<h3>Remember The Sabbath</h3>
<p>The Sabbath is a day of rest. Among it's practical benefits (naps for the whole family!), it also serves to remind us that the increase in our lives is not down to our own working.  We are led to believe that working long hours and sacrificing time with family and loved ones is what it takes to be "successful".  By allowing me to observe a day of rest from work, God is reminding me that ultimately, He is the One who provides for me.  Yes I work hard, but <a href="http://www.biblegateway.com/passage/?search=James+1%3A17&amp;version=NIV">every good thing in my life comes from God</a>. The apostle Paul elaborates on this idea in the first letter to the church at Corinth:</p>
<blockquote>
  <p>What then is Apollos? What is Paul? Servants through whom you believed, as the Lord assigned to each. I planted, Apollos watered, but God gave the growth. So neither he who plants nor he who waters is anything, but only God who gives the growth.</p>
  <small><a href="http://www.biblegateway.com/passage/?search=1+Corinthians+3%3A5-8&amp;version=ESV">1 Corinthians 3:5-8</a></small>
</blockquote>

<p>In that context he's talking about his work in the ministry of the Gospel, but the principle is clear: ultimately God is the one who prospers (or does not prosper) the labor of His people. Much more can be said about this point and how it relates to contentment. It's enough for now to remember that while you are working hard, God is the one who is directing your life, opening and closing doors, and adding (or not adding) increase through your labors.</p>

   ]]></content>
 </entry>
 
 <entry>
   <title>Things To Look Out For When Building An App</title>
   <link href="http://ericfarkas.com/posts/things-to-look-out-for-when-building-a-large-application"/>
   <updated>2013-04-02T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/things-to-look-out-for-when-building-a-large-application</id>
   <content type="html"><![CDATA[
     <p>A while back I found <a href="http://simon.incutio.com/notes/2006/summit/schachter.txt">a great set of notes</a> that were taken at a presentation by <a href="https://delicious.com/">del.icio.us</a> creator <a href="https://twitter.com/joshu">Joshua Schachter</a> at the 2006 Future Of Web Apps summit.  They were really helpful to me in my growth as a developer.  Unfortunately the notes are no longer available at the original URL, so I've taken the liberty to reproduce them here.</p>

<p>Again, these are not my own notes (credit goes to <a href="https://twitter.com/simonw">Simon Willison</a>) but I want to preserve them for posterity's sake. If you know of an "official" location for these notes please let me know.</p>

<ul>
<li><p>Browser quirks. CSS/JavaScript/rendering. IE caching.</p></li>
<li><p>Scaling: avoid early optimization. SQL doesn't map well to these problems - think about how to split up data over multiple machines. Understand indexing strategies, profile every SQL statement. Nagios or similar for monitoring.</p></li>
<li><p>Tags don't map well to SQL. Sometimes you can prune based on usage - only index the first few pages for example. This keeps indexes small and fast.</p></li>
<li><p>Some latency in the system is OK - work out where you have leeway, e.g. RSS feeds can fall a few minutes behind without anyone minding.</p></li>
<li><p>People are always going to abuse your system (scraping, greasemonkey, etc.)</p></li>
<li><p>"Idiots are a lot smarter than you" - wait to see what breaks before you fix it.</p></li>
<li><p>Learn Apache - tuning can make things a lot faster. Understand headers, mod_rewrite (a dark art). Put a proxy in front of Apache e.g. Perlbal from LiveJournal - one guy on a modem can suck up lots of resources otherwise.</p></li>
<li><p>Images off a different server, RSS from a different server.</p></li>
<li><p>"Save site for offline use" feature in IE is particularly nasty.</p></li>
<li><p>The easier the API to get in and out of, the more people will use it. There's a long tail of smart developers. Stuff like SOAP discourages adoption. No API key = people can play with it faster; drives attention.</p></li>
<li><p>Don't expose your unique id's to the outside world (php?id=1 etc.) People can scrape through everything very easily. This is why del.icio.us uses MD5 hashes of links instead.</p></li>
<li><p>Giving everything a unique ID in the database is a scaling problem in its own right.</p></li>
<li><p>Features: the features you put in are as important as the ones you leave out. There's no "send a note" in del.icio.us feature because e-mail already exists.</p></li>
<li><p>I don't add featues that are available elsewhere e.g. messaging</p></li>
<li><p>When people ask for features, get to the bottom of why they are asking for that exact thing. Solve the problem, rather than doing exactly what your asked for.</p></li>
<li><p>With tags, people ask for "A and B and NOT C or D" - but less than 1% of queries even use more than a single tag.</p></li>
<li><p>RSS important in del.icio.us, because it's a native way for people to access lists (of links). Put RSS everywhere you can. del.icio.us does way more RSS traffic than HTML or API stuff - partly because of poorly written readers.</p></li>
<li><p>Understand the headers - especially if-not-modified.</p></li>
<li><p>Make sure the URLs follow the path of the site. DON'T include session data, drop ugly details that are to do with the system, not the user (.php, .aspx, ?, &amp;, etc.)</p></li>
<li><p>URLs are prime real estate - respect them</p></li>
<li><p>When you chose what to build, solve a problem you have yourself so you can be sure to understand it. Passion counts. It's cheap and easy to build stuff, so other people will be building it too.</p></li>
<li><p>A niche product with a limited audience is still good business (with how advertising and PayPal work)</p></li>
<li><p>Every day that you don't have something properly out in the world (not on an invite only beta) you're losing a chance to gain users. Get it out there ASAP.</p></li>
<li><p>Aggregation is often a focus of attention (latest, most active, etc.)</p></li>
<li><p>As the population gets larger, the bias drifts; del.icio.us/popular becomes less interesting to the original community members. Work out ways to let the system fragment in to different areas of attention.</p></li>
<li><p>"Spam is attention theft" - that's one of the reasons del.icio.us doesn't have a top 10 links of all time - it's an attractive nuisance.</p></li>
<li><p>When you've figured out someone is spamming, don't let them know – let them keep posting and just silently junk their stuff.</p></li>
<li><p>Make users do the minimum amount of work. But make them do something.</p></li>
<li><p>Understand the user's motivation: "You have to understand the selfish user" – user #1 has to find the system useful or you won't get user #2. Systems that only become useful when lots of people are using them usually fail, because there's no incentive for people to contribute themselves. The real trick is to make the user base you have want to invite more people in to the system.</p></li>
<li><p>Manage your effort - be careful where you spend your efforts.</p></li>
<li><p>Don't waste time building features nobody uses.</p></li>
<li><p>Measurement: watch your system intensely: "Intuition is ideas backed by numbers"</p></li>
<li><p>Measure behavior rather than claims. del.icio.us doesn't have stars because why would you bookmark something that was no good? This way people bookmark things that they really care about rather than trying to tell the system things.</p></li>
<li><p>User Acceptance Testing (UAT) is important. Make the system suitable for the people actually using the system. Everybody on the team should see this in action. Labs are great but expensive. If you don't have a lab do ghetto testing in Starbucks. We did one day then two days user testing in a user testing lab.</p></li>
<li><p>Goals skew the results. People don't read, they cram crap in to boxes. Let people wander don't give them tasks.</p></li>
<li><p>You have to speak the user's language. "Bookmarks" are what you call them if you use Netscape of Firefox - most users these days know the term "favourite" instead. Half of his population (? users) didn't know what a bookmark was.</p></li>
<li><p>Don't make users register before they can get in to your site. Maybe even give them an anonymous account to play with. A lot of users want to know what they'll get if they register - especially from fear of giving out email address, spyware etc. You can't tell them; they're not going to read it. You have to show them.</p></li>
<li><p>Use Verbs - doing words - to prompt actions.</p></li>
<li><p>If users do have to register, send them straight back to where they were when they're done. Don't dump them on the homepage.</p></li>
<li><p>"Design Grammar" - if you're presenting a system that's different from how other things work (del.icio.us had novel tags, save your bookmarks to the web) you should still try to reflect the design patterns of the web.</p></li>
<li><p>Morals: You have to develop a sense of morals when you build your system. It's the user's data; it's not yours. Make sure they can remove themselves and their account if they want to.</p></li>
<li><p>Infection: Understand infection vectors for promoting your system. "Enable evangelism". RSS lets you get at users who don't use your system directly. Also think about iCal, M3U - anything that a desktop app can consume over HTTP. Do an inventory to get into every desktop app. possible.</p></li>
</ul>

   ]]></content>
 </entry>
 
 <entry>
   <title>A (Short) Rant About Working Remotely</title>
   <link href="http://ericfarkas.com/posts/a-short-rant-about-working-remotely"/>
   <updated>2013-01-31T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/a-short-rant-about-working-remotely</id>
   <content type="html"><![CDATA[
     <p>I get emails on a weekly basis from recruiters looking for developers.  The first question I respond with is, "Are you open to remote workers?", to which the answer, 99% of the time, is "No".</p>

<p>The reasoning is inevitably something along the lines of "They're an early stage/small company, so they want to have everyone in the office", as if being a young or small start-up necessarily means that you have to have everyone together, as if there's no possible way to build a company otherwise.</p>

<p>I get the reasons why face time is important.  This is why even companies that are advocates of remote work, like GitHub and 37signals, have company-wide meetups at least once a year.  Even an arrangement where a dev can come in once a week, or when needed during crunch time for a project or a special planning meeting, seems reasonable.  But I don't see a reason why, in 2013, given the tools we have, a developer has to be on-site at a desk every day, as the normal operating procedure.  Think of how many times companies miss out on really good developers just because they're not open to remote workers.</p>

<p>I joined <a href="https://talentsoup.com">TalentSoup</a> as a technical co-founder, and worked for a year and a half with my partner before we met face to face.  All communication was done on the phone, through email, Basecamp, GitHub, iChat, whatever.  We built (and continue to build) a profitable company, completely remotely.  So I just don't get the reluctance from other companies to embrace remote workers.  Are the problems you're working on that difficult, is your product that special, that everyone needs to be in the same room every working day?</p>

<p>I'm really disappointed at the state of remote work in the startup universe.  Hopefully it will change in the coming months and years as companies realize the resources that exist outside of their small part of the world.</p>

   ]]></content>
 </entry>
 
 <entry>
   <title>Setting up statsd + graphite on Ubuntu 12.04 LTS</title>
   <link href="http://ericfarkas.com/posts/statsd-graphite-ubuntu"/>
   <updated>2013-01-18T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/statsd-graphite-ubuntu</id>
   <content type="html"><![CDATA[
     <p>There are many great tutorials about setting up <a href="https://github.com/etsy/statsd">statsd</a> and <a href="http://graphite.wikidot.com/">graphite</a>, specifically on Ubuntu 12.04.  The best walk through I found was <a href="https://github.com/janoside/ubuntu-statsd-graphite-setup">https://github.com/janoside/ubuntu-statsd-graphite-setup</a>.  I'd like to add some things that were left out of that tutorial that I had to figure out.</p>

<h3>Database Creation</h3>
<p>The above Gist leaves out the initial database creation.  Be sure to thoroughly read <a href="http://graphite.wikidot.com/installation">http://graphite.wikidot.com/installation</a> so you know at which step to create the db. I did this step after configuring Apache but before restarting the server.</p>

<h3>WSGISocketPrefix</h3>
<p>If you see an error message similar to the following:</p>

<p><pre>(2)No such file or directory: mod_wsgi (pid=19506): Unable to connect to WSGI daemon process 'graphite' on '/etc/apache2/run/wsgi.19365.1.1.sock' after multiple attempts.</pre></p>

<p>That's a clue to edit <pre>/etc/apache2/sites-available/default</pre> and make sure that the configuration for <code>WSGISocketPrefix</code> is set as follows:</p>

<p><pre>WSGISocketPrefix /var/run/apache2/wsgi</pre></p>

<p>Thanks to <a href="http://marcelo-olivas.blogspot.com/2012/06/installing-graphite-on-ubuntu-1204.html">Marcelo Olivas</a> for that tip.&lt;/a&gt;

<h3>Target WSGI script '/opt/graphite/conf/graphite.wsgi' cannot be loaded as Python module.</h3>
<p>If you see this error, make sure that apache owns the directory</p>
<p><pre>/opt/graphite/storage/logs/webapp</pre></p>

<p>This <a href="https://answers.launchpad.net/graphite/+question/178110">thread</a> pointed me in the right direction.</p>

<p>Good luck.</p>

<h3>See Also</h3>
<p><a href="https://github.com/github/statsd-ruby">statsd-ruby</a></p>
<p><a href="http://codeascraft.etsy.com/2011/02/15/measure-anything-measure-everything/">Measure anything, measure everything</a></p>
</p>

   ]]></content>
 </entry>
 
 <entry>
   <title>Learning - Interesting Array Manipulation</title>
   <link href="http://ericfarkas.com/posts/learning-interesting-array-manipulation"/>
   <updated>2013-01-03T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/learning-interesting-array-manipulation</id>
   <content type="html"><![CDATA[
     <p>I said in the post about my <a href="http://ericfarkas.com/posts/learning-plan-for-2013/">2013 learning plans</a> that I'd blog about whatever I learn, even if it's dead simple or something I should have known already.  This is my first such post.</p>

<p>Let's start with this array:</p>

<p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">a</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">9</span> <span class="p">]</span>
<span class="c1">#=&gt; [1, 3, 5 , 7, 9]</span></code></pre></figure>

</p>

<p>We can replace two elements with one using the following notation:</p>

<p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1">#=&gt;a = [1, 3, 5 , 7, 9]</span>
<span class="n">a</span><span class="p">[</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span> <span class="p">]</span> <span class="o">=</span> <span class="s1">'foo'</span>
<span class="c1">#=&gt;a = [1, 3, "foo", 9]</span></code></pre></figure>

</p>

<p>Think of <code>a[ 2, 2 ] = "foo"</code> as meaning, "starting at index 2, replace 2 elements with the following value".  We can modify the same notation to insert a value but not replace anything in the array:</p>

<p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1">#=&gt;a = [1, 3, "foo", 9]</span>
<span class="n">a</span><span class="p">[</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span> <span class="p">]</span> <span class="o">=</span> <span class="s1">'bar'</span>
<span class="c1">#=&gt;a = [1, 3, "bar", "foo", 9]</span></code></pre></figure>

</p>

<p>The above has the same effect as doing <code>a.insert(2, "bar")</code>.

<p>The range notation can also be used to replace a range of elements, like so:</p>

<p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1">#=&gt;a = [1, 9, 8, 7, "bar", "foo", 9]</span>
<span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="o">..</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
<span class="c1">#=&gt;a = ["bar", "foo", 9]</span></code></pre></figure>

</p>

<p>Think of this as "replace elements at indexes 0 to 3 with the following".  The interesting thing about both of these methods of array manipulation is that the number of new elements you're assigning doesn't have to equal the number of elements you're replacing.  Using our original array, I can do the following:</p>

<p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1">#=&gt;a = [1, 3, 5 , 7, 9]</span>
<span class="n">a</span><span class="p">[</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span> <span class="p">]</span> <span class="o">=</span> <span class="s2">"fizz"</span><span class="p">,</span> <span class="s2">"buzz"</span><span class="p">,</span> <span class="s2">"fizz"</span><span class="p">,</span> <span class="s2">"buzz"</span>
<span class="c1">#=&gt;a = [1, 3, "fizz", "buzz", "fizz", "buzz", 9]</span>

<span class="c1">#the above is equivalent to:</span>
<span class="c1">#=&gt;a = [1, 3, 5 , 7, 9]</span>
<span class="n">a</span><span class="p">[</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span> <span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"fizz"</span><span class="p">,</span> <span class="s2">"buzz"</span><span class="p">,</span> <span class="s2">"fizz"</span><span class="p">,</span> <span class="s2">"buzz"</span><span class="p">]</span>
<span class="c1">#=&gt;a = [1, 3, "fizz", "buzz", "fizz", "buzz", 9]</span>

<span class="c1"># using range notation, we can do the same as above:</span>
<span class="c1">#=&gt;a = [1, 3, 5 , 7, 9]</span>
<span class="n">a</span><span class="p">[</span><span class="mi">2</span><span class="o">..</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"fizz"</span><span class="p">,</span> <span class="s2">"buzz"</span><span class="p">,</span> <span class="s2">"fizz"</span><span class="p">,</span> <span class="s2">"buzz"</span>
<span class="c1">#=&gt;a = [1, 3, "fizz", "buzz", "fizz", "buzz", 9]</span></code></pre></figure>

</p>

<p>In each example I replaced two elements with four elements.  The array grows automatically (see documentation on <a href="http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-5B-5D-3D">[]=</a>)</p>

<p>One last thing.  If you specify a range outside of the size of the array, the intermin elements will be set to <code>nil</code>:</p>

<p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1">#=&gt;a = ["bar", "foo", 9]</span>
<span class="n">a</span><span class="p">[</span><span class="mi">5</span><span class="o">..</span><span class="mi">6</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"fizz"</span><span class="p">,</span> <span class="s2">"buzz"</span>
<span class="c1">#=&gt;a = ["bar", "foo", 9, nil, nil, "fizz", "buzz"]</span></code></pre></figure>

</p>

<p>As always in Ruby, there are multiple ways to accomplish the same thing.</p>

<h3>See Also</h3>
<p><a href="http://www.ruby-doc.org/core-1.9.3/Array.html">Class: Array (Ruby 1.9.3)</a></p>
</p>

   ]]></content>
 </entry>
 
 <entry>
   <title>Learning Plan For 2013</title>
   <link href="http://ericfarkas.com/posts/learning-plan-for-2013"/>
   <updated>2012-11-28T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/learning-plan-for-2013</id>
   <content type="html"><![CDATA[
     <p>I've started to think about and plan how I will improve my development skills in 2013. My goals are:</p>
<ul>
 <li><p>Deepen my knowledge of the Ruby language</p></li>
 <li><p>Learn CoffeeScript</p></li>
 <li><p>Become familiar with database technologies other than MySQL, especially MongoDB</p></li>
 <li><p>Consistently write about what I am learning, whether it's simple or not</p></li>
 <li><p>Write a Ruby driver for <a href="https://github.com/bitly/nsq">NSQ</a></p></li>
</ul>

<p>I will achieve my goals in this manner:</p>
<ul>
  <li><p>Read <a href="http://pragprog.com/book/tbcoffee/coffeescript">CoffeeScript: Accelerated JavaScript Development</a> by Trevor Burnham (160 pages)</p></li>
  <li><p>Read <a href="http://pragprog.com/book/ruby3/programming-ruby-1-9">Programming Ruby 1.9 (3rd edition): The Pragmatic Programmers' Guide</a> by Dave Thomas, with Chad Fowler and Andy Hunt (944 pages)</p></li>
  <li><p>Read <a href="http://www.amazon.com/Eloquent-Ruby-Addison-Wesley-Professional/dp/0321584104">Eloquent Ruby</a> by Russ Olsen (448 pages)</p></li>
  <li><p>Read <a href="http://pragprog.com/book/ppmetr/metaprogramming-ruby">Metaprogramming Ruby: Program Like the Ruby Pros</a> by Paolo Perrotta (296 pages)</p></li>
  <li><p>Read <a href="http://pragprog.com/book/rwdata/seven-databases-in-seven-weeks">Seven Databases in Seven Weeks</a> by Eric Redmond and Jim R. Wilson (352 pages)</p></li>
  <li><p>Read <a href="http://www.amazon.com/MongoDB-Definitive-Guide-Kristina-Chodorow/dp/1449381561/">MongoDB: The Definitive Guide</a> by Kristina Chodorow and Michael Dirolf (216 pages)</p></li>
  <li><p>Read and thoroughly understand the code behind one of <a href="http://rubyeventmachine.com/">EventMachine</a>, <a href="https://github.com/macournoyer/thin">Thin</a>, <a href="http://www.sinatrarb.com/">Sinatra</a>, <a href="http://mongomapper.com/">MongoMapper</a> or <a href="http://rack.github.com/">Rack</a>, then write about it.</p></li>
  <li><p>Read <a href="http://pragprog.com/book/btlang/seven-languages-in-seven-weeks">Seven Languages In Seven Weeks</a> by Bruce A. Tate (328 pages)</p></li>
</ul>

<p>That's approximately 2200 pages (Programming Ruby is 944 pages but the second half of the book is language reference which I won't be "reading").  So 2200/365 is approximately 6 pages a day, or 42 pages a week.  Some of the books I am reading will cover material I am already familiar with, but I personally find it helpful to consistently review the basics.</p>

<p>I will post my progress here.  In the past I have been embarrassed to write about the things I am learning because I feel others have said it better already, and perhaps I'm posting about things I should have known already.  But that is a counterproductive mindset to have.  First of all, it betrays a conceit that anyone actually reads these posts in the first place.  Secondly, it keeps me from engaging in what is one of the best ways to complete the learning experience, and that is to write about it and teach others.</p>

<p>I'm looking forward to firming up the knowledge I already have, and getting deeper into Ruby, the language I have come to love.  I'm also excited about digging into an open source project that I have used and admire, and learning from the masters.</p>

   ]]></content>
 </entry>
 
 <entry>
   <title>Dynamic Images (Or A Lightweight Gravatar)</title>
   <link href="http://ericfarkas.com/posts/dynamic-images-or-a-lightweight-gravatar"/>
   <updated>2012-10-03T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/dynamic-images-or-a-lightweight-gravatar</id>
   <content type="html"><![CDATA[
     <p>We recently rolled out <a href="https://talentsoup.com/producers">Creative Commissary</a>, our project management tool for image producers.  It's a completely separate app from <a href="https://talentsoup.com">TalentSoup</a> in every way.  They do not share databases, and communicate via a JSON-based RESTful API.  Clients build and manage projects in Commissary, and the talent details (name, contact info, etc.) are stored in TalentSoup.</p>

<p>In TalentSoup, talent have the option of selecting any of their photos as the main photo.  This is the photo whose thumbnail will be shown in search results and project galleries.  This main photo is the talent's first impression on the client, and therefore the talent's most important photo.</p>

<p>Originally, when doing a search return (Commissary sending search parameters to TalentSoup, TalentSoup returning a search result to Commissary), I was including the static URL for the main photo at the time of the search as the <code>main_photo</code> value.  This value would be stored in Commissary and would be referenced when rendering a gallery page for the client to look at.  One thing I didn't take into account, however, was that talent might change their <code>main_photo</code> anytime after the gallery for that particular project was built.  When that happened, the image being displayed in the gallery wouldn't change, because the URL was being stored statically on the Commissary side.</p>

<p>This is a problem because sometimes talent change their <code>main_photo</code> based on what type of project they're being considered for (we let them know when they're added to a gallery, and what type of job it is).  For example, right now we're managing a job for a client who is going to be photographing people running.  As a result, some talent changed their <code>main_photo</code> to show them running or doing some sort of physical exercise.  This should be reflected in the galleries, obviously!</p>

<p>Basically what I needed was a service like <a href="http://gravatar.com">Gravatar</a>.  One URL I could pass around between TalentSoup and Commissary that would always render the given talent's <code>main_photo</code>.  I came up with a simple solution.  I am not sure if this is the best way to accomplish this, but it works. Here's a controller action that lives on the TalentSoup side:</p>

<p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1">#app/controllers/users_controller.rb</span>
<span class="k">class</span> <span class="nc">TalentController</span> <span class="o">&lt;</span> <span class="no">ApplicationController</span>
  <span class="k">def</span> <span class="nf">main_photo</span>
    <span class="vi">@user</span> <span class="o">=</span> <span class="no">User</span><span class="p">.</span><span class="nf">find</span><span class="p">(</span><span class="n">params</span><span class="p">[</span><span class="ss">:id</span><span class="p">],</span> <span class="ss">:include</span> <span class="o">=&gt;</span> <span class="ss">:main_photo</span><span class="p">)</span>
    <span class="n">redirect_to</span> <span class="vi">@user</span><span class="p">.</span><span class="nf">main_photo</span><span class="p">.</span><span class="nf">url</span><span class="p">(</span><span class="ss">:medium</span><span class="p">)</span> <span class="c1"># medium thumbnail url</span>
  <span class="k">end</span>
<span class="k">end</span></code></pre></figure>

</p>

<p>It takes the talent's <code>id</code> as a parameter and will always display the <code>main_photo</code>.  Now I can do this on the Commissary side:</p>

<p>

<figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">"https://talentsoup.com/talent/&lt;%= @talent.id %&gt;/main_photo"</span> <span class="nt">/&gt;</span></code></pre></figure>

</p>

<p>And I'll always get the <code>main_photo</code> for a given talent even when they change it.  We can make this more efficient by caching on the TalentSoup side, and invalidating when the talent changes their main photo.</p>

   ]]></content>
 </entry>
 
 <entry>
   <title>Sinatra, ActiveRecord, and MySQL</title>
   <link href="http://ericfarkas.com/posts/sinatra-activerecord-and-mysql"/>
   <updated>2012-09-06T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/sinatra-activerecord-and-mysql</id>
   <content type="html"><![CDATA[
     <p>If you want to use ActiveRecord with <a href="http://www.sinatrarb.com/">Sinatra</a>, the <a href="https://github.com/janko-m/sinatra-activerecord">sinatra-activerecord</a> gem is the way to go.  The examples in their documentation are for the <code>sqlite3</code> adapter.  I thought it'd be helpful to show how I used this gem with MySQL instead.  I created a <code>models</code> folder in my app root, where I store my ActiveRecord models.  You can include all of them in one file (like <code>models.rb</code>) or give each model it's own file, and include it explicitly.  We'll use the former for this example.</p>

<p>
<pre>
# config/database.yml
database: dbFoo
username: db_user
password: db_pass
host: localhost
port: 9999
</pre>
</p>

<p>Now we tell the gem about our db settings:</p>

<p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1"># app.rb</span>
<span class="nb">require</span> <span class="s1">'sinatra'</span>
<span class="nb">require</span> <span class="s1">'sinatra/activerecord'</span>
<span class="nb">require</span> <span class="s1">'yaml'</span>
<span class="nb">require</span> <span class="s1">'./models/models.rb'</span>

<span class="no">DB_CONFIG</span> <span class="o">=</span> <span class="no">YAML</span><span class="o">::</span><span class="nb">load</span><span class="p">(</span><span class="no">File</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="s1">'config/database.yml'</span><span class="p">))</span>

<span class="n">set</span> <span class="ss">:database</span><span class="p">,</span> <span class="s2">"mysql://</span><span class="si">#{</span><span class="no">DB_CONFIG</span><span class="p">[</span><span class="s1">'username'</span><span class="p">]</span><span class="si">}</span><span class="s2">:</span><span class="si">#{</span><span class="no">DB_CONFIG</span><span class="p">[</span><span class="s1">'password'</span><span class="p">]</span><span class="si">}</span><span class="s2">@</span><span class="si">#{</span><span class="no">DB_CONFIG</span><span class="p">[</span><span class="s1">'host'</span><span class="p">]</span><span class="si">}</span><span class="s2">:</span><span class="si">#{</span><span class="no">DB_CONFIG</span><span class="p">[</span><span class="s1">'port'</span><span class="p">]</span><span class="si">}</span><span class="s2">/</span><span class="si">#{</span><span class="no">DB_CONFIG</span><span class="p">[</span><span class="s1">'database'</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>

<span class="n">get</span> <span class="s1">'/'</span> <span class="k">do</span>
  <span class="vi">@items</span> <span class="o">=</span> <span class="no">Item</span><span class="p">.</span><span class="nf">all</span>
  <span class="n">erb</span> <span class="ss">:index</span>
<span class="k">end</span></code></pre></figure>

</p>

<p>Simple, and you get all the power of ActiveRecord as well as the ability to run migrations.</p>

<h3>See Also</h3>
<p><a href="http://www.sinatrarb.com/">Sinatra</a></p>
<p><a href="https://github.com/janko-m/sinatra-activerecord">sinatra-activerecord</a></p>

   ]]></content>
 </entry>
 
 <entry>
   <title>Pipe Fabrication with QuickPen 3D and CSVs</title>
   <link href="http://ericfarkas.com/posts/pipe-fabrication-with-quickpen-3d-and-csvs"/>
   <updated>2012-08-26T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/pipe-fabrication-with-quickpen-3d-and-csvs</id>
   <content type="html"><![CDATA[
     <p><i>I've been told that it's good practice to blog about code you've written, and the thought process behind it.  Doing so gives people an insight into how you approach problems, which at times is more important than what exactly you wrote.  This is such a post.</i></p>

<p>My full-time job is as a mechanical draftsman for an HVAC contractor.  Our work is mostly in high-end residential apartment buildings and hotels in the 5 boroughs of New York City.  We build steam and water-based HVAC systems (sometimes both in the same building).  At work, we use <a href="http://www.quickpen.com/index.php/Products/PipeDesigner-3D-Overview.html">QuickPen Pipe Designer 3D</a>, on top of AutoCAD, to draw 3D models of our mechanical piping.</p>

<center>
  <div>
    <img src="/assets/images/prv.png" class="img-polaroid" />
    <p><i>A PRV station</i></p>
  </div>
</center>

<h3>Coordination</h3>
<p>To get pipe to the field, the draftsmen first take the contract drawings from the architect and engineer, and we draw our pipe on the floor layout.  We then attend coordination meetings, where all trades (plumbers, electricians, sheetmetal, etc.) work on a set of drawings that has everyone's "stuff" on them.  This lets us resolve conflicts and hits.  Pipe moves around, duct gets raised or lowered, and so on.  When all trades sign off on the drawing for a particular floor, the draftsmen are then free to go back to their offices, update their own shop drawings, and work on fabricating their pipe.  The adoption of <a href="http://usa.autodesk.com/building-information-modeling/">BIM</a> and related software stacks promises to make/has made some of these steps unncessary, but many jobs are still coordinated like this.</p>

<h3>Fabrication</h3>
<p>The next goal for the draftsman is to hand the fitters in the shop what are called "fabrication sheets", or "cut sheets", that detail what needs to be fabricated, and what tag that piece should be given.</p>

<center>
  <div>
    <img src="/assets/images/cut-sheets.png" class="img-polaroid" />
    <p><i>Fabrication pieces</i></p>
  </div>
</center>

<p>In the above image, <code>R-03</code> is the tag number given to a piece of pipe that is 1-1/2" in diameter, 9'-6-1/4" long, and has a 1-1/2"x3/4" tee on one end.  We only want one of these pieces tagged R-03.  A fitting on the end of a piece like this is called a "make-up fitting". Usually, threaded pipe like this only has one make-up fitting. The other end of the pipe is a threaded end, and the fitters put these pieces together to construct all the piping on a given floor. We send "shop drawings" to the field that detail how these pieces fit together:</p>

<center>
  <div>
    <img src="/assets/images/balloon-dwg.png" class="img-polaroid" />
      <p><i>Shop drawing with pipes tagged</i></p>
  </div>
</center>

<p>QuickPen makes it (almost) easy to do all this.  I draw my pipe in 3D, at real elevations. I then use QuickPen's ISO manager to create my fabrication pieces by literally clicking on a piece of pipe, and it's make-up fitting.  QuickPen auto-increments the counter as I create pieces.</p>

<h3>The Problem</h3>
<p>While QuickPen makes it easy to tag your pipe for fabrication, and make a shop drawing with ballons for each tag, it doesn't make it THAT easy to create the cut sheets.  When you ask QuickPen to export your Bill Of Materials so that you can make a spreadsheet to print out and give to the fabricators in the shop, you're given the option to export to a CSV.  Here is what QuickPen gives you, truncated for our purposes:</p>

<pre>
"Iso Number","Size","Quantity","Length","Long Description"
"R-02","1-1/2""","1","9'-6 1/4""","PIPE, S/STD A-53 GRADE B ERW T.B.E."
"R-02","1-1/2""x3/4""","1","","TEE REDUCING, THRD, 150LB MALLEABLE IRON"
"S-13","2""","1","9'-6 1/4""","PIPE, S/STD A-53 GRADE B ERW T.B.E."
"S-13","2""x3/4""","1","","TEE REDUCING, THRD, 150LB MALLEABLE IRON"
</pre>

<p>And so on, for each piece.  The CSV is always un-ordered by ISO number (tag number). So basically what you get is a listing of each individual component of a fabrication piece, and not the whole piece itself.  Sometimes this is OK, because there are pieces that may have more than two components.  But 95% of the time a fabrication piece is a length of pipe and a fitting (tee, elbow, valve, coupling, etc.).  I have to massage this CSV so that it's useful to the shop fabricators.</p>

<p>For a while I did this by hand, which was tedious.  I made mistakes as well, which were costly in real dollar terms.  When union steamfitters call the office while they're standing on the 50th floor deck of a building, in the middle of winter, screaming that your pipe doesn't fit...well, that costs everyone money in wasted time and material.  In this way, drafting is different from much of the programming I've done recently.  Aside from the processing of subscriptions, bugs that occur on <a href="https://talentsoup.com">TalentSoup</a> don't <i>immediately</i> result in lost money, but simply an annoyance.  Drafting is different: a mistake could cost tens of thousands of dollars.</p>

<p>So after spending so much time on these CSVs, and making some bad mistakes, I decided to let the computer handle the CSVs for me.  This problem was always begging to be solved by a script.  The result is <a href="http://github.com/cut-sheets">cut-sheets</a>.</p>

<h3>Walk-Through</h3>
<p>Now that I told you more than you wanted to know about mechanical piping, I want to quickly walk though the parsing script.</p>

<p>First, I shamelessly steal Rails' <code>blank?</code> method, which is useful in this context.  Then I set up some constants that map to the column indexes in the CSV.  It's more readable this way. Then I read the CSV in as an array.</p>

<p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="nb">require</span> <span class="s1">'csv'</span>

<span class="k">class</span> <span class="nc">Object</span>
  <span class="k">def</span> <span class="nf">blank?</span>
    <span class="nb">respond_to?</span><span class="p">(</span><span class="ss">:empty?</span><span class="p">)</span> <span class="p">?</span> <span class="n">empty?</span> <span class="p">:</span> <span class="o">!</span><span class="nb">self</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="no">ISO_NUMBER</span>  <span class="o">=</span> <span class="mi">0</span>
<span class="no">SIZE</span>        <span class="o">=</span> <span class="mi">1</span>
<span class="no">QUANTITY</span>    <span class="o">=</span> <span class="mi">2</span>
<span class="no">LENGTH</span>      <span class="o">=</span> <span class="mi">3</span>
<span class="no">DESCRIPTION</span> <span class="o">=</span> <span class="mi">4</span>

<span class="n">fabrication_pieces_as_array</span> <span class="o">=</span> <span class="no">CSV</span><span class="p">.</span><span class="nf">read</span><span class="p">(</span><span class="s2">"isos.csv"</span><span class="p">)</span></code></pre></figure>

</p>

<p>Sometimes, QuickPen's Bill of Materials generator brings in pieces of pipe or fittings that are not part of any fabrication piece.  I remove them from my array so I can process the CSV knowing that I am only working with fabrication pieces. The motivation for want to assume this will be clear shortly.</p>

<p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">fabrication_pieces_as_array</span><span class="p">.</span><span class="nf">delete_if</span> <span class="p">{</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span> <span class="n">x</span><span class="p">[</span><span class="no">ISO_NUMBER</span><span class="p">].</span><span class="nf">blank?</span> <span class="p">}</span></code></pre></figure>

</p>

<p>Next, I change some of the descriptions of the pieces to conform to our shop standard.  Also, if the current array element is a fitting (which doesn't have a length as it's not a piece of pipe), then I put the fitting size into the description.  This is so when I make this element the make-up fitting of a piece of pipe, I get the fitting size in the description without any other manipulation.</p>

<p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">fabrication_pieces_as_array</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span>
  <span class="n">x</span><span class="p">[</span><span class="no">DESCRIPTION</span><span class="p">].</span><span class="nf">gsub!</span><span class="p">(</span><span class="sr">/, 150.*/</span><span class="p">,</span> <span class="s1">''</span><span class="p">)</span>
  <span class="n">x</span><span class="p">[</span><span class="no">DESCRIPTION</span><span class="p">].</span><span class="nf">gsub!</span><span class="p">(</span><span class="sr">/ 150.*/</span><span class="p">,</span> <span class="s1">''</span><span class="p">)</span>
  <span class="n">x</span><span class="p">[</span><span class="no">DESCRIPTION</span><span class="p">].</span><span class="nf">gsub!</span><span class="p">(</span><span class="s1">' PIPE'</span><span class="p">,</span> <span class="s1">''</span><span class="p">)</span>
  <span class="n">x</span><span class="p">[</span><span class="no">DESCRIPTION</span><span class="p">]</span> <span class="o">=</span> <span class="n">x</span><span class="p">[</span><span class="no">SIZE</span><span class="p">]</span> <span class="o">+</span> <span class="s2">" "</span> <span class="o">+</span> <span class="n">x</span><span class="p">[</span><span class="no">DESCRIPTION</span><span class="p">]</span> <span class="k">if</span> <span class="n">x</span><span class="p">[</span><span class="no">LENGTH</span><span class="p">].</span><span class="nf">blank?</span>
<span class="k">end</span></code></pre></figure>

</p>

<p>Now that my <code>fabrication_pieces_as_array</code> object is cleaned up, I can start combining pipe pieces with their make-up fittings.  First I create a hash using Ruby's awesome <code>group_by</code> method.  What I get back is a Hash whose keys are the <code>ISO_NUMBER</code>, or tag number.

<p>
<pre>
  {"R-02"=&gt;[["R-02", "1-1/2\"", "1", "9'-6 1/4\"", "PIPE, S/STD A-53 GRADE B ERW T.B.E."],
            ["R-02", "1-1/2\"x3/4\"", "1", "", "1-1/2\"x3/4\" TEE REDUCING, THRD"]],
   "R-03"=&gt;[["R-03", "1-1/2\"", "1", "9'-6 1/4\"", "PIPE, S/STD A-53 GRADE B ERW T.B.E."],
            ["R-03", "1-1/2\"x3/4\"", "1", "", "1-1/2\"x3/4\" TEE REDUCING, THRD"]],
   "R-04"=&gt;[["R-04", "1-1/2\"", "1", "9'-6 1/4\"", "PIPE, S/STD A-53 GRADE B ERW T.B.E."],
            ["R-04", "1-1/2\"x3/4\"", "1", "", "1-1/2\"x3/4\" TEE REDUCING, THRD"]]}
</pre>
</p>

<p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">iso_pieces</span> <span class="o">=</span> <span class="n">fabrication_pieces_as_array</span><span class="p">.</span><span class="nf">group_by</span><span class="p">{</span><span class="o">|</span><span class="n">row</span><span class="o">|</span> <span class="n">row</span><span class="p">[</span><span class="no">ISO_NUMBER</span><span class="p">]}</span></code></pre></figure>

<p>

<p>Now I can test to see how many pieces each tag number has.  As I said before, 95% of the pieces I make will will have two components: a length of pipe and a fitting.  For cases where the pieces are more complex, I handle those manually, usually by making a sketch of the piece in QuickPen.  I'll make a note on the cut sheet to "See Sketch" for that pieces.  Otherwise, I now go through my original array.  For each element I test to see if it's <code>ISO_NUMBER</code> number has two components, and if the <code>LENGTH</code> column is not <code>nil?</code>, meaning this element is the pipe portion of the fabrication piece that also has one make-up fitting.  I add the fitting row to the pipe row because the pipe row has the pipe <code>LENGTH</code>; it just "feels" more natural to do it that way.</p>

<p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">fabrication_pieces_as_array</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span>
  <span class="k">if</span> <span class="n">iso_pieces</span><span class="p">[</span><span class="n">x</span><span class="p">[</span><span class="no">ISO_NUMBER</span><span class="p">]].</span><span class="nf">size</span> <span class="o">==</span> <span class="mi">2</span> <span class="n">and</span> <span class="o">!</span><span class="n">x</span><span class="p">[</span><span class="no">LENGTH</span><span class="p">].</span><span class="nf">blank?</span>
    <span class="n">x</span><span class="p">[</span><span class="no">DESCRIPTION</span><span class="p">]</span> <span class="o">=</span> <span class="n">iso_pieces</span><span class="p">[</span><span class="n">x</span><span class="p">[</span><span class="no">ISO_NUMBER</span><span class="p">]].</span><span class="nf">select</span><span class="p">{</span> <span class="o">|</span><span class="n">y</span><span class="o">|</span> <span class="n">y</span><span class="p">[</span><span class="no">LENGTH</span><span class="p">].</span><span class="nf">blank?</span> <span class="p">}.</span><span class="nf">first</span><span class="p">[</span><span class="no">DESCRIPTION</span><span class="p">]</span>
  <span class="k">end</span>
<span class="k">end</span></code></pre></figure>

</p>

<p>Now that I've replaced the <code>DESCRIPTION</code> column of each piece of pipe with the corresponding make-up fitting, I can remove the rows of make-up fittings, which, again, don't have a <code>LENGTH</code> value. Then I sort the array by <code>ISO_NUMBER</code>.  This is not necessary, as I can do this in Excel when add this information to our template, but it saves me a step.</p>

<p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">fabrication_pieces_as_array</span><span class="p">.</span><span class="nf">delete_if</span> <span class="p">{</span><span class="o">|</span><span class="n">x</span><span class="o">|</span> <span class="n">x</span><span class="p">[</span><span class="no">LENGTH</span><span class="p">].</span><span class="nf">blank?</span> <span class="n">and</span> <span class="n">iso_pieces</span><span class="p">[</span><span class="n">x</span><span class="p">[</span><span class="no">ISO_NUMBER</span><span class="p">]].</span><span class="nf">size</span> <span class="o">==</span> <span class="mi">2</span><span class="p">}.</span><span class="nf">sort!</span><span class="p">{</span> <span class="o">|</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="o">|</span> <span class="n">x</span><span class="p">[</span><span class="no">ISO_NUMBER</span><span class="p">]</span> <span class="o">&lt;=&gt;</span> <span class="n">y</span><span class="p">[</span><span class="no">ISO_NUMBER</span><span class="p">]</span> <span class="p">}</span></code></pre></figure>

</p>

<p>Lastly, I generate a new CSV with all the pieces and their make-up fittings.  Pieces that have more &gt; 2 components are also listed, but they have not been "combined" together, so I'll resolve them manually. At the bottom of the CSV I also generate a bill of materials, which is a count of each fitting, so the shop knows how many of each to order from the supply house. Ruby's <code>group_by</code> gets all the distinct pieces into a hash, and then it's as simple as getting the <code>size</code> of each key.</p>

<p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="no">CSV</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="s2">"cut-sheets.csv"</span><span class="p">,</span> <span class="s2">"wb"</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">csv</span><span class="o">|</span>
  <span class="n">csv</span> <span class="o">&lt;&lt;</span> <span class="p">[</span><span class="s2">"ISO"</span><span class="p">,</span> <span class="s2">"SIZE"</span><span class="p">,</span> <span class="s2">"QUANTITY"</span><span class="p">,</span> <span class="s2">"LENGTH"</span><span class="p">,</span> <span class="s2">"DESCRIPTION"</span><span class="p">]</span>
  <span class="n">fabrication_pieces_as_array</span><span class="p">.</span><span class="nf">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span> <span class="n">csv</span> <span class="o">&lt;&lt;</span> <span class="p">[</span><span class="n">x</span><span class="p">[</span><span class="no">ISO_NUMBER</span><span class="p">],</span> <span class="n">x</span><span class="p">[</span><span class="no">SIZE</span><span class="p">],</span> <span class="n">x</span><span class="p">[</span><span class="no">QUANTITY</span><span class="p">],</span> <span class="n">x</span><span class="p">[</span><span class="no">LENGTH</span><span class="p">],</span> <span class="n">x</span><span class="p">[</span><span class="no">DESCRIPTION</span><span class="p">]]</span> <span class="p">}</span>
  <span class="n">fabrication_pieces_as_array</span><span class="p">.</span><span class="nf">group_by</span> <span class="p">{</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span> <span class="n">x</span><span class="p">[</span><span class="no">DESCRIPTION</span><span class="p">]</span> <span class="p">}.</span><span class="nf">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">key</span><span class="p">,</span> <span class="n">values</span><span class="o">|</span> <span class="n">csv</span> <span class="o">&lt;&lt;</span> <span class="p">[</span><span class="s2">""</span><span class="p">,</span> <span class="s2">""</span><span class="p">,</span> <span class="n">values</span><span class="p">.</span><span class="nf">size</span><span class="p">,</span> <span class="s2">""</span><span class="p">,</span> <span class="n">key</span><span class="p">]</span> <span class="p">}</span>
<span class="k">end</span></code></pre></figure>

</p>

<p>The finished CSV looks like this:</p>

<p>
<pre>
Iso Number,Size,Quantity,Length,Long Description
R-01,"1-1/4""",1,"9'-6 1/4""","PIPE, S/STD A-53 GRADE B ERW T.B.E."
R-02,"1-1/2""",1,"9'-6 1/4""","1-1/2""x3/4"" TEE REDUCING, THRD"
R-03,"1-1/2""",1,"9'-6 1/4""","1-1/2""x3/4"" TEE REDUCING, THRD"
R-04,"1-1/2""",1,"9'-6 1/4""","1-1/2""x3/4"" TEE REDUCING, THRD"
R-05,"1-1/4""",1,"9'-6 1/4""","1-1/4""x3/4"" TEE REDUCING, THRD"
R-08,"1-1/4""",1,"9'-6 1/4""","1-1/4""x3/4"" TEE REDUCING, THRD"
R-09,"1-1/4""",1,"9'-6 1/4""","1-1/4""x3/4"" TEE REDUCING, THRD"
R-10,"1-1/4""",1,"9'-6 1/4""","1-1/4""x3/4"" TEE REDUCING, THRD"
R-11,"1-1/4""",1,"9'-6 1/4""","1-1/4""x3/4"" TEE REDUCING, THRD"
...
...
"","",3,"","1-1/2""x3/4"" TEE REDUCING, THRD"
"","",8,"","1-1/4""x3/4"" TEE REDUCING, THRD"
"","",9,"","2""x3/4"" TEE REDUCING, THRD"
"","",1,"","2-1/2""x3/4"" TEE REDUCING, THRD"
"","",1,"","2-1/2""x2"" REDUCER, CONC "
"","",1,"","4""x3/4"" THREAD-OLET"
</pre>
</p>

<p>I can plug that into our template, and I am good to go.  Manually, this would take up to an hour depending on how many pieces are on the drawing.  This script takes less than a second.</p>

<p>This is a simple script but it's made my life easier, and I got to write out my thought process, which was fun.  If you have any suggestions for improvements, feel free to reach out.</p>

<h3>See Also</h3>
<p><a href="https://github.com/speric/cut-sheets/">cut-sheets on GitHub</a></p>
</p></p></p>

   ]]></content>
 </entry>
 
 <entry>
   <title>Eager Loading With Authlogic</title>
   <link href="http://ericfarkas.com/posts/eager-loading-with-authlogic"/>
   <updated>2012-08-23T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/eager-loading-with-authlogic</id>
   <content type="html"><![CDATA[
     <p>I've used <a href="https://github.com/binarylogic/authlogic/">authlogic</a> for authentication and session management on a number of projects.  For one application, I wanted to eager-load an association at the time of a successful sign-in.  I thought it'd be helpful to demonstrate the code here, since it took some digging through the documentation and other examples to figure out how to accomplish this.</p>

<p>Basically you want to create a new session within a <code>with_scope</code> block, and pass a <code>find_options</code> hash with whatever options you need.  Here's the <code>create</code> action in the <code>UserSessions</code> controller:</p>

<p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">UserSessionsController</span> <span class="o">&lt;</span> <span class="no">ApplicationController</span>
  
  <span class="k">def</span> <span class="nf">create</span>
    <span class="no">UserSession</span><span class="p">.</span><span class="nf">with_scope</span><span class="p">(</span><span class="ss">:find_options</span> <span class="o">=&gt;</span> <span class="p">{</span><span class="ss">:include</span> <span class="o">=&gt;</span> <span class="ss">:photos</span><span class="p">})</span> <span class="k">do</span>
      <span class="vi">@user_session</span> <span class="o">=</span> <span class="no">UserSession</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">params</span><span class="p">[</span><span class="ss">:user_session</span><span class="p">])</span>
    <span class="k">end</span>
    <span class="k">if</span> <span class="vi">@user_session</span><span class="p">.</span><span class="nf">save</span>
      <span class="n">flash</span><span class="p">[</span><span class="ss">:notice</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"Login successful!"</span>
      <span class="n">redirect_back_or_default</span> <span class="n">account_url</span>
    <span class="k">else</span>
      <span class="n">render</span> <span class="ss">:action</span> <span class="o">=&gt;</span> <span class="ss">:new</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span></code></pre></figure>

</p>

<h3>See Also</h3>
<p><a href="http://rdoc.info/github/binarylogic/authlogic">authlogic documentation</a></p>

   ]]></content>
 </entry>
 
 <entry>
   <title>Global Exception Handling With Bugsnag</title>
   <link href="http://ericfarkas.com/posts/global-exception-handling-with-rails-3-and-bugsnag"/>
   <updated>2012-07-09T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/global-exception-handling-with-rails-3-and-bugsnag</id>
   <content type="html"><![CDATA[
     <p>At <a href="https://talentsoup.com">TalentSoup</a>, we recently launched a new application privately to a number of our trusted customers.  For exception handling, I decided to give <a href="http://bugsnag.com">bugsnag</a> a try.  In the past I've used the <a href="https://github.com/rails/exception_notification">exception_notification</a> gem, and have even rolled my own solution for handling exceptions, but for this new app, I thought I'd do something new. I'm a big fan of leveraging existing "solutions" for common tasks, so I can focus on the core business of the application (see <a href="http://fhwang.net/2012/02/19/Buy-vs-build-for-an-early-stage-startup">Buy-vs-build for an early stage startup</a>).</p>

<p>bugsnag has nice <a href="https://bugsnag.com/docs/notifiers/ruby">documentation</a> to help you get started. What I wanted to do was just catch every exception that's generated by the app, regardless of specific type.  As the app matures and we decide what we want to do in a particular case, we'll handle each exception type differently, but for now, a global catch-all will suffice:</p>

<p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1"># config/initializers/bugsnag.rb</span>
<span class="no">Bugsnag</span><span class="p">.</span><span class="nf">configure</span> <span class="k">do</span> <span class="o">|</span><span class="n">config</span><span class="o">|</span>
  <span class="n">config</span><span class="p">.</span><span class="nf">api_key</span> <span class="o">=</span> <span class="s2">"API_KEY"</span>
  <span class="n">config</span><span class="p">.</span><span class="nf">ignore_classes</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">end</span>

<span class="c1"># app/controllers/application.rb</span>
<span class="k">class</span> <span class="nc">ApplicationController</span> <span class="o">&lt;</span> <span class="no">ActionController</span><span class="o">::</span><span class="no">Base</span>
  <span class="n">rescue_from</span> <span class="no">Exception</span><span class="p">,</span> <span class="ss">:with</span> <span class="o">=&gt;</span> <span class="ss">:handle_public_excepton</span>
  
  <span class="kp">protected</span>

  <span class="k">def</span> <span class="nf">handle_public_excepton</span><span class="p">(</span><span class="n">exception</span><span class="p">)</span>
    <span class="n">render</span> <span class="ss">:template</span> <span class="o">=&gt;</span> <span class="s2">"shared/exception"</span>
  <span class="k">end</span>
<span class="k">end</span></code></pre></figure>

</p>

<p>So we catch every exception, and display a generic error page that lives in <code>app/views/shared/</code>. This wound up being trivial but it was a good excuse to dig into Rails 3 internals and learn about how exceptions are handled within the framework.</p>

<h3>See Also</h3>
<p><a href="http://m.onkey.org/rescue-from-dispatching">rescue_from dispatching</a></p>
<p><a href="https://github.com/rails/rails/blob/master/activesupport/lib/active_support/rescuable.rb">rails/activesupport/lib/active_support/rescuable.rb</a></p>

   ]]></content>
 </entry>
 
 <entry>
   <title>Full-Time/Part-Time Co-Founder Dynamics</title>
   <link href="http://ericfarkas.com/posts/full-time-part-time-co-founder-dynamics"/>
   <updated>2012-06-01T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/full-time-part-time-co-founder-dynamics</id>
   <content type="html"><![CDATA[
     <p>I received a lot of feedback, via <a href="http://news.ycombinator.com/item?id=4044044">Hacker News</a>, Twitter, and email, from my post titled <a href="http://ericfarkas.com/posts/how-to-do-a-startup-on-the-side-and-not-lose-your-family/">How To Do A Startup On The Side And Not Lose Your Family</a>.  Based on that feedback, I have a lot of ideas for future posts.  There are a lot of people out there trying to do the "startup on the side" thing while leading a full family life, and perhaps there hasn't been a lot written specifically for that group.  I do not claim to be an expert, but my experience, limited though it may be, might be helpful for those folks.  This post is about co-founder dynamics, particularly in the case of one co-founder being full-time, the other being part-time.</p>

<p>As with my last post, this is simply my <a href="http://epistemocrat.blogspot.com/">n=1</a> experience.  What follows is not meant to be prescriptive but rather descriptive.  It might seem crazy and foolish but it works for me.</p>

<h3>School of Hard Knocks</h3>
<p>In 2005, 3 of my friends and I created a social networking startup. My 3 co-founders were working on the project full-time.  I had just gotten married, and was one year into a great job as a Java developer at a large bank in NYC, with a baby on the way.  There was no way I was leaving that situation to chase the dream full-time.  So our setup was 3 full-time guys, me part-time, with the expectation that through either revenue or investment, I'd one day be able to work full-time.  I wound up leaving before I had that opportunity, after about 18 months.  I was terrible at balancing work/life/startup, and the strain on my young marriage caused me to neglect working on the startup, which was not fair to my co-founders.  A graceful exit was the best option for all parties.</p>

<p>In 2009 I joined <a href="http://talentsoup.com">TalentSoup</a>.  My co-founder, Rad Harrell, had started the company in 2006, and brought me on board as a technical co-founder.  The setup there was similar: Rad does TalentSoup full-time, it's how he feeds his family.  I do my work part-time.</p>

<p>So that's my experience.  Two startups, both done part-time while my co-founders were full-time.  The first was unsustainable for me, my involvement in the second is still going strong after 2 1/2 years.</p>

<h3>Qualities To Look For In A co-founder</h3>
<p>Before discussing the dynamics of how co-founders work together, let's take a step back and talk about beginning that relationship in the first place.  Much has been written about the qualities to look for in a co-founder, technical or otherwise.  To me, the most important thing is character.  Do they value what I value?  Are their priorities, even if they don't have a family like me, the same as mine?  Do we have common ground on which to relate to one another, and understand each other?  Is this person not only trustworthy, but open and honest?  These are not trivial concerns.  Doing a startup is very similar to a marriage in that, in many ways, you are sharing a part of your soul with another person.  Anything that you find mildly annoying or grating about the other person will certainly show up, magnified 1,000 times, in a co-founder relationship, especially one that takes place in the context of having a family and other external pressures.</p>

<p>Trusthworthiness, which is the part of character that's the most important to me, is a tricky thing to test for.  I've lived and worked in New York my whole life, and as a result I've developed stereotypical New York cynicism.  I default to "I'm not buying it".  This cynicism, while sometimes harmful in other areas, is absolutely an asset for testing trustworthiness.  When someone speaks to me, does my instinct incline me to believe them, or dismiss what they're saying?  I think I have a good instinct for that kind of stuff, developed over time, having heard dozens of startup ideas and talked to countless people.</p>

<p>This came in handy when I first spoke to Rad.  We had a phone conversation for an hour, and he pitched me on the project.  He was open about everything: the past, the current state of the company in all areas,  what his vision for the future was, and what he was willing to give to get me on board.  There was a recognition that I would be the technology lead, that his expertise was limited in that area, and I'd have freedom to do what I felt needed to be done.  You might think that's too much information to give in a first discussion, but his openness, as well as my gut telling me that this guy was being absolutely real with me, endeared me to him.  I remember telling my wife that I liked Rad so much after that call, I felt like I wanted to do the startup just to see him succeed, never mind what would be in it for me.</p>

<p>This whole trust thing is the cornerstone to the whole co-founder relationship.  As you'll see shortly.</p>

<h3>The Dirty Details</h3>
<p>So now you've found a co-founder.  If both of you are going to work full-time, it's pretty easy to decide you'll split the equity somewhere around 50/50.  But what if one of you works full-time while the other works part-time?  How do you split equity? This is where things get tricky.</p>

<p>Keep this in mind: your number one goal in a startup is to ship something people want.  Especially in the early stages, work has to happen at a fast and furious pace.  You are in constant shipping mode.  Whenever you're actually sitting down, working on your startup, a couple of hours wasted on anything other than shipping code is a disaster. Keeping this in mind will help in two ways when deciding equity splits:</p>
<ul>
    <li><p>Even though figuring this split out is very important, it's not the most important thing.</p></li>
    <li><p>When you're spending energy on anything in an early startup (including equity splits), you're asking: "How will this help me ship code?"</p></li>
</ul>

<p>That second point often gets lost in the mix when these discussions take place.  I've seen things like this: <i>"I'm full-time and I get X%, my part-time co-founder gets Y%, and when he goes full-time, I'll have X-10% and he'll get Y+10%"</i>.  I've been the guy on the other side of that equation, and I can tell you that it doesn't motivate me to know that I get more equity if I am full-time.  In fact, I think knowing that there's more % waiting for me if I can just cross the full-time chasm actually stresses me out, which affects me emotionally, which affects me mentally, which negatively impacts my ability to...wait for it...ship code.  Call me weak-minded but that's how I'm wired.  You might be different; n=1.  Maybe the aforementioned approach works for your personality type, in which case, do it!</p>

<p>So whatever you are thinking the percentage splits are, might I suggest just making them that way from the start?  Of course everyone should be vested, and the appropriate contractual steps should be taken to ensure everyone's backs are covered.  But if, as the full-time guy, you really trust your co-founder, and really trust that he's working as hard as he can to make the company a success, then why not start with whatever your "when you're full-time" percentage is?  If you can't trust your co-founder, then maybe you should find another one.</p>

<p>Notice I am not suggesting hard and fast percentage amounts.  There are alot of considerations: which one is the technical co-founder, and therefore actually building the product?  Are both?  Are neither?  Has either partner invested money into the company for bootstrapping?  Is the business existing and profitable already? In these discussions, be open and honest with your wants.</p>

<p>It comes down to this: the equity split shouldn't be used a carrot on a stick, but rather as a tool to create good morale for the people involved in the startup.  By all means, vest, and CYA with contracts, etc., but at the end of the day, you either trust your partner or you don't.</p>

<h3>Actual Working</h3>

<p>You have a co-founder, and you have all the equity stuff worked out so you'll know how many millions you'll get when Google acquires you.  You want your Ferrari in red, right?  With black leather?  Sure, we can do that.</p>

<p>Now you get to work.  You hustle and make the most of all the time you have, balancing as you go.  You make use of things like <a href="http://basecamp.com">Basecamp</a>, <a href="http://campfirenow.com/">Campfire</a>, iChat, text messages, etc. to communicate asynchronously.  And you don't IM your partner about a bug, you open a new issue in <a href="http://github.com">GitHub</a> so he can look at it when it's convenient for him, and you both have a log to refer back to.  If you're a non-technical co-founder, you learn basic HTML so you can do copy work on the site, and you learn how git works so you can be involved.  Spencer Fry wrote a <a href="http://spencerfry.com/whats-a-non-programmer-to-do">great post</a> about this a while back.  If you're the technical guy, you look at how you can make your co-founder's life easier through automating common admin tasks. Most of all, you...chill out.  If your co-founder takes a night, or two, or three off, it's ok.  Because you trust him.  He's not "deceiving me by not working for his fair share", he's doing what he needs to do, and when he gets back you know he's going to kill it.</p>

<p>TalentSoup was an existing business making money when I joined, but it was not a freestanding entity.  That's changed.  We've automated many of the administrative tasks around the site, things Rad was doing manually, or tasks he wanted to do but could not.  This increased efficiencies, meaning we could do more work in less time, and therefore make more money because we could handle more jobs simultanenously.  We could focus on serving clients and not on the tedious stuff.  I also conceived and implemented our paid subscription service, <a href="https://talentsoup.com/signup">Webcomp Pro</a>, which created a new revenue stream.  In other words, I am not just building features that Rad dreamt up.  I am actively involved in product development, short-term and long-term, always on the lookout to create revenue through increasing our efficiency, or introducing a new product.  I am a partner in the business, with an equity state that makes me happy and frees me to think about shipping code, not chasing a carrot.</p>

<p>Flexibility in the when and where is also very important.  Don't set a "minimum expected hours per week".  If you're working with someone who has a full-time job and family, and you add the expectation of X amount of hours per week on top of that to justify an equity percentage, it's going to be more harmful than helpful.  I speak from personal experience, being that family guy.  Now of course, if over the long term your partner is not pulling their weight, then you say what needs to be said, or do what needs to be done.  But I like the idea of judging based on results only.  If I am consistently shipping code that customers are using, and we are making money, does it matter how many hours I worked last week, or that I worked those hours in my boxers in bed late at night while everyone is sleeping?  No, it does not.  Ship code.  Everything else is details.</p>

<p>You also celebrate success, however small.  New feature launched?  Let's have some beers together over iChat.  First paying customer? Alright!  Our 1,000th user just signed up?  Let's take the night off and take our wives out.  Working asynchronously, in different locations (Rad is in beautiful Savannah, GA and I am on Long Island), means you have to be intentional about building the camraderie that being in the same room would normally bring.  It's not easy, but it can be done.  Sometimes I laugh at myself for the ridiculous things I celebrate, like fixing an annoying bug or changing the layout of a page, but then I remember these small celebrations are necessary because they give me an emotional boost, which helps me ship code.</p>

<h3>Choose Your Own Adventure</h3>
<p>I was on a job interview once, and the person interviewing me asked what I consider success to be, just generally, not necessarily with relation to work, though it could be that.  Whatever came into my mind.  My honest answer was that success to me meant having a strong marriage, and children who grow up to love me and love God as well.  I was kind of surprised by my answer.  Before any business achievement, that's how I define success.  And given that, my relationship with my co-founder makes perfect sense.  And he is the same way (step 1: same values).  We want TalentSoup to succeed financially.  I want to make a lot of money; I am not embarrassed about that.  But more than that I want to have a strong family, I want to live a good life and enjoy it.  So I work hard, yes, but I also remember to relax and slow down.  I don't stress about what Rad is or isn't doing, because I trust him, and he trusts me.  If something needs to be said, either of us would say it.  And if things completely broke down, there are legal structures in place to protect both of us.  But I don't operate out of that.  I operate on the assumption that we're both trying to build something beautiful together, in good faith, and if over a short period of time life gets in the way, that's ok.</p>

<p>If you're doing a startup on the side while you have a family, you're already choosing a difficult path.  Don't make it worse by partnering up with someone you can't trust.</p>

   ]]></content>
 </entry>
 
 <entry>
   <title>How To Do A Startup On The Side And Not Lose Your Family</title>
   <link href="http://ericfarkas.com/posts/how-to-do-a-startup-on-the-side-and-not-lose-your-family"/>
   <updated>2012-05-30T00:00:00+00:00</updated>
   <id>http://ericfarkas.com/posts/how-to-do-a-startup-on-the-side-and-not-lose-your-family</id>
   <content type="html"><![CDATA[
     <p>In October 2009, I joined <a href="https://talentsoup.com">TalentSoup</a>, as the technical co-founder and lead developer.  There's a really crazy story about how I wound up finding Rad Harrell and TalentSoup, but in short, I answered a call for help in <a href="https://twitter.com/#!/human3rror/status/4367475923">this tweet</a> and the rest is my history.  Oh, and the first thing I did when I joined TalentSoup was ditch Drupal for Rails.</p>

<h3>My So-Called Life</h3>
<p>I was at the time, and still am, gainfully employed as a mechanical draftsman for a large and well respected HVAC contractor whose work is mainly in the 5 boroughs of NYC.  The story of how a guy who has been programming since the age of 12, has a BS in Comp Sci and spent the early part of his career as a developer in the financial industry ended up doing mechanical drafting is also a long story, but one for another day.</p>

<p>As of this writing, I am 29 years old.  I am the married father of three great kids.  I have a mortgage.  In addition to all of that, and my full-time job as a draftsman, and TalentSoup on nights and weekends, I have the following obligations and interests:
<ul>
<li><p>Elder at <a href="http://trinitychurchlongisland.com">Trinity Church</a>, where I also help teach Sunday School</p></li>
<li><p>I enjoy <a href="http://rivendellcraftbrewery.com">homebrewing</a></p></li>
<li><p>I try to read as much as time allows on wide range of subjects</p></li>
<li><p>Watching Chelsea FC (an emotionally traumatic experience lately)</p></li>
<li><p>Work out regularly (<a href="http://www.flexcart.com/members/elitefts/default.asp?pid=2976">5/3/1</a> or <a href="http://gymjones.com">Gym Jones</a>-style)</p></li>
</ul>
<p>Not to mention generally hanging out and enjoying "the good life".  I also have very strong convictions about not doing or thinking about work on Sundays.  So if a day is 24 hours, and I need to sleep at least 6-8 of them, and I only really have 6 days of the week in which to do all of the aforementioned "stuff", how do I fulfill all my obligations?</p>

<p>What follows is my own <a href="http://epistemocrat.blogspot.com/">n=1</a> experience.  Every person, family, and life situation is different. Here's what's worked for me and helped me bootstrap a debt free, profitable company while having a day job, a family, and a life outside of programming.</p>

<h3>Buy-In</h3>
<p>By far the biggest win in my situation is the support of my wife.  She not only tolerates my involvement in a startup, she actively supports me and roots for me.  She wants to see us succeed.  She knows and loves my co-founder and his family.  She asks about the business, unprompted.  All of these things together make the situation workable.  Without her support, there's no way I could do a startup and have a healthy marriage and family life.</p>

<h3>Priorities: How Do They Work?</h3>
<p>Spousal/SO support is the first step.  The second step is just as important, and closely related: establishing priorities.  Every post I've ever read about doing startups with a family talks about establishing priorities, but the actual process of doing so is taken for granted.  I don't think it should be.  Again, this is n=1 for me, but I've learned to go about making priorities by thinking about my life in this following manner:</p>

<code>inner life -&gt; relationships -&gt; provision -&gt; employment -&gt; obligations -&gt; startup -&gt; enjoyment</code>

<h3>Inner Life</h3>
<p>The book of Proverbs says "Keep your heart with all vigilance, for from it flow the springs of life" (<a href="http://www.biblegateway.com/passage/?search=Proverbs+4%3A23&amp;version=ESV">4:23</a>).  Everything I do in life is affected by the state of my heart.  Am I depressed?  Happy?  Anxious?  Angry?  All of these heart conditions affect the way I interface with my wife, kids, friends, co-workers; they affect the way I do my work and my outlook on life in general.  It's a virtuous/vicious cycle: the happier (or more depressed) I am, the better (or worse) I work and live, which makes me happier (or more depressed).  Therefore my first priority is to "keep my heart".  I do this through prayer, meditation, and Scripture reading, and by regularly being part of worship.</p>

<h3>Relationships</h3>
<p>In reality, those categories mentioned above are not water-tight.  They spill over into each other, going up and down the chain.  My inner life affects everything that comes after it, but that doesn't mean my work doesn't affect my inner life.  With that said, I next consider relationships, the most important being with my wife, and after that with my children.  Even with my wife's support, there are times when she needs personal time with me.  A common text message I send to my business partner is "Nikki needs a night, I'll see you tomorrow".  We'll get some good Belgian ale, make popcorn, and watch a movie.  A simple night, but we reconnect, and that's important.  There has to be a give and take.</p>

<p>Time with my kids, especially at their young ages, is important as well.  I have a lot of room to improve in this area, but the best advice I can give when it comes to time with your kids is "be present".  It's so easy to be with my kids physically, but mentally be thinking about a bug that needs fixing, or a feature I'm in the middle of working on.  It takes intentional effort to be mentally present.  One thing that's helped is taking notes throughout the day, either with <a href="http://fieldnotesbrand.com/">Field Notes</a> or in <a href="http://basecamp.com/">Basecamp</a>.  Being diligent in this regard means I'm less stressed about losing an idea or thought while I'm away from my computer.  When the kids are asleep, I can just check on the notes I've left myself throughout the day.</p>

<h3>Provision &amp; Employment</h3>
<p>These two are so closely related, they warrant being discussed together. As a man, with a family depending on me, I have to be sure I am providing for them, materially.  This means food on the table, clothes on their backs, heat in the winter, etc.  The primary means of doing this is via a regular job, which I have.  Being that my day job provides most of the money my family depends on, I need to make sure my startup pursuits do not affect my day job.  When I am in the office, I am working hard.  That means not working on startup work on my boss' dime.  It also means being mentally present at work as well. </p>

<h3>Obligations</h3>
<p>Responsibilities that I have that fall outside of the employment/provision spectrum would be something like be an elder at Trinity.  Right now, being an elder is the only thing I do that falls in this category, and most of my elder work (besides a meeting once a month) can take place at home through email or on the phone.  But this work is something my family and I highly value, and are committed to.</p>

<h3>Startup</h3>
<p>Turns out that the thing which occupies my mind (and my dreams) most of the time is, in reality, further down on the priority chain than you'd have thought.  Not much really to say here.  If you've read this far, you know what doing a startup is like.</p>

<h3>Enjoyment</h3>
<p>This is a catch-all for any activity I enjoy that, while personally fulfilling, is spent apart from my family and/or does not contribute to the provision need mentioned earlier.  Working out, reading, etc.  Again, enjoyments are one way to improve my inner life, so even though this is last on the list, it's also important, but not as important.</p>

<h3>Tying It Together</h3>
<p>So now I have my priorities, listed in my order of importance.  Realizing that they are all related, I nevertheless run every opportunity through the priority framework, and ask the question: where does it fit?  Given what's been going on in my life in the last couple of days/weeks/months, can I pursue this opportunity without harming something higher up the priority chain?  For example, I enjoy playing soccer.  My brother and his buddies regularly play on Saturday mornings at a high school not far from my house.  Most weeks, given how busy things normally are, I would not be able to justify spending a Saturday morning away from my kids doing something like that.  It doesn't contribute to anything above "enjoyment" in the priority chain, and whatever small "inner life" benefit I'd get by playing soccer would be negated by the harm it'd do to my relationship with my wife and children, knowing that dad had a free Saturday morning but spent it kicking a ball around instead of taking us out to breakfast.</p>

<p>There are times, however, when for some reason I've been able to spend a good amount of time with my kids during the week, and taking a few hours to play soccer on a Saturday isn't a big deal.  It's a play-it-by-ear situation.  But most of the time, if I have free time, I try and spend it with my family instead of for myself.</p>

<p>I also have to turn down some legitimate provision opportunities as well because of the harm they'd do to my relationships.  A full-time job and part-time startup take up a lot of energy, and adding something like a short-term consulting project to the mix, even though it may pay well, is something I can't do.  In the last year I've turned down 3 such opportunities.</p>

<p>Likewise, there are some jobs I wouldn't take because of the impact it'd have on my family life.  Things like consistently long hours (in a day job) are a deal breaker for me.  That might disqualify me for a job at many web startups, and that's OK with me.  Marco Arment recently had a great post titled <a href="http://www.marco.org/2012/05/24/old-farts">Old Farts Know How To Code</a> that sums up my feelings on the matter.</p>

<h3>Practical Tips</h3>
<ul>
	<li><p>Get your spouse or SO's buy-in.  Until that happens, I'd suggest not going forward.</p></li>
	<li><p>Take time to focus on your inner life, in whatever way makes sense to you.</p></li>
	<li><p>When you're with your family or friends, "be there" mentally.  Chances are, that bug or feature can wait.</p></li>
	<li><p>Beg, borrow, and steal...time.  I've started bringing my laptop to my day job, so I can work on TalentSoup during lunch.  That's 5 extra hours a week.  Sometimes I wake up early and work before my day job.  Many nights I stay up late so I can work when everyone's asleep, without taking time away from my family.</p></li>
	<li><p>Something has to give, and it's usually your hobbies.  I've made a rule that if I do not workout in the morning before my day job, then I can't work out for the rest of the day.  This forces me to pursue my "hobby" on my time, so I don't take time away from my family or startup.</p></li>
	<li><p>On a regular basis, leave the laptop on your desk and take your kids out for ice cream, or go for a walk around the neighborhood.  Life is short, and you don't get these years back. Be flexible.</p></li>
	<li><p>Turn off the iPhone.  Easier said than done, and I guarantee I am a worse offender than you.  But it needs to be done.</p></li>
</ul>
<p>I certainly do not keep these guidelines as well as I should.  But I am learning, and I'm a lot better at balancing my time now than I have been in the past.</p>
</p>

   ]]></content>
 </entry>
 
</feed>
