<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>The Hippy Hacker</title>
    <link>http://evan.tiggerpalace.com/rss/</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>On spreading heavenly glory</description>
    
    
        <item>
          <title>Emacs: A strange new world (Part 1 of many)</title>
          <description>&lt;p&gt;I often find, when adopting a new tool or language, to try to learn how to use it as it was meant to be used.  Sure you could write Ruby code like a Java developer but far better to write Ruby like a Ruby developer.  Idiom\
s matter.                                                                                                                                                                                                                      &lt;/p&gt;

&lt;p&gt;To that end, lets approach Emacs as a beginner with few preconceived notions from VIM. I&amp;#8217;m not suggesting that you forget all of the lovely features that you enjoyed in VIM but instead that you should start with the basics\
 and build up from there.                                                                                                                                                                                                      &lt;/p&gt;

&lt;p&gt;So to begin at the beginning:                                                                                                                                                                                                  &lt;/p&gt;

&lt;p&gt;A quick google led me to Emacs&amp;#8217;s built-in tutorial: &lt;code&gt;C-h t&lt;/code&gt;.  The built-in tutorial is a fantastic place to start.  I found it more accessible, due to its narrow focus, than vim&amp;#8217;s.  That said, the tutorial will \
give you just enough to be comfortable with simple navigation within emacs.                                                                                                                                                    &lt;/p&gt;

&lt;p&gt;Among the many features the tutorial will introduce you to is &amp;#8220;help on help&amp;#8221;: &lt;code&gt;C-h C-h&lt;/code&gt; is perhaps your best friend.  From there, emacs provides several different avenues to discover new functionality and elabor\
ate upon what you will learn.                                                                                                                                                                                                  &lt;/p&gt;

&lt;h2&gt;Help yourself!&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;C-h C-h&lt;/code&gt;: help on help, literally. This function gives a summary of all of the built in help features and the keybindings to invoke them directly.                                                               &lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-h b&lt;/code&gt;: list all keybindings.                                                                                                                                                                                    &lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-h c&lt;/code&gt;: display the function run by a specific keybinding                                                                                                                                                        &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Copying, yanking, pasting, deleting, and killing&lt;/h2&gt;

&lt;p&gt;As a newly-minted Emacs user, you&amp;#8217;re probably wondering how to yank and delete.  Be warned &amp;#8220;yank&amp;#8221; means exactly the opposite in Emacs as it does in VIM.  Wacky, right?                                                        &lt;/p&gt;

&lt;p&gt;In VIM, you yanked/deleted text and then pasted it.  With Emacs, you &amp;#8220;copy&amp;#8221; or &amp;#8220;kill&amp;#8221; text then &lt;a href=&quot;#yanking&quot;&gt;&amp;#8220;yank&amp;#8221;&lt;/a&gt; it into place.&lt;/p&gt;

&lt;p&gt;With all of this in mind, let&amp;#8217;s turn to our new friend &lt;code&gt;C-h b&lt;/code&gt;.                                                                                                                                                     &lt;/p&gt;

&lt;h2&gt;Text search&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;C-s RET &lt;search text&gt;&lt;/code&gt;: This puts you in interactive search mode (which, frankly, at this point, I&amp;#8217;ve far from mastered).  At its most basic, interactive search will navigate you forward through your current bu\
ffer toward the first matching characters.  Subsequent presses of &lt;code&gt;C-s&lt;/code&gt; will lead you to matches further forward in the buffer and then eventually wrap to the top of the buffer.                                   &lt;/p&gt;

&lt;h2&gt;Discovering functions&lt;/h2&gt;

&lt;p&gt;My first big “Ah ha” moment with emacs came when I realized that I could use to invoke any &lt;a href=&quot;#interactive&quot;&gt;“interactive”&lt;/a&gt; functions in emacs.  That is, you enter &lt;code&gt;M-x&lt;/code&gt; then begin typing the name of a function.  Aft\
er a few letters, if you hit return, emacs opens a window showing you all of the matching function names.                                                                                                                      &lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;yanking&quot;/&gt;yanking&lt;/a&gt;: I&amp;#8217;m sure there&amp;#8217;s a scholarly article somewhere in uncovering the history of yanking in the *NIX community but I will leave that as an exercise for the extremely atypical readers.&lt;br/&gt;
&lt;a name=&quot;interactive&quot;/&gt;interactive&lt;/a&gt;: functions are emacs lisp functions containing a call to the &amp;#8220;interactive&amp;#8221; function thus informing Emacs that they may be invoked interactively.                                                                                                            &lt;/p&gt;</description>
          <pubDate>Wed, 24 Apr 2013 12:00:19 GMT</pubDate>
          <guid>http://evan.tiggerpalace.com/articles/2013/04/24/emacs-a-strange-new-world-part-1-of-many/</guid>
          <link>http://evan.tiggerpalace.com/articles/2013/04/24/emacs-a-strange-new-world-part-1-of-many/</link>
        </item>
    
        <item>
          <title>Modality kills (or how I learned to love emacs and stop swearing at tmux)</title>
          <description>&lt;p&gt;I&amp;#8217;m an Emacs switcher.&lt;/p&gt;

&lt;p&gt;There. I&amp;#8217;m out of the closet.&lt;/p&gt;

&lt;p&gt;After 18 long years of vi, I finally switched to emacs.  Despite many attempted explanations in &amp;lt;= 140 characters and numerous requests, I&amp;#8217;ve relented and written this to explain why.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve been a remote worker for over 4 years now.  But, as an extrovert (yes, I&amp;#8217;m freakish that way as a developer), I love to pair program.  I&amp;#8217;ve &lt;a href=&quot;http://evan.tiggerpalace.com/articles/2011/10/17/some-people-call-me-the-remote-pairing-guy-/&quot;&gt;blogged about my pair-programming tool chain in the past&lt;/a&gt;.  That tool chain has continued to evolve.  The crucial point: I need to live in my shell to remote pair as I do.&lt;/p&gt;

&lt;p&gt;And most recently, I learned that modality kills.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i0.kym-cdn.com/entries/icons/original/000/010/692/19789999.jpg&quot;&gt;&lt;/img&gt;&lt;/p&gt;

&lt;p&gt;VI is modal. Tmux, my preferred terminal multiplexer, is also modal.&lt;/p&gt;

&lt;p&gt;modal * modal = modality&lt;sup&gt;2&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Put another way, usability goes straight to hell.&lt;/p&gt;

&lt;p&gt;So here I am, minding my own business, writing some code in VI.  When, all of a sudden, I decide that I want to switch to my terminal running in the other window in my vertically split tmux session.  So I switch windows and try to scroll up with &lt;code&gt;Ctrl-u&lt;/code&gt;.  What the hell?  Why doesn&amp;#8217;t this work?  &lt;code&gt;Ctrl-u Ctrl-u Ctrl-u&lt;/code&gt; dammit!&lt;/p&gt;

&lt;p&gt;Oh. Right. I&amp;#8217;m in tmux. &lt;code&gt;Ctrl-b [ Ctrl-u&lt;/code&gt; works. Finally.&lt;/p&gt;

&lt;p&gt;Now repeat this a few hundred times.&lt;/p&gt;

&lt;p&gt;(Much cursing at VI and tmux have been elided here to reduce your enjoyment of this article.)&lt;/p&gt;

&lt;p&gt;The basal ganglia, physical memory, doesn&amp;#8217;t understand this modal shit.  You&amp;#8217;re doing something.  Then you&amp;#8217;re doing something similar.  It should work pretty much the same way, dammit.  If I&amp;#8217;m banging around in a terminal or hunting a sabertooth tiger the mental model should remain consistent.  But, oh, that&amp;#8217;s right: digital reality has little basis in the real world.  Unfortunately, our brains just don&amp;#8217;t quite get that.&lt;/p&gt;

&lt;p&gt;And, dammit, modality makes all of that worse.&lt;/p&gt;

&lt;p&gt;Sure, I learned to cope with VIs modality. Sort of.  Let&amp;#8217;s be honest, VI users.  You &lt;strong&gt;know&lt;/strong&gt; that you frequently are in command mode when you thought you were in insert mode and vice versa.  But you develop coping strategies.  Then you almost forget that you&amp;#8217;re using them.&lt;/p&gt;

&lt;p&gt;Now imagine having to have habits to cope with making that same mistake but in a shell within tmux instead of the VI session that you thought you were in.&lt;/p&gt;

&lt;p&gt;Down this path lies madness.&lt;/p&gt;

&lt;p&gt;And, so, I found my way to emacs.  Emacs gives you eshell for standard: a LISP-based terminal emulator.  ansi-term is a small step up from eshell.  But I still found myself having problems with it.  Then my friend Avdi Grimm pointed me at multi-term.  I have been happy ever since.&lt;/p&gt;

&lt;p&gt;You see, multi-term is a &amp;#8220;major mode&amp;#8221; of emacs.  While it does commandeer a great many of the ordinary key bindings, at least I can scroll up or search through a multi-term history the same way that I would any ordinary emacs buffer.  Though, for the life of me, I cannot understand why scroll down automatically throws me back to the prompt instead of actually scrolling down.&lt;/p&gt;

&lt;p&gt;Oh, did I mention that emacs has an actual programming language, emacs lisp, instead of the vim&amp;#8217;s sadomasochistic vision of hell known as vimscript?&lt;/p&gt;

&lt;p&gt;Yes, I still use tmux.  But now I solely use tmux per its name: as a terminal multiplexer.  I don&amp;#8217;t need to create windows: emacs gives me that.  I don&amp;#8217;t search within tmux sessions: emacs gives me that.  Tmux barely matters any more except for facilitating sharing my session with another user.  And that&amp;#8217;s about it.&lt;/p&gt;

&lt;p&gt;In case you&amp;#8217;re deeply concerned about the productivity hit, I was running at about 75% or so after just a few days.&lt;/p&gt;

&lt;p&gt;If you remote pair and live in the shell, you owe it to yourself: switch to emacs.&lt;/p&gt;</description>
          <pubDate>Mon, 11 Feb 2013 12:36:00 GMT</pubDate>
          <guid>http://evan.tiggerpalace.com/articles/2013/02/11/modality-kills-or-how-i-learned-to-love-emacs-and-stop-swearing-at-tmux/</guid>
          <link>http://evan.tiggerpalace.com/articles/2013/02/11/modality-kills-or-how-i-learned-to-love-emacs-and-stop-swearing-at-tmux/</link>
        </item>
    
        <item>
          <title>Conciseness > Verbosity > Leaky </title>
          <description>&lt;p&gt;Naming is one of those two well known problems in computer science.&lt;/p&gt;

&lt;p&gt;It is key to abstraction.  An abstraction with a poor name will often be misunderstood.&lt;/p&gt;

&lt;p&gt;As I teach myself Clojure, I find myself reflecting on all of the functional code that I&amp;#8217;ve seen in my career: the Lisp, Haskell, Erlang, and Clojure.&lt;/p&gt;

&lt;p&gt;There is a single common thread through them all that troubles me: the names chosen for their core library.  There&amp;#8217;s a terseness to all of them.  It makes for a steeper learning curve.  However, for some aspiring functional programmers, the curve may be so steep as to be exclusionary.&lt;/p&gt;

&lt;p&gt;Some examples&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;foldl/foldr (Haskell)&lt;/li&gt;
&lt;li&gt;conj (Clojure)&lt;/li&gt;
&lt;li&gt;car / cdr (Lisp)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lisp, as the grand-daddy of functional languages, perhaps set the trend.  Lisp functions names tend toward the spartan and terse.  More recent functional languages perhaps follow suit.&lt;/p&gt;

&lt;p&gt;The core functions outline the idiomatic use of the language.  And, so, most functional programs I&amp;#8217;ve seen have a strong tendency toward abbreviated names for their functions and their variables.&lt;/p&gt;

&lt;p&gt;I fail to see how this is a good thing.&lt;/p&gt;

&lt;p&gt;I can hear them now: &amp;#8220;But, Evan, you&amp;#8217;re a pathetic C/Java/Ruby programmer who has only dabbled in functional programming.  You just don&amp;#8217;t understand.&amp;#8221;&lt;/p&gt;

&lt;p&gt;What am I missing here?  We&amp;#8217;re far from the world where programmers may have measure code in byte sizes due to storage constraints.  Can we all agree then, in this modern age, that we can stop fussing over saving bytes and just use meaningful (in the literal interpretation: full of meaning) names?&lt;/p&gt;

&lt;p&gt;While I prefer conciseness, I&amp;#8217;ll gladly take verbosity in its absence.  Either are better than a name so terse that it results in a leaky abstraction!&lt;/p&gt;</description>
          <pubDate>Mon, 17 Dec 2012 19:50:03 GMT</pubDate>
          <guid>http://evan.tiggerpalace.com/articles/2012/12/17/conciseness-verbosity-leaky/</guid>
          <link>http://evan.tiggerpalace.com/articles/2012/12/17/conciseness-verbosity-leaky/</link>
        </item>
    
        <item>
          <title>Use Rails until it hurts</title>
          <description>&lt;p&gt;Over the past year, there has been a strong popular push toward what I&amp;#8217;ll describe as purely &lt;a href=&quot;http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod&quot;&gt;SOLID-based&lt;/a&gt; approaches to building Rails apps.  While I attempt to adhere to SOLID as a series of guidelines, they are just that: guidelines.&lt;/p&gt;

&lt;p&gt;Evidently, once, someone caught me saying &amp;#8220;Use Rails until it hurts&amp;#8221;.  By this, I meant &amp;#8220;don&amp;#8217;t preemptively implement around perceived Rails weaknesses solely to respect SOLID/your-favorite-OO-principle&amp;#8221;.  This does not add value to an application.&lt;/p&gt;

&lt;p&gt;I recently wrote about &lt;a href=&quot;http://evan.tiggerpalace.com/articles/2012/11/07/accepts_nested_attributes_for-often-considered-harmful/&quot;&gt;#accepts_nested_attributes_for&lt;/a&gt;.  In that post, I explained that there are clear circumstances where #accepts_nested_attributes_for will save you time and code.  However, in many cases, it won&amp;#8217;t.  And, for those, I began working on an alternative.&lt;/p&gt;

&lt;p&gt;Contingencies are good.  Once you deviate from Rails&amp;#8217; &amp;#8220;golden path&amp;#8221;, your work can quickly become challenging.  But knowing that a person/tool/technique has a weakness does not mean that you automatically preempt them.  It means that you should remain aware of that weakness.  You should compensate for weakness when it becomes an issue.  To do so sooner smacks of angst.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s consider the discussion &lt;a href=&quot;http://devblog.avdi.org/2012/11/12/rubytapas-episode-21-domain-model-events/&quot;&gt;here&lt;/a&gt; around the &lt;a href=&quot;http://c2.com/cgi/wiki?ObserverPattern&quot;&gt;Observer pattern&lt;/a&gt; versus the benefit of a tightly coupled imperative style.  The Observer pattern decouples event producers from event consumers.  For that matter, the Observer pattern is similar to Queue-based messaging services such as the &lt;a href=&quot;http://doc.omg.org/formal/04-10-11.pdf&quot;&gt;CORBA Notification Service&lt;/a&gt;, &lt;a href=&quot;http://docs.oracle.com/cd/E19957-01/816-5904-10/816-5904-10.pdf&quot;&gt;Java Messaging Service(JMS)&lt;/a&gt;, and all of those that followed save that it is, typically, implemented in a synchronous fashion and within a single process.&lt;/p&gt;

&lt;p&gt;As cited in the C2 wiki, the Observer pattern is best used for &amp;#8220;dynamic relationships between objects.&amp;#8221;  There are relatively clear guidelines around when to consider employing it.&lt;/p&gt;

&lt;p&gt;So what about when relationships are not dynamic?&lt;/p&gt;

&lt;p&gt;Under these circumstances, I posit that tight coupling can be helpful.&lt;/p&gt;

&lt;p&gt;What is tight coupling good for?  Used selectively, in a word: clarity.&lt;/p&gt;

&lt;p&gt;Which is clearer? (Please bear with my non-ActiveRecord ActiveRecord example for the sake of argument)&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/4127337.js?file=harder.rb&quot;&gt;&lt;/script&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/4127329.js?file=simpler.rb&quot;&gt;&lt;/script&gt;

&lt;p&gt;The Observer (listener)-based example at the top decouples the &lt;em&gt;save&lt;/em&gt; event from the &lt;em&gt;pushing the change to the client&lt;/em&gt; event.  While you can argue that these are two different responsibilties, they are both directly related to the change on the User&amp;#8217;s name.  I argue that this approach adds unecessary indirection.&lt;/p&gt;

&lt;p&gt;To speak more broadly, I argue that our campaign against tight coupling has simply gone too far.&lt;/p&gt;

&lt;p&gt;In the latter case, we have less code!  This is, often, considered a good thing&lt;sup&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. The controller, responsible for performing the change to the User object, also pushes a notification to the client of the change. The tight coupling makes this entirely clear: &lt;strong&gt;when I change the user&amp;#8217;s name and save the user, &lt;em&gt;I immediately push the change out on a socket to the client&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Yes, you can make a case for extracting the behavior from the UserController#update method into its own method or even class.&lt;/p&gt;

&lt;p&gt;Whether to extract the logic out of the controller or not should be a fuzzy decision.  Yes, the update method is clearly responsible for more than just routing.  This is &amp;#8220;bad&amp;#8221;, right?  Or is it?&lt;/p&gt;

&lt;p&gt;If we extract a class to represent the context of the User&amp;#8217;s name changing, we&amp;#8217;ve just created another file and another class.  Also, where does this class go?  To me, it&amp;#8217;s just a delegate of the controller.  It&amp;#8217;s certainly not business logic.  Pushing a message out on a socket does not represent business logic at all.  Instead, it&amp;#8217;s just how we interface with our View/Client.  Extracting a class, in this case, increases the cognitive burden on ourselves or any developer who comes after us.&lt;/p&gt;

&lt;p&gt;If we extract a private method instead of extracting a class, we&amp;#8217;ve added a layer of indirection instead of abstraction.  Frankly, I&amp;#8217;d lean toward something like this.&lt;/p&gt;

&lt;p&gt;But, clearly, this will lead to a fat controller!  ¡Qué terrible!&lt;/p&gt;

&lt;p&gt;Personally, I would instead characterize it as a controller of a healthy weight.&lt;/p&gt;

&lt;p&gt;Moderation is key.  Noticing its lack is as well.&lt;/p&gt;

&lt;p&gt;I hope that, from the above example, you&amp;#8217;ve decided to stop factoring everything into another class and, occasionally, give tight coupling a chance. That said, if you&amp;#8217;re among those who write &amp;#8220;god classes&amp;#8221;, &amp;#8220;god methods&amp;#8221;, and is unfmiliar with &amp;#8220;loose coupling&amp;#8221;, I strongly suggest reading &lt;a href=&quot;http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052&quot;&gt;Working With Legacy Code&lt;/a&gt; by Michael Feathers (the man who coined &amp;#8220;SOLID&amp;#8221;).&lt;/p&gt;

&lt;p&gt;Rails isn&amp;#8217;t perfect. But it is one of the best solutions for the problem space that most of us work in.  Use Rails until it hurts.  Don&amp;#8217;t preemptively replace Rails features.  Use Rails until you find yourself writing more code doing it &amp;#8220;The Rails Way&amp;#8221; than if you rolled your own solution.  Then identify an alternative solution.  Use that alternative solution as your application&amp;#8217;s fallback convention for when the matching Rails convention fails.&lt;/p&gt;

&lt;p&gt;Or, as a peer of mine, wrote:&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot; data-in-reply-to=&quot;266980176406126593&quot;&gt;&lt;p&gt;@&lt;a href=&quot;https://twitter.com/elight&quot;&gt;elight&lt;/a&gt; Refactoring to patterns &amp;gt; starting with patterns IMO.&lt;/p&gt;&amp;mdash; Brian P. Hogan (@bphogan) &lt;a href=&quot;https://twitter.com/bphogan/status/266980378609332224&quot; data-datetime=&quot;2012-11-09T19:07:37+00:00&quot;&gt;November 9, 2012&lt;/a&gt;&lt;/blockquote&gt;

&lt;script src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;p&gt;While Rails provides many solutions out of the box, you should make a concerted effort to keep your own personal toolbox of fallback techniques (such as the &lt;a href=&quot;http://evan.tiggerpalace.com/articles/2012/11/07/accepts_nested_attributes_for-often-considered-harmful/&quot;&gt;Form object&lt;/a&gt;) on hand.  Share them.  Convert them into tools for use by your peers whenever possible.&lt;/p&gt;

&lt;p&gt;&lt;sup&gt;&lt;a name=&quot;1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; As code itself is a liability!&lt;/p&gt;</description>
          <pubDate>Wed, 21 Nov 2012 13:12:13 GMT</pubDate>
          <guid>http://evan.tiggerpalace.com/articles/2012/11/21/use-rails-until-it-hurts/</guid>
          <link>http://evan.tiggerpalace.com/articles/2012/11/21/use-rails-until-it-hurts/</link>
        </item>
    
        <item>
          <title>#accepts_nested_attributes_for (often) considered harmful</title>
          <description>&lt;p&gt;&lt;strong&gt;TL;DR: &lt;em&gt;#accepts_nested_attributes_for&lt;/em&gt; is not evil but it should be used infrequently. It often results in brittle code.  Consider using &lt;a href=&quot;http://rubygems.org/gems/redtape&quot;&gt;the redtape gem&lt;/a&gt; (which offers an implementation of the &amp;#8220;Form Object&amp;#8221; pattern), instead.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As a long time &lt;em&gt;#accepts_nested_attributes_for&lt;/em&gt; critic, I was excited when Bryan Helmkamp introduced us to the idea of the &amp;#8220;Form obect&amp;#8221; in his &lt;a href=&quot;http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/&quot;&gt;7 Patterns to Refactor Fat ActiveRecord Models&lt;/a&gt; blog post.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;#accepts_nested_attributes_for&lt;/em&gt; is used, in ActiveRecord classes, to reduce the amount of code in Rails applications needed to create/update records across multiple tables with a single HTTP POST/PUT.  As with many things Rails, this is convention-driven: the ActiveRecord classes expect to receive their POST/PUT parameter according to specific naming conventions used solely for nested data.&lt;/p&gt;

&lt;p&gt;While this sometimes results in less code, it often results in &lt;strong&gt;brittle code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In order to benefit from this coupling, we now have to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write forms/HTTP clients that will send the nested data expected by the model&lt;/li&gt;
&lt;li&gt;Have the receiving controller action simply passes the data through to the correct &amp;#8220;top-level&amp;#8221; model&amp;#8217;s &lt;em&gt;#new&lt;/em&gt; method.&lt;/li&gt;
&lt;li&gt;Not require additional massaging of the HTTP params otherwise we&amp;#8217;re just writing more code which is what &lt;em&gt;#accepts_nested_attributes_for&lt;/em&gt; is trying so hard to avoid.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my experience, use of nested forms often requires at least some massaging of the data if not outright removal of &lt;em&gt;#accepts_nested_attributes_for&lt;/em&gt; at a later time in favor of handling the data manually within the controller action.&lt;/p&gt;

&lt;p&gt;That is, it&amp;#8217;s brittle.&lt;/p&gt;

&lt;p&gt;So let&amp;#8217;s go on a tangent: &amp;#8220;best practices&amp;#8221;.&lt;/p&gt;

&lt;p&gt;&amp;#8220;Best practices&amp;#8221; are dangerous.  Few, if any, so-called &amp;#8220;best practices&amp;#8221; are universally best.  They&amp;#8217;re perhaps best in a particular context.  Yet developers often treat them as panaceas (a discussion for another day&amp;#8230;).&lt;/p&gt;

&lt;p&gt;So let&amp;#8217;s put this in context:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Only use &lt;em&gt;#accepts_nested_attributes_for&lt;/em&gt; if all of these conditions are met&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The form/API data requires no pre-processing prior to hand-off to your &lt;em&gt;ActiveRecord::Base&lt;/em&gt;&amp;#8217;s &lt;em&gt;#new&lt;/em&gt; method.&lt;/li&gt;
&lt;li&gt;(If you have a UI,) The UI fields can map, one-to-one, to the model fields; You know that you can afford to tightly couple the view and model so that they vary codependently on one another.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Conversely&amp;#8230;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use &lt;a href=&quot;http://rubygems.org/gems/redtape&quot;&gt;redtape&lt;/a&gt; if you need your UI to vary independently from your model.&lt;/strong&gt;&lt;a href=&quot;#1&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Consider using &lt;a href=&quot;http://rubygems.org/gems/redtape&quot;&gt;redtape&lt;/a&gt; if your input data requires pre-processing prior to hand-off to the model.  Obviously, you can do this in a private/protected method of your controller as well.&lt;/p&gt;

&lt;p&gt;Ultimately, the goal is to have working, maintainable code that satisfies your needs with minimal effort.  Choose the simplest path to arrive there.  Consider your options and weight them accordingly.&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;1&quot;&gt;&lt;b&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/b&gt;&lt;/a&gt;: I know what some devs out there are thinking: &amp;#8220;But, Evan, &lt;a href=&quot;http://en.wikipedia.org/wiki/Single_responsibility_principle&quot;&gt;SRP&lt;/a&gt; says I should always allow them to vary independently.&amp;#8221;  Yeah, well, &lt;strong&gt;&lt;em&gt;sometimes you should break the rules&lt;/strong&gt;&lt;/em&gt; but that should be the exception and not the norm.  Not that SRP is a &amp;#8220;rule&amp;#8221; so much as a &amp;#8220;guideline&amp;#8221;.  Pretty much the only &amp;#8220;rule&amp;#8221; of software development is &amp;#8220;thy program should execute deterministically&amp;#8221;.&lt;/p&gt;

&lt;p&gt;UPDATE 1: I had considered making this argument in my &lt;a href=&quot;http://windycityrails.org/videos2012/#1&quot;&gt;Frustration Driven Development&lt;/a&gt; talk but, then, I didn&amp;#8217;t have a solution at the time.  I hate providing a criticism without presenting an alternative&amp;#8230;&lt;/p&gt;

&lt;p&gt;UPDATE 2: &lt;em&gt;Redtape::Form&lt;/em&gt; includes &lt;em&gt;ActiveModel::Validations&lt;/em&gt;.  You can add validations to your Redtape::Form just as you would an ActiveRecord::Base subclass. &lt;strong&gt;Beware&lt;/strong&gt;: Don&amp;#8217;t duplicate validations from your model in your Redtape::Form.  Instead, add validations if your form inputs are raw values requiring processing before being used in your model.  Your form can then catch these errors early and provide contextually useful error messages.&lt;/p&gt;</description>
          <pubDate>Wed, 07 Nov 2012 09:13:46 GMT</pubDate>
          <guid>http://evan.tiggerpalace.com/articles/2012/11/07/accepts_nested_attributes_for-often-considered-harmful/</guid>
          <link>http://evan.tiggerpalace.com/articles/2012/11/07/accepts_nested_attributes_for-often-considered-harmful/</link>
        </item>
    
        <item>
          <title>The DCamp Manifesto</title>
          <description>&lt;h1&gt;What is this &amp;#8220;DCamp&amp;#8221; thing I keep hearing about?&lt;/h1&gt;

&lt;p&gt;The typical conference model is involves a handful of one-to-many exchanges of information.  The conference model assumes that you, as an audience member, will gain the most value by receiving information directly from a few people.  It is, in essence, a classroom.&lt;/p&gt;

&lt;h1&gt;DCamp assumes you don&amp;#8217;t do well in classrooms&lt;/h1&gt;

&lt;p&gt;In 2008, when DCamp was created, and Ruby still wasn&amp;#8217;t quite mainstream, Ruby developers were, on the whole, brilliant.  It seemed wrong, to me, to have an elite few who were frequently speaking at conferences.&lt;/p&gt;

&lt;p&gt;In my experiences, speakers are typically extroverts.  This in no way implies that introverts have nothing to offer.  But introverts seem to put themselves out there with less frequency.  And so conferences would typically feature the same extroverts again and again.&lt;/p&gt;

&lt;p&gt;When you attend a conference, how many open laptops do you see?  How many people are paying attention?  How many are socializing with other attendees besides at the inevitable &amp;#8220;drink up&amp;#8221; after-party.when they get some alcohol in them?&lt;/p&gt;

&lt;p&gt;I wanted to lure out the introverts.  I wanted to hear what they have to say.&lt;/p&gt;

&lt;h1&gt;DCamp puts people on a level playing field&lt;/h1&gt;

&lt;p&gt;We don&amp;#8217;t have &amp;#8220;talks&amp;#8221;.  We have &amp;#8220;sessions&amp;#8221;.&lt;/p&gt;

&lt;p&gt;Or, to put it more bluntly, there&amp;#8217;s a &amp;#8220;no talking head&amp;#8221; rule.&lt;/p&gt;

&lt;p&gt;No one stands at the front of the room and lectures to you (except maybe during 5 minute lightning talks).  Presentations often serve to elevate and separate the presenter from the participants.  That&amp;#8217;s not our way.&lt;/p&gt;

&lt;p&gt;Campers collectively decide on topics that interest them.&lt;/p&gt;

&lt;p&gt;Anyone who proposes the topic for a session is responsible to be the &lt;strong&gt;facilitator&lt;/strong&gt; for that session. Facilitating in no way implies expertise in the topic.  It connotes a strong enough interest in the topic to moderate a discussion or a hands-on activity.  The facilitator is there to keep the conversation flowing and to ensure that no one individual monopolizes the floor.  Because&amp;#8230;&lt;/p&gt;

&lt;h1&gt;Time is limited&lt;/h1&gt;

&lt;p&gt;Sessions are typically 30 minutes.  Originally, they weren&amp;#8217;t.  But, over the years, I found that shorter sessions leave people hungry for more.  The last thing you want is to have a session drag on past its inevitable conclusion.&lt;/p&gt;

&lt;p&gt;Either a session will be too long or too short.  If the session is too long, people become tired, bored, and listless.  If it is too short, they&amp;#8217;re still excited and eager.  They&amp;#8217;re more likely to continue the discussion on their own terms during breaks or after DCamp.&lt;/p&gt;

&lt;h1&gt;You&amp;#8217;re responsible for your education&lt;/h1&gt;

&lt;p&gt;If a session isn&amp;#8217;t valuable to you, the Open Space model provides &amp;#8220;The Rule of Two Feet&amp;#8221;.  You have two feet (or perhaps 4 wheels): use them.  Go to another session.  Or take a nap.  Or hang out with other brilliant people and shoot the shit.&lt;/p&gt;

&lt;p&gt;Other than the Code Retreat, each morning, we collectively decide on the content.&lt;/p&gt;

&lt;p&gt;We spend about fifteen minutes in a plenary brainstorming session.&lt;/p&gt;

&lt;p&gt;The next fifteen minutes are spent proposing topics.  Everyone is given pens, paper, and duct tape.  You scribble down topics that interest you and your name next to the topic.  Then you slap the topic up on the &amp;#8220;wall o&amp;#8217; topics&amp;#8221;.&lt;/p&gt;

&lt;p&gt;Fifteen more are spent &lt;a href=&quot;http://martinfowler.com/bliki/DotVoting.html&quot;&gt;dot voting&lt;/a&gt; on topics.&lt;/p&gt;

&lt;p&gt;The camp is set loose for fifteen to thirty minutes while a few of us sort the topics out into a schedule.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;ve learned that, typically, a two-track schedule works best where one track has votes in descending order and the other ascending.  This tends to minimizes the number of session conflicts for campers.&lt;/p&gt;

&lt;p&gt;But we usually have a third track: for newbies.&lt;/p&gt;

&lt;p&gt;The newbie track tends to be predictable each year as it rehashes a lot of the same territory: setting up a development environment, basic Ruby skills, using git, then an introduction to web development with Ruby.  More experienced developers take turns, throughout the day, leading these hands-on sessions.  Teaching is a great way to discover knowledge gaps for more experienced developers.  To that extent, everyone wins!&lt;/p&gt;

&lt;h1&gt;DCamp encourages participation&lt;/h1&gt;

&lt;p&gt;Yes, you can be a wallflower through all of DCamp.  But it&amp;#8217;s not easy.&lt;/p&gt;

&lt;p&gt;First, there are the sessions, that you&amp;#8217;ve already read about.&lt;/p&gt;

&lt;p&gt;Then there&amp;#8217;s the &lt;a href=&quot;http://coderetreat.org/&quot;&gt;Code Retreat&lt;/a&gt;.  The retreat gives you about six opportunities to pair with people you&amp;#8217;ve just met to solve a problem.  Even if you&amp;#8217;re an introvert, it&amp;#8217;s not too hard to get together with another developer and just do your thing.&lt;/p&gt;

&lt;p&gt;And then there&amp;#8217;s the chores.&lt;/p&gt;

&lt;p&gt;At DCamp, there&amp;#8217;s:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No catering&lt;/li&gt;
&lt;li&gt;No restaurants&lt;/li&gt;
&lt;li&gt;No hotel staff&lt;/li&gt;
&lt;li&gt;No hotel&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yes, the first DCamp was at a hotel.  The event worked but, boy, was that hotel a pain in the ass to work with!  Really, it is far cheaper, more fulfilling, and an overall better experience to just do it yourself!&lt;/p&gt;

&lt;p&gt;The event provides the venue, a (relatively) comfortable place to sleep, bathing facilities, electricity, a kitchen, and space to hold sessions.&lt;/p&gt;

&lt;p&gt;Getting supplies to the camp is tricky.  For the first few years, that was all me, me, me and&amp;#8230; let me see&amp;#8230; *me*!  But, as with &lt;a href=&quot;http://en.wikipedia.org/wiki/Stone_soup&quot;&gt;stone soup&lt;/a&gt;, campers began to notice that everything went better when they participated in pretty much every phase of the event including the logistics.  Bear in mind: this didn&amp;#8217;t happen overnight!  Most early assistance that I received was ad hoc at best.  It wasn&amp;#8217;t until perhaps until the fourth DCamp when campers, of their own accord, became proactively involved in logistics.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m not complaining but that was a lot of shit to buy, lifr, and haul mostly on my own!  Having more logistical help has been wonderful!&lt;/p&gt;

&lt;p&gt;Oh, and you&amp;#8217;re on your own for internet at DCamp.&lt;/p&gt;

&lt;p&gt;That&amp;#8217;s right: bring your own internet and wifi.&lt;/p&gt;

&lt;h1&gt;DCamp is free&lt;/h1&gt;

&lt;p&gt;At first, it was $100.  Then the US economy melted down.  While our sector has withstood most of the storm, not all of us were so fortunate.&lt;/p&gt;

&lt;p&gt;So&amp;#8230; free (as in beer).&lt;/p&gt;

&lt;p&gt;Again, that means the entrance fee, the food, the venue, everything: free.&lt;/p&gt;

&lt;p&gt;That is, in truth, the event sponsors pay for it.&lt;/p&gt;

&lt;p&gt;Yes, DCamp is listed as $1337 on the Eventbrite page.  They require a for-pay ticket to be listed.  If you don&amp;#8217;t get the joke&amp;#8230;&lt;/p&gt;

&lt;h1&gt;DCamp is frugal&lt;/h1&gt;

&lt;p&gt;If you include the cost of t-shirts, DCamp costs around USD $5k per year to produce.&lt;/p&gt;

&lt;h1&gt;DCamp attendees are curated&lt;/h1&gt;

&lt;p&gt;I&amp;#8217;ve used &lt;a href=&quot;http://www.eventbrite.com&quot;&gt;Eventbrite&lt;/a&gt; to handle mass-email, registration, and wait lists for DCamp.  Each year, I create coupon codes in Eventbrite.  These codes get distributed to community leaders who I trust and respect.  Each code is usually good for 5 registrations at a time.  These leaders are then responsible to find the awesome people who will populate DCamp that year.  Once a code is used up, typically, I refill it.  &lt;a href=&quot;http://www.meetup.com/Arlington-Ruby/&quot;&gt;Some communities&lt;/a&gt; are rabid DCamp fans so I titrate the release of codes to them.  Otherwise, they would utterly overwhelm the event.  This would not be a bad thing except&amp;#8230;&lt;/p&gt;

&lt;h1&gt;DCamp supports diversity&lt;/h1&gt;

&lt;p&gt;Monoculture is death.  We are stronger when we have a diverse set of individuals to learn from.  And, so, I encourage, and actively attempt to draw from, people from all walks to participate.  In the past, we have had software testers, a film director, an investment banker, women, men, people black, yellow, white, straight, and queer.  Variety is not only healthy but damn fun!&lt;/p&gt;

&lt;h1&gt;DCamp is not commercial&lt;/h1&gt;

&lt;p&gt;Commerce is out there but it&amp;#8217;s not part and parcel to the event.  Sure, we all work for a living.  And our sponsors generously help the event occur each year.  But, first and by far foremost, the event is about its participants: the campers.  If the campers win, the sponsors win.&lt;/p&gt;

&lt;p&gt;Though we&amp;#8217;ve had repeat sponsors: they occasionally get a good hire from DCamp!&lt;/p&gt;

&lt;p&gt;DCamp is for technical people.  NO RECRUITERS.  NO MBAs (unless they&amp;#8217;ve become programmers).  Because&amp;#8230;&lt;/p&gt;

&lt;h1&gt;DCamp is not for profit&lt;/h1&gt;

&lt;p&gt;No one makes money from producing DCamp.  When I created it, I was an overpaid government contractor.  DCamp was born for love of Ruby and its community and not greed.  It continues in that vein.&lt;/p&gt;

&lt;h1&gt;DCamp is finite&lt;/h1&gt;

&lt;p&gt;DCamp is size constrained to 78 people: the number of beds available at Cabin Camp 3 in Prince William Forest National Park.  We want to ensure that each and every camper adds to the value of the whole.  This means that we welcome neophytes, journeyman, and experts alike.  You&amp;#8217;re qualified to be a DCamper if you&amp;#8217;re:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inquisitive&lt;/li&gt;
&lt;li&gt;Passionate about sharing your knowledge&lt;/li&gt;
&lt;li&gt;Someone who plays well with others&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Due to the recent surge in interest, there will be &lt;strong&gt;&lt;em&gt;exactly 0% growth&lt;/strong&gt;&lt;/em&gt; in the size of DCamp.&lt;/p&gt;

&lt;p&gt;Instead, I encourage you to make your own DCamp.  This is the entirety of the reason for this piece.&lt;/p&gt;

&lt;h1&gt;DCamp is remote&lt;/h1&gt;

&lt;p&gt;DCamp is off the beaten path, removed from civilization, a little difficult to reach.  Coming and going can be a challenge.  And that has proven fortunate because&amp;#8230;&lt;/p&gt;

&lt;h1&gt;DCamp is a community&lt;/h1&gt;

&lt;p&gt;I will in no way pretend that I intended every aspect that has made DCamp the wonderful event that it has become.  Much of the above was discovered through serendipity and some from suggestions from within and without.  But we, the campers, noticed these gems.  Then we integrated them into our ethos.&lt;/p&gt;

&lt;p&gt;I make every effort to include past campers.  While I do not curate registration, I am personally responsible for the wait list.  Preference always goes to past campers.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because, over the three-to-four nights that people spend at DCamp, we forge tight bonds.  This happens naturally when you are constrained to the same physical space with the same 78 or so people with similar interests.&lt;/p&gt;

&lt;p&gt;And, so, each DCamp serves as a reunion of sorts for returning campers.&lt;/p&gt;

&lt;h1&gt;At the end of it all&lt;/h1&gt;

&lt;p&gt;We get together and hold a retrospective.  We discuss what felt good and what didn&amp;#8217;t.  Lessons are shared and, sometimes, relearned.  Occasionally, a worthwhile lesson is lost year to year.&lt;/p&gt;

&lt;p&gt;Finally, we gather together, &lt;a href=&quot;http://programmer.97things.oreilly.com/wiki/index.php/The_Boy_Scout_Rule&quot;&gt;clean the camp&lt;/a&gt; in no more than 30 minutes, the remaining food is divvied up among folks who can use it, then folks depart.&lt;/p&gt;

&lt;p&gt;Oh and I&amp;#8217;m left with a small lost and found. Hooray. ;-)&lt;/p&gt;

&lt;h1&gt;What&amp;#8217;s the point?&lt;/h1&gt;

&lt;p&gt;If you didn&amp;#8217;t pick up on it along the way, DCamp is, at its core, a four night nerd &lt;a href=&quot;http://en.wikipedia.org/wiki/Commune&quot;&gt;commune&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;In closing&lt;/h1&gt;

&lt;p&gt;The purpose of this piece was to provide the inspiration and insight for you to roll your own DCamp.  Should you decide to, please do reach out to me.  I would be glad to provide counsel and would love to attend!&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re a former camper and find that I forgot to include some essential insight, please do let me know!&lt;/p&gt;</description>
          <pubDate>Sat, 06 Oct 2012 09:13:15 GMT</pubDate>
          <guid>http://evan.tiggerpalace.com/articles/2012/10/06/the-dcamp-manifesto/</guid>
          <link>http://evan.tiggerpalace.com/articles/2012/10/06/the-dcamp-manifesto/</link>
        </item>
    
        <item>
          <title>DCI that respects the method cache</title>
          <description>&lt;p&gt;Ryan Bates sent this pithy tweet earlier today:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://img.skitch.com/20111125-jbkx9wnasfh264sppd5guyef7n.jpg&quot;&gt;&lt;/img&gt;&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve been toying with DCI lately.  But the techniques spelled out to date &lt;a href=&quot;http://andrzejonsoftware.blogspot.com/2011/02/dci-and-rails.html&quot;&gt;here&lt;/a&gt; and &lt;a href=&quot;http://saturnflyer.com/blog/jim/2011/10/04/oop-dci-and-ruby-what-your-system-is-vs-what-your-system-does/&quot;&gt;here&lt;/a&gt; use Object.extend.  Extending an object blows away the method cache, slightly reducing performance.  &lt;/p&gt;

&lt;p&gt;So, as I lazed in bed, reading this tweet while dreaming of turkey to come, it hits me: instead of implementing the Delegator pattern through extend, let&amp;#8217;s just use an actual Delegator object.&lt;/p&gt;

&lt;p&gt;Simple example below based on the usage of &lt;a href=&quot;https://github.com/rubypair/rubypair/blob/master/app/models/user/new_user_provisioner.rb&quot;&gt;NewUserProvisioner&lt;/a&gt; within &lt;a href=&quot;http://rubypair.com&quot;&gt;RubyPair&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Our good friend &lt;a href=&quot;http://www.ruby-doc.org/stdlib-1.9.2/libdoc/delegate/rdoc/SimpleDelegator.html&quot;&gt;SimpleDelegator&lt;/a&gt; is defined in &amp;#8220;delegate.rb&amp;#8221; in stdlib, courtesy of &lt;a href=&quot;http://blog.grayproductions.net/&quot;&gt;James Edward Gray II&lt;/a&gt;.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/1392671.js&quot;&gt; &lt;/script&gt;</description>
          <pubDate>Thu, 24 Nov 2011 18:25:44 GMT</pubDate>
          <guid>http://evan.tiggerpalace.com/articles/2011/11/24/dci-that-respects-the-method-cache/</guid>
          <link>http://evan.tiggerpalace.com/articles/2011/11/24/dci-that-respects-the-method-cache/</link>
        </item>
    
        <item>
          <title>Some people call me "the remote pairing guy"...</title>
          <description>&lt;p&gt;I&amp;#8217;ve been remote pairing with folks for a couple of years now.  However, it&amp;#8217;s only the past few months that I decided that heavyweight application-based solutions just weren&amp;#8217;t working for me.&lt;/p&gt;

&lt;h2&gt;Expectatons&lt;/h2&gt;

&lt;p&gt;I expect my remote pairing experience to be as close to in person as possible.  To that extent, what I desire is:&lt;/p&gt;

&lt;h4&gt;Responsive&lt;/h4&gt;

&lt;p&gt;When I, or my pair, types, I expect to see it on screen in near real-time.  Even a one second delay is potentially too much.&lt;/p&gt;

&lt;h4&gt;Low bandwidth requirement&lt;/h4&gt;

&lt;p&gt;I often pair with people on the opposite side of the country.  Higher bandwidth solutions tend to suffer more due to lack of bandwidth&lt;/p&gt;

&lt;h4&gt;Audio and Video&lt;/h4&gt;

&lt;p&gt;I need to be able to both hear &lt;strong&gt;&lt;em&gt;and see&lt;/strong&gt;&lt;/em&gt; my pair when pairing whenever possible.  Without video, body language can&amp;#8217;t be communicated.&lt;/p&gt;

&lt;p&gt;For instance, ever noticed how you will often gesticulate when you&amp;#8217;re on the phone.  Feels stupid, right?  It&amp;#8217;s human, it&amp;#8217;s communication, and so it matters to pairing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;I need my video of my pair, and vice versa, whenever I can get it.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;FYI, I tend to place the video of my pair just beneath the camera on my screen.  I also work to keep the video o my pair visible at all times.  More on that in a bit.&lt;/p&gt;

&lt;h4&gt;Modular&lt;/h4&gt;

&lt;p&gt;The above two reasons mean that I need to be able to pick and choose which features of my pairing environment I&amp;#8217;ll use based on internet weather.  All-in-one solutions dont lend themselves well to this.&lt;/p&gt;

&lt;h4&gt;Cost&lt;/h4&gt;

&lt;p&gt;I don&amp;#8217;t want my pairs to have to pay for extra products or services to pair with me.&lt;/p&gt;

&lt;h4&gt;Learning curve&lt;/h4&gt;

&lt;p&gt;I want to use well-known and usable tools so that my pairs aren&amp;#8217;t wasting time fighting the tools when they should be pairing with me.&lt;/p&gt;

&lt;h2&gt;I&amp;#8217;ve tried&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;VNC&lt;/li&gt;
&lt;li&gt;Teamviewer&lt;/li&gt;
&lt;li&gt;Mac OS X Screensharing&lt;/li&gt;
&lt;li&gt;Skype Screensharing&lt;/li&gt;
&lt;li&gt;Google Plus Screensharing &amp;amp; Hangouts&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;li&gt;Screen&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these have let me down.&lt;/p&gt;

&lt;h4&gt;VNC (and Mac Screensharing)&lt;/h4&gt;

&lt;p&gt;VNC and Mac Screensharing (allegedly VNC under the hood) are both bandwidth intensive, typically proving too unresponsive for sustained pairing.  On-screen updates often lag one to several seconds.&lt;/p&gt;

&lt;h4&gt;Teamviewer&lt;/h4&gt;

&lt;p&gt;Teamviewer is generally responsive.  &lt;/p&gt;

&lt;p&gt;But it&amp;#8217;s way too expensive!  A single license runs ~$700!  Sure, it&amp;#8217;s for life.  But then my pair has to have it as well.  Granted, Teamviewer is free for non-commercial use.&lt;/p&gt;

&lt;p&gt;I also had it crash a pair&amp;#8217;s Linux machine!  This did not give me good vibes.  Your mileage may vary.&lt;/p&gt;

&lt;h4&gt;Skype&lt;/h4&gt;

&lt;p&gt;Ah, Skype. How I love to hate you.&lt;/p&gt;

&lt;p&gt;The laundry list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Screensharing is unidirectional: My pair can see my desktop but they can&amp;#8217;t effect changes&lt;/li&gt;
&lt;li&gt;Frequent dropped connections&lt;/li&gt;
&lt;li&gt;Screensharing frequently hangs while audio continues to operate as normal.  This can only be corrected by dropping and restarting the call!  FAIL!&lt;/li&gt;
&lt;li&gt;Frequent compatibility issues with older versions of Skype&lt;/li&gt;
&lt;li&gt;Video may be the most bandwidth intensive of the tools I&amp;#8217;ve tried that provide video&lt;/li&gt;
&lt;li&gt;Skype 5 has one of the least usable interfaces ever conceived in the 21st century&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just don&amp;#8217;t use it.  Really.  Don&amp;#8217;t.&lt;/p&gt;

&lt;h4&gt;Google Plus Screensharing &amp;amp; Hangouts&lt;/h4&gt;

&lt;p&gt;G+ is a different beast from Skype, though it has some similar features.&lt;/p&gt;

&lt;p&gt;G+ screensharing is also a strange beast.  It&amp;#8217;s a feature within G+ Hangouts, a group video chat provided by G+.  Like Skype, it&amp;#8217;s unidirectional.  I know, bummer, right?  But it&amp;#8217;s &lt;strong&gt;&lt;em&gt;extremely&lt;/strong&gt;&lt;/em&gt; responsive compared to Skype.  Alas, again, it&amp;#8217;s unidirectional.  That won&amp;#8217;t work.&lt;/p&gt;

&lt;p&gt;But G+&amp;#8217;s audio and video in Hangout is simply amazing.  And it&amp;#8217;s cross-platorm.  The only sad part is that it uses Flash; it&amp;#8217;s pretty CPU intensive.  For example, it would peg both cores on my 11&amp;#8221; Core 2 Duo Macbook Air.  &lt;/p&gt;

&lt;p&gt;Let me provided emphasis here: &lt;strong&gt;&lt;em&gt;I strongly prefer G+ Hangouts for my A/V while pairing&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;h4&gt;Tmux/Screen&lt;/h4&gt;

&lt;p&gt;Tmux and GNU Screen are basically two different takes on the same idea.  &lt;/p&gt;

&lt;p&gt;They&amp;#8217;re session multiplexeres.  &lt;/p&gt;

&lt;p&gt;English, please? &lt;/p&gt;

&lt;p&gt;They let you open multiple shells within a single terminal shell.  You can also share the Screen/Tmux session via a socket with other users on the same machine.&lt;/p&gt;

&lt;p&gt;Again, for emphasis, &lt;strong&gt;&lt;em&gt;I use tmux whenever possible when pairing&lt;/strong&gt;&lt;/em&gt;.  I  have my pairs SSH into a machine under my control, fire up tmux, and off we go to the races!  My impression is that it&amp;#8217;s more a matter of taste; I&amp;#8217;ve seen Screen work as well.&lt;/p&gt;

&lt;p&gt;Delving into the details of SSH is a bit of scope for this article but you can read more about the basics &lt;a href=&quot;http://inside.mines.edu/~gmurray/HowTo/sshNotes.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Tmux (and screen) is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open source and easily acquired&lt;/li&gt;
&lt;li&gt;Extremely low bandwidth over SSH&lt;/li&gt;
&lt;li&gt;Most responsive option of the bunch&lt;/li&gt;
&lt;li&gt;Tmux has a shallow learning curve: it&amp;#8217;s easy to become productive with it quickly.  I&amp;#8217;ve seen numerous developers learn enough Tmux to be productive in it within a minute or two of explaining how to navigate between terminal sessions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Nut&amp;#8217;s n&amp;#8217; Bolts&lt;/h2&gt;

&lt;p&gt;As I mentioned above, the high level of my pairing stack is&amp;#8230;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;G+ Hangouts&lt;/li&gt;
&lt;li&gt;Tmux&lt;/li&gt;
&lt;li&gt;SSH&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;#8230; but there are few more parts to the equation.&lt;/p&gt;

&lt;h4&gt;I typically pair with people on a machine behind a router&lt;/h4&gt;

&lt;p&gt;I use a &lt;a href=&quot;http://www.dd-wrt.com/site/index&quot;&gt;DD-WRT&lt;/a&gt; router.  DD-WRT is an open source router firmware that works on a whole range of off-the-shelf routers.  Among other awesome features, it has a nice built-in feature to keep &lt;a href=&quot;http://dyn.com/dns/&quot;&gt;DynDNS&lt;/a&gt; current with the router&amp;#8217;s internet-facing IP address.  Because, like many people, I lack a static internet IP address (they&amp;#8217;re just a tad finite, you know?), I use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A free DynDNS account&lt;/li&gt;
&lt;li&gt;Keep DynDNS updated through DD-WRT&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, because I control the router, I port forward SSH from the router to my internal machine of choice.  Advice here: don&amp;#8217;t keep your SSH on the well known port 22 for security reasons.&lt;/p&gt;

&lt;h4&gt;I use a Mac&lt;/h4&gt;

&lt;p&gt;While I can do a passing job of faking it as a Linux sys admin, I prefer not to.  Sorry, Linux peeps.&lt;/p&gt;

&lt;p&gt;That said, OS X has this handy little checkbox in the Sharing -&gt; Remote Login preferences to help you secure your SSH:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://img.skitch.com/20111017-thsp8fqbqs79gkg2edeqc58afb.jpg&quot; /&gt;&lt;/p&gt;

&lt;h4&gt;Working with SSH on a Mac&lt;/h4&gt;

&lt;p&gt;I also need to be able to easily add and remove users based on their SSH public keys.  Most importantly, I need to be able to tell OSX that these newly created users should be allowed to connect to my machine via SSH. This took a little bit of research and, frankly, is OS X arcana.  As such, I wrote a pair of quick-and-dirty scripts that automate the chore for me.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/1293506.js?file=add_user.rb&quot;&gt; &lt;/script&gt;

&lt;script src=&quot;https://gist.github.com/1293356.js?file=remove_user.rb&quot;&gt;&lt;/script&gt;

&lt;h4&gt;Recap&lt;/h4&gt;

&lt;p&gt;My whole stack amounts to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;G+ for audio-video chat while pairing&lt;/li&gt;
&lt;li&gt;A shared Tmux session running on a Mac under my control made accessible via a DynDNS address hidden behind a DD-WRT router port forwarding SSH to the Mac with users provisioned/removed via a couple of scripts on an as-needed basis.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And, so, I bid you happy remote pairing!&lt;/p&gt;</description>
          <pubDate>Mon, 17 Oct 2011 12:23:56 GMT</pubDate>
          <guid>http://evan.tiggerpalace.com/articles/2011/10/17/some-people-call-me-the-remote-pairing-guy-/</guid>
          <link>http://evan.tiggerpalace.com/articles/2011/10/17/some-people-call-me-the-remote-pairing-guy-/</link>
        </item>
    
        <item>
          <title>Helping you fish better!</title>
          <description>&lt;p&gt;Helping you fish better!&lt;/p&gt;

&lt;p&gt;In one form or another, I&amp;#8217;ve been a contractor for the vasty majority of my career: building other people&amp;#8217;s software for them.  Along the way, I have mentored developers, &lt;a href=&quot;http://rubydcamp.org&quot;&gt;founded and continue to run a conference&lt;/a&gt; (now going into its fifth year) to enrich and educate both beginning developers and expert alike, have shared some of what I have learned along the way by speaking at user groups and conferences, and &lt;a href=&quot;rubypair.com&quot;&gt;regularly pair with distant developers to both educate, share with, socialize, and learn from them&lt;/a&gt; (I wrote most of RubyPair as well).&lt;/p&gt;

&lt;p&gt;This has led me to realize that I am happiest when I am helping eager developers improve their skills.  Seeing the &amp;#8220;eureka&amp;#8221; moments can only be described as a rush!&lt;/p&gt;

&lt;p&gt;A couple of months ago, I began setting aside at least 3 hours each week, when I&amp;#8217;m not on travel, to remote pair or otherwise consult with other developers on Open Source.  Again, that time is only for Open Source and not for commercial use.  I&amp;#8217;ve taught a lot.  I&amp;#8217;ve learned a few things.  I&amp;#8217;ve met some cool people who I wouldn&amp;#8217;t have otherwise.  It&amp;#8217;s been a blast!&lt;/p&gt;

&lt;p&gt;As the Chinese proverb goes:&lt;/p&gt;

&lt;p&gt;Give a man a fish and you feed him for a day. Teach a man to fish and you feed him for a lifetime.&lt;/p&gt;

&lt;p&gt;That&amp;#8217;s what I&amp;#8217;d been doing.  I simply had not put a label on it!  The mentoring, the conference and user group presentations, the (not-so-) occasional rant about why people should be writing their tests first and then move on to evolve a Test Driven Development discipline: it has all been about trying to help other developers get better.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;d blog but, while not a terrible writer, I don&amp;#8217;t have the writing bug as much as some. But, man, do I &lt;em&gt;ever&lt;/em&gt; love a good conversation or pairing session!&lt;/p&gt;

&lt;p&gt;I want to touch and enrich lives.  I want to help people fish, that is: write software, better!&lt;/p&gt;

&lt;p&gt;What only occurred to me a month ago was that this mentoring fills a real need.  I could make a living off of helping people have &amp;#8220;eureka&amp;#8221; moments!&lt;/p&gt;

&lt;p&gt;And, so, for anyone who is looking to improve: this one&amp;#8217;s for you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;DANGER WILL ROBINSON!  COMMERCIAL PITCH FOLLOWS!&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Via &lt;a href=&quot;http://tripledogdare.net&quot;&gt;Triple Dog Dare&lt;/a&gt; (I admit, I really need to update this page with more recent work but I&amp;#8217;ve been too busy!!!), over the past several months, &lt;a href=&quot;http://keas.com&quot;&gt;I have helped bootstrap one company from almost no Rails knowledge to a working application&lt;/a&gt;.  For another client, I&amp;#8217;ve provided occasional periodic one-on-one mentoring in building his web startup with Rails (shhhh&amp;#8230;.. it&amp;#8217;s a secret for now!).  For both, the majority of the collaboration has been online.  Although, for the former client, I&amp;#8217;ve occasional traveled out to San Fran to help them onsite.  San Fran is just such a terrible town to visit, after all &amp;#8211; and, yes, I&amp;#8217;m kidding; San Fran is pretty awesome.&lt;/p&gt;

&lt;p&gt;But, yes, most of the mentoring occurs online.  Sometimes I&amp;#8217;m answering questions via email, more often IM, doing a code review, or helping via VOIP or a remote pairing session.&lt;/p&gt;

&lt;p&gt;And, let me tell you, remote pairing works pretty darn well.  The technology is not only there but it&amp;#8217;s been there for some time.  Frankly, VOIP was the missing component for a long time.  The other technologies involved are tried and true *NIX apps.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ll write about remote pairing in a later post.  It&amp;#8217;s &lt;a href=&quot;rubypair.com/about&quot;&gt;been at the forefront of my mind a great deal lately&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you or a team you work with is new to Rails and you believe you would benefit from someone to shepherd you through the learning process, &lt;a href=&quot;mailto:hello@tripledogdare.net&quot;&gt;drop me a line&lt;/a&gt;!&lt;/p&gt;</description>
          <pubDate>Fri, 23 Sep 2011 15:29:04 GMT</pubDate>
          <guid>http://evan.tiggerpalace.com/articles/2011/09/23/helping-you-fish-better/</guid>
          <link>http://evan.tiggerpalace.com/articles/2011/09/23/helping-you-fish-better/</link>
        </item>
    
        <item>
          <title>The automated testing confessional</title>
          <description>&lt;p&gt;Hi, my name is Evan.  And I don&amp;#8217;t always start a new app by writing tests.&lt;/p&gt;

&lt;p&gt;There, I said it!  Crazy, right?  Well, ok, maybe within our test-obsessed Ruby world.&lt;/p&gt;

&lt;p&gt;As much as I promote automated testing and Test Driven Development, and you can call me a hypocrite, but I don&amp;#8217;t always TDD or even test first.  &lt;em&gt;Sometimes I just want to write some %#@&amp;amp;ing code!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But here&amp;#8217;s the catch: it almost always bites me in the ass later.&lt;/p&gt;

&lt;p&gt;Take for example &lt;a href=&quot;http://rubypair.com&quot;&gt;Ruby Pair&lt;/a&gt;.  Ruby Pair is, currently, a humble little directory of people interested in pairing on Ruby, remotely or in-person, for fun or to work on open source.&lt;/p&gt;

&lt;p&gt;Bad Evan!  You only started writing tests a few weeks in!&lt;/p&gt;

&lt;p&gt;Now that I&amp;#8217;ve berated myself&amp;#8230;&lt;/p&gt;

&lt;p&gt;Ruby Pair hasn&amp;#8217;t been my full time job; it&amp;#8217;s been my hobby project for the past 3 weeks.  When I&amp;#8217;m working on a project for fun, or on my own dime, I&amp;#8217;m more likely to try to see how far I can get without automated tests.&lt;/p&gt;

&lt;p&gt;Why?  Because I&amp;#8217;m lazy, dammit!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;The key is to &lt;a href=&quot;http://c2.com/cgi/wiki?LazinessImpatienceHubris&quot;&gt;be lazy in a good way&lt;/a&gt;.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;RATHOLE&lt;/p&gt;

&lt;p&gt;So I have another confession: until I found Ruby, Perl was my favorite tool to avoid writing shell scripts.  I deplore writing shell scripts.  Sure, I live in the shell (zsh, thank you very much) on a daily basis but that doesn&amp;#8217;t mean that I have to code for the shell using the shell!&lt;/p&gt;

&lt;p&gt;/RATHOLE&lt;/p&gt;

&lt;p&gt;Larry Wall, the author of Perl, talks about the &amp;#8220;three great virtus of a programmer&amp;#8221;.  He lists laziness chiefly among them.  When Larry says &amp;#8220;laziness&amp;#8221;, he means the kind of lazy where you&amp;#8217;ll go to great lengths to avoid doing unecessary work later.&lt;/p&gt;

&lt;p&gt;Sounds a little like automated testing, if you think about it.&lt;/p&gt;

&lt;p&gt;When writing a new app, at first, it&amp;#8217;s almost always easier for me to begin by just banging out code.  How many times have you set up authentication in an application?  Or created a User class or a users table?  Pretty motherhood and apple pie, right?&lt;/p&gt;

&lt;iframe width=&quot;420&quot; height=&quot;345&quot; src=&quot;http://www.youtube.com/embed/j_qQ7WvZ3QM&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;So you&amp;#8217;re writing your code, you think everything&amp;#8217;s fine, everything&amp;#8217;s good.  Then the next thing you know, you&amp;#8217;re on fire!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Ahem&lt;/em&gt; Ok, I mean &amp;#8220;you discover that your code base is a flying spaghetti monster&amp;#8221;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://evan.tiggerpalace.com/files/spaghetti_monster.jpeg&quot; style=&quot;width: 50%;&quot;&gt;&lt;/img&gt;&lt;/p&gt;

&lt;p&gt;My point is twofold:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;You don&amp;#8217;t miss something until it&amp;#8217;s no longer there.  It is important and reasonable to sometimes avoid writing automated tests.&lt;/strong&gt;&lt;/em&gt;  Now don&amp;#8217;t go and use that as an excuse to your momma if you get busted for it.  Occasionally skipping your automated tests is a healthy way to develop an appreciation for them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Not every piece of code should necessarily be tested.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;BLASPHEMY!&lt;/strong&gt;&lt;/em&gt;  Right?&lt;/p&gt;

&lt;p&gt;Well, not really&amp;#8230;&lt;/p&gt;

&lt;p&gt;Have you ever tested every path in your application?  If you say &amp;#8220;yes&amp;#8221; then that application must have been no larger than a few methods.&lt;/p&gt;

&lt;p&gt;Instead, we pick and choose what to test.  We do it all of the time.&lt;/p&gt;

&lt;p&gt;Typically, most of us write tests for the happy path.  &lt;em&gt;&amp;#8220;What&amp;#8217;s the happy path?&amp;#8221;&lt;/em&gt;, I&amp;#8217;m occasionally asked.  It&amp;#8217;s that magical case when all of your inputs are valid, all of your external dependencies are met, and so everything works as expected.  Everything else is a &amp;#8220;sad path&amp;#8221; a.k.a. &amp;#8220;degenerate&amp;#8221; or &amp;#8220;edge&amp;#8221; case.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;&amp;#8220;What not to test&amp;#8221; is a heuristic that varies from project to project.  Personally, I decide what not to test based on the (1) risk and (2) impact of failure of the particular component/feature.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A couple of anncecdotal examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;ALMOST ALWAYS TEST&lt;/strong&gt;&lt;/em&gt;: Whenever I&amp;#8217;m dealing with currencies, virtual or otherwise, I&amp;#8217;m writing a test.  Few things tick off a user faster than mishandling their money!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;RARELY TEST&lt;/strong&gt;&lt;/em&gt;: Authentication?  Psh!  I&amp;#8217;ve set up Devise enough times.  For the happy path, it&amp;#8217;s easy!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you&amp;#8217;re not familiar with the basic ideas behind &lt;a href=&quot;http://en.wikipedia.org/wiki/Risk_management&quot;&gt;risk management&lt;/a&gt; (and you&amp;#8217;re too lazy to follow that Wikipedia link), use this rule of thumb: just how confident are you that your code will work?  How bad will it be if it doesn&amp;#8217;t?  Listen to your Jiminy Cricket.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://evan.tiggerpalace.com/files/jiminy_cricket.jpeg&quot;&gt;&lt;/img&gt;&lt;/p&gt;

&lt;p&gt;To sum up: not TDDing or writing your tests first is a decision.  If you&amp;#8217;re going to make that decision, do it in an informed way.  Occasionally, writing code without tests serves as a useful touchstone to remind us why we write tests and use TDD.&lt;/p&gt;</description>
          <pubDate>Sun, 04 Sep 2011 07:23:59 GMT</pubDate>
          <guid>http://evan.tiggerpalace.com/articles/2011/09/04/the-automated-testing-confessional/</guid>
          <link>http://evan.tiggerpalace.com/articles/2011/09/04/the-automated-testing-confessional/</link>
        </item>
    
    
  </channel>
</rss>

