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

  <title><![CDATA[yonkeltron.com]]></title>
  <link href="http://yonkeltron.com/atom.xml" rel="self"/>
  <link href="http://yonkeltron.com/"/>
  <updated>2011-11-18T11:11:24-05:00</updated>
  <id>http://yonkeltron.com/</id>
  <author>
    <name><![CDATA[Jonathan E. Magen]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Quick thoughts on client-side template rendering]]></title>
    <link href="http://yonkeltron.com/blog/2011/11/17/quick-thoughts-on-client-side-template-rendering/"/>
    <updated>2011-11-17T19:05:00-05:00</updated>
    <id>http://yonkeltron.com/blog/2011/11/17/quick-thoughts-on-client-side-template-rendering</id>
    <content type="html"><![CDATA[<p>Very recently, there was a
<a href="https://plus.google.com/u/0/115060278409766341143/posts/ViaVbBMpSVG">discussion posted</a>
about the Google+ team&#8217;s usage of client-side template rendering. The
discussion continued on the
<a href="http://dailyjs.com/2011/11/17/discussion/">DailyJS blog</a> which asked
a few questions about appropriate usages of client-side rendering for
performance, design or philosophical reasons. This got me thinking
enough to write down some of my thoughts as I have recently
experimented with client-side rendering for both personal projects and
work. For reference, I have been toying with
<a href="http://documentcloud.github.com/underscore/">underscore templates</a>.</p>

<p>For this discussion let&#8217;s define performance as having two components:</p>

<ul>
<li>Resource utilization</li>
<li>Speed</li>
</ul>


<p>Naturally, in this simplification both items overlap quite a bit and
misrepresent the actual nature of the issue, blah, blah, yadda,
yadda. Ok so the computer scientist faculty taught us all that
optimization entails either maximizing something or minimizing
something. Let&#8217;s discuss performance optimization in the general case
by optimizing each performance component separately. Explicitly:
minimizing resource utilization and maximizing speed.</p>

<p>With respect to resource utilization, consider the example of
generating a page containing a large report. The server has to query
the database for all required data and instantiate necessary data
structures. Thousands of database records could create a very large
object graph very quickly, thus consuming lots of memory. Next, the
server must perform the required calculations or whatever data
manipulation operations required to create the report. This means
consuming CPU cycles and (usually) eating up more memory. Already,
resource consumption in terms of IO, memory and processing power can
clock in at high levels, even after significant optimization. After
all this, the server then must render the markup to display the
content which, in the case of many reports, means plenty of repetitive
markup surrounding the stuff you spent all that time preparing.</p>

<p>In this case, why not just ship the data to the client and generate
markup from a few templates in-browser? The more you can farm work out
to clients, the fewer resources you have to consume on the
server. This means less time your app spends in the HTTP request cycle
and the sooner GC can run freeing memory, tempfile file handles can be
closed and your app can begin relinquishing all resources, returning
them back to the loving arms of the OS.</p>

<p>The same goes for bandwidth and transmission time (even gzip
compression which you use currently, right!?) as, even next to large,
JSON-serialized data, full-blown pages full of repetitive HTML tags
appear huge by comparison. Which brings us to the next item:
speed. (Yeah, I did mention the overlap, right?)</p>

<p>The sooner the server can ship the data, the sooner the browser can
start rendering. The Google+ guys made it clear that when they do send
markup, they frequently flush IO buffers to send ready-made chunks to
the browser. This enables browsers to render sooner and begin fetching
external resources like CSS, JS and images. With client-side
rendering, shipping only data to the browser can get you the same
effect. With proper incremental rendering, you render the content at
the top of the report (a very good place to start) first thus showing
the user some activity.</p>

<p>As another example, take ActiveRecord-powered form validation in
Rails. The default behavior seen most commonly has, in cases of
validation failure, the entire form being re-rendered and sent to the
client.</p>

<figure class='code'><figcaption><span>Re-render the &#8220;new&#8221; action on validation failure  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">respond_to</span> <span class="k">do</span> <span class="o">|</span><span class="nb">format</span><span class="o">|</span>
</span><span class='line'>  <span class="k">if</span> <span class="vi">@model</span><span class="o">.</span><span class="n">save</span>
</span><span class='line'>    <span class="nb">format</span><span class="o">.</span><span class="n">html</span> <span class="p">{</span> <span class="n">redirect_to</span> <span class="n">model_path</span><span class="p">(</span><span class="vi">@model</span><span class="p">)</span> <span class="p">}</span>
</span><span class='line'>  <span class="k">else</span>
</span><span class='line'>    <span class="nb">format</span><span class="o">.</span><span class="n">html</span> <span class="p">{</span> <span class="n">render</span> <span class="ss">:action</span> <span class="o">=&gt;</span> <span class="ss">:new</span><span class="p">,</span> <span class="ss">:status</span> <span class="o">=&gt;</span> <span class="ss">:unprocessable_entity</span> <span class="p">}</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>However, as any moderately-experienced Rails dev knows, after failing
validation, the ActiveRecord model makes available a hash of errors.
Therefore, shipping only the error data offers a significant size
reduction during transmission.</p>

<figure class='code'><figcaption><span>Only ship back the errors hash on validation failure  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">respond_to</span> <span class="k">do</span> <span class="o">|</span><span class="nb">format</span><span class="o">|</span>
</span><span class='line'>  <span class="k">if</span> <span class="vi">@model</span><span class="o">.</span><span class="n">save</span>
</span><span class='line'>    <span class="nb">format</span><span class="o">.</span><span class="n">json</span> <span class="p">{</span> <span class="n">render</span> <span class="ss">:json</span> <span class="o">=&gt;</span> <span class="vi">@model</span> <span class="p">}</span>
</span><span class='line'>  <span class="k">else</span>
</span><span class='line'>    <span class="nb">format</span><span class="o">.</span><span class="n">json</span> <span class="p">{</span> <span class="n">render</span> <span class="ss">:json</span> <span class="o">=&gt;</span> <span class="vi">@model</span><span class="o">.</span><span class="n">errors</span><span class="p">,</span> <span class="ss">:status</span> <span class="o">=&gt;</span> <span class="ss">:unprocessable_entity</span> <span class="p">}</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>As for philosophy, different people have different views on moving
business logic to the client side. Some business logic can move easily
to the browser while other business logic can not or should not
move. Twitter, for example, has made a point of
<a href="http://engineering.twitter.com/2010/09/tech-behind-new-twittercom.html">becoming clients of their own API</a>
moving significant pieces of functionality to the browser. In our case
of report rendering, why not move some of the calculations to the
browser? Conversely, if a web app were a game, you might not want to
move too much business logic to the browser if that might make it
easier for players to cheat. Those who believe in client-side business
logic will, by definition, have a much easier time accepting the idea
of client-side rendering as well. For others, it may take a little
more exploration for people to warm up to the idea.</p>

<p>Google has a reputation for measuring almost everything. Therefore, I
imagine that they did not make the decision to implement client-side
template rendering in Google+ simply for the lols. They have
tremendous experience with all types of content and page fragments so
should have copious performance data to look at.</p>

<p>Similarly, we (mere mortal developers) can learn from the ideas of
measurement-influenced design decisions. Run some simulations to see
which meets your performance requirements: rendering the page on the
server and transmitting it to the browser or just sending the data and
generating markup on the client. Right tool for the right job and
different strokes for different folks. Or whatever.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[My Talk at the NewHaven.rb October Lightning Talk Meetup]]></title>
    <link href="http://yonkeltron.com/blog/2011/10/23/my-talk-at-the-newhaven-dot-rb-october-lightning-talk-meetup/"/>
    <updated>2011-10-23T14:27:00-04:00</updated>
    <id>http://yonkeltron.com/blog/2011/10/23/my-talk-at-the-newhaven-dot-rb-october-lightning-talk-meetup</id>
    <content type="html"><![CDATA[<p>Exactly one week ago, I had the pleasure of giving a brief talk at
<a href="http://newhavenrb.org">NewHaven.rb&#8217;s</a> October Lightning Talk
meetup. The other presenters totally put me to shame but I did have
fun with
<a href="http://static.yonkeltron.com/presentations/crunchpipe-intro/">slides introducing</a>
my new RubyGem,
<a href="https://github.com/yonkeltron/CrunchPipe">CrunchPipe</a>. I hope that
CrunchPipe will evolve sufficiently so that it might provide a useful
mechanism to help developers organize computation using the pipeline
pattern. Furthermore, I find myself very interested in suggestions
regarding methods of making CrunchPipe suitable for distributed
programming. Checkout the
<a href="https://github.com/yonkeltron/CrunchPipe">slides</a> for an overview and
code examples.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Back in Action]]></title>
    <link href="http://yonkeltron.com/blog/2011/10/05/back-in-action/"/>
    <updated>2011-10-05T08:07:00-04:00</updated>
    <id>http://yonkeltron.com/blog/2011/10/05/back-in-action</id>
    <content type="html"><![CDATA[<p>So, I&#8217;ve done two things wrong. First, I&#8217;ve not blogged anything new
in quite some time after obviously finding many awesome
things. Second, I&#8217;ve been negligent in maintaining the WordPress
installation which used to run this site. With the high development
speed that&#8217;s been going on in the WordPress project, there have been,
as there are with any application, some bugs. Some of these are
security-related. I&#8217;d also like to emphasize that it&#8217;s not my host
which has done anything wrong here. Nor is it the fault of the
WordPress developers! Both gave me the tools to keep my instance
running and up to date. I just got lazy, busy with work and careless
so things fell into disrepair, blah, blah, blah.</p>

<p>Therefore, I&#8217;ve migrated to
<a href="https://github.com/mojombo/jekyll/wiki">jekyll</a> and
<a href="http://octopress.org/">octopress</a> for great justice. Now, I write in
markdown, compile the site with a Ruby toolchain and deploy via git,
ssh or rsync (still working out what I want to do for deploy).</p>

<p>Hooray!</p>

<p>So yeah, that&#8217;s what I&#8217;m working on for the moment.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[By the way, I'm engaged!]]></title>
    <link href="http://yonkeltron.com/blog/2011/02/20/by-the-way-im-engaged/"/>
    <updated>2011-02-20T10:45:47-05:00</updated>
    <id>http://yonkeltron.com/blog/2011/02/20/by-the-way-im-engaged</id>
    <content type="html"><![CDATA[<p>After more than enough time, I&#8217;m finally
<a href="http://sandjohyeah.com">engaged to be married to Sarah</a>!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[xz, all the cool kids are using it]]></title>
    <link href="http://yonkeltron.com/blog/2010/11/04/xz-all-the-cool-kids-are-using-it/"/>
    <updated>2010-11-04T21:21:36-04:00</updated>
    <id>http://yonkeltron.com/blog/2010/11/04/xz-all-the-cool-kids-are-using-it</id>
    <content type="html"><![CDATA[<p>At work, we recently stopped using both
<a href="http://en.wikipedia.org/wiki/Bzip2">bzip2</a> and
<a href="http://en.wikipedia.org/wiki/Gzip">gzip</a> for compression. Instead,
we&#8217;re now using <a href="http://en.wikipedia.org/wiki/Xz">xz</a> which
utilizes the
<a href="http://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Markov_chain_algorithm">LZMA2</a>
algorithm. Why on earth would someone switch compression
algorithms? I&#8217;ll tell you why. Because, I have used xz to compress
all manner of files and it consistently out-performs bzip2! For
example, I compressed a 66mb SQL dump with both xz and bzip2. The
results were that xz created a file over 1.5mb smaller than the one
created by bzip2. <code>original: 67386kb</code> <code>bzip2: 5716.972kb</code>
<code>xz: 4117.625kb</code> To the casual user this might not seem like a lot
but for large files and archives, the savings add up.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Newschool Git workflow with Magit]]></title>
    <link href="http://yonkeltron.com/blog/2010/08/25/newschool-git-workflow-with-magit/"/>
    <updated>2010-08-25T08:17:05-04:00</updated>
    <id>http://yonkeltron.com/blog/2010/08/25/newschool-git-workflow-with-magit</id>
    <content type="html"><![CDATA[<p>I&#8217;ve been on a roll with using
<a href="http://en.wikipedia.org/wiki/Emacs">Emacs</a> to make my workflow
more efficient. So far, so good. The latest major addition is my
adoption of the most-excellent
<a href="http://philjackson.github.com/magit/magit.html">Magit</a> mode for
integrating <a href="http://git-scm.com/">Git</a> and Emacs in a
wonderfully-efficient way. One of the best features is that you get
a magit-status buffer which acts like your Git command center. From
there you can perform whatever actions you want and call up any
repository information you need with ease. The feature I really
wish it had was a
<a href="http://www.kernel.org/pub/software/scm/git/docs/git-blame.html">git-blame</a>
viewer but Magit has so dramatically improved my git workflow that
I really don&#8217;t care.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Great post about Emacs keyboard macros]]></title>
    <link href="http://yonkeltron.com/blog/2010/07/16/great-post-about-emacs-keyboard-macros/"/>
    <updated>2010-07-16T14:45:41-04:00</updated>
    <id>http://yonkeltron.com/blog/2010/07/16/great-post-about-emacs-keyboard-macros</id>
    <content type="html"><![CDATA[<p>I always find great stuff on the
<a href="http://emacs-fu.blogspot.com">emacs-fu</a> blog but today I read a
particularly-wonderful post about
<a href="http://emacs-fu.blogspot.com/2010/07/keyboard-macros.html">Emacs keyboard macros</a>.
Like the author, I&#8217;ve been a long-time Emacs user but never really
got into keyboard macros because it&#8217;s been quite easy to produce an
<a href="http://en.wikipedia.org/wiki/Emacs_Lisp">elisp</a> one-liner in many
cases. That being said, this seems like a great time to learn so I
look forward to reading more on the topic of
<a href="http://www.emacswiki.org/emacs/KeyboardMacros">keyboard macros</a> as
well as learning some
<a href="http://www.emacswiki.org/emacs/KeyboardMacrosTricks">new tricks</a>.
Thanks for a great post!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[newhaven.rb hackfest tomorrow!]]></title>
    <link href="http://yonkeltron.com/blog/2010/06/30/newhaven-rb-hackfest-tomorrow/"/>
    <updated>2010-06-30T10:00:54-04:00</updated>
    <id>http://yonkeltron.com/blog/2010/06/30/newhaven-rb-hackfest-tomorrow</id>
    <content type="html"><![CDATA[<p>Tomorrow, in New Haven, CT will be the &#8220;Ruby, White and Blue&#8221;
Hackfest run by newhaven.rb. We&#8217;ll be working on a few projects
including
<a href="http://github.com/yonkeltron/NHV-Ruby-site">the group&#8217;s site</a> and
most likely some <a href="http://github.com/sandal/prawn">Prawn</a> and
<a href="http://github.com/yonkeltron/scosugbot">ScosugBot</a> stuff.
Beginners and people interested in learning are more than welcome
and we hope to have some excellent projects for people to get
started on. Fill out the <a href="http://is.gd/d9ZiB">RSVP form</a> and we&#8217;ll
meet at 6pm EST at
<a href="http://www.bluestatecoffee.com/">Blue State Coffee</a> on Thursday,
July 1st. Bring a computer and let&#8217;s write some code.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Blogs that sort of make fun of others]]></title>
    <link href="http://yonkeltron.com/blog/2010/06/06/blogs-that-sort-of-make-fun-of-others/"/>
    <updated>2010-06-06T16:02:41-04:00</updated>
    <id>http://yonkeltron.com/blog/2010/06/06/blogs-that-sort-of-make-fun-of-others</id>
    <content type="html"><![CDATA[<p>I have recently been exposed to several different blogs which make
fun of others. I am unsure as to what this genre signifies. Perhaps
I shall ask a sociologist. In the meantime, here is my list so far.
Additions are welcome and will get you a mention and a link.
-   <a href="http://www.peopleofwalmart.com/">People of Walmart</a> (classic)
-   <a href="http://www.deargirlsaboveme.com/">Dear Girls Above Me</a>
-   <a href="http://www.latfh.com/">Look At This Fucking Hipster</a> (buy the</p>

<pre><code>[book](http://amzn.com/0312624972)!)
</code></pre>

<ul>
<li><a href="http://lesbianswholooklikejustinbieber.tumblr.com/">Lesbians who look like Justin Bieber</a></li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Creating a Ruby DSL]]></title>
    <link href="http://yonkeltron.com/blog/2010/05/13/creating-a-ruby-dsl/"/>
    <updated>2010-05-13T22:44:43-04:00</updated>
    <id>http://yonkeltron.com/blog/2010/05/13/creating-a-ruby-dsl</id>
    <content type="html"><![CDATA[<p>Tons of people in the Ruby community go on and on about
<a href="http://en.wikipedia.org/wiki/Domain_Specific_Language">domain-specific languages (abbreviated DSL)</a>
and how wonderful they are. In most cases, I agree with them. I
began to wonder how I could go about leveraging Ruby&#8217;s
awesomely-flexible syntax to create my own DSL. To illustrate my
quest, I have written this article. It assumes you know Ruby. The
example details are completely fictitious and just contrived enough
to be interesting. I promise, the code will be the main focus and I
will link/point to other resources which might be helpful to
budding DSL designers like myself. <strong>Problem</strong> The Dream Castle
Architectural Firm (D-CAF, among friends) wants a tool which it can
use for very high-level prototyping of custom homes. They need it
to be understandable by both computers and humans. It only needs to
keep track of the following things:
-   Houses - Each house has a name
-   Floors - Each house has multiple floors. Each floor has a</p>

<pre><code>number
</code></pre>

<ul>
<li>Rooms - Each floor has multiple rooms and each room has a type</li>
</ul>


<p>The only other requirement is that the DSL be translatable to plain
English so that they can show it to customers. No problem.
<strong>Solution</strong> The DSL for the high-level specification of custom
houses will look like the following:</p>

<pre><code>CustomHouse.build :home do
  floor(1) {
    room :den
    room :kitchen
  }

  floor(2) {
    room :bedroom
    room :bathroom
  }
end
</code></pre>

<p>That&#8217;s it. You specify that a house should be built, that it has a
name, some floors and each floor has some rooms. Simple, easy and
100% pure Ruby. Notice the cunning usage of both do/end and bracket
notation for defining blocks. The outer block passed to
<code>CustomHouse#build</code> uses do/end syntax while the blocks passed to
<code>House#floor</code> use the bracket syntax. These could easily be
reversed (or combined or whatever) but it makes it look pretty and
helps to visually differentiate things so that you (the developer)
and the user (the architect) can things more clearly. Plus, when
you print the output (calling <code>to_s</code> on the instance of <code>House</code>
which gets returned), you get the following wonderful text:</p>

<pre><code>House named home has 2 floors.
Floor 1 has 2 rooms (den, kitchen)
Floor 2 has 2 rooms (bedroom, bathroom)
</code></pre>

<p>It&#8217;s a small house, don&#8217;t be a wiseacre. So, how can such a DSL be
built? <strong>Implementation</strong> Let&#8217;s write the implementation for this
together. First, we&#8217;re going to start of with a module named
<code>CustomHouse</code>. In Ruby, modules are just classes so we&#8217;ll define a
class method called <code>build</code> which will behave like a factory
method.</p>

<pre><code>module CustomHouse
  def self.build(name, &amp;block)
    house = House.new(name)
    house.instance_eval(&amp;block)
    return house
  end
end
</code></pre>

<p>As you can see, the method takes two params, a name and a block.
The first thing that it does is create an instance of the House
class (which we have not yet defined) passing in the name
parameter. Second it
calls <a href="http://ruby-doc.org/core-1.8.7/classes/Object.html#M000607">instance_eval</a>
on the house passing in the block. This ventures into the territory
of <a href="http://en.wikipedia.org/wiki/Metaprogramming">metaprogramming</a>
which is great fun but beyond the scope of this document, though I
am sure others have used it for DSL construction (coincidentally,
if you are interested in Ruby metaprogramming, buy
<a href="http://amzn.com/1934356476">this book</a>). Suffice it to say that it
executes the supplied block in the context of the House instance.
Finally, the <code>CustomHouse#build</code> method returns the instance
of <code>House</code>. (There are those who believe that *any* type of eval
is fundamentally evil. I have been taught this many times and I try
to avoid using eval on an actualy string whenever possible. Still,
someone with a better understanding of Ruby internals might be able
to better explain if this in any better.) Next, let&#8217;s define what
the code for the <code>House</code> class looks like. As a note, it will be
defined in the <code>CustomHouse</code> module, technically making the
fully-namespaced name of the class <code>CustomHouse::House</code>.</p>

<pre><code>class House
  attr_accessor :name, :floors

  def initialize(name = '')
    @name = name.to_s
    @floors = []
  end

  def floor(number, &amp;block)
    fl = Floor.new(number)
    fl.instance_eval(&amp;block)
    @floors &lt; &lt; fl
  end

  def to_s
    str = "House named #{@name} has #{@floors.length} floors.\n"
    @floors.each do |f|
      str &lt;&lt; f.to_s
    end
    str
  end
end
</code></pre>

<p>The above code should appear relatively simple. The House class has
only a few methods. First, it has a constructor function which
takes a name and a block, setting the name as an instance variable
and another instance variable, <code>@floors</code>, which is just an empty
array. Next, it has a method called <code>floor</code> which takes a number
and a block. The guts of this method should look familiar to you
because it mimics almost exactly the <code>build</code> factory method defined
on <code>CustomHouse</code>. Finally, it has a <code>to_s</code> method because of the
requirement that the DSL be translatable to plain English for
clients to check out. If we can just dwell for a moment on the
<code>floor</code> method, notice that, it too, takes a block and uses
<code>instance_eval</code>. It then adds the newly-constructed instance of
<code>Floor</code> to the array in <code>@floor</code>. Let&#8217;s look at the <code>Floor</code> class
now.</p>

<pre><code>class Floor
  attr_accessor :number, :rooms

  def initialize(number = 0)
    @number = number
    @rooms = []
  end

  def room(type)
    @rooms &lt; &lt; Room.new(type)
  end

  def to_s
    str = "Floor #{@number} has #{@rooms.length} rooms ("
    @rooms.each do |r|
      str += "#{r.type}, "
    end
    str.chop!.chop!
    str += ")\n"
    str
  end
end
</code></pre>

<p>There shouldn&#8217;t be anything confusing about the above code as it
doesn&#8217;t use any sort of block eval. In fact, the only thing left to
look at is the class for <code>Room</code> which is even less impressive.</p>

<pre><code>class Room
  attr_reader :type

  def initialize(type)
    @type = type
  end
end
</code></pre>

<p>That&#8217;s it. Seriously, that&#8217;s the entire implementation of the DSL.
You pass a block to <code>CustomHouse#build</code> which gets executed in the
context of a new instance of <code>House</code>. The block calls the
<code>House#floor</code> method with a block which in turn gets executed in
the context of a new instance of <code>Floor</code>. The Floor#room method
adds new <code>Room</code> instances to the class and that&#8217;s basically it.
Here&#8217;s all the code together with the example:</p>

<pre><code>module CustomHouse

  def self.build(name, &amp;block)
    house = House.new(name)
    house.instance_eval(&amp;block)
    return house
  end

  class House
    attr_accessor :name, :floors

    def initialize(name = '')
      @name = name.to_s
      @floors = []
    end

    def floor(number, &amp;block)
      fl = Floor.new(number)
      fl.instance_eval(&amp;block)
      @floors &lt;&lt; fl
    end

    def to_s
      str = "House named #{@name} has #{@floors.length} floors.\n"
      @floors.each do |f|
        str &lt;&lt; f.to_s
      end
      str
    end
  end

  class Floor
    attr_accessor :number, :rooms

    def initialize(number = 0)
      @number = number
      @rooms = []
    end

    def room(type)
      @rooms &lt;&lt; Room.new(type)
    end

    def to_s
      str = "Floor #{@number} has #{@rooms.length} rooms ("
      @rooms.each do |r|
        str += "#{r.type}, "
      end
      str.chop!.chop!
      str += ")\n"
      str
    end
  end

  class Room
    attr_reader :type

    def initialize(type)
      @type = type
    end
  end
end

h = CustomHouse.build :home do
  floor(1) {
    room :den
    room :kitchen
  }

  floor(2) {
    room :bedroom
    room :bathroom
  }
end

puts h
</code></pre>

<p>Try running it and see what happens! Then try writing other
definitions for custom houses and experience the theoretical joy of
the hypothetical architectural firm.
<strong>DSL construction techniques</strong> For clarification and context, I&#8217;d
like to share some other, smaller examples which build on this
technique and demonstrate one more. Behold, a DSL for feeding
Pandas:</p>

<pre><code>Panda.feed {
  nom :bamboo
  nom :chocolate
}
</code></pre>

<p>The implementation of this is both simple and straightforward.</p>

<pre><code>class Panda
  def self.feed(&amp;block)
    panda = Panda.new
    panda.instance_eval(&amp;block)
  end

  def nom(food)
    #whatever
  end
end
</code></pre>

<p>Since the block is evaluated in the context of the new <code>Panda</code>
instance, it has access to the <code>Panda#nom</code> method. For people
deathly afraid of eval, there is this alternative syntax:</p>

<pre><code>Panda.feed do |p|
  p.nom :bamboo
  p.nom :chocolate
end
</code></pre>

<p>Which is implemented with <code>yield</code> instead of <code>instance_eval</code> like
so:</p>

<pre><code>class Panda
  def self.feed
    yield Panda.new
  end

  def nom(food)
    # whatever
  end
end
</code></pre>

<p>For a wonderful and inspiring treatment of Ruby DSLs and associated
patterns, see the
<a href="http://mwrc2009.confreaks.com/13-mar-2009-18-10-jive-talkin-dsl-design-and-construction-jeremy-mcanally.html">most-excellent talk on the matter given by Jeremy McAnally at the 2009 Mid West Ruby Conference</a>.
<strong>Conclusion</strong> DSLs are a fantastic tool which can help to simplify
complicated and repetitive tasks. Ruby is very good for creating
DSLs but it is not the only good tool out there. I advise you look
into the creation of DSLs with Scala and, the best DSL-creation
tool there ever was, Lisp Macros. I am interested in improving this
tutorial for the benefit of those programmers who wish to learn
about DSL construction but don&#8217;t know where to start.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Continuity Control presents at Finovate]]></title>
    <link href="http://yonkeltron.com/blog/2010/05/11/continuity-control-presents-at-finovate/"/>
    <updated>2010-05-11T17:46:52-04:00</updated>
    <id>http://yonkeltron.com/blog/2010/05/11/continuity-control-presents-at-finovate</id>
    <content type="html"><![CDATA[<p>Pleased to say that <a href="http://continuity.net">Continuity Control</a> has
gotten some rather positive feedback while presenting at this
year&#8217;s <a href="http://finovate.com/">Finovate</a>! While not the only
feedback, some of my favorites here: Tweets:
<a href="http://twitter.com/bvinteractive/status/13809793918">one</a> -
<a href="http://twitter.com/netbanker/status/13809781985">two</a> -
<a href="http://twitter.com/rclow/status/13809897357">three</a> -
<a href="http://twitter.com/scotthuber/status/13809729425">four</a> -
<a href="http://twitter.com/consected/status/13809841671">five</a> Photos:
<a href="http://www.flickr.com/photos/37841506@N02/4599133645/">one</a> -
<a href="http://www.flickr.com/photos/37841506@N02/4599140061/">two</a> Truly
proud of be part of the team.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Debian package state backup and restore]]></title>
    <link href="http://yonkeltron.com/blog/2010/04/19/debian-package-state-backup-and-restore/"/>
    <updated>2010-04-19T21:24:02-04:00</updated>
    <id>http://yonkeltron.com/blog/2010/04/19/debian-package-state-backup-and-restore</id>
    <content type="html"><![CDATA[<p>While getting into <a href="http://github.com/carlhuda/bundler">bundler</a>
(which is great, btw), I recalled how often I have longed for a way
to do something similar in Debian. What I&#8217;d really like to be able
to do is something like <code>aptitude backup</code> and get some sort of
backup file which contained all of the packages I had asked to be
installed so that I could install a new base system and then do an
<code>aptitude restore</code> and have those packages be installed. Obviously,
this would pull in the required dependencies which is what we
wanted anyway. I&#8217;ve seen only a few attempts at this and most are
pretty hairy. Is there a good way to do this currently? Are there
plans for this in the future? Is this an irrational desire?</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Building shared libraries]]></title>
    <link href="http://yonkeltron.com/blog/2010/04/08/building-shared-libraries/"/>
    <updated>2010-04-08T20:12:41-04:00</updated>
    <id>http://yonkeltron.com/blog/2010/04/08/building-shared-libraries</id>
    <content type="html"><![CDATA[<p>Being a Debian user, I don&#8217;t make a habit of compiling things by
hand and on those occasions when I do need to do so, I usually use
apt-build (good article, though a bit old
<a href="http://polishlinux.org/linux/debian/apt-build-optimize-debian/%20">here</a>).
However, today I had to get a particularly odd shared library with
a very specific version to match a production environment we have
at work. So, I downloaded the tarball, which was quite large, and
then compiled it. Which took four and a half minutes on my
dual-core (1.83GHz) ThinkPad running <code>make -j 4</code> which isn&#8217;t all
that slow, really. Once it was completed, I looked around (grepped
around) for the output file and was dismayed to discover that there
weren&#8217;t any. After tinkering around for about an hour, I finally
figured out that you can request shared libraries be built by
providing an option to the configure script:
<code>./configure --enable-shared</code> Shortly thereafter, I got the shared
library version I needed and was on the road again. Just a useful
tip which I hope can be of help to someone.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Newest public key ]]></title>
    <link href="http://yonkeltron.com/blog/2010/03/29/newest-public-key/"/>
    <updated>2010-03-29T14:28:00-04:00</updated>
    <id>http://yonkeltron.com/blog/2010/03/29/newest-public-key</id>
    <content type="html"><![CDATA[<p>My GPG public key had expired a few months ago so I made a new one
and set this one not to expire. Backed up in many places this one
is so I&#8217;ll be excited to get it signed at the upcoming
<a href="http://scosug.org">SCOSUG</a> key signing party. So you can get it
<a href="http://yonkeltron.com/my-public-key/">right here on this page</a> and
<a href="http://static.yonkeltron.com/yonkeltron.asc">download it right here</a>.
Also, this post was written on my Android phone (which I love)
using the Wordpress app.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[HTML5 has custom data attributes]]></title>
    <link href="http://yonkeltron.com/blog/2010/03/25/html5-has-custom-data-attributes/"/>
    <updated>2010-03-25T11:16:35-04:00</updated>
    <id>http://yonkeltron.com/blog/2010/03/25/html5-has-custom-data-attributes</id>
    <content type="html"><![CDATA[<p>So, I know that the <a href="http://microformats.org/">Microformats</a>
project has has varying degrees of success in their endeavor to
embed data in HTML such that it does not violate web standards.  As
<a href="http://ejohn.org/blog/html-5-data-attributes/">John Resig pointed out</a>,
others have used things like XML namespacing in XHTML to achieve
similar goals. The most notable usages of this technique are most
likely to be found in the
<a href="http://www.w3.org/TR/xhtml-rdfa-scenarios/">applications</a> of
<a href="http://en.wikipedia.org/wiki/RDFa">RDFa</a>. However, when looking at
the new
<a href="http://blog.solnic.eu/2009/09/08/unobtrusive-javascript-helpers-in-rails-3">unobtrusive JavaScript helpers</a>
in the forthcoming Rails 3, I was tipped off to the huge scope of
the new data- attributes in <a href="http://html5.org/">HTML5</a>. The custom
data- attributes excite me. In HTML5, including any arbitrary
attribute may be included in any element provided that it is
prefixed with data- and doesn&#8217;t interfere with the rest of the
standard. Anything. So I can do the following and have it be
perfectly valid:</p>

<pre><code>&lt;div data-panda="bamboo"&gt; Whatever &lt;div&gt;
</code></pre>

<p>How awesome is that?</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rails + Merb = Rails 3]]></title>
    <link href="http://yonkeltron.com/blog/2010/03/17/rails-merb-rails-3/"/>
    <updated>2010-03-17T10:33:42-04:00</updated>
    <id>http://yonkeltron.com/blog/2010/03/17/rails-merb-rails-3</id>
    <content type="html"><![CDATA[<p>I&#8217;m rather excited about this. Saw this talk
<a href="http://www.infoq.com/presentations/katz-rails3">right here</a>. Oh,
and then there&#8217;s
<a href="http://blog.rubybestpractices.com/posts/gregory/022-rbp-now-open.html">this</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Enthusiasts talk shop casually]]></title>
    <link href="http://yonkeltron.com/blog/2010/03/08/enthusiasts-talk-shop-casually/"/>
    <updated>2010-03-08T14:22:15-05:00</updated>
    <id>http://yonkeltron.com/blog/2010/03/08/enthusiasts-talk-shop-casually</id>
    <content type="html"><![CDATA[<p>I spent some time with a few colleagues yesterday and came to the
conclusion that true enthusiasts gravitate toward talking shop with
one another. This is true even of casual situations. I&#8217;ve had
plenty of &#8220;getting to know you&#8221; and &#8220;let&#8217;s just hang&#8221; social
situations with other geeks where we might start out talking about
any old thing but end up having an enthusiastic exchange about
computers. I don&#8217;t view this is as negative. On the other hand, 
plenty of mailing lists and other communication media devoted to
discussions of specific topics end up going &#8220;off-topic&#8221; as people
socialize more generally. Fine, so it goes both ways. It&#8217;s good to
love what you love and even better to share it.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Neato article about NoSQL on Ars Technica]]></title>
    <link href="http://yonkeltron.com/blog/2010/02/24/neato-article-about-nosql-on-ars-technica/"/>
    <updated>2010-02-24T11:46:28-05:00</updated>
    <id>http://yonkeltron.com/blog/2010/02/24/neato-article-about-nosql-on-ars-technica</id>
    <content type="html"><![CDATA[<p>I am very excited by some of the NoSQL stuff out there and enjoyed
<a href="http://arstechnica.com/business/data-centers/2010/02/-since-the-rise-of.ars/">a recent Ars Technica article</a>.
The first page is some neat background
and<a href="http://arstechnica.com/business/data-centers/2010/02/-since-the-rise-of.ars/2">the second page has a good overview</a>of
some NoSQL options out there.
http://arstechnica.com/business/data-centers/2010/02/-since-the-rise-of.ars/</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The zen of backup theory]]></title>
    <link href="http://yonkeltron.com/blog/2010/02/11/the-zen-of-backup-theory/"/>
    <updated>2010-02-11T13:33:42-05:00</updated>
    <id>http://yonkeltron.com/blog/2010/02/11/the-zen-of-backup-theory</id>
    <content type="html"><![CDATA[<p>When stuck inside due to all the snow, there is no better time to
consider the topic of backup. Seriously, backup is important and
the issue is fascinating.  The area of backup brings together so
many topics in computing. Think about it! To do backup
successfully, you must deal with data transfer, data integrity
validation, networks, distributed systems, compression and, if
you&#8217;re doing it right, cryptography. It is not just computer
science however, but also workflow management and that
somewhat-nebulous-yet-often-referred-to thing of systems thinking.
I got to thinking about the topic of backups and was curious as to
the state of research as well as backup tools. A great intro to
so-called &#8220;backup theory&#8221; is available on the
<a href="http://en.wikipedia.org/wiki/Backup">&#8216;Backup&#8217; Wikipedia article</a>
and
<a href="http://www.educ.umu.se/~cobian/backuptheory.htm">others have written</a>
on the subject
<a href="http://www.google.com/search?q=backup%20theory">(Google will verify</a>
that this is true). As it turns out, advances in storage have
recently offered many new opportunities for improving the way that
a given backup process might work. Several distributed
fault-tolerant filesystems are coming along quite nicely. Though
the <a href="http://labs.google.com/papers/gfs.html">Google File System</a>
and the equivalent <a href="http://hadoop.apache.org/hdfs/">HDFS</a> project
which is part of <a href="http://hadoop.apache.org/">Apache&#8217;s Hadoop</a> have
gotten much attention, there are other options.
<a href="http://www.gluster.org/">GlusterFS</a> (follow
<a href="http://twitter.com/gluster">GlusterFS on Twitter</a>, perhaps?) and
<a href="http://ceph.newdream.net/">Ceph</a> are two excellent examples of
Free/Open Source Software projects which offer the compelling combo
of fault tolerance and distributed storage. They each employ
replication and have similar architectures insofar as they abstract
individual machines into &#8220;chunks&#8221; or &#8220;blocks&#8221; and manage
replication automatically. One interesting difference is that while
GlusterFS exports filesystems &#8220;as-is&#8221; (see the docs for an
explanation), Ceph exports entire block devices. So then what about
the theory and goals of backup? In my opinion, backing up is not
enough. Having a backup plan and executing it perfectly doesn&#8217;t
mean a thing if the data can&#8217;t be recovered.  (In fact this issue
relates strongly to a larger discussion of reliability. Rather than
focusing exclusively on total time spent in a failure state,
individuals concerned with reliability would also do well to
consider how fast a system can recover from those failures. If a
system can be up and running again after only 5 minutes, then that
system can go down 12 times before reaching an hour of downtime. If
another system takes 20 minutes to rebound from a failure, then
that system can only go down 3 times!) I haven&#8217;t yet gotten to
thinking about the problem of restoration following failure for
anything other than plain old files. For example, I backup my
personal data to servers in Philadelphia and California in addition
to an external hard drive in my apartment. I make careful use of 
old stand-byes like
<a href="http://en.wikipedia.org/wiki/Tar_(file_format">tar</a>),
<a href="http://en.wikipedia.org/wiki/Gzip">gzip</a> and
<a href="http://en.wikipedia.org/wiki/Rsync">rsync</a> along with a checksum
utility like <a href="http://en.wikipedia.org/wiki/Md5sum">md5sum</a> or, more
recently, something in the
<a href="http://en.wikipedia.org/wiki/Sha1sum">SHA</a> family. Plus I use the
<a href="http://git-scm.com/">git</a> revision control system for code and
<a href="http://joey.kitenet.net/code/etckeeper/">etckeeper</a> for config. By
backing up all of my configuration data in addition to my personal
files, I make it so that I can easily return a given system to a
usable state, if not restoring it perfectly. I have successfully
restored systems by doing little more than a reverse rsync. To be
fair, I just spoke about about the few systems under my personal
control which constitute a small and limited case. I back up to
different locations which is good practice but my local copy is
certainly not sufficient for anything industrial. If the disk
breaks, I&#8217;m out of luck. Considering a larger-scale system is when
GlusterFS, Ceph and others would come in handy. Obviously there are
a <a href="http://amzn.com/0596102461">great</a>
<a href="http://amzn.com/0596001533">many</a>
<a href="http://amzn.com/0471227145">books</a>
<a href="http://amzn.com/1420076396">written</a> about
<a href="http://amzn.com/1430226625">this topic</a> but, for the purposes of
discussion, if I were to build a platform for the reliable storage
of huge amounts of data, my project would look something like
this&#8230; First, I would round up spare computers with room for extra
disks. They machines would not need to be particularly fast or
possess large amounts of memory. I&#8217;m not sure of the exact hardware
requirements for either GlusterFS
(<a href="http://gluster.com/community/documentation/index.php/Storage_Server_Installation_and_Configuration#Hardware_Requirements">vague wiki entry</a>)
or Ceph but it&#8217;s hard to imagine that they&#8217;d require huge amounts
of anything but disk space. Anyway, if my organization had old
desktops or something which were being replaced then they might be
perfect candidates. Second comes storage. It seems that at the time
of this writing, one can purchase a 1TB hard disk for around US$85.
Let us assume that 20 desktop machines could be procured and each
had two spare disk slots. For around US$3500 (figuring 2 US$85
disks per machine and a little more for tax+shipping, etc.) one
could buy 20TB of storage. Now, it&#8217;s not quite that simple as the
fault-tolerance scheme in both GlusterFS and Ceph relies on
replication. Assuming the accepted replication factor of 3 (a norm
adhered to by the Google File System), that would reduce the 20TB
storage block by a third  leaving around 6 and two thirds terabytes
of fault-tolerant storage. Filesystems of this type usually require
cluster control processes which (ideally, I think) reside on
dedicated machines so an extra machine or two would also be
required. I got a good explanation of how metadata servers work in
GFS/HDFS by reading the
<a href="http://hadoop.apache.org/common/docs/current/hdfs_design.html">HDFS design document</a>,
actually. Metadata servers and other control processes serve
similar functions. Ceph documents are very explicit about not
having a single point of failure whereas GlusterFS is not quite so
adamant. I need some help figuring out if GlusterFS is as
fault-tolerant in that respect. For under US$4000, one could
theoretically build over 6TB of fault-tolerant distributed storage
(provided that spare machines are plentiful, something which
shouldn&#8217;t be a problem for organizations with a semi-regular
hardware replacement cycle). Now, as for the usage of that storage
system for backup, it&#8217;s a different piece of the discussion. I&#8217;ve
seen quite a few setups where a single-but-very-large server
provides networked storage to a large number of users via something
like samba or NFS. In this case, the big server is usually blessed
with some complicated RAID arrangement which people put entirely
too much faith in. No one ever listens that RAID is not a backup
strategy. Personally, I don&#8217;t believe in hardware reliability
because it seems silly to spend money trying to prevent hardware
from failing when you know it&#8217;s going to break (eventually) anyway.
I&#8217;m not saying that RAID isn&#8217;t useful because it *is* useful and
has a place. What I am saying is that it&#8217;s not backup. So if an
organization has a big network storage server then where does that
get backed up to? It&#8217;s hard to backup 6 TB off site but it can
(certainly) be done. However, if an organization is lucky enough to
have multiple buildings then a distributed storage cluster like I
described earlier would be an excellent addition to the overall
backup infrastructure. Putting a few machines in different
buildings and using it as a place to shadow the main file server
and whatever else needs to be backed up would grant an added
measure of security. Snow days are a good time for thinking and my
backup jobs went smoothly. However, I feel as if I have begun a
track of study which might yield some good results. Granted, it&#8217;s
not just about the technology
(<a href="http://arxiv.org/abs/cs/0412074">humans screw things up</a>) but the
ability to build reliable and fault-tolerant storage systems for
massive amounts of data using only commodity hardware is a huge
boon to users everywhere. This concludes my backup rant.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Cool Free/Open Source Software from Google]]></title>
    <link href="http://yonkeltron.com/blog/2009/12/28/cool-freeopen-source-software-from-google/"/>
    <updated>2009-12-28T17:59:10-05:00</updated>
    <id>http://yonkeltron.com/blog/2009/12/28/cool-freeopen-source-software-from-google</id>
    <content type="html"><![CDATA[<p>As has been spoken about endlessly
(<a href="http://ostatic.com/blog/the-quieter-side-of-open-source-at-google">OStatic</a>,
<a href="http://www.osnews.com/story/22663/35_Google_Open_Source_Projects_That_You_Probably_Don_t_Know">OSnews</a>),
there is a great blog post from 0x1fff with many (started at 35, is
now many more)
<a href="http://blog.0x1fff.com/2009/12/35-google-open-source-projects-that-you.html">open source projects from Google</a>.
In fact and indeed, there is some cool stuff on there. I knew about
<a href="http://code.google.com/p/google-caja/">Caja</a> and
<a href="http://code.google.com/p/protobuf/">Protocol Buffers</a> (wish there
was a JS port of protocol buffers) but did not know about
<a href="http://code.google.com/p/crush-tools/">CRUSH</a> and
<a href="http://code.google.com/p/skia/">skia</a>. Honestly, there are plenty
of cool projects out there and my already-positive opinion of
Google is only bolstered by the fact that they give back so
willingly. Gotta love it.</p>
]]></content>
  </entry>
  
</feed>
