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

  <title><![CDATA[Narnach's blog]]></title>
  <link href="https://blog.narnach.com/atom.xml" rel="self"/>
  <link href="https://blog.narnach.com/"/>
  <updated>2022-09-12T15:30:04+02:00</updated>
  <id>https://blog.narnach.com/</id>
  <author>
    <name><![CDATA[Wes Oldenbeuving]]></name>
    <email><![CDATA[wes@narnach.com]]></email>
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[.gitignore does not unignore my file!]]></title>
    <link href="https://blog.narnach.com/blog/2022/dot-gitignore-does-not-unignore-my-file/"/>
    <updated>2022-09-12T15:17:11+02:00</updated>
    <id>https://blog.narnach.com/blog/2022/dot-gitignore-does-not-unignore-my-file</id>
    <content type="html"><![CDATA[<p>Today I ran into an interesting edge case that my colleague and I could not easily explain until we checked the <code>git</code> manual. I’m sharing the details because even after using <code>git</code> for 15 years, I was mildly surprised by the behavior. Luckily, it <em>does</em> make sense now that I understand the underlying reasons.</p>

<h2>What&rsquo;s .gitignore?</h2>

<p>Anyone using <a href="https://git-scm.com/">git</a> for version control is likely familiar with the <code>.gitignore</code> file where you can specify which file name patterns <code>git</code> will ignore by default when you perform various actions, such as <code>git status</code>, <code>git diff</code> and <code>git add</code>. It’s <em>very</em> useful to ignore generated files and temporary files. You can add a line that starts with a <code>!</code> to make it NOT ignore files with that pattern. Patterns are evaluated top to bottom, and the last pattern that matches a file will determine if it’s ignored or not.</p>

<h2>What we did</h2>

<p>We wanted to add a simple <code>.gitkeep</code> file to preserve the <code>tmp/pids</code> directory in our project on all machines that checked out the project. This arguably trivial operation did not work and took me a while to figure out <em>why</em> it did not work.</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class=''><span class='line'># Lets git NOT ignore .gitkeep files, i.e. always check them in:
</span><span class='line'>echo "!.gitkeep" &gt;&gt; .gitignore
</span><span class='line'>touch tmp/pids/.gitkeep
</span><span class='line'>git status
</span><span class='line'># ... tmp/pids/.gitkeep is NOT listed as new file</span></code></pre></td></tr></table></div></figure>


<h2>Why it did not work</h2>

<p>So why is the file we just told <code>git</code> we want to NOT ignore still getting ignored? It’s because our <code>.gitignore</code> already contained this handy line that ignored all temporary files (because they have no place being checked in!)</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>/tmp/*</span></code></pre></td></tr></table></div></figure>


<p>This line makes <code>git</code> ignores all files and directories inside <code>tmp</code>. It’s also the direct reason why our earlier change did not give the result we want. After some reading of the <a href="https://git-scm.com/docs/gitignore">manual</a>, I found this relevant bit (emphasis mine):</p>

<blockquote><p>An optional prefix &ldquo;!&rdquo; which negates the pattern; any matching file excluded by a previous pattern will become included again. <strong>It is not possible to re-include a file if a parent directory of that file is excluded.</strong> Git doesn’t list excluded directories for performance reasons, so any patterns on contained files have no effect, no matter where they are defined.</p></blockquote>

<p>It <em>really</em> makes sense from a performance perspective to <em>not</em> recurse into children of ignored directories to see if they happen to be <em>not</em> ignored.</p>

<p><strong>TL;DR: you need to re-include an ignored parent directory if you want to customize rules for its contents.</strong></p>

<h2>How to make git really NOT ignore your file</h2>

<p>Let’s update <code>.gitignore</code> using our new knowledge. The <code>git diff</code> after my changes:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class=''><span class='line'> /tmp/*
</span><span class='line'>+!/tmp/pids
</span><span class='line'>+/tmp/pids/*.pid
</span><span class='line'>+!.gitkeep</span></code></pre></td></tr></table></div></figure>


<p>The order of operations here is:</p>

<ul>
<li>Ignore <code>/tmp/*</code> and all its children</li>
<li>Add <code>/tmp/pids</code> back</li>
<li>Ignore all <code>.pid</code> files in <code>tmp/pids</code> (because those are the only ones generated there)</li>
<li>Globally enable <code>.gitkeep</code></li>
</ul>


<h2>Alternative: use the &ndash;force</h2>

<p>Alternatively, you can use <code>git add --force tmp/pids/.gitkeep</code> to add it while ignoring <code>.gitignore</code> rules. Arguably that’s faster than checking the manual and thinking about it, but it also prevents you from learning <em>why</em> it failed to work in the first place.</p>

<p>This worked for me &trade;, so I hope it helps you as well. If you run into issues, feel free to reach out to me via <a href="http://twitter.com/narnach">Twitter</a> or <a href="mailto:wes@narnach.com">email</a>. I&rsquo;m an experienced <a href="https://www.narnach.com/">Ruby software developer</a> with a focus on back-end systems and an obsession with code quality. I even have a few Ruby on Rails <a href="https://www.rormaas.com/">maintenance services</a> that I offer. If you still need to upgrade to Rails 6, then grab the handy free <a href="https://www.rormaas.com/rails_upgrades.html#our-rails-upgrade-process">checklist</a> or reach out to have me do it for you.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[System tests in rails 6 + rspec + vcr + capybara]]></title>
    <link href="https://blog.narnach.com/blog/2021/system-tests-in-rails-6-plus-rspec-plus-vcr-plus-capybara/"/>
    <updated>2021-05-27T14:33:03+02:00</updated>
    <id>https://blog.narnach.com/blog/2021/system-tests-in-rails-6-plus-rspec-plus-vcr-plus-capybara</id>
    <content type="html"><![CDATA[<p>Getting this setup working took me an hour of searching the web to get some of the interactions working, so I hope this helps you do it faster and avoid some pitfalls I stumbled into.</p>

<h2>Summary</h2>

<p>This post describes some of the obstacles I ran into getting proper JS-supported system tests working in my up-to-date Rails app, <a href="https://www.infinity-feed.com/">Infinity Feed</a>.</p>

<p>It <em>used</em> to be complex to get Capybara working with a JS-enabled headless browser for your integration tests. This has gotten significantly easier with Rails 5.x and got another boost with 6.x.</p>

<p>If your knowledge about Rails frontend testing still stems from the Rails v4 or v5 era, you might be pleasantly surprised by how easy it can be now.</p>

<h2>Setting the scene</h2>

<p>For this blog post, the relevant bits of my stack are:</p>

<ul>
<li>capybara 3.35</li>
<li>faraday 1.4</li>
<li>rails 6.1</li>
<li>rspec 3.10</li>
<li>rspec-rails 5.0</li>
<li>turbo-rails 0.5</li>
<li>vcr 6.0</li>
<li>webdrivers 4.6</li>
<li>webmock 3.13</li>
</ul>


<p>You’ve got the usual suspects here that test Rails with RSpec. I use unit tests for models and other plain old Ruby objects (POROs), there are controller tests for specific interactions and there <em>was</em> a feature test intended to test my frontend interactions. This is done differently in the modern era by using system tests.</p>

<p>I use Faraday for HTTP calls, so <a href="https://github.com/vcr/vcr">VCR</a> + Webmock is part of my test stack to intercept &amp; record HTTP calls so they can be replayed without hitting the network during my tests. This makes tests more consistent and faster. Win-win!</p>

<p>I had a feature test written with out-of-the-box Capybara which appeared to work just fine, until I wanted to test that <a href="https://turbo.hotwire.dev">Hotwire Turbo</a> was doing its magic to make automatic JS-powered HTTP calls to replace my HTML with new HTML. The JS did not get executed in my tests!</p>

<p>So, I had to figure out how to enable JS. Remembering how much of an ordeal this used to be, and how often the best practices changed, I started searching the internet for how it is done in 2021.</p>

<h2>System tests have replaced features</h2>

<p>Since Rails 5.0/5.1 there are <a href="https://guides.rubyonrails.org/testing.html#system-testing">system tests</a>, which are similar to the old feature tests we had, but now Rails <a href="https://github.com/rspec/rspec-rails/tree/5-0-maintenance#feature-specs">handles all of the overhead</a> you <em>used</em> to have to do yourself. You can stop futzing with DatabaseCleaner and configuring Puma to run in-process. It’s all taken care of by Rails now.</p>

<p>Since Rails 6, integration with browsers for testing happens via the <a href="https://github.com/titusfortner/webdrivers">webdrivers</a> project, which handles downloading and updating the browser for you. It just works! Just beware of unexpected VCR interactions (see below).</p>

<h2>Migrating features to system tests</h2>

<p>It’s really easy:</p>

<ul>
<li>Move feature files from <code>spec/features/</code> to <code>spec/system/</code></li>
<li>Change <code>type: :feature</code> to <code>type: :system</code> if needed for these files</li>
</ul>


<p>Add this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>  <span class="n">before</span> <span class="p">{</span> <span class="n">driven_by</span> <span class="ss">:selenium_chrome_headless</span> <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>To the top of your system test files to pick a driver that supports JS. You can use this to <a href="https://api.rubyonrails.org/classes/ActionDispatch/SystemTestCase.html">configure</a> different browsers and screen sizes.</p>

<p>And now you have working system tests!</p>

<p>There’s a few extra things left to configure if you need them.</p>

<h2>Devise integration</h2>

<p>If you use <a href="https://github.com/heartcombo/devise">Devise</a> to handle your authentication, you should register its integration test helpers to be used in feature and system tests:</p>

<figure class='code'><figcaption><span></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="c1"># spec/rails_helper.rb</span>
</span><span class='line'>
</span><span class='line'><span class="no">RSpec</span><span class="o">.</span><span class="n">configure</span> <span class="k">do</span>
</span><span class='line'>  <span class="n">config</span><span class="o">.</span><span class="n">include</span> <span class="no">Devise</span><span class="o">::</span><span class="no">Test</span><span class="o">::</span><span class="no">IntegrationHelpers</span><span class="p">,</span> <span class="ss">type</span><span class="p">:</span> <span class="ss">:feature</span>
</span><span class='line'>  <span class="n">config</span><span class="o">.</span><span class="n">include</span> <span class="no">Devise</span><span class="o">::</span><span class="no">Test</span><span class="o">::</span><span class="no">IntegrationHelpers</span><span class="p">,</span> <span class="ss">type</span><span class="p">:</span> <span class="ss">:system</span>
</span><span class='line'>  <span class="c1"># ...</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>This enables the <em>very</em> useful <code>sign_in</code> helper function, so your tests can focus on testing actual features instead of always having to simulate a login.</p>

<h2>VCR integration</h2>

<p>VCR helps you intercept HTTP calls during tests, as I mentioned earlier. The thing is that Webdrivers automatically checks if the latest version of the browser is installed and downloads it if needed. As you can imagine, this did <em>not</em> play well with VCR.</p>

<p>My solution is to force the webdriver to check for an update <em>before</em> I configure VCR. VCR also needs to be told not to interfere with system test calls.</p>

<figure class='code'><figcaption><span></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>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="c1"># spec/rails_helper.rb</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># RSpec.configure do</span>
</span><span class='line'><span class="c1">#   ...</span>
</span><span class='line'><span class="c1"># end</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Load this and update the driver before loading VCR.</span>
</span><span class='line'><span class="c1"># If you don&#39;t, VCR will intercept the version check.</span>
</span><span class='line'><span class="nb">require</span> <span class="s1">&#39;webdrivers&#39;</span>
</span><span class='line'><span class="no">Webdrivers</span><span class="o">::</span><span class="no">Chromedriver</span><span class="o">.</span><span class="n">update</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Configure VCR to don&#39;t interfere with system tests</span>
</span><span class='line'><span class="no">VCR</span><span class="o">.</span><span class="n">configure</span> <span class="k">do</span> <span class="o">|</span><span class="n">config</span><span class="o">|</span>
</span><span class='line'>  <span class="c1"># 127.0.0.1 is for system tests so whitelist it</span>
</span><span class='line'>  <span class="n">config</span><span class="o">.</span><span class="n">ignore_hosts</span> <span class="s1">&#39;127.0.0.1&#39;</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1"># My personal settings, feel free to ignore/change</span>
</span><span class='line'>  <span class="n">config</span><span class="o">.</span><span class="n">cassette_library_dir</span> <span class="o">=</span> <span class="s1">&#39;spec/fixtures/vcr_cassettes&#39;</span>
</span><span class='line'>  <span class="n">config</span><span class="o">.</span><span class="n">hook_into</span> <span class="ss">:webmock</span><span class="p">,</span> <span class="ss">:faraday</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Conclusion</h2>

<p>This worked for me &trade;, so I hope it helps you as well. If you run into issues, feel free to reach out to me via <a href="http://twitter.com/narnach">Twitter</a> or <a href="mailto:wes@narnach.com">email</a>. Besides being close to launching a smart RSS reader over at <a href="https://www.infinity-feed.com">Infinity Feed</a>, I&rsquo;m a <a href="https://www.narnach.com/">freelance Ruby software developer</a> with a focus on back-end systems and an obsession with code quality.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Launching is scary]]></title>
    <link href="https://blog.narnach.com/blog/2021/launching-is-scary/"/>
    <updated>2021-05-11T18:34:36+02:00</updated>
    <id>https://blog.narnach.com/blog/2021/launching-is-scary</id>
    <content type="html"><![CDATA[<p>Until you decide to make your product available to the world, it’s just <em>yours</em>. <em>You</em> get to add to it, remove from it and change it however you want. <em>You</em> can do this without risk of anyone getting upset that you changed or removed their favorite feature. There is nobody to <em>judge</em> your product. Yet.</p>

<p>When you <em>do</em> launch, everything changes. Suddenly it’s not only <em>yours</em> anymore, it’s also <em>theirs</em>. Your users (who preferably turn into your customers) will start to use it. They develop attachments to what is there. They get frustrated with what <em>they</em> don’t like. They will, collectively, present you with conflicting requests to make changes.</p>

<p>The worst outcome is that nobody cares, and all that&rsquo;s left is you and your disappointment.</p>

<p><em>Not</em> launching, just yet, in order to fix that one bug, to tweak that one thing… it’s so tempting! You get to keep it for yourself, just for a little while longer.</p>

<p>The problem is that this mindset is similar to analysis paralysis: you can get stuck in it without ever launching. There is always something <em>more</em> you can do. Something to add, something to fix. It will <em>never</em> be perfect, but you can trick yourself into trying to achieve it. In reality, you’re just avoiding the potential for disappointment that <em>could</em> come from an unsuccessful launch.</p>

<p>I’ve read somewhere that if you are not at least a <em>little</em> ashamed of what you have launched, you have waited too long. It always sounded wise and useful, but now that I’m getting closer to launching <a href="https://www.infinity-feed.com/">Infinity Feed</a>, my mind is spinning and grasping at all kinds of excuses for why I should wait <em>just a little longer</em>.</p>

<p>How I’ve been dealing with it? I’ve started talking to folks about what I’m building. I’ve <a href="https://blog.narnach.com/blog/2021/having-another-look-at-crypto/">hinted</a> yesterday in the footer of my blog post that it will go live soon-ish. I’ve put up a marketing placeholder page (which read okay at the time, but now I just want to rip it off and replace it with my new one). Basically: I’ve started building momentum that should result in me launching the thing I’ve been announcing.</p>

<p>Now if you’ll excuse me, I have a <em>few</em> more things to do before I hit the “deploy” button for real. Launching really is scary, but this post pushed me another step closer to doing it.</p>

<p>Curious? Want to say something? Feel free to reach out to me via <a href="http://twitter.com/narnach">Twitter</a> or <a href="mailto:wes@narnach.com">email</a>. Besides being close to launching a smart RSS reader over at <a href="https://www.infinity-feed.com">Infinity Feed</a>, I&rsquo;m a <a href="https://www.narnach.com/">freelance Ruby software developer</a> with a focus on back-end systems and an obsession with code quality. I’ve also decided to look at cryptocurrencies again, so expect me to mention that again in the future.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Having another look at crypto]]></title>
    <link href="https://blog.narnach.com/blog/2021/having-another-look-at-crypto/"/>
    <updated>2021-05-10T22:26:49+02:00</updated>
    <id>https://blog.narnach.com/blog/2021/having-another-look-at-crypto</id>
    <content type="html"><![CDATA[<blockquote><p>Addition on 8 September 2022: note that I never published a follow-up for this due to how obvious it is that a <em>lot</em> of crypto is a scam, and how ethically dubious a lot of practices are. As a layperson, assume you will get fleeced when you enter the ecosystem. The amount of tinfoil and conspiracy theories in this scene promote Fear/Uncertainty/Doubt (FUD) which aims at getting new people to add money to the crypto ecosystem in order to prop up prices for folks already invested. Sound familiar? Yep, it&rsquo;s a huge pyramid scheme! See also: <a href="https://www.youtube.com/watch?v=YQ_xWvX1n9g">Line goes up</a>, a good video that breaks down the ecosystem and issues.</p></blockquote>

<h2>Why now?</h2>

<p>Two of my friendly colleagues disappeared into a crypto-shaped black hole over the last three months. They re-emerged, talking with great enthusiasm about it. They have doubled their seed money, and talk about all the potential for the technologies in the space. I must admit, they have broken down some of my long held skepticism, so it’s time to look at it again myself and see if their hype is real.</p>

<p>For context: I’m coming at this as a crypto skeptic software developer. I looked at Bitcoin when it was <em>very</em> new (5+ years ago?) and did not get it. It seemed like speculation on a virtual coin without intrinsic value or purpose. It smelled a lot like a pyramid scheme. Association with black market trade did not help. In the last few years the negative environmental impact of Bitcoin has not made me a fan either.</p>

<p>I’ve looked into speculative trade before. I’ve had a good look at <a href="https://en.wikipedia.org/wiki/Foreign_exchange_market">ForEx</a> in 2012-2013, doing paper trading, lots of reading, and some programmatic stuff, before deciding the speculative stuff was not really for me. Similarly I’ve read up on stock market investment, including <a href="https://www.investopedia.com/terms/b/bengraham.asp">Benjamin Graham</a>’s classic book.</p>

<p>The crypto world has developed a lot in the last few years. It’s not just Bitcoin anymore, so let’s dive back in to see what’s up with it now.</p>

<p>In case it’s not obvious: I’m <em>not</em> an expert, this is not financial advise, etc. Feel free to point me in the direction of more solid info where I can learn.</p>

<h2>Setting goals</h2>

<p>It’s good to clarify what your goals are when you start with something. It helps you direct your search for information, and might help a bit against temptations.</p>

<p>My high level goals:</p>

<ul>
<li>Try to understand how it works</li>
<li>Try to understand what you need to get started</li>
<li>Try to get a basic setup working to interface with the systems (buy/sell coins, use a smart contract, etc)</li>
<li>How do you make money? Look at fees, <em>fundamentals</em> and historic trends/behaviors… is there a minimum amount of money at which you “need” to start to mitigate overhead and fees? How is starting with €100 vs €1000 vs €10000? What trade strategies are there and how do you balance risk vs reward? Are certain coins/tokens better than others? Can stock/ForEx strategies be adapted, index fund strategies?  <em>Why (not)?</em></li>
<li>Actually try to make money if the previous goal resulted in something which gave me enough confidence that it might work. Again, try to come up with a plan that balances risk vs reward (I’m inclined towards spreading risk and draining profits at set percentage increases; ideally I withdraw a fixed percentage of my profits so eventually I’m only working with my profits)</li>
<li>Making stuff: how hard is it to write a smart contract?</li>
<li>Making stuff: how hard is it to build tools that interface with the systems? DAPs (?) / distributed applications are a thing.</li>
</ul>


<h2>The very basics: how does it work?</h2>

<p>First goal: I want to <strong>understand</strong> how things work in crypto in 2021. Below is my understanding so far. It will probably be wrong on a lot of accounts, but that’s why it’s nice to write down so I can correct it later.</p>

<p>Which pieces are there on the market? What types of coins/tokens/contracts/etc are there? My very limited understanding right now is:</p>

<ul>
<li>Coins. Stable or not. Serious or not. I’ve heard the term “shitcoins” multiple times already, so not all coins have the same esteem.</li>
<li>Tokens, fungible or not (fungible is another word for interchangeable, fiat currency is fungible, because each euro is the same as another euro. A non-fungible token is closer to a signed and numbered limited edition collector’s item, one is <em>not</em> the same as another). What is the difference between a coin and a token?</li>
<li>Smart contracts.

<ul>
<li>Programming angle: is there one programming language, or many? How generic or domain specific is this? What are best practices? What are common pitfalls? How does debugging work? How does your toolchain look: is there versioning and source control? How does testing look? Static analysis? Are there code libraries or dependencies?</li>
<li>Functional angle: how are they <em>used</em>? What other classes of products are stacked on top? I heard about contracts being deployed as neutral agents who just operate protocols defined by the contract (or by multiple contracts), with ownership voided so they truly are running the way they are until the end of time. How have folks dealt with bugs, viruses, etc? How does the infrastructure work that powers this? Who pays for it and how?</li>
</ul>
</li>
<li>DeFi, decentralized finance. Mumble, mumble, “and then you buy your house via DeFi because banks don’t have money so they don’t underwrite mortgages anymore.” Yeah, I’m still a bit puzzled about this. This would involve pretty good real-world legal contracts to defer transfer of ownership to a smart contract, and to have the smart contract somehow enforce that the offline land registry (that’s what we have in the Netherlands at least) is updated to reflect the <em>actual</em> owner of a piece of land.</li>
</ul>


<h2>Where do coins/tokens come from?</h2>

<p>I know Bitcoin has miners who burn CPU/GPU/FPGA time to calculate hashes in order to process transactions and create new bitcoins in the process. Transactions are relatively slow and expensive (a Google search led me to <a href="https://privacypros.io/tools/bitcoin-fee-estimator/">this</a> which claims 1MB per 10 minutes of transaction bandwidth, currently you pay 3-10 USD per transaction depending on how much of a hurry you are in (10-60 min delay). That’s relatively little if if your trade is for thousands of dollars, but a lot for a cup of coffee.</p>

<p>Look into how/why Bitcoin has a 4-year periodicity in its prices. There’s something about regularly scheduled restrictions in how many new coins are mined, so total new supply decreases and as such value doubles. This makes huge waves and affects all coins, apparently. My friends keep talking about how the next few months will have huge gains and then it’ll dry up. <strong>Why?</strong></p>

<p>How do the other coin types do this? There are <strong>Proof of Stake</strong> coins (vs Bitcoin’s Proof of Work) where there’s a finite supply of coins which are setup via smart contracts, have a buy-in ahead of time and then freely trade once they go live. There’s a thing about burning coins as part of the protocol so they get more valuable over time. There’s also a thing about staking claims, where you freeze your coins temporarily in exchange for a percentage of the transaction fees? Time periods here are daily or weekly, so it’s all incredibly rapid compared to the yearly rates traditional banks pay.</p>

<h2>What are the fundamentals here?</h2>

<p>Analogy to the stock market, where each stock represents a piece of ownership of a company. Shares earn dividends for you merely holding on to them. There’s also profit/loss based on the resale value of the share. Companies have revenue, profit, equity, capital reserves, etc. A lot of metrics you can contrast to the share performance.</p>

<p>Based on this you can choose to go long on a share (i.e. you buy it and just hold on to it), avoid it, or do risky things such as shorting (that is, you borrow a share to sell it now and promise to buy it back later; if it works you pocket the profit, if you fail your loss has no hard limit other than the share price). While at it: don’t <strong>every</strong> borrow money to invest. Only play with what you can afford to lose.</p>

<p>Do things like stop/loss orders exist in crypto? What are the new options that have no analogy in the classic markets?</p>

<h2>How does it connect back to the real/offline world?</h2>

<p>How can you use it, right now? Better question: how <em>is</em> crypt used right now? How mature are the products? What are common pitfalls, and how have those been mitigated?</p>

<p>How user friendly / approachable is crypto? How close are we to my parents (who are tech late adopters) using this for something useful? How close are we to them being able to explain it to someone else?</p>

<h2>Tooling &amp; usability</h2>

<p>My friends mentioned that there’s a lot of rough edges and opportunity for quality of life tools. What would be useful? Is there a reason these don’t exist yet? Is there an opportunity to monetize some of this?</p>

<h2>Risk management</h2>

<p>To manage risk you have to be aware of risks. What are the obvious ones?</p>

<p>Crypto exchanges / brokers can run away with your coins, and apparently that’s just a risk you have to accept. Crypto is dog-eat-dog world, like the game Eve Online. Don’t trade with what you can’t afford to lose. How can you identify trustworthy ones, besides just going with what everyone is doing? If you can’t do this, how can you identify the (obviously) untrustworthy ones?</p>

<p>Wallets, ledgers, accounts. Somewhere to store your coins/tokens/etc. In my mind it’s close to how your SSH keys also control your bank account. Public/private key encryption. Is this model accurate? Be cautious and careful. What are good practices for keeping things safe?</p>

<p>Who are the big fishes in each pond, and what are their interests? When they move, they can generate huge waves. Stop/loss orders which normally might make sense could get triggered <em>hard</em> due to big fish movements. My friends mention that folks trading on margin tend to have their contracts enforced at the end of the day/week/month/quarter. The quarterly ones were unexpected to them due to the volatility they caused. Knowing what/when happens means you can anticipate it.</p>

<p>There is the obvious loss of value, loss of trade volume/liquidity, risk of the huge fishes in the market making splashes, problems with underlying things (i.e. if one coin is connected with others, they have a relation).</p>

<h2>Where/how to start?</h2>

<p>Writing this down helped me get a picture of what I <em>think</em> I know. Plenty of questions and uncertainty, so next is filling in the gaps and double checking myself, then checking with my friends if my understanding matches theirs.</p>

<p>I’m going to work the high-level goals from top to bottom, I think.</p>

<p>Feel free to reach out to me via <a href="http://twitter.com/narnach">Twitter</a> or <a href="mailto:wes@narnach.com">email</a>. Besides my foray into cryptocurrencies, I&rsquo;m a <a href="https://www.narnach.com/">freelance Ruby software developer</a> with a focus on back-end systems and an obsession with code quality. I&rsquo;m also developing a smart RSS reader over at <a href="https://www.infinity-feed.com">Infinity Feed</a> (beta should go live soon-ish).</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Experimenting with recording gameplay on Twitch and Youtube]]></title>
    <link href="https://blog.narnach.com/blog/2015/experimenting-with-recording-gameplay-on-twitch-and-youtube/"/>
    <updated>2015-01-20T22:34:09+01:00</updated>
    <id>https://blog.narnach.com/blog/2015/experimenting-with-recording-gameplay-on-twitch-and-youtube</id>
    <content type="html"><![CDATA[<p>I have been playing videogames for over 20 years as one of my primary hobbies. During the last few years, I have watched other people play games on <a href="https://www.youtube.com/narnach">Youtube</a> and <a href="http://twitch.tv">Twitch.tv</a>. Watching Youtube videos of people playing games has become my primary means of evaluating whether to get a new game or not. Trailer videos and reviews often paint an inaccurate picture of what the game will be like. Watching someone play the game is the most honest way to see what a game <em>really</em> is like playing. Some streamers also happen to be very entertaining to watch.</p>

<h2>The experience</h2>

<p>This weekend I experimented with streaming my own Diablo III gameplay on <a href="http://www.twitch.tv/narnach">my Twitch TV Channel</a>. This was my first time recording and broadcasting. It was an interesting experience.</p>

<p>Streaming a game is definitely an different way to play a game. Having the microphone on and your gameplay recorded feels a little bit like giving a presentation. For me, this meant that I felt very nervous, awkward and self-conscious at first. It made me lose my train of thought a couple of times, etc. After a while it got more comfortable, so the side-effects of being nervous went away a little.</p>

<p>Another thing to get used to is multi-tasking between the game and commentating on what you&rsquo;re doing.</p>

<p>After streaming with zero watchers, I wanted to watch my recordings to see how I did. Twitch kept pausing the video to buffer every 30 seconds, despite my bandwidth being more than sufficient. I figured it was a limitation of Twitch. Luckily, Twitch makes it easy to export streams to <a href="https://www.youtube.com/user/Narnach">my Youtube channel</a>, which does not have issues with bandwidth.</p>

<h2>Tech</h2>

<p>For my setup, I started with Nvidia Shadowplay (which comes as part of the video card drivers) to record my gameplay, downscale the footage from my 1440p screen to a 720p video and stream it straight to Twitch TV. I recorded my voice-over with my gaming headset while playing the game.</p>

<p>Shadowplay was a very easy and low-barrier way to get started. The default settings are <em>very</em> conservative, so the result looked horrible to my very spoiled eyes. I had to increase the output resolution and bitrate to make it look a little bit better, but the Twitch stream output was nothing like watching Youtube videos in the same 720p resolution.</p>

<p>Looking for a better way to record and broadcast my video, I followed Twitch&rsquo;s recommendation of <a href="https://obsproject.com/">Open Broadcaster Software (OBS)</a>. They have a <a href="http://help.twitch.tv/customer/portal/articles/1262922-open-broadcaster-software">good guide on how to configure it</a>.</p>

<p>The visual quality went up, but I kept pushing too close against the maximum bitrate of 3500 kbit in order to make the stream look as good as possible. In fact, 3500 kbit is not enough to make the video look decent to me. Twitch starts getting buffering issues above 3000 kbit, but looked noticeably worse when I lowered my bitrate that far.</p>

<p>So: I was not happy with the quality of my stream on Twitch, yet my plan was to also get the footage on Youtube for later watching. Having zero subscribers to your (new) streaming channel means nobody sees it anyway. So I decided to skip Twitch and upload straight to Youtube. Uploading directly to Youtube allows me to record higher content at a (much) higher bitrate. Heck, I could upload a 1440p video in a crazy high bandwidth.</p>

<p>To determine what bitrate would be possible, what would be good and what would be a good baseline, I recorded a couple of short clips at different bitrates.</p>

<ol>
<li>20mbit 1440p video looked fabulous, but my machine started making noticeably more noise by spinning up fans to cool itself. I&rsquo;ve got quite a powerful setup, which I&rsquo;ve tuned to make as little noise as needed even during reasonably high load. When it starts to make noise, I know I&rsquo;m pushing against limits.</li>
<li>10mbit 1440p looked very good. It did not cause noisy fans.</li>
<li>8mbit 1440p still looked very good. In fact, I could not distinguish it from the 10mbit video. This is the bitrate I went with for recording my gameplay.</li>
</ol>


<p>The Youtube video processing process is also interesting to look at. You upload the video, then they start processing it. Once this is done, the lowest quality version of the video (360p) is available. Invisibly in the background they keep processing increasingly higher quality versions (480p, 720p, 1080p and finally 1440p). Once the video list shows (HD) after the title&rsquo;s name, the 720p version is available. This background process will take a couple of hours, depending on the length of the video.</p>

<p>I settled on uploading videos at night as unlisted, then making them public the next morning.</p>

<h2>Gameplay</h2>

<p>Oh, yes. I was recording playing a game.</p>

<p>I was playing Diablo III: Reaper of Souls, which has been out for over a year now. Last week Blizzard released the <a href="http://eu.battle.net/d3/en/blog/17561388/patch-212-now-live-in-europe-14-01-2015">2.1.2 patch</a> in preparation for the Season being reset in early February.</p>

<p>At the launch of Season 1, I briefly tried it. At the time there were ways to exploit the game to get a maximum level character in two hours. For me this took the fun out of it. How can you compete on a ladder of sorts if you&rsquo;re up against cheaters?</p>

<p>Blizzard hotfixed the ways to cheat out reasonably soon, but I had given up on it at that point. Now that a new season is coming up and it looks like people will actually be racing to reach the top, I&rsquo;m interested in participating again.</p>

<p>So to see what my chances would be, I created a brand new hardcore character in Season 1. Hardcore characters stay dead once they get killed in game. You only live once. I like the added challenge of keeping a character alive.</p>

<p>The first night I played 6 hours and reached level 50 by playing the game in adventure mode. The second night I played about 3 hours to reach level 60. The third night I played another 3 or so hours to reach level 70 (the maximum) and reach my goal. Total time taken: 12.5 hours.</p>

<p>The key is to not push the difficulty level to extreme from the get-go, and to play in Adventure mode instead of the campaign. You have a more focused leveling experience and it&rsquo;s nice not having to go through the low level parts of the campaign yet again. The gameplay is dumbed down quite a bit because this part serves as a tutorial of sorts. In adventure mode there is no tutorial, because you only unlock it after completing the campaign once.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Boolean Externalities]]></title>
    <link href="https://blog.narnach.com/blog/2014/boolean-externalities/"/>
    <updated>2014-09-19T01:53:00+02:00</updated>
    <id>https://blog.narnach.com/blog/2014/boolean-externalities</id>
    <content type="html"><![CDATA[<p>This is motivated/inspired by Avdi Grimm&rsquo;s post on Boolean Externalties</p>

<p>  <a href="http://devblog.avdi.org/2014/09/17/boolean-externalities/">http://devblog.avdi.org/2014/09/17/boolean-externalities/</a></p>

<p>In his post he asks the question: if a predicate returns false, why does it do so?
If you chain a lot of predicates, it&rsquo;s hard to figure out why you get the answer you get.</p>

<p>Consider this example. It implements simple chained predicate logic to determine if the object is scary.</p>

<figure class='code'><figcaption><span></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>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">SimpleBoo</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">scary?</span>
</span><span class='line'>    <span class="n">ghost?</span> <span class="o">||</span> <span class="n">zombie?</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">ghost?</span>
</span><span class='line'>    <span class="o">!</span><span class="n">alive?</span> <span class="o">&amp;&amp;</span> <span class="n">regrets?</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">zombie?</span>
</span><span class='line'>    <span class="o">!</span><span class="n">alive?</span> <span class="o">&amp;&amp;</span> <span class="n">hungry_for_brains?</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">alive?</span>
</span><span class='line'>    <span class="kp">false</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">regrets?</span>
</span><span class='line'>    <span class="kp">false</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">hungry_for_brains?</span>
</span><span class='line'>    <span class="kp">false</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>Following the chain of logic, something is scary if it&rsquo;s either a ghost or a zombie.
They are both not alive, but a ghost has regrets and a zombie is hungry for brains.
This is the code as I would probably write it for a production app. It&rsquo;s simple and very easy to read.</p>

<p>The downside is that if you want to know <em>why</em> something is scary, you have to go and read the code.
You can not ask the object <em>why</em> it arrived at its conclusion.</p>

<h2>Why</h2>

<p>The following is a logical next step in the evolution of the code:
I have modified the code so it can explain <em>why</em> a predicate returns true or false,
though there is a tremendous &ldquo;cost&rdquo; in length and legibility.</p>

<figure class='code'><figcaption><span></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>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">WhyNotBoo</span>
</span><span class='line'>  <span class="c1"># The object is scary if there is a reason for it to be scary.</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">scary?</span>
</span><span class='line'>    <span class="n">why_scary</span><span class="o">.</span><span class="n">any?</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1"># Why is this object scary?</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">why_scary</span>
</span><span class='line'>    <span class="n">reasons</span> <span class="o">=</span> <span class="o">[]</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1"># Early termination if this object is *not* scary.</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">reasons</span> <span class="k">unless</span> <span class="n">ghost?</span> <span class="o">||</span> <span class="n">zombie?</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1"># Recursively determine why this object is scary.</span>
</span><span class='line'>    <span class="n">reasons</span><span class="o">.</span><span class="n">concat</span><span class="p">(</span><span class="o">[</span><span class="ss">:ghost</span> <span class="o">=&gt;</span> <span class="n">why_ghost</span><span class="o">]</span><span class="p">)</span> <span class="k">if</span> <span class="n">ghost?</span>
</span><span class='line'>    <span class="n">reasons</span><span class="o">.</span><span class="n">concat</span><span class="p">(</span><span class="o">[</span><span class="ss">:zombie</span> <span class="o">=&gt;</span> <span class="n">why_zombie</span><span class="o">]</span><span class="p">)</span> <span class="k">if</span> <span class="n">zombie?</span>
</span><span class='line'>    <span class="n">reasons</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1"># For the &quot;why not&quot; question we re-implement the &quot;why&quot; logic in reverse.</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">why_not_scary</span>
</span><span class='line'>    <span class="n">reasons</span> <span class="o">=</span> <span class="o">[]</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">reasons</span> <span class="k">if</span> <span class="n">ghost?</span> <span class="o">||</span> <span class="n">zombie?</span>
</span><span class='line'>    <span class="n">reasons</span><span class="o">.</span><span class="n">concat</span><span class="p">(</span><span class="o">[</span><span class="ss">:not_ghost</span> <span class="o">=&gt;</span> <span class="n">why_not_ghost</span><span class="o">]</span><span class="p">)</span> <span class="k">unless</span> <span class="n">ghost?</span>
</span><span class='line'>    <span class="n">reasons</span><span class="o">.</span><span class="n">concat</span><span class="p">(</span><span class="o">[</span><span class="ss">:not_zombie</span> <span class="o">=&gt;</span> <span class="n">why_not_zombie</span><span class="o">]</span><span class="p">)</span> <span class="k">unless</span> <span class="n">zombie?</span>
</span><span class='line'>    <span class="n">reasons</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">ghost?</span>
</span><span class='line'>    <span class="n">why_ghost</span><span class="o">.</span><span class="n">any?</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">why_ghost</span>
</span><span class='line'>    <span class="k">return</span> <span class="o">[]</span> <span class="k">unless</span> <span class="o">!</span><span class="n">alive?</span> <span class="o">&amp;&amp;</span> <span class="n">regrets?</span>
</span><span class='line'>
</span><span class='line'>    <span class="o">[</span><span class="ss">:not_alive</span><span class="p">,</span> <span class="ss">:regrets</span><span class="o">]</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">why_not_ghost</span>
</span><span class='line'>    <span class="n">reasons</span> <span class="o">=</span> <span class="o">[]</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">reasons</span> <span class="k">if</span> <span class="n">ghost?</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">reasons</span> <span class="o">&lt;&lt;</span> <span class="ss">:alive</span> <span class="k">if</span> <span class="n">alive?</span>
</span><span class='line'>    <span class="n">reasons</span> <span class="o">&lt;&lt;</span> <span class="ss">:no_regrets</span> <span class="k">unless</span> <span class="n">regrets?</span>
</span><span class='line'>    <span class="n">reasons</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">zombie?</span>
</span><span class='line'>    <span class="n">why_zombie</span><span class="o">.</span><span class="n">any?</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">why_zombie</span>
</span><span class='line'>    <span class="k">return</span> <span class="o">[]</span> <span class="k">unless</span> <span class="o">!</span><span class="n">alive?</span> <span class="o">&amp;&amp;</span> <span class="n">hungry_for_brains?</span>
</span><span class='line'>
</span><span class='line'>    <span class="o">[</span><span class="ss">:not_alive</span><span class="p">,</span> <span class="ss">:hungry_for_brains</span><span class="o">]</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">why_not_zombie</span>
</span><span class='line'>    <span class="n">reasons</span> <span class="o">=</span> <span class="o">[]</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">reasons</span> <span class="k">if</span> <span class="n">zombie?</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">reasons</span> <span class="o">&lt;&lt;</span> <span class="ss">:alive</span> <span class="k">if</span> <span class="n">alive?</span>
</span><span class='line'>    <span class="n">reasons</span> <span class="o">&lt;&lt;</span> <span class="ss">:not_hungry_for_brains</span> <span class="k">unless</span> <span class="n">hungry_for_brains?</span>
</span><span class='line'>    <span class="n">reasons</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">alive?</span>
</span><span class='line'>    <span class="kp">true</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">regrets?</span>
</span><span class='line'>    <span class="kp">false</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">hungry_for_brains?</span>
</span><span class='line'>    <span class="kp">false</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>Yes, that&rsquo;s a <em>lot</em> more code. All composite predicates have a &ldquo;why_[predicate]&rdquo; and a &ldquo;why_not_[predicate]&rdquo; version.
Now you can ask if something is scary and why (or why not).</p>

<p>There are a few problems with this approach:</p>

<ol>
<li>The logic is not in <code>scary?</code>, where you would expect it.</li>
<li>The logic is duplicated between <code>why_scary</code> and <code>why_not_scary</code>. Don&rsquo;t Repeat Yourself, or you will get logic bugs.</li>
<li>There is a lot more code. A lot of boilerplate code, but also multiple concerns in the same method: bookkeeping and actual logic.</li>
</ol>


<h2>Cleaner code</h2>

<p>Let&rsquo;s see if we can make the code legible again, while preserving the functionality of &ldquo;why&rdquo; and &ldquo;why not&rdquo;.</p>

<figure class='code'><figcaption><span></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>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">ReasonBoo</span> <span class="o">&lt;</span> <span class="no">EitherAll</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">scary?</span>
</span><span class='line'>    <span class="n">either</span> <span class="ss">:ghost</span><span class="p">,</span> <span class="ss">:zombie</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">ghost?</span>
</span><span class='line'>    <span class="n">all</span> <span class="ss">:not_alive</span><span class="p">,</span> <span class="ss">:regrets</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">zombie?</span>
</span><span class='line'>    <span class="n">all</span> <span class="ss">:not_alive</span><span class="p">,</span> <span class="ss">:hungry_for_brains</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">alive?</span>
</span><span class='line'>    <span class="kp">false</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">regrets?</span>
</span><span class='line'>    <span class="kp">false</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">hungry_for_brains?</span>
</span><span class='line'>    <span class="kp">false</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>So far, so good. The code is <em>very</em> legibile, but there is a mysterious superclass <code>EitherAnd</code>.
Before we look at <em>how</em> it works, let&rsquo;s look at <em>what</em> it allows us to do:</p>

<figure class='code'><figcaption><span></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>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">boo</span> <span class="o">=</span> <span class="no">ReasonBoo</span><span class="o">.</span><span class="n">new</span>
</span><span class='line'><span class="n">boo</span><span class="o">.</span><span class="n">scary?</span> <span class="c1"># =&gt; false</span>
</span><span class='line'><span class="n">boo</span><span class="o">.</span><span class="n">why_scary</span> <span class="c1"># =&gt; []</span>
</span><span class='line'><span class="n">boo</span><span class="o">.</span><span class="n">why_not_scary</span> <span class="c1"># =&gt; [{:not_ghost=&gt;[:not_regrets]}, {:not_zombie=&gt;[:not_hungry_for_brains]}]</span>
</span><span class='line'>
</span><span class='line'><span class="n">boo</span><span class="o">.</span><span class="n">ghost?</span> <span class="c1"># =&gt; false</span>
</span><span class='line'><span class="n">boo</span><span class="o">.</span><span class="n">why_ghost</span> <span class="c1"># =&gt; []</span>
</span><span class='line'><span class="n">boo</span><span class="o">.</span><span class="n">why_not_ghost</span> <span class="c1"># =&gt; [:not_regrets]</span>
</span><span class='line'>
</span><span class='line'><span class="n">boo</span><span class="o">.</span><span class="n">zombie?</span> <span class="c1"># =&gt; false</span>
</span><span class='line'><span class="n">boo</span><span class="o">.</span><span class="n">why_zombie</span> <span class="c1"># =&gt; []</span>
</span><span class='line'><span class="n">boo</span><span class="o">.</span><span class="n">why_not_zombie</span> <span class="c1"># =&gt; [:not_hungry_for_brains]</span>
</span></code></pre></td></tr></table></div></figure>


<p>For each predicate that uses <code>either</code> or <code>all</code> we can ask why or why not it&rsquo;s true and the response is a chain of predicate checks.</p>

<h2>How we get cleaner code</h2>

<p>If you want to make your code legible, there usually has to be some dirty plumbing code.
In this example we have hidden this in a superclass, but it could have been a module as well without too much effort.</p>

<p>In order to keep the code easier to read, I have chosen to not extract duplicate logic into helper methods.</p>

<p>This class implements two methods: <code>either</code> and <code>all</code>.</p>

<p>Both methods have the same structure:</p>

<ol>
<li>Setup the why_[predicate] and why_not_[predicate] methods.</li>
<li>Evaluate each predicate until we reach a termination condition.</li>
<li>Track which predicates were true/false to explain <em>why</em> we got the result we did.</li>
</ol>


<figure class='code'><figcaption><span></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>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
<span class='line-number'>97</span>
<span class='line-number'>98</span>
<span class='line-number'>99</span>
<span class='line-number'>100</span>
<span class='line-number'>101</span>
<span class='line-number'>102</span>
<span class='line-number'>103</span>
<span class='line-number'>104</span>
<span class='line-number'>105</span>
<span class='line-number'>106</span>
<span class='line-number'>107</span>
<span class='line-number'>108</span>
<span class='line-number'>109</span>
<span class='line-number'>110</span>
<span class='line-number'>111</span>
<span class='line-number'>112</span>
<span class='line-number'>113</span>
<span class='line-number'>114</span>
<span class='line-number'>115</span>
<span class='line-number'>116</span>
<span class='line-number'>117</span>
<span class='line-number'>118</span>
<span class='line-number'>119</span>
<span class='line-number'>120</span>
<span class='line-number'>121</span>
<span class='line-number'>122</span>
<span class='line-number'>123</span>
<span class='line-number'>124</span>
<span class='line-number'>125</span>
<span class='line-number'>126</span>
<span class='line-number'>127</span>
<span class='line-number'>128</span>
<span class='line-number'>129</span>
<span class='line-number'>130</span>
<span class='line-number'>131</span>
<span class='line-number'>132</span>
<span class='line-number'>133</span>
<span class='line-number'>134</span>
<span class='line-number'>135</span>
<span class='line-number'>136</span>
<span class='line-number'>137</span>
<span class='line-number'>138</span>
<span class='line-number'>139</span>
<span class='line-number'>140</span>
<span class='line-number'>141</span>
<span class='line-number'>142</span>
<span class='line-number'>143</span>
<span class='line-number'>144</span>
<span class='line-number'>145</span>
<span class='line-number'>146</span>
<span class='line-number'>147</span>
<span class='line-number'>148</span>
<span class='line-number'>149</span>
<span class='line-number'>150</span>
<span class='line-number'>151</span>
<span class='line-number'>152</span>
<span class='line-number'>153</span>
<span class='line-number'>154</span>
<span class='line-number'>155</span>
<span class='line-number'>156</span>
<span class='line-number'>157</span>
<span class='line-number'>158</span>
<span class='line-number'>159</span>
<span class='line-number'>160</span>
<span class='line-number'>161</span>
<span class='line-number'>162</span>
<span class='line-number'>163</span>
<span class='line-number'>164</span>
<span class='line-number'>165</span>
<span class='line-number'>166</span>
<span class='line-number'>167</span>
<span class='line-number'>168</span>
<span class='line-number'>169</span>
<span class='line-number'>170</span>
<span class='line-number'>171</span>
<span class='line-number'>172</span>
<span class='line-number'>173</span>
<span class='line-number'>174</span>
<span class='line-number'>175</span>
<span class='line-number'>176</span>
<span class='line-number'>177</span>
<span class='line-number'>178</span>
<span class='line-number'>179</span>
<span class='line-number'>180</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">EitherAll</span>
</span><span class='line'>  <span class="c1"># This method mimics the behavior of &quot;||&quot;. These two lines are functionally equivalent:</span>
</span><span class='line'>  <span class="c1">#</span>
</span><span class='line'>  <span class="c1">#   ghost? || zombie? # =&gt; false</span>
</span><span class='line'>  <span class="c1">#   either :ghost, :zombie # =&gt; false</span>
</span><span class='line'>  <span class="c1">#</span>
</span><span class='line'>  <span class="c1"># The bonus of `either` is that afterwards you can ask why or why not:</span>
</span><span class='line'>  <span class="c1">#</span>
</span><span class='line'>  <span class="c1">#   why_not_scary # =&gt; [{:not_ghost=&gt;[:not_regrets]}, {:not_zombie=&gt;[:not_hungry_for_brains]}]</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">either</span><span class="p">(</span><span class="o">*</span><span class="n">predicate_names</span><span class="p">)</span>
</span><span class='line'>    <span class="c1">#</span>
</span><span class='line'>    <span class="c1"># 1. Setup up the why_ and why_not_ methods</span>
</span><span class='line'>    <span class="c1">#</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1"># Two arrays to track the why and why not reasons.</span>
</span><span class='line'>    <span class="n">why_reasons</span>         <span class="o">=</span> <span class="o">[]</span>
</span><span class='line'>    <span class="n">why_not_reasons</span>     <span class="o">=</span> <span class="o">[]</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1"># This is a ruby 2.0 feature that replaces having to regexp parse the `caller` array.</span>
</span><span class='line'>    <span class="c1"># Our goal here is to determine the name of the method that called us.</span>
</span><span class='line'>    <span class="c1"># In this example it is likely to be the `scary?` method.</span>
</span><span class='line'>    <span class="n">context_method_name</span> <span class="o">=</span> <span class="n">caller_locations</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span><span class="o">[</span><span class="mi">0</span><span class="o">].</span><span class="n">label</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1"># Strip the trailing question mark</span>
</span><span class='line'>    <span class="n">context</span>             <span class="o">=</span> <span class="n">context_method_name</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="sr">/\?$/</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">to_sym</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1"># Set instance variables for why and why not for the current context (calling method name).</span>
</span><span class='line'>    <span class="c1"># In our example, this is going to be @why_scary and @why_not_scary.</span>
</span><span class='line'>    <span class="nb">instance_variable_set</span><span class="p">(</span><span class="s2">&quot;@why_</span><span class="si">#{</span><span class="n">context</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">why_reasons</span><span class="p">)</span>
</span><span class='line'>    <span class="nb">instance_variable_set</span><span class="p">(</span><span class="s2">&quot;@why_not_</span><span class="si">#{</span><span class="n">context</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">why_not_reasons</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1"># Create reader methods for `why_scary` and `why_not_scary`.</span>
</span><span class='line'>    <span class="nb">self</span><span class="o">.</span><span class="n">class</span><span class="o">.</span><span class="n">class_eval</span> <span class="k">do</span>
</span><span class='line'>      <span class="kp">attr_reader</span> <span class="ss">:&quot;why_</span><span class="si">#{</span><span class="n">context</span><span class="si">}</span><span class="ss">&quot;</span><span class="p">,</span> <span class="ss">:&quot;why_not_</span><span class="si">#{</span><span class="n">context</span><span class="si">}</span><span class="ss">&quot;</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">#</span>
</span><span class='line'>    <span class="c1"># 2. Evaluate each predicate until one returns true</span>
</span><span class='line'>    <span class="c1">#</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">predicate_names</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">predicate_name</span><span class="o">|</span>
</span><span class='line'>      <span class="c1"># Transform the given predicate name into a predicate method name.</span>
</span><span class='line'>      <span class="c1"># We check if the predicate needs to be negated, to support not_&lt;predicate&gt;.</span>
</span><span class='line'>      <span class="n">predicate_name_string</span> <span class="o">=</span> <span class="n">predicate_name</span><span class="o">.</span><span class="n">to_s</span>
</span><span class='line'>      <span class="k">if</span> <span class="n">predicate_name_string</span><span class="o">.</span><span class="n">start_with?</span><span class="p">(</span><span class="s1">&#39;not_&#39;</span><span class="p">)</span>
</span><span class='line'>        <span class="n">negate</span>                <span class="o">=</span> <span class="kp">true</span>
</span><span class='line'>        <span class="n">predicate_method_name</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">#{</span><span class="n">predicate_name_string</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="sr">/^not_/</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">?&quot;</span>
</span><span class='line'>      <span class="k">else</span>
</span><span class='line'>        <span class="n">negate</span>                <span class="o">=</span> <span class="kp">false</span>
</span><span class='line'>        <span class="n">predicate_method_name</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">#{</span><span class="n">predicate_name_string</span><span class="si">}</span><span class="s2">?&quot;</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>      <span class="c1"># Evaluate the predicate</span>
</span><span class='line'>      <span class="k">if</span> <span class="n">negate</span>
</span><span class='line'>        <span class="c1"># Negate the return value of a negated predicate.</span>
</span><span class='line'>        <span class="c1"># This simplifies the logic for our success case.</span>
</span><span class='line'>        <span class="c1"># `value` is always true if it is what we ask for.</span>
</span><span class='line'>        <span class="n">value</span> <span class="o">=</span> <span class="o">!</span><span class="n">public_send</span><span class="p">(</span><span class="n">predicate_method_name</span><span class="p">)</span>
</span><span class='line'>      <span class="k">else</span>
</span><span class='line'>        <span class="n">value</span> <span class="o">=</span> <span class="n">public_send</span><span class="p">(</span><span class="n">predicate_method_name</span><span class="p">)</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>      <span class="c1">#</span>
</span><span class='line'>      <span class="c1"># 3. Track which predicates were true/false to explain *why* we got the answer we did.</span>
</span><span class='line'>      <span class="c1">#</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">if</span> <span class="n">value</span>
</span><span class='line'>        <span class="c1"># We have a true value, so we found what we are looking for.</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1"># If possible, follow the chain of reasoning by asking why the predicate is true.</span>
</span><span class='line'>        <span class="k">if</span> <span class="nb">respond_to?</span><span class="p">(</span><span class="s2">&quot;why_</span><span class="si">#{</span><span class="n">predicate_name</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
</span><span class='line'>          <span class="n">why_reasons</span> <span class="o">&lt;&lt;</span> <span class="p">{</span> <span class="n">predicate_name</span> <span class="o">=&gt;</span> <span class="n">public_send</span><span class="p">(</span><span class="s2">&quot;why_</span><span class="si">#{</span><span class="n">predicate_name</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span> <span class="p">}</span>
</span><span class='line'>        <span class="k">else</span>
</span><span class='line'>          <span class="n">why_reasons</span> <span class="o">&lt;&lt;</span> <span class="n">predicate_name</span>
</span><span class='line'>        <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1"># Because value is true, clear the reasons why we would not be.</span>
</span><span class='line'>        <span class="c1"># They don&#39;t matter anymore.</span>
</span><span class='line'>        <span class="n">why_not_reasons</span><span class="o">.</span><span class="n">clear</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1"># To ensure lazy evaluation, we stop here.</span>
</span><span class='line'>        <span class="k">return</span> <span class="kp">true</span>
</span><span class='line'>      <span class="k">else</span>
</span><span class='line'>        <span class="c1"># We have a false value, so we continue looking for a true predicate</span>
</span><span class='line'>        <span class="k">if</span> <span class="n">negate</span>
</span><span class='line'>          <span class="c1"># Our predicate negated, so we want to use the non-negated version.</span>
</span><span class='line'>          <span class="c1"># In our example, if `alive?` were true, we are not a zombie because we are not &quot;not alive&quot;.</span>
</span><span class='line'>          <span class="c1"># Our check is for :not_alive, so the &quot;why not&quot; reason is :alive.</span>
</span><span class='line'>          <span class="n">negative_predicate_name</span> <span class="o">=</span> <span class="n">predicate_name_string</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="sr">/^not_/</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">to_sym</span>
</span><span class='line'>        <span class="k">else</span>
</span><span class='line'>          <span class="c1"># Our predicate is not negated, so we need to use the negated predicate.</span>
</span><span class='line'>          <span class="c1"># In our example, we are not scary because we are not a ghost (or a zombie).</span>
</span><span class='line'>          <span class="c1"># Our check is for :scary, so the &quot;why not&quot; reason is :not_ghost.</span>
</span><span class='line'>          <span class="n">negative_predicate_name</span> <span class="o">=</span> <span class="s2">&quot;not_</span><span class="si">#{</span><span class="n">predicate_name_string</span><span class="si">}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">to_sym</span>
</span><span class='line'>        <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1"># If possible, follow the chain of reasoning by asking why the predicate is false.</span>
</span><span class='line'>        <span class="k">if</span> <span class="nb">respond_to?</span><span class="p">(</span><span class="s2">&quot;why_</span><span class="si">#{</span><span class="n">negative_predicate_name</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
</span><span class='line'>          <span class="n">why_not_reasons</span> <span class="o">&lt;&lt;</span> <span class="p">{</span> <span class="n">negative_predicate_name</span> <span class="o">=&gt;</span> <span class="n">public_send</span><span class="p">(</span><span class="s2">&quot;why_</span><span class="si">#{</span><span class="n">negative_predicate_name</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span> <span class="p">}</span>
</span><span class='line'>        <span class="k">else</span>
</span><span class='line'>          <span class="n">why_not_reasons</span> <span class="o">&lt;&lt;</span> <span class="n">negative_predicate_name</span>
</span><span class='line'>        <span class="k">end</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>    <span class="c1"># We failed because we did not get a true value at all (which would have caused early termination).</span>
</span><span class='line'>    <span class="c1"># Clear all positive reasons.</span>
</span><span class='line'>    <span class="n">why_reasons</span><span class="o">.</span><span class="n">clear</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1"># Explicitly return false to match style with the `return true` a few lines earlier.</span>
</span><span class='line'>    <span class="k">return</span> <span class="kp">false</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1"># This method works very similar to `either`, which is defined above.</span>
</span><span class='line'>  <span class="c1"># I&#39;m only commenting on the differences here.</span>
</span><span class='line'>  <span class="c1">#</span>
</span><span class='line'>  <span class="c1"># This method mimics the behavior of &quot;&amp;&amp;&quot;. These two lines are functionally equivalent:</span>
</span><span class='line'>  <span class="c1">#</span>
</span><span class='line'>  <span class="c1">#   !alive? &amp;&amp; hungry_for_brains?</span>
</span><span class='line'>  <span class="c1">#   all :not_alive, :hungry_for_brains</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">all</span><span class="p">(</span><span class="o">*</span><span class="n">predicate_names</span><span class="p">)</span>
</span><span class='line'>    <span class="n">context_method_name</span> <span class="o">=</span> <span class="n">caller_locations</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span><span class="o">[</span><span class="mi">0</span><span class="o">].</span><span class="n">label</span>
</span><span class='line'>    <span class="n">context</span>             <span class="o">=</span> <span class="n">context_method_name</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="sr">/\?$/</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">to_sym</span>
</span><span class='line'>    <span class="n">why_reasons</span>         <span class="o">=</span> <span class="o">[]</span>
</span><span class='line'>    <span class="n">why_not_reasons</span>     <span class="o">=</span> <span class="o">[]</span>
</span><span class='line'>    <span class="nb">instance_variable_set</span><span class="p">(</span><span class="s2">&quot;@why_</span><span class="si">#{</span><span class="n">context</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">why_reasons</span><span class="p">)</span>
</span><span class='line'>    <span class="nb">instance_variable_set</span><span class="p">(</span><span class="s2">&quot;@why_not_</span><span class="si">#{</span><span class="n">context</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">why_not_reasons</span><span class="p">)</span>
</span><span class='line'>    <span class="nb">self</span><span class="o">.</span><span class="n">class</span><span class="o">.</span><span class="n">class_eval</span> <span class="k">do</span>
</span><span class='line'>      <span class="kp">attr_reader</span> <span class="ss">:&quot;why_</span><span class="si">#{</span><span class="n">context</span><span class="si">}</span><span class="ss">&quot;</span><span class="p">,</span> <span class="ss">:&quot;why_not_</span><span class="si">#{</span><span class="n">context</span><span class="si">}</span><span class="ss">&quot;</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">predicate_names</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">predicate_name</span><span class="o">|</span>
</span><span class='line'>      <span class="n">predicate_name_string</span> <span class="o">=</span> <span class="n">predicate_name</span><span class="o">.</span><span class="n">to_s</span>
</span><span class='line'>      <span class="k">if</span> <span class="n">predicate_name_string</span><span class="o">.</span><span class="n">start_with?</span><span class="p">(</span><span class="s1">&#39;not_&#39;</span><span class="p">)</span>
</span><span class='line'>        <span class="n">negate</span>                <span class="o">=</span> <span class="kp">true</span>
</span><span class='line'>        <span class="n">predicate_method_name</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">#{</span><span class="n">predicate_name_string</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="sr">/^not_/</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">?&quot;</span>
</span><span class='line'>      <span class="k">else</span>
</span><span class='line'>        <span class="n">negate</span>                <span class="o">=</span> <span class="kp">false</span>
</span><span class='line'>        <span class="n">predicate_method_name</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">#{</span><span class="n">predicate_name_string</span><span class="si">}</span><span class="s2">?&quot;</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">if</span> <span class="n">negate</span>
</span><span class='line'>        <span class="n">value</span> <span class="o">=</span> <span class="o">!</span><span class="n">public_send</span><span class="p">(</span><span class="n">predicate_method_name</span><span class="p">)</span>
</span><span class='line'>      <span class="k">else</span>
</span><span class='line'>        <span class="n">value</span> <span class="o">=</span> <span class="n">public_send</span><span class="p">(</span><span class="n">predicate_method_name</span><span class="p">)</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>      <span class="c1"># The logic is the same as `either` until here. The difference is:</span>
</span><span class='line'>      <span class="c1">#</span>
</span><span class='line'>      <span class="c1"># * Either looks for the first true to declare success</span>
</span><span class='line'>      <span class="c1"># * And looks for the first false to declare failure</span>
</span><span class='line'>      <span class="c1">#</span>
</span><span class='line'>      <span class="c1"># This means we have to reverse our logic.</span>
</span><span class='line'>      <span class="k">if</span> <span class="n">value</span>
</span><span class='line'>        <span class="k">if</span> <span class="nb">respond_to?</span><span class="p">(</span><span class="s2">&quot;why_</span><span class="si">#{</span><span class="n">predicate_name</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
</span><span class='line'>          <span class="n">why_reasons</span> <span class="o">&lt;&lt;</span> <span class="p">{</span> <span class="n">predicate_name</span> <span class="o">=&gt;</span> <span class="n">public_send</span><span class="p">(</span><span class="s2">&quot;why_</span><span class="si">#{</span><span class="n">predicate_name</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span> <span class="p">}</span>
</span><span class='line'>        <span class="k">else</span>
</span><span class='line'>          <span class="n">why_reasons</span> <span class="o">&lt;&lt;</span> <span class="n">predicate_name</span>
</span><span class='line'>        <span class="k">end</span>
</span><span class='line'>      <span class="k">else</span>
</span><span class='line'>        <span class="k">if</span> <span class="n">negate</span>
</span><span class='line'>          <span class="n">negative_predicate_name</span> <span class="o">=</span> <span class="n">predicate_name_string</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="sr">/^not_/</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">to_sym</span>
</span><span class='line'>        <span class="k">else</span>
</span><span class='line'>          <span class="n">negative_predicate_name</span> <span class="o">=</span> <span class="s2">&quot;not_</span><span class="si">#{</span><span class="n">predicate_name_string</span><span class="si">}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">to_sym</span>
</span><span class='line'>        <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">if</span> <span class="nb">respond_to?</span><span class="p">(</span><span class="s2">&quot;why_</span><span class="si">#{</span><span class="n">negative_predicate_name</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
</span><span class='line'>          <span class="n">why_not_reasons</span> <span class="o">&lt;&lt;</span> <span class="p">{</span> <span class="n">negative_predicate_name</span> <span class="o">=&gt;</span> <span class="n">public_send</span><span class="p">(</span><span class="s2">&quot;why_</span><span class="si">#{</span><span class="n">negative_predicate_name</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span> <span class="p">}</span>
</span><span class='line'>        <span class="k">else</span>
</span><span class='line'>          <span class="n">why_not_reasons</span> <span class="o">&lt;&lt;</span> <span class="n">negative_predicate_name</span>
</span><span class='line'>        <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>        <span class="n">why_reasons</span><span class="o">.</span><span class="n">clear</span>
</span><span class='line'>        <span class="k">return</span> <span class="kp">false</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">why_not_reasons</span><span class="o">.</span><span class="n">clear</span>
</span><span class='line'>    <span class="k">return</span> <span class="kp">true</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>


<h2>Conclusion</h2>

<p>It is possible to provide traceability for <em>why</em> a boolean returns its value with less than 200 lines of Ruby code and minor changes to your own code.</p>

<p>Despite the obvious edge cases and limitations, it&rsquo;s nice to know there is a potential solution to the problem of not knowing <em>why</em> a method returns <code>true</code> or <code>false</code>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[New blog and a status update]]></title>
    <link href="https://blog.narnach.com/blog/2012/new-blog/"/>
    <updated>2012-01-10T17:34:00+01:00</updated>
    <id>https://blog.narnach.com/blog/2012/new-blog</id>
    <content type="html"><![CDATA[<p>During Christmas I moved my blog from Blogspot to <a href="http://blog.narnach.com">blog.narnach.com</a> using <a href="http://octopress.org/">Octopress</a>.</p>

<p>Blogspot served me well at first, but after a while I got tired of fighting with it. Having to write your posts in raw HTML to make them look decent is so 20th century. Because Octopress is <a href="http://github.com/mojombo/jekyll">Jekyll</a> with all kinds of nice stuff on top, I can now write my posts in <a href="http://daringfireball.net/projects/markdown/">Markdown</a> and be happy again. Deployment is easy as well, since Octopress just generates static HTML and uses scp to put it on my server. I have to admit, it feels good to have complete control over my own blog on my own domain.</p>

<p>The last blog post I imported was written a long time ago, in 2009, while I was still working for yoMedia. Oh boy how things have changed since then.</p>

<p>Since 1 September 2009 I am the proud owner of my one-man company, Narnach. My original plan was to split my time 50/50 between building my own projects and freelancing as a software developer. It took a month for the first freelance opportunity to present itself. While working with that client, another opportunity came along and I&rsquo;ve been busy non-stop ever since. In all the freelance fun I completely forgot about doing my own projects, though. Funny how that goes.</p>

<p>2010 was a good year. For most of my projects, I worked together with Gerard de Brieder of <a href="http://govannon.net">Govannon</a> as a two-men freelance army and that collaboration worked out well. In 2011, Gerard got himself a physical office that we moved into. Soon, Gokhan Arli of <a href="http://sylow.net">Sylow</a> joined us as third man on the team.</p>

<p>2011 has been my busiest year yet. It went so well that for the first half year I averaged 60 hour weeks just to be able to keep up with all the work. The second half of the year I finally learned to say &ldquo;NO&rdquo; to new opportunities, so things quieted down a bit to &ldquo;regular&rdquo; 35 hour weeks. Still, I worked way more than I should have and in December I was displaying symptoms of what, according to Wikipedia, may be a <a href="http://en.wikipedia.org/wiki/Burnout_(psychology)">Burnout</a>. So I went on vacation on 20 December and I took almost three weeks off to relax and recover. It seems to have helped!</p>

<p>For 2012 I have decided to change two things.</p>

<p>First, I&rsquo;m slowing down my freelance activities. This means taking on less new clients and letting some existing clients go. The result should be less stress and more energy to work for the clients I am keeping.</p>

<p>Second, I&rsquo;m revisiting my original plan of developing my own project. Freelancing is fun, but you are always helping other people grow <em>their</em> company. I finally have an idea that I would like to develop, so I figure now is the best time to start. The change from my original plan is that this will strictly be an evening/weekend thing. &ldquo;They&rdquo; say it takes at least a year or two to achieve &ldquo;overnight success&rdquo;, so I figure I&rsquo;d not quit my day job as a freelancer just yet.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[A possible future for web-based communication]]></title>
    <link href="https://blog.narnach.com/blog/2009/a-possible-future-for-web-based-communication/"/>
    <updated>2009-06-24T09:52:00+02:00</updated>
    <id>https://blog.narnach.com/blog/2009/a-possible-future-for-web-based-communication</id>
    <content type="html"><![CDATA[<p>My recent post on the <a href="https://blog.narnach.com/blog/2009/kings-of-code-side-event-amsterdam-dot-rb-unconference/">Kings of code side event</a> got too long, so I extracted the following into its own blog post. It is a collection of thoughts on a possible presentation topic.</p>

<p>People like to communicate with each other. Centuries ago we wrote letters and sent them with the merchants, hoping they would arive. The telegraph was a revolution: we could send a message faster, cheaper and with more certainty of delivery. The telephone was even more revolutionary: direct communication over a long distance.</p>

<p>In the age of the internet, change happens even faster. E-mail has been around for &ldquo;ages&rdquo;, just like various forms of chat services have come and gone.</p>

<p>Broadcasting has gone through a similar change. It started with spoken announcements; proclamations from the king. At some point there were pamphlets and posters. Books can be seen as a way to broadcast a message. Newspapers are a periodic form of broadcast. Radio enabled long-distance audio broadcasting without the cost of creating a physical carrier for the message. Television added moving images to radio.</p>

<p>Now we have the internet, where we go through similar stages.</p>

<p>Static, web 1.0, websites are pamplets re-invented. Old concepts in an electronic shape. Ebooks are electronic books. Newspapers try to put their content on their own websites, updating them daily to bring their news to the masses. E-mail newsletters just scream &ldquo;newspaper&rdquo; to me. Radio can be found as streaming audio.</p>

<p>As we have become more familiar with the internet and with an increased access through broadband, cable and fiber, we have started to innovate with the new medium. RSS changed the direction of broadcast from push to pull. youTube may have started as a way to share existing videos, but it has since grown to a place where anyone can make themselves heard. That is many to many communication.</p>

<p>The internet made interactivity a lot easier than in the off-line world. Web forums and UseNet allow groups of users to interact with each other through written messages. Blogs allow everyone to have their own newspaper column. Instead of an opinions page in the newspaper that is the internet, every writer gets their own column and they all respond and refer to each other&rsquo;s writing.</p>

<p>Twitter is the latest thing. It is a hybrid between instant messaging, e-mail and RSS feeds. People say it does not scale, yet the Twitter engineers keep making it better and more and more people are able to use it. Is there a limit to which it can scale? Is its centralized server model not going to be an important limitation on both scale and freedom later on? When there are six billion people using one and the same service, relying on it for an important part of their daily communications, how much can you trust on one company to take care of it?</p>

<p>Would it not be better to turn it into a distributed service? It has sucessfully scaled e-mail, Jabber/XMPP, the telephone network and internet itself. E-mail, as a world-wide service, has never gone down, even if individual servers might go down from time to time.</p>

<p>Traditional media has its problems. Paper flyers, mail-delivered advertising and commercials on the radio and television are a few examples. The relatively high price of print media or traditional broadcasting limits the amount of these forms of advertising. This makes it somewhat bearable. In contrast, spam via e-mail, blog comments, web forum posts and instant messages have no such limitations. It&rsquo;s virtually free to broadcast your message to a million people, so it happens a lot and people really don&rsquo;t like it.</p>

<p>E-mail spam can happen because there is a near-zero cost or risk for the sender. The same goes for other on-line communication. It can be interesting to consider the friend-of-a-friend model, such as is seen on Linked In and other social networks?</p>

<p>To send a message to someone, the whole connection chain between sender and receiver must be known, no matter how long it is. If someone spams, it means there is a chain of real people connecting them to you. This means the sender is traceable instead of anonymous. If you flag a message as spam, the whole chain is notified that they were part of a spam chain. This means people can choose to ban the spammer from using them as a connection in sending a message. It also means you can identify people who act as a gateway for spammers to send messages to other people.</p>

<p>The nice thing about treating communication as a social network activity is that it makes people more aware that they are dealing with people. By taking anonymity out of the equation, it lowers the tendency of people to act like a <a href="http://www.penny-arcade.com/comic/2004/03/19/">Total Fuckwad</a> when they think nobody is watching them.</p>

<p>Are there other ways to look at communication, to turn it upside-down and re-investigate how it works? What is going to be the next Twitter?</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[A possible future for package management]]></title>
    <link href="https://blog.narnach.com/blog/2009/a-possible-future-for-package-management/"/>
    <updated>2009-06-22T21:35:00+02:00</updated>
    <id>https://blog.narnach.com/blog/2009/a-possible-future-for-package-management</id>
    <content type="html"><![CDATA[<p>My recent post on the <a href="https://blog.narnach.com/blog/2009/kings-of-code-side-event-amsterdam-dot-rb-unconference/">Kings of code side event</a> got too long, so I extracted the following into its own blog post. It is a collection of thoughts on a possible presentation topic.</p>

<p>RubyGems has been around for ages and has made it relatively easy to distribute Ruby code. Not everyone uses it, though. Some prefer to use the Debian package manager, or whatever their OS provides, instead. This is very useful if a gem has external dependencies, but it is not as portable as RubyGems.</p>

<p>RIP was recently released (well it is only version 0.0.1, but still) as something to use complementary to RubyGems. It does not allow relative version requirements (&lt;, &lt;=, >=, >) for dependencies, only exact version requirements. It borrows the concept of virtual environments from the Python world. A different approach to package management out in the wild means people will gain new insights. What can we learn here? Where lies the right balance between having rigid, version specific, dependencies and open-ended dependencies?</p>

<p>Thinking along the dependency management line, why do we require exact versions or do we put an upper limit on accepted versions? The only reason I can think of is incompatibilities introduced in later versions, but is it right <b>at all</b> to introduce backward incompatibilities in your API? Can&rsquo;t we learn something from functional programming here?</p>

<p>In FP, pure functions don&rsquo;t have side effects. One of the implications is that the data they receive does not get altered. You don&rsquo;t add a new item to an existing array; you return a new array with the new item appended to the existing array. Because of this, there is no problem when you have a multi-threaded program: there is no risk that two threads will try to modify a shared resource at the same time.</p>

<p>This means you don&rsquo;t need mutexes to lock an object to one thread while it manipulates the object. No mutexes means no deadlocks or other headaches associated with threading.</p>

<p>What was I talking about? Ah yes, dependencies and how they relate to functional programming. Explicit version dependencies can be seen as mutexes: only one version is allowed to be used at once. Two versions of a library can not be loaded at the same time. This is good if the two versions are incompatible. It is bad if the newer version only <i>adds</i> new functionality to the library.</p>

<p>What if you would build your library in a way that resembles the pure functions of functional programming? No side effects in this case means there are no nasty surprises when upgrading. If your program works with version 1 of the library, it will work without changes with version 1000. Existing functionality is immutable.</p>

<p>To make this work, new versions should only introduce new behaviour, they can not change old behaviour. I think making bugfixes would be ok, but performance enhancements are not, as it might be that you introduce negative side effects in <i>some</i> edge cases, thereby breaking someone&rsquo;s app. Maybe fixing bugs will actually break someone&rsquo;s app if they depended on buggy behaviour. Hmmm&hellip;.</p>

<p>This makes dependency management rather easy. You set a minimum version requirement for the libraries you use and you can just upgrade the libraries to newer versions as they become available. New applications that use new features can co-exist with old applications that use old features from the same library.</p>

<p>Under this model, if you plan to radically re-architect a project, you could fork it and release it under a new name. Rails v1., Rails2 v1, Rails3 v1. A downside is that forks can have a large shared codebase, but there will no longer be conflicts between versions of one project.</p>

<p>Has anyone ever explored the possibilities of library development along these lines? Did it work or were there problems that I have overlooked? What good features of the &lsquo;current&rsquo; systems would you lose?</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Kings of Code side-event: Amsterdam.rb unconference]]></title>
    <link href="https://blog.narnach.com/blog/2009/kings-of-code-side-event-amsterdam-dot-rb-unconference/"/>
    <updated>2009-06-21T13:10:00+02:00</updated>
    <id>https://blog.narnach.com/blog/2009/kings-of-code-side-event-amsterdam-dot-rb-unconference</id>
    <content type="html"><![CDATA[<p>The <a href="http://kingsofcode.org">Kings of Code</a> (KoC) conference is going to be held on 30 June 2009. The day before, monday 29 June, is side-event day. Sander van der Vliet, the KoC organizer, posted a message to the Amsterdam.rb mailing list last wednesday to ask if we were interested in organizing a side-event on the 29th.</p>

<p>After only a couple of us replied to Sander&rsquo;s e-mail, we knew none of the <s>heroes</s> usual people would step forward to organize this. On friday, Julio Javier Cichelli (<a href="http://twitter.com/monsieur_rock">@monsieur_rock</a>) sent me a direct message on Twitter about my thoughts on how the unconference should be organized. From there, we discussed how to get it organized, how to get speakers and what we were going to present. In short, we stepped forward to organize the side-event.</p>

<p>Next I tweeted to ask for presenters. The message got re-tweeted a number of times and almost within minutes there is feedback from multiple people willing to do a presentation. At the end of the day we have 6 people willing to speak. Using Twitter to organize something is a really quick and powerful way to do it.</p>

<p>As more and more people indicate they are willing to speak (thank you all!) the focus moves from finding speakers to handling the details of making it all work. At what time do we start? How many hours do we have? Is there wifi? Is there a beamer? The further you go, the more you discover there are things you should find out or arrange.</p>

<p>Next week we need to find a sponsor for the venue and we need to start thinking about the things that need to be done on the event day itself. We also need to confirm time and location with all presenters and announce the side-event.</p>

<h2>Unconference</h2>


<p>The side-event is an unconference. I have never been to one, so I can only go by what is on the internet. A characteristic of unconferences is that there is no fixed agenda. There are no time slots. It is not about one person being an expert and bestowing wisdom upon the attendees, but about the attendees sharing wisdom with each other. I like that.</p>

<p>Everybody knows something other people can benefit from, so the more opportunities there are for everyone to contribute, the more everyone will learn. Any one of the attendees can decide on the spot they want to talk about something, show code or sing a song. I hope people will do this.</p>

<p>The <a href="http://devnology.nl">Devnology</a> meetings have impressed upon me the importance of interactivity at a gathering of people, so I hope we can give the unconference an interactive twist.</p>

<p>After a presenter is done speaking, we&rsquo;ll try to get a group discussion started on the topic. Once the discussion starts to fade, or starts to run in circles, we can ask for the next speaker to get on stage and introduce a next topic.</p>

<p>After the last speaker, we can try to spark group discussions by encouraging people to approach the speakers and ask them questions. This, in turn, can create a number of smaller discussions, with the speakers being the center of interactivity. It&rsquo;s a great way to get to know new people.</p>

<p>Between 6 more or less confirmed speakers, group discussions, short breaks and (I hope) spontaneous speakers, it looks like we will actually fill up the 5 hours we have available to us.</p>

<h2>Finding a theme</h2>


<p>Unconferences tend to have a theme, this is so people can prepare themselves and to have some form of coherence between talks. This is trickier, as I did not really think about this until now.</p>

<p>Here is a list of topics that people have expressed they want to talk about:</p>

<ul><li>CouchDB (or an introduction to Erlang)</li>
  <li>Communicative Programming with Ruby</li>
  <li>Code reviews</li>
  <li>Using Rails for Location based search</li>
  <li>Short and Sweet II</li>
  <li>MacRuby, RESTful web services and other cool things</li></ul>


<p>If I do a bit of creative extrapolating, one topic that can be extracted from this is &ldquo;The Future of Web Development (using Ruby)&rdquo;. Let me explain by briefly looking at each topic:</p>

<ul><li>CouchDB is a possible future of databases. It&#8217;s not relational, so it has different scaling needs compared to &#8216;traditional&#8217; relational databases.</li><li>RESTful services are the next big thing. Within the Ruby/Rails world it&#8217;s becoming a de-facto standard on how to design a web service. The rest of the webdev world seems to be following along here.</li><li>If you look at the last decade or two and how the dominant languages have changed, it becomes apparent that code is getting way more readable. Shorter, leaner code is more readable because there is just less code. People use more expressive languages that can do more with less code. Code has become more communicative (at least in Ruby) because of the focus on good conventions like intention revealing naming. DSLs are another good example of readability. If a non-programmer can read your code, you know it is readable.</li><li>Alternative Ruby implementations are a way into the future for the language. Diversity allows different ideas to be explored at the same time. The same goes for alternative web frameworks. They are a breeding ground for innovation, which is what you need to get a future that is different from the present.</li><li>Code reviews are a way to ensure that code written in the past is actually good enough to be kept around in the future.</li><li>Location-based search has a futuristic sound to it, so it fits the theme.</li></ul>




<h2>Thoughts on The Future of Web Development (using Ruby)</h2>


<p>The Future is an interesting topic that can be applied in a lot of ways. Here&rsquo;s a number of ideas for presentations:</p>

<h3>The future of server administration</h3>


<p>With VPSes and cloud computing becoming available everywhere, is there still a need to own your server hardware? With services like Heroku, Github webpages and Disqus, do you still need to even know how to install Ruby or how to configure Apache?</p>

<p>Even if you don&rsquo;t use these services, by using tools like Capistrano, Ubuntu Machine, Deprec or Rudy, you can still simplify deployment and server management. Does simplifying these things bring new opportunities? What does a sysadmin do with the time saved by these tools and services? Are there new possibilities opened by freeing up sysadmin time? What are they?</p>

<h3>The future of package management</h3>


<p>I have addressed this in a <a href="https://blog.narnach.com/blog/2009/a-possible-future-for-package-management/">separate blog post</a>.</p>

<h3>The future of web-based communication</h3>


<p>I have addressed this in a <a href="https://blog.narnach.com/blog/2009/a-possible-future-for-web-based-communication/">separate blog post</a>.</p>

<h2>My personal experience so far</h2>


<p>Between asking Sander for info (via Twitter, of course), discussing things with Julio and discussing details with speakers, there is quite some communication going on. It&rsquo;s exciting and a little scary at the same time.</p>

<p>I&rsquo;m a natural introvert, so I tend to avoid communication when I can get away with it. It&rsquo;s not often that I approach other people first. Taking an active role in helping to organize an unconference like this is therefore quite a bit outside of my comfort zone.</p>

<p>So why the heck am I doing this? One reason is because I want to see it happen. If nobody does it for you, do it yourself. The other reason is is that I want to expand my comfort zone. Someone wise once wrote: <i>&ldquo;If something does not scare you at least a little bit, it is not worth doing.&rdquo;</i>
It might sound be a bit extreme, but the core idea is valuable nonetheless: a very good way to learn things is to do the things that scare you.</p>

<p>Helping to organize a side-event for KoC will most definitely be a great learning experience.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Upgraded to ruby 1.9.1]]></title>
    <link href="https://blog.narnach.com/blog/2009/upgraded-to-ruby-1-dot-9-1/"/>
    <updated>2009-06-11T19:07:00+02:00</updated>
    <id>https://blog.narnach.com/blog/2009/upgraded-to-ruby-1-dot-9-1</id>
    <content type="html"><![CDATA[<h2>The short story</h2>


<p>Today I upgraded my Macbook to ruby 1.9.1 (patchlevel 129) as the main version of Ruby I use. It was not really intentional, but now that I have it, I&rsquo;m kind of sticking with it. That&rsquo;s the short story. There&rsquo;s also a long story that involves a server, lots of logs and me not paying attention.</p>

<h2>The long story</h2>


<p>Earlier today I wanted to analyze 2.5GB of Rails log files. Because it is not such a good idea to do that on a live production server, I decided to use the one server that never really does anything: the backup server. It&rsquo;s hidden all the way in the back of our server network, far away from the business of our webservers, so it is the perfect place to do some heavy number crunching. After sending the 2.5GB of Rails log files over with <i>scp -C</i> (-C stands for compress) I tried to install the <i>request-log-analyzer</i> gem, but there was no gem command.</p>

<p>A quick <i>ruby -v</i> resulted in bash telling me there is no ruby. My confused reaction went along the lines of: <i>&ldquo;No Ruby? What? We have a server without Ruby? How can this be?&rdquo;</i> I checked the server&rsquo;s sources dir and there was actually a dusty tarball for ruby 1.8.6 sitting undisturbed. I immediately jumped on it and started to unpack it and ran <i>./configure</i>.</p>

<p>While waiting for this to end, I thought about Ruby 1.9.1 and it&rsquo;s promise of speed and the huge stack of logs I was planning to start working on. I never made it to the <i>make &amp;&amp; sudo make install</i> part for Ruby 1.8.6.</p>

<p>After downloading the latest Ruby 1.9.1 tarball to my desktop and sending it through a chain of servers to the poor ruby-less backup server, a <i>./configure &amp;&amp; make &amp;&amp; sudo make install</i> made it all happy again. It actually purrs if you listen close enough to your SSH session.</p>

<p>In the meanwhile I figured I&rsquo;d upgrade my local Ruby 1.9.0p0 install to the latest patchlevel, so I also perfomed the <i>./configure &amp;&amp; make &amp;&amp; sudo make install</i> ritual on my own machine as well. As a habit I always run a &lsquo;-v&rsquo; check to see if the version did get installed, but I accidentally typed <i>ruby -v</i> instead of <i>ruby1.9 -v</i> and to my surprise it said:</p>

<pre>ruby 1.9.1p129 (2009-05-12 revision 23412) [i386-darwin9.7.0]</pre>


<p>Oh, oh. That was not supposed to happen. That should have been Ruby 1.8.6!
A check for ruby1.9 showed it was still the old Ruby 1.9.1:</p>

<pre>ruby 1.9.1p0 (2009-01-20 revision 21700) [i386-darwin9]</pre>


<p>Since the server was done installing as well, I jumped over to there. Unfortunately, request-log-analyzer did not like ruby 1.9:</p>

<pre>
$ request-log-analyzer log/production.log
Request-log-analyzer, by Willem van Bergen and Bart ten Brinke - version 1.1
Website: http://github.com/wvanbergen/request-log-analyzer

/usr/local/lib/ruby/gems/1.9.1/gems/request-log-analyzer-1.1.6/lib/request_log_analyzer.rb:27:in `require': /usr/local/lib/ruby/gems/1.9.1/gems/request-log-analyzer-1.1.6/lib/request_log_analyzer/output/fixed_width.rb:48: invalid multibyte char (US-ASCII) (SyntaxError)
/usr/local/lib/ruby/gems/1.9.1/gems/request-log-analyzer-1.1.6/lib/request_log_analyzer/output/fixed_width.rb:48: invalid multibyte char (US-ASCII)
/usr/local/lib/ruby/gems/1.9.1/gems/request-log-analyzer-1.1.6/lib/request_log_analyzer/output/fixed_width.rb:48: syntax error, unexpected $end, expecting '}'
...   => { :horizontal_line => '━', :vertical_line => '┃', ...
...                               ^
      from /usr/local/lib/ruby/gems/1.9.1/gems/request-log-analyzer-1.1.6/lib/request_log_analyzer.rb:27:in `load_default_class_file'
      from /usr/local/lib/ruby/gems/1.9.1/gems/request-log-analyzer-1.1.6/lib/request_log_analyzer/output.rb:4:in `const_missing'
      from /usr/local/lib/ruby/gems/1.9.1/gems/request-log-analyzer-1.1.6/lib/request_log_analyzer/controller.rb:38:in `const_get'
      from /usr/local/lib/ruby/gems/1.9.1/gems/request-log-analyzer-1.1.6/lib/request_log_analyzer/controller.rb:38:in `build'
      from /usr/local/lib/ruby/gems/1.9.1/gems/request-log-analyzer-1.1.6/bin/request-log-analyzer:88:in `<top>'
      from /usr/local/bin/request-log-analyzer:19:in `load'
      from /usr/local/bin/request-log-analyzer:19:in `<main>'
</main></top></pre>


<p>So now we know Ruby 1.9 is strict on character encoding and does not like this particular version of the gem. My natural reaction is to switch to my local machine and do a github checkout of the source and build a new gem:</p>

<pre>
$ gh clone wvanbergen/request-log-analyzer
/usr/local/lib/ruby/gems/1.9.1/gems/github-0.3.4/lib/github/extensions.rb:11: warning: undefining `object_id' may cause serious problem
/usr/local/lib/ruby/gems/1.9.1/gems/github-0.3.4/lib/github.rb:149:in `module_eval': /usr/local/lib/ruby/gems/1.9.1/gems/github-0.3.4/lib/commands/commands.rb:40: syntax error, unexpected ')' (SyntaxError)
helper.tracking.sort { |(a,),(b,)| a == helper.origin ? -...
                            ^
/usr/local/lib/ruby/gems/1.9.1/gems/github-0.3.4/lib/commands/commands.rb:40: syntax error, unexpected '|', expecting '='
...per.tracking.sort { |(a,),(b,)| a == helper.origin ? -1 : b ...
...                               ^
/usr/local/lib/ruby/gems/1.9.1/gems/github-0.3.4/lib/commands/commands.rb:40: syntax error, unexpected '}', expecting keyword_end
...rigin ? 1 : a.to_s <=> b.to_s }.each do |(name,user_or_url)|
...                               ^
      from /usr/local/lib/ruby/gems/1.9.1/gems/github-0.3.4/lib/github.rb:149:in `load'
      from /usr/local/lib/ruby/gems/1.9.1/gems/github-0.3.4/lib/github.rb:66:in `block in activate'
      from /usr/local/lib/ruby/gems/1.9.1/gems/github-0.3.4/lib/github.rb:65:in `each'
      from /usr/local/lib/ruby/gems/1.9.1/gems/github-0.3.4/lib/github.rb:65:in `activate'
      from /usr/local/lib/ruby/gems/1.9.1/gems/github-0.3.4/bin/gh:8:in `<top>'
      from /usr/local/bin/gh:19:in `load'
      from /usr/local/bin/gh:19:in `<main>'
</main></top></pre>


<p>Aargh! Another gem that does not play well with Ruby 1.9.</p>

<p>At this point I was kind of fed up with gems not working with Ruby 1.9, so I decided to use a script I wrote ages ago to do simple log crunching. It did not look as pretty as request-log-analyzer, but since it was <i>my</i> script, I felt it would be easiest to fix if it was wrong.</p>

<p>The script did needed a little tweaking to work on Ruby 1.9, but that went pretty ok. The script started crunching, and crunching, and crunching and grew to about 800M (not bad for holding about a gazillion URLs and their call times, standard deviations and more relevant numbers). It was mostly done, generating a new report to highlight different stats every minute or so. And then the Ruby process died. There was something about character encoding and UTF-8:</p>

<pre>
analyze_log.rb:232:in `split': invalid byte sequence in UTF-8 (ArgumentError)
      from analyze_log.rb:232:in `block in <main>'
      from analyze_log.rb:231:in `each'
      from analyze_log.rb:231:in `<main>'
</main></main></pre>


<p>Luckily, there were enough reports done so that I could look at the numbers I wanted to see.</p>

<h2>Conclusion</h2>


<p>This experience has taught me two things:</p>

<ul><li>Being an early adopter is rarely a smooth experience. You&#8217;re playing with new features before other people do, but the flip side is that you will run into problems and that you will have to fix them yourself.
</li><li>I really dislike character encodings. Tell me again, why aren&#8217;t we just using plain old ASCII? <span style="font-weight: bold;">*grumbles*</span>
</li></ul>


<p>Next up is checking/fixing my own Rubygems to guarantee they at least do work with Ruby 1.9.1p129. A better world starts with you doing your best to improve it.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Devnology: a bridge between developer communities]]></title>
    <link href="https://blog.narnach.com/blog/2009/devnology-a-bridge-between-developer-communities/"/>
    <updated>2009-05-12T08:41:00+02:00</updated>
    <id>https://blog.narnach.com/blog/2009/devnology-a-bridge-between-developer-communities</id>
    <content type="html"><![CDATA[<h2>What is Devnology?</h2>


<p><a href="http://devnology.nl">Devnology</a> is a foundation that organizes meetings for software developers. Their goal is to bridge the gap between the many different communities that exist for the many programming languages and platforms that a software developer can choose to use. The background of the founders is mainly in the Windows world.</p>

<p>In order to learn from others, Devnology was started as a way to help developers share and learn tips and tricks, insights, tools, news and insights. In this respect, it is similar to how the <a href="http://amsterdam-rb.org/" name="Utrecht.rb">Ruby</a> <a href="http://groups.google.com/group/utrecht-rb" name="Utrecht.rb">User</a> <a href="http://groups.google.com/group/twente-rb" name="Twente.rb">Group</a> meetings work as a way to learn from each other. The difference is that the Ruby meetings are more heavily focused on socializing, while Devnology meetings are balanced more towards learning.</p>

<p><a href="http://ruby-lang.org">Ruby</a> meetings tend to be fun beer nights: we gather in the pub, drink beer (or ice tea) and talk all night long about topics that can include Ruby, tools, new companies or projects, freelancing, pet projects and much, much more. Sometimes someone gets a laptop on the table and shows what they are working on, usually in the form of a live demo or by showing code. The key difference between Ruby meetings and Devnology meetings is the organized format of Devnology meetings. Devnology meetings have a limit on attendance, a pre-arranged location that is either rented or sponsored and they have a speaker or theme to provide enough fuel to keep the conversations going for the whole evening.</p>

<h2>Building bridges</h2>


<p>Getting to know new people is a chance to learn about new ways of thinking. The more different people you meet, the more you can learn. Within a single community, there tends to be an overlap in certain ways of thinking. As an example, let&rsquo;s contrast Rubyists and Windows developers.</p>

<p>Rubyists, in my experience, tend to be young and eager to try out new things. There are quite a few people that learn on the job and don&rsquo;t have a formal education. A lot of them work at smaller companies or as freelancer and they are pretty passionate about what they do. Due to <a href="http://rubyonrails.org">Rails</a>, a lot of work is in web development. Open Source is very important and everyone is more or less expected to have an account on <a href="http://github.com">Github</a> to share their code. A lot of people have a Mac or at least run Linux on their laptop. I don&rsquo;t know anyone who is serious about Windows as a developer platform for Ruby. There are some tools for Windows, but support is poor compared to Linux and Mac. Rubyists tend to be intimate with the command line and they tend to know at least a little bit of how to operate a Linux server. From front-end HTML/CSS design, through Rails code to a MySQL database design, from automated unit testing, integration testing and performance testing, a Ruby developer tends to know at least a bit about everything. Chances are, they will fulfill multiple or all of these roles on their projects.</p>

<p>In contrast, the handful of Windows developers I met at the last Devnology meeting tend to be older than Rubyists and appear a bit more formal. There are quite a bit of consultants working for larger companies. I actually heard people describe themselves as Software Architect and talk about corporate ladders as the most normal thing in the world. For a Rubyist to say that would be strange.</p>

<p>For me, these two groups are kind of opposites. Due to this, they would normally not interact much. This causes knowledge to be discovered independently and to be spread in their own communities. What is new in one group could be discovered a year later by the other group. If the two groups interact and share knowledge, the knowledge sharing might happen earlier. This is where Devnology can add a lot of value.</p>

<h3>The git story</h3>


<p>A good example of knowledge that is not universal is the <a href="http://git-scm.com/">Git</a> distributed source code management system. For Rubyists, it is the SCM to use. Subversion is so 2007. In the Windows world, Subversion is still the way to go and Git is largely unknown. Git was developed by Linus Torvalds, of Linux kernel fame, to replace Bitkeeper after Bitkeeper stopped being free. Git has great support on Linux and Mac, but Windows support took a while to get going.</p>

<p>Being distributed, Git does not depend on a central repository to store all code. When you have a checkout of the code, you have the full repository. This includes all history and branches, tags, etc. Git supports a centralized workflow, where everyone pushes their changes to a single server and pulls their updates from there. Through git-svn, it is possible to even use git to interact with Subversion repositories.</p>

<p>The advantages of Git becomes more interesting in the Github model: everyone on the team has a public repository on Github and a private repository on their laptop. You work locally and then push your changes to your public repository. Then you pull changes from other people&rsquo;s public repositories, work offline for a bit and push all changes back to your public repository. Other people can then pull in your changes and so on. This is almost an evolutionary approach to coding, where the best patches get pulled in by a lot of people and remain with the project. For closed source projects, you can use Github&rsquo;s private repositories, which you can share with people of your choice. In the Ruby world, Github is becoming a social network for developers.</p>

<p>My personal &ldquo;I am so glad I use Git instead of Subversion&rdquo; moment came when the old server we use to keep a number of private repositories on had a HDD failure. We just put in a new HDD, uploaded my working copies of all repositories and got back to work. During the week we had no central server, we committed code to local branches and ran a built-in git server to share new patches over the network. With Subversion we would have needed to do extra work to regularly backup the central repository and we could not have created new patches during the week the server was down.</p>

<h2>Last week&#8217;s Devnology meeting</h2>


<p>Last week wednesday I attended Devnology&rsquo;s second meeting and had a great evening. There were about 18 people, mostly .NET and Java developers, but there were also two Smalltalkers, a Pythonist and me as a Rubyist. Though a lot of references and examples used the Windows platform and it&rsquo;s tools and languages, the discussion went about fundamentals that apply to all platforms, languages and communities. The meeting type was Round Table discussion and it was divided into two parts, each with their own topics.</p>

<h3>First part</h3>


<p>We gathered a number of topics and then voted on them. The two topics we would be discussing were: Generalist vs Specialist and Learning on the job vs Computer Science.</p>

<p>Generalist vs Specialist was interesting because it immediately became clear that everyone had a different opinion on what the terms meant. Is it specific to a language, a business domain, a platform, a role in the team or something else entirely? What is the scope in which you define these terms? It is interesting to question this. I always thought of myself as a Generalist, because I can do almost anything required in our company: be the sysadmin, be the software architect, design the database, write back-end code, write front-end code, test the system, plan the project and lead the team. On the other hand I am a Specialist, because all my knowledge is focused within the Ruby and Rails environment. I would be lost on Windows with a .NET project to develop a GUI application.</p>

<p>After a bit, the discussion flowed over to Learning on the Job vs Computer Science. Arguments that were put forth for CS are that it gives you a broad knowledge of different ways to solve a problem. Learning on the Job saves you four years and immediately starts to teach you what you need to know. You might not know the theoretical background about why things work the way the do, but you will be able to apply it.</p>

<p>The discussion also highlighted interesting perspectives of people who initially started to work and then later got their CS degree. Going this route gives you a lot more practical context to put the theory in. This is the opposite of the CS-first approach, where you first learn a lot of &lsquo;useless&rsquo; theory that only later on becomes relevant when it gets a context in your job. A lot of theory might never get a proper context, I can imagine.</p>

<p>I initially started on a CS-ish route by studying Artificial Intelligence, but I did not find it challenging enough. For this reason I quit and found myself a job, where I did find a challenge and learned a lot of things. From time to time I do find myself hungry for the knowledge I could have gained at a CS course. The problem is that the school system is, in my opinion, very fake with grades as goals instead of knowledge as supreme goal. It&rsquo;s been four years since I left university and I only have vague memories of most of the things I learned, while I was always among the best scoring students. On the other hand, I also tend to forget how to use certain software libraries I knew intimately half a year ago but never used since then. I think that the details of what you know will fade, but the general concepts you learn will probably expand your way of thinking and stay.</p>

<h3>Second part</h3>


<p>The question of this part was &ldquo;What is/are your favorite&hellip;?&rdquo; A couple of suggested things to list were people&rsquo;s top-3 books, blogs, podcasts, tools.</p>

<p>My choice was the <a href="http://pragprog.com">Pragmatic Programmers</a>. They started as simple software developers turned authors, but they went on to build a publishing house for software books. Whenever I want to learn something new, I always check in there is a PragProg book or screencast available. They introduced the concept of beta books, which are books that have a beta version published as PDF while the author is still writing the book. This is great, as the author gets a lot of feedback to make the printed book better. If the book has source code that contains a bug, you can just click the &lsquo;Report Errata&rsquo; button at the bottom of the PDF and submit a bug report and possible fix for the code on that page. Getting your hands on an early version of a book also means that you can read it way before the paper version even ships.</p>

<p>A second choice is <a href="http://peepcode.com">Peepcode</a>, which sells professional screencasts on a wide range of topics. Recently they also started publishing smaller eBooks as PDF. A lot of early work is focused on Ruby, but more recent work covers a wider range of topics. Non-ruby topics include Git, Emacs, Clojure, Objective-C, Productivity, Javascript and more.</p>

<h2>Conclusion</h2>


<p>Devnology is a great initiative that I intend to support by means of attending meetings and generating publicity in the Ruby communities I am part of. Sharing knowledge between previously unconnected communities is a good thing and I hope it will be a huge success.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Ruby quick tip]]></title>
    <link href="https://blog.narnach.com/blog/2009/ruby-quick-tip/"/>
    <updated>2009-04-21T15:41:00+02:00</updated>
    <id>https://blog.narnach.com/blog/2009/ruby-quick-tip</id>
    <content type="html"><![CDATA[<p>I just discovered two different ways to create a fixed-length array filled with a default value.</p>

<pre code="prettyprint lang-ruby">
Array.new(5,1) # => [1,1,1,1,1]
[1] * 5        # => [1,1,1,1,1]
</pre>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[SimpleGate]]></title>
    <link href="https://blog.narnach.com/blog/2009/simplegate/"/>
    <updated>2009-01-26T08:18:00+01:00</updated>
    <id>https://blog.narnach.com/blog/2009/simplegate</id>
    <content type="html"><![CDATA[<p>At <a href="http://www.yomedia.com/">yoMedia</a> we frequently have to perform simple tasks on servers that are only reachable by hopping through a number of other servers. To deploy Rails, Merb or Ruby projects, we use <a href="http://www.capify.org/">Capistrano</a> and it works great. It is easy to configure and you can set it to use any number of gateway servers if that is needed to reach a server.</p>

<p>When deploying ruby gems or executing arbitrary commands, Capistrano does not really work for me. Don&rsquo;t get me wrong, the upload:deploy task is great if you want to send an updated project file to your deployed project. Sending a gem or configuration file to an arbitrary directory on the server is not as easy. It is hard to break out of its project-sized box.</p>

<p>Our strategy so far has been to try and minimize our interaction with servers that were more than one hop away from our laptops. When we did have to restart a daemon or look at log files, we would have to do the SSH hop, hop, hop ritual and do our thing. Then exit, exit, exit until we&rsquo;re back on our laptop&rsquo;s bash shell. Having RSA key logins to a number of servers saves the trouble of having to enter passwords, but the manual SSH-hopping does get tedious after a while.</p>

<p>Being the kind of programmer who rather scripts the tedious things away rather than perfecting his typing speed to speed up repetitive tasks, I figured it must be possible to automate these things. Knowing I&rsquo;m not the only one with this problem, Google led me to a solution. <a href="http://net-ssh.rubyforge.org/gateway/v1/api/index.html">Net-ssh-gateway</a> (NSG). Thank you, Jamis Buck!</p>

<p>NSG makes it possible to establish an SSH connection through a gateway server to the next gateway server behind it using port forwarding. Repeat this multiple times until you&rsquo;ve connected to the final server. The code for this looks like this:</p>

<script src="https://gist.github.com/52730.js"></script>


<p>Since this is rather bulky and non-DRY code, let&rsquo;s condense it into something that involves less repeating of code:</p>

<script src="https://gist.github.com/52727.js"></script>


<p>Capistrano uses NSG internally for its <a href="http://github.com/capistrano/capistrano/blob/32de6356ba6175074c0ddec3b27ab3ae0c6ce635/lib/capistrano/configuration/connections.rb">gateway connection</a> code, but it seems kinda tightly coupled with Capistrano internals. Also, when I looked at it for the first time, I did not really get how it worked or what it did. To gain a better understanding, I decided to extract the relevant code into a script and rework it to be stand-alone.</p>

<p>The great thing about trying to do something with code you don&rsquo;t really understand is that you will understand it once you have dissected it far enough. After that, you can work with it and adapt it to suit your needs.</p>

<p>This resulted in an early version of <a href="http://github.com/Narnach/simple_gate">SimpleGate,</a> my attempt at creating a wrapper library around NSG to make gateway chaining easier. The first version was simply the relevant Capistrano method reworked to work in isolation. The next version improved on the gateway chaining by making at as easy as calling SimpleGate.new.through_to(%w[foo bar baz]) to connect through foo and bar to baz.</p>

<p>SimpleGate also has a ServerDefinition to wrap a simple YAML configuration file that stores the actual server connection information. This is useful for cronjob-activated scripts and other non-interactive code when you have a password authentication server in the chain of gateways. For command line tools using SimpleGate, it saves typing.</p>

<p>Capistrano has a good support for SSH, its configuration files and the various authentication schemes. Passwords and RSA keys are both not a problem. SimpleGate currently only supports passwords, as that is what NSG supports out of the box. RSA key logins are a todo item. For configuration, it does the simplest thing that can possibly work: just store the connection info as a plain YAML file in ~/.servers.yml.</p>

<p>After two minor version bumps, I had something that was good enough to build a script that connected through multiple gateway servers to my target and request its uptime. The next step was to execute arbitrary commands, which was a small modification.</p>

<p>Here I discovered another hard to reproduce feature that Capistrano executes in a really nice way: sudo passwords. For some reason I still have to discover, SimpleGate does not let me enter a password when asked for it on the remote server: it just fails the password check and quits. I guess that is another todo item.</p>

<p>After discovering this I wanted to check up on another server that was hidden behind a number of hops and started to change the hard-coded gateway connection sequence in my test script to connect to the new server.</p>

<p>Woah! Wait! Full stop.</p>

<p>Hard-coded connection info is not good. The server name should be a command line option and the connection sequence should be figured out by the script, not by me. Since I was not interested in manually working out all possible connection sequences, I figured it was time to add a simple path-finding Router class to the project&hellip;</p>

<p>After a quick read of relevant sections in <a href="http://www.amazon.com/Prolog-Programming-Artificial-Intelligence-Bratko/dp/0201403757">Bratko</a>, to refresh my knowledge of the topic, I decided to model the search space as a directed non-cyclical graph and search through it using a simple depth-first recursive search algorithm. Support for cyclical graphs will be another todo.</p>

<p>For every node in the network, all its possible connections are described in a YAML file, that is just a Hash of Arrays with server name strings. A special &lsquo;local&rsquo; node represents my laptop or any arbitrary internet-connected system. The search algorithm comes down to:</p>

<ol><li>If we search from target to target, return that the route is target.</li><li>If the current node has outgoing connection possibilities, try them all, keep the shortest and return it with the current node prepended to the returned list of nodes.</li><li>If there are no outgoing nodes, return nil.</li></ol>


<p>This results in a relatively naive path finder, but with only 15 nodes in my network, this is not much of a problem. Smarter algorithms can be added once I actually need them.</p>

<p>A version bump later I remembered by original goal: upload a gem, install it and restart the daemon associated with it. Restarting is all done in userland, so that is not a problem. Installation requires sudo, which is still a todo item. Uploading was still open.</p>

<p>NSG can open a normal net/ssh session. <a href="http://net-ssh.rubyforge.org/sftp/v2/api/index.html">net/sftp</a> can use this session to do file transfers. A quick copy-paste-adjust later I had a new executable for copying a single file to a single server, through an arbitrary number of hops.</p>

<p>Right now SimpleGate is at version 0.5.0 and it has the three items noted above as left to do. Then it has its core functionality and should be polished up for its 1.0 version.</p>

<p>The command line tools should get parameter support and a &ndash;help interface. Then the config files should both be documented and command-line editable. Once those things are in, multi-server support might be useful. In a Capistrano-like fashion connect to multiple servers (sequentially or in parallel) and execute commands on all of them or upload file(s) to them. The file uploader can get a better interface instead of mimicking the code.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Result of ACK: Future]]></title>
    <link href="https://blog.narnach.com/blog/2008/result-of-ack-future/"/>
    <updated>2008-12-09T09:13:00+01:00</updated>
    <id>https://blog.narnach.com/blog/2008/result-of-ack-future</id>
    <content type="html"><![CDATA[<p>Wikipedia&rsquo;s definition of a <a href="http://en.wikipedia.org/wiki/Future_%28programming%29">Future</a> in programming:</p>

<blockquote>In computer science, <span style="font-weight: bold;">futures</span> and <span style="font-weight: bold;">promises</span> are closely related constructs used for synchronization in some concurrent programming languages. They both refer to an object that acts as a proxy for a result that is initially not known, usually because the computation of its value has not yet completed.</blockquote>


<p>Yesterday evening a number of <a href="http://groups.google.com/group/amsterdam-rb/browse_thread/thread/2a38b6b85f3e7bbb">Rubyists from Amsterdam</a> came together in the public library with our laptops to do cool computer stuff until the library closed.</p>

<p>Among the topics we discussed were new-ish programming languages such <a href="http://olabini.com/blog/?s=ioke">Ioke</a> and <a href="http://clojure.org/">Clojure</a>. From here the discussion went to the languages that preceded them, like <a href="http://research.sun.com/self/language.html">Self</a> and <a href="http://www.iolanguage.com/">IO</a>.</p>

<p>I think that at some point someone asked &ldquo;What can IO do that Ruby can&rsquo;t do?&rdquo;, so we started looking at the list of features of IO. There we discovered <a href="http://www.iolanguage.com/scm/io/docs/IoGuide.html#Concurrency-Futures">futures</a>.</p>

<p>Futures look nifty: create an object that does not yet have a value and then move on and eventually do something with the object when you need its value. It will block if there is no value yet, which makes sense, but as long as you don&rsquo;t need the value, you can just move on with your business. This can be useful to do heavy computations or to initiate asynchronous interaction with a remote API. As long as you don&rsquo;t need the result immediately, a future can be useful.</p>

<p>Then I mentioned Ruby&rsquo;s <a href="http://apidock.com/ruby/Thread/value">Thread#value</a>, which was new to people. So a bit of code was created that looked similar to:</p>

<pre code="prettyprint lang-ruby">
# sleeps for 3 seconds, then prints 615
t = Thread.new { sleep 3; 123}
puts t.value * 5
</pre>


<p>Explicitly creating a Thread and calling its value does the trick, but it is not very elegant. If you read it, you will probably end think, &ldquo;What is that Thread doing? Oh, there&rsquo;s a #value call there. Thread + #value is a future!&rdquo;. Or you don&rsquo;t make the connection and misunderstand what this code is doing.</p>

<p>How should it look then to be more elegant?</p>

<pre code="prettyprint lang-ruby"># sleeps for 3 seconds, then prints 615
f = future { sleep 3; 123}
puts f * 5
</pre>


<p>So, this is way more elegant! You see it is a future, because it says so! If you don&rsquo;t know about futures, there is Wikipedia or Google and you might figure out what it does.</p>

<p>In order to make this happen, we need to define a future method that returns an object that when called returns Thread#value for that future. A proxy object. This leads to the next implementation:</p>

<pre code="prettyprint lang-ruby">class Proxy
 def initialize(&amp;block)
   @thread = Thread.new(&amp;block)
 end

 def method_missing(*args, &amp;block)
   @thread.value.send(*args, &amp;block)
 end
end

def future(&amp;block)
 Proxy.new(&amp;block)
end

f = future { sleep 3; 123}
puts f * 5
</pre>


<p>We created a Proxy class to do the threading logic and use method_missing to capture method calls, which we re-direct to Thread#value.</p>

<p>This works as long as you don&rsquo;t call methods defined on Object or Kernel, because you get those for free in every class. You need to either avoid using them or get rid of them. There is <a href="http://onestepback.org/index.cgi/Tech/Ruby/BlankSlate.rdoc">BlankSlate</a>, but since we were just trying to make our idea work, we just un-defined most methods on the object. Then we had the crazy idea to drop the Proxy object altogether and make Thread function as its own Proxy object. Thread, say bye-bye to your methods!</p>

<p>Here is the final bit of code we produced:</p>

<script src="https://gist.github.com/33661.js"></script>


<p>Then the library closed so we went home, after which I polished it a bit and created a <a href="http://github.com/Narnach/future/tree">github project</a> for it.</p>

<p>This morning my colleague, Filip Slagter, asked me if there wasn&rsquo;t already a library to do futures in Ruby. After a bit of <a href="http://github.com/search?q=future">searching</a>, I found there <a href="http://github.com/cho45/future">is one</a>. And it looks nice! Still, I like to re-invent the wheel. It is the best way to learn how something works.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Adventures in REIA land]]></title>
    <link href="https://blog.narnach.com/blog/2008/adventures-in-reia-land/"/>
    <updated>2008-11-30T16:04:00+01:00</updated>
    <id>https://blog.narnach.com/blog/2008/adventures-in-reia-land</id>
    <content type="html"><![CDATA[<p>One of my current interests is the new <a href="http://reia-lang.org/">Reia</a> programming language, created by <a href="http://tonyarcieri.org/">Tony Arcieri</a>. The wiki contains most of the documentation, but but besides a simple &ldquo;Hello, World!&rdquo; and <a href="http://github.com/tarcieri/reia/tree/master/examples/fibonacci.re">Fibonacci</a> implementation, there is not much working code. Reia is a work in progress, so that makes sense.</p>

<p>Philipp Pirozhkov created <a href="http://github.com/pirj/ryan/tree/master">Ryan</a>, a web framework built on top of Reia and <a href="http://yaws.hyber.org/">YAWS</a>. For reasons I have yet to figure out, it does not want to build on my machine. At least there&rsquo;s more code to look at to learn the language. Ryan also has a RSpec-like syntax for writing tests, which look interesting.</p>

<p>Starting with web development might be a bit too ambitious for me. I actually managed to mess up a simple &ldquo;Hello, world!&rdquo; example, so I&rsquo;m starting slow.
Note to self: methods in Reia have parentheses. It&rsquo;s not Ruby, where you can omit them.</p>

<p>Wrong hello world:</p>

<pre class="prettyprint lang-reia">puts "Hello, world!"
</pre>


<p>Proper hello world:</p>

<pre class="prettyprint lang-reia">puts("Hello, world!")
</pre>


<p>Sincy my brain still thinks in Ruby, let&rsquo;s start with a simple bit of Ruby code and convert it to Reia.</p>

<p>First, the Ruby code:</p>

<pre class="pretttyprint lang-ruby">[1,2,3].each { |n| puts n }
</pre>


<p>This prints out three lines with 1, 2 and 3 on them.
Now the same code in Reia:</p>

<pre class="prettyprint lang-reia">[1,2,3].each { |n| puts(n.to_s()) }
</pre>


<p>The two obvious differences:</p>

<ol><li>All method calls need their parentheses. So use &#8220;puts(&#8216;String&#8217;)&#8221; instead of &#8220;puts &#8216;String&#8217;&#8221;.</li><li>The int has to be explicitly cast to a String.</li></ol>


<p>Just like Ruby, Reia has multiple ways to write this code. Another Ruby-esque way to write it is by using the &lsquo;do&rsquo; block notation instead of curly braces:</p>

<pre class="prettyprint lang-reia">[1,2,3].each do |n|
  puts(n.to_s())
</pre>


<p>Notice the puts() is indented and there is no &ldquo;end&rdquo;: that is the Python-style indentation at work. A third way to write the code is by (ab)using <a href="http://en.wikipedia.org/wiki/List_comprehension">List Comprehensions</a>:</p>

<pre class="pretty-print lang-reia">[puts(x.to_s()) | x in [1,2,3]]
</pre>


<p>This is the strangest form for me, since Ruby does not have something similar. The way I interpret it is by reading from right to left: for each x in [1,2,3], do the puts thingy left of the pipe.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Hello, world!]]></title>
    <link href="https://blog.narnach.com/blog/2008/hello-world/"/>
    <updated>2008-11-30T15:25:00+01:00</updated>
    <id>https://blog.narnach.com/blog/2008/hello-world</id>
    <content type="html"><![CDATA[<p>After complaining over and over that I should really get myself a blog, I finally have one! Now, let&rsquo;s be nice and let me introduce myself.</p>

<p>My name is Wes Oldenbeuving and I&rsquo;m a programmer from Amsterdam, the Netherlands. My hobbies include reading books and blogs, playing <a href="http://www.xfire.com/profile/narnach/">video games</a>, watching tv series and <a href="http://github.com/Narnach">programming</a>.</p>

<p>My interests cover a wide variety of topics like computer science, economic theory, history, (melodic) metal music, politics, philosophy, personal growth and cooking. I&rsquo;m not a great chef, but I do try to improvise on recipes every once in a while.</p>

<p>I have been programming (in Ruby) since March 2006 for the Dutch company <a href="http://www.yomedia.com/">yoMedia</a>. Ruby on Rails is what brought me to Ruby, but it is not the only thing keeping me. Ruby as a language is really nice to work with and works for both simple scripts, to automate mundane tasks, and to build complex applications. The people in the local Ruby communities are also nice, smart and full of <s>crazy</s> creative ideas.</p>

<p>We have a number of regular events that I attend 99% of the time: <a href="http://amsterdam-rb.org/">Amsterdam.rb</a>, <a href="http://groups.google.com/group/utrecht-rb">Utrecht.rb</a> and the soon-to-start <a href="http://groups.google.com/group/amsterdam-rb/browse_thread/thread/2a38b6b85f3e7bbb">Amsterdam.rb screen-peeking diner thingy</a>.</p>

<p>I expect my blog posts to mainly cover programming-related topics, though they will not necessarily be all about Ruby. In fact, expect the first posts to be about the new <a href="http://www.reia-lang.org">Reia</a> programming language.</p>
]]></content>
  </entry>
  
</feed>
