<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[the science department blog]]></title><description><![CDATA[Thoughts on software engineering from two decades of experience across engineering management, product management and design tailored for entrepreneurial engineers.]]></description><link>https://blog.scidept.com/</link><image><url>https://blog.scidept.com/favicon.png</url><title>the science department blog</title><link>https://blog.scidept.com/</link></image><generator>Ghost 5.78</generator><lastBuildDate>Mon, 06 Apr 2026 09:14:06 GMT</lastBuildDate><atom:link href="https://blog.scidept.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Language that  t̶e̶s̶t̶s̶ writes Code]]></title><description><![CDATA[<p>Last week, there was a bit of drama on <a href="https://www.youtube.com/watch?v=tNmgmwEtoWE&amp;ref=blog.scidept.com" rel="noreferrer">YouTube</a>, <a href="https://www.reddit.com/r/csMajors/comments/1c3jqxa/devin_ai_fake/?ref=blog.scidept.com" rel="noreferrer">Reddit</a> (by way of tiktok), and across the web about Devin.ai, a paid LLM that purportedly is a full-fledged developer and was able to complete tasks that were posted by real people to Upwork. It turns out it can&</p>]]></description><link>https://blog.scidept.com/language-that-tests-writes-code/</link><guid isPermaLink="false">6622d1f14fb28d04d5440a81</guid><dc:creator><![CDATA[Will Clark]]></dc:creator><pubDate>Fri, 19 Apr 2024 21:09:33 GMT</pubDate><media:content url="https://blog.scidept.com/content/images/2024/04/DALL-E-2024-04-19-13.21.07---A-futuristic-scene-of-a-robot-sitting-at-a-desk--intensely-focused-on-writing-code-on-multiple-computer-screens.-The-robot-has-a-sleek--metallic-body-.webp" medium="image"/><content:encoded><![CDATA[<img src="https://blog.scidept.com/content/images/2024/04/DALL-E-2024-04-19-13.21.07---A-futuristic-scene-of-a-robot-sitting-at-a-desk--intensely-focused-on-writing-code-on-multiple-computer-screens.-The-robot-has-a-sleek--metallic-body-.webp" alt="Language that  t&#x336;e&#x336;s&#x336;t&#x336;s&#x336; writes Code"><p>Last week, there was a bit of drama on <a href="https://www.youtube.com/watch?v=tNmgmwEtoWE&amp;ref=blog.scidept.com" rel="noreferrer">YouTube</a>, <a href="https://www.reddit.com/r/csMajors/comments/1c3jqxa/devin_ai_fake/?ref=blog.scidept.com" rel="noreferrer">Reddit</a> (by way of tiktok), and across the web about Devin.ai, a paid LLM that purportedly is a full-fledged developer and was able to complete tasks that were posted by real people to Upwork. It turns out it can&apos;t do that, but I&apos;m not here to dog pile on this situation.</p><p>Several people have asked me what I think about AI while raising money for my new company, <a href="http://www.kickplan.com/?ref=blog.scidept.com" rel="noreferrer">Kickplan</a> (which helps people monetize AI in SaaS but isn&apos;t an AI company per se). I also had a great email exchange with my friend <a href="http://www.c2.com/?ref=blog.scidept.com" rel="noreferrer">Ward Cunningham </a>about an old technology that got me thinking about it again, and I think there&apos;s a lot we can learn about &quot;LLM developers&quot; from it.</p><h2 id="cucumber">Cucumber </h2><p>In the 2008 - 2012 time period, in the Ruby on Rails community (and later beyond), a testing methodology based on a library called <a href="https://www.youtube.com/watch?v=Hc65D12fV8Y&amp;ref=blog.scidept.com" rel="noreferrer">Cucumber</a> became popular. Cucumber was a riff on an older concept that Ward Cunningham invented and was popularized in Java called FIT or &quot;framework for integrated testing.&quot; The idea was that non-engineers could specify how software behaved by describing the start and end behavior of the software, sometimes with natural language and sometimes with spreadsheets or other artifacts. And you wrote these documents first, but I don&apos;t need to be as specific as writing the actual Ruby (or other) code required to implement it. Once the code was written, the documents could generate code that would automatically prove that your software did what it was supposed to do.</p><p>Here&apos;s what that looks like:</p><pre><code class="language-Gherkin">Feature: Change password

  Scenario: Change my password
    Given I am signed in
    When I go to the edit user page
    And I fill out change password section with my password and &quot;newsecret&quot; and &quot;newsecret&quot;
    And I press &quot;Change password&quot;
    Then I should see &quot;Password changed&quot;
    Then I should be on the new user session page
    When I sign in with password &quot;newsecret&quot;
    Then I should be on the stream page
</code></pre>
<p>Is this clear what you want the software to do? It&apos;s not bad, but unfortunately, you still have to write all the actual code, as well as the underlying code that turns these natural langage steps into actual tests. </p><p>In theory, I absolutely loved the idea of collaborating with stakeholders to decide the behavior of software in a way they could understand. When I put on an engineering hat, there&apos;s so much cognitive overload that I don&apos;t want to make all the engineering choices and figure out the optimal behavior. It&apos;s too much. If we can reduce the ceremony by specifying how software should behave and verifying it behaves that way with the same code, you kill more than 2 birds with one stone.</p><p>However, in 2024, I&apos;d be shocked if you know of ANY company that uses Cucumber or any FIT testing at scale. And if they do, I&apos;d be SHOCKED if they started using it in the last 4 years. There&apos;s a bunch of reasons why, but the biggest is the <em>specificity problem</em>. </p><h2 id="specificity-and-process">Specificity and Process</h2><p>To control software&apos;s behavior, you have to be very specific. In fact, you need to be so specific that you always create a formal language so that words have specific meanings and you control the vocabulary your team uses. You&apos;ll need to craft and refine this language and collaborate with others. You&apos;ll need some formalized way to merge multiple work streams together. Finally, you&apos;ll need a process, once it&apos;s been merged, to check the correctness of that merged code against what he machines understand.</p><p>Congratulations, you&apos;ve created a programming language and now follow a software development lifecycle.</p><h2 id="llm-based-software-engineering">LLM-based Software Engineering </h2><p>The problem with thinking that an LLM can become a software engineer is twofold: </p><ol><li>The hard problem of software engineering is designing systems that result in behaviors that create sufficient value for users. </li><li>To control a code generation machine with sufficient specificity to achieve the desired outcome, you ultimately have to be really, <em>really</em> specific.</li></ol><p>Most of the outrage pointed at Devin.ai has revolved around problem #1. The code it generated was not correct, and it didn&apos;t actually create value for its users. Furthermore, it&apos;s so simplistic it can&apos;t actually design a <em>system</em>. It can only do 1 thing a programmer does, generate words chosen from a controlled vocabulary in a specific grammar prompted by natural language. And while that may seem complicated to non-programmers, that&apos;s not the hard part of programming computers.</p><p>But we&apos;re missing the point of what we&apos;ve learned with FIT/Cucumber.  When it comes to using an &quot;AI&quot; to generate code, no matter how advanced the &quot;AI&quot; eventually becomes <em>specificity</em> is still going to be the issue. To actually get repeatable and behaviorally software systems of sufficient complexity to sell them as a product or build a business around, from an LLM, you have to become a &quot;prompt engineer&quot; and if you have to be a &quot;prompt engineer&quot; to the extent that you learn the GPT-4 specific controlled vocabulary at a high level, I think you will find you&apos;ve now learned a new programming language. And if someone was unwilling or unable to learn Python, and non-trivial software systems require GitHub repos with thousands or millions of lines of &quot;natural&quot; language prompts, painfully crafted so that Devin or ChatGPT or Llama or <em>whatever</em> can actually generate something of value, instead of Ruby or Python, then what have we gained? </p><h2 id="agi-will-tell-us-how-to-fix-this">AGI Will Tell Us How To Fix This </h2><figure class="kg-card kg-video-card kg-width-regular" data-kg-thumbnail="https://blog.scidept.com/content/media/2024/04/v12044gd0000cocss17og65q45u4rhrg_thumb.jpg" data-kg-custom-thumbnail>
            <div class="kg-video-container">
                <video src="https://blog.scidept.com/content/media/2024/04/v12044gd0000cocss17og65q45u4rhrg.mp4" poster="https://img.spacergif.org/v1/576x1024/0a/spacer.png" width="576" height="1024" playsinline preload="metadata" style="background: transparent url(&apos;https://blog.scidept.com/content/media/2024/04/v12044gd0000cocss17og65q45u4rhrg_thumb.jpg&apos;) 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"/>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"/>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:24</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1&#xD7;</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"/>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"/>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            
        </figure><p>Or, I guess, maybe we&apos;ll just let the machines decide what software should without our input at all. What could go wrong?</p><p></p><p></p><p></p><p></p><p></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Sending Passbook Push Notifications with Houston and Sidekiq]]></title><description><![CDATA[<p>The <a href="http://nomad-cli.com/?ref=blog.scidept.com">Nomad</a>&#xA0;collection of iOS/Ruby tools are a great resource. I recently switched how Goldstar is sending out push notifications from Grocer to <a href="https://github.com/nomad/houston?ref=blog.scidept.com">Houston</a>.</p>
<p>Grocer has gone unmaintained for most of 2014, and it was obvious how to recover from a problem we were having with it where</p>]]></description><link>https://blog.scidept.com/sending-passbook-push-notifications-with-houston/</link><guid isPermaLink="false">661aec324fb28d04d5440911</guid><dc:creator><![CDATA[Will Clark]]></dc:creator><pubDate>Wed, 23 Jul 2014 00:15:19 GMT</pubDate><content:encoded><![CDATA[<p>The <a href="http://nomad-cli.com/?ref=blog.scidept.com">Nomad</a>&#xA0;collection of iOS/Ruby tools are a great resource. I recently switched how Goldstar is sending out push notifications from Grocer to <a href="https://github.com/nomad/houston?ref=blog.scidept.com">Houston</a>.</p>
<p>Grocer has gone unmaintained for most of 2014, and it was obvious how to recover from a problem we were having with it where Apple would close the persistent connection we were using to send notifications, and so any notification sent after that would be lost. So I used <a href="http://joshsymonds.com/blog/2013/10/17/sidekiq-plus-houston-production-ready/?ref=blog.scidept.com">Josh Symonds&#x2019; technique</a> (with some tweaks I&#x2019;ll mention later) to send them in a more robust way.</p>
<p>The one thing that Grocer does out of the box that Houston didn&#x2019;t that we really needed was a way to send Passbook Push Notifications. These&#xA0;just like regular Push Notifications, however they are totally blank, sent to a token the pass registers with your server, and only work against the&#xA0;**Production&#xA0;**push notification gateway, using a different SSL certificate than your standard cert. This causes some problems because Houston assumes the Rails development environment should send pushes against the dev apple gateway.</p>
<p>So, what this means in reality&#xA0;is that you need 2 pools of persistent connections to apple&#x2019;s gateway, and you need to override the gateway that Houston defaults to to be the production one <em>only</em> for the passbook updates.</p>
<p>Here&#x2019;s the gist of the code I used:</p>
<pre><code>class APNConnection
  def initialize(pem, uri)
    @uri = uri
    @certificate = File.read(pem)
    setup
  end

  def setup
    @connection = Houston::Connection.new(@uri, @certificate, nil)
    @connection.open
  end

  def write(data)
    begin
      raise &quot;Connection is closed&quot; unless @connection.open?
      @connection.write(data)
    rescue Exception =&gt; e
      attempts ||= 0
      attempts += 1

      if attempts &lt; 5
        setup
        retry
      else
        raise e
      end
    end
  end

  def method_missing(m, *args, &amp;block)
    @connection.send(m, *args)
  end
end
</code></pre>
<p>Then, in an initializer, I set it up like this:</p>
<pre><code>$APN_POOL = ConnectionPool.new(:size =&gt; 2, :timeout =&gt; 300) do
    uri = Rails.env.production?? Houston::APPLE_PRODUCTION_GATEWAY_URI : Houston::APPLE_DEVELOPMENT_GATEWAY_URI
 APNConnection.new(GOLDSTAR_PEM_PATH, uri)
end
</code></pre>
<pre><code>$PASSBOOK_POOL = ConnectionPool.new(:size =&gt; 2, :timeout =&gt; 300) do
    APNConnection.new(GOLDSTAR_PASSBOOK_PEM_PATH, Houston::APPLE_PRODUCTION_GATEWAY_URI)
end
</code></pre>
<p>Now we have two pools and the passbook push notifications are only using the production gateway. Notice we&#x2019;re using two different PEM files. The PASSBOOK_PEM file I&#x2019;m using is taken from the &#x201C;Pass Type IDs&#x201D; section of the Apple developer site. Download and convert to PEM just like you would a regular push notification certificate. It&#x2019;s also the same certificate you&#x2019;re signing your passes with.</p>
<p><img src="https://i2.wp.com/monosnap.com/image/PnsuISAS8d0QYWXfZnNZv8LxifZn5b.png?resize=1001%2C782" alt="Apple Developer Site" loading="lazy"></p>
<p>Finally, we need to construct a notification.</p>
<pre><code>notification = Houston::Notification.new(device: registration.push_token)
$PASSBOOK_POOL.with do |conn|
    conn.write notification.message
end
</code></pre>
<p>The important part of this code is that the &#x201C;device&#x201D; we&#x2019;re sending this to is not actually a device token, like a regular push notification, but instead the pushToken that comes over when a passbook pass registers with your web service.</p>
<p>And that&#x2019;s it.You should now be able to send both push notifications and passbook push notifications in the same app.</p>
]]></content:encoded></item><item><title><![CDATA[Working Software]]></title><description><![CDATA[<p>I&#x2019;ve been thinking about what the minimum requirement for a programmer is. It&#x2019;s an interesting topic. No one talks about it, really. What&#x2019;s the most basic skill a programmer must possess to call themselves a &#x201C;professional programmer&#x201D;?</p>
<p>I&#x2019;d like to</p>]]></description><link>https://blog.scidept.com/working-software/</link><guid isPermaLink="false">661aec324fb28d04d544090f</guid><dc:creator><![CDATA[Will Clark]]></dc:creator><pubDate>Mon, 23 Jan 2012 15:00:21 GMT</pubDate><content:encoded><![CDATA[<p>I&#x2019;ve been thinking about what the minimum requirement for a programmer is. It&#x2019;s an interesting topic. No one talks about it, really. What&#x2019;s the most basic skill a programmer must possess to call themselves a &#x201C;professional programmer&#x201D;?</p>
<p>I&#x2019;d like to think that we could look at some other professions and see how they define it. Doctors have the saying &#x201C;do no harm&#x201D;, pretty good. Architects, I&#x2019;d guess, have to be able to design a building that doesn&#x2019;t implode. Plumbers have to build a system of pipes that doesn&#x2019;t get backed up and doesn&#x2019;t leak. Lawyers, at the most basic level, just need to know the laws. They just need to be correct.</p>
<p>If you try to fix your sink, and it starts spraying water all over your kitchen, you might proclaim &#x201C;I&#x2019;m no plumber!&#x201D;. If you gave medical advice to someone, and they got sick, you&#x2019;d say &#x201C;I&#x2019;m no doctor!&#x201D;. Almost all statements prefaced with IANAL are wrong, because that person doesn&#x2019;t actually know what the laws say.</p>
<p>I think we could sum this up by saying, the basis of most professions is the ability to not break anything, or be incorrect in what you say.</p>
<p>So, what can we say about programming? How do you define what makes someone a professional? Correctness? All software that I&#x2019;ve ever used has been incorrect in one way or another, so we&#x2019;re going to have to throw that one out. Let&#x2019;s get even more basic.</p>
<p>The minimum attribute of being a profession programmer is that you deliver working programs. Your code works. It does not break. It does not make things worse.</p>
<p>How many programmers do you know that can say that?</p>
]]></content:encoded></item><item><title><![CDATA[Expanding on the Law of Demeter]]></title><description><![CDATA[<p>Recently, my friend <a href="http://avdi.org/devblog/2011/07/05/demeter-its-not-just-a-good-idea-its-the-law/?utm_source=feedburner&amp;utm_medium=feed&amp;utm_campaign=Feed%3A+VirtuousCode+%28Virtuous+Code%29">Avdi Grim posted a great explanation of the Law of Demeter</a> (LoD). It&#x2019;s been tweeted and posted all over the web, so hopefully you saw it and read it. I&#x2019;m totally in agreement with his conclusions in that post, and LoD is a</p>]]></description><link>https://blog.scidept.com/law-of-demeter/</link><guid isPermaLink="false">661aec324fb28d04d544090e</guid><category><![CDATA[active_record]]></category><category><![CDATA[bdd]]></category><category><![CDATA[behaviour]]></category><category><![CDATA[demeter]]></category><category><![CDATA[rails]]></category><category><![CDATA[ruby]]></category><dc:creator><![CDATA[Will Clark]]></dc:creator><pubDate>Sat, 23 Jul 2011 15:28:51 GMT</pubDate><content:encoded><![CDATA[<p>Recently, my friend <a href="http://avdi.org/devblog/2011/07/05/demeter-its-not-just-a-good-idea-its-the-law/?utm_source=feedburner&amp;utm_medium=feed&amp;utm_campaign=Feed%3A+VirtuousCode+%28Virtuous+Code%29">Avdi Grim posted a great explanation of the Law of Demeter</a> (LoD). It&#x2019;s been tweeted and posted all over the web, so hopefully you saw it and read it. I&#x2019;m totally in agreement with his conclusions in that post, and LoD is a code smell I see in every MVC project I have ever worked in.</p>
<p>I&#x2019;m going to pick on Avdi&#x2019;s post just a little, but this is more-so criticism of every LoD explanation I&#x2019;ve ever read. I think all of these explanations of LoD are actually quite contrite and not addressing the real problem. Avdi (and others) seem to focus on &#x201C;Structrual Coupling&#x201D; or exposing the &#x201C;internal&#x201D; (actually external*) structure of your objects to other objects that don&#x2019;t need to know it.</p>
<p>An Example:</p>
<pre><code class="language-ruby">def user_info(user) 
    &quot;Name: #{user.name}. Boss: #{user.department.try(:head).try(:name)}&quot;
end
</code></pre>
<p>Avdi does a beautiful job illustrating why this code is a problem but I want to go a little deeper.</p>
<p>The more insidious LoD violation see in codebases is what I&#x2019;d call &#x201C;behavioral&#x201D; LoD violations, or, when the behavior of a class relies on the behavior of objects that are distant in the object graph.</p>
<p>My example needs a little setup. Lets say you have Vehicles which has_many <a href="http://en.wikipedia.org/wiki/Automobile_platform?ref=blog.scidept.com">Platforms</a> which has_many Models which has_many Versions (and Platforms has many Version through models). Pretty simple 4 level deep object graph that a car manufacturer might have. A very common set of objects you might want is to know which Platforms are actually in production. Some our outdated, some are future, but you want all the platforms that are currently in production.</p>
<p>Now, I know how I&#x2019;d do this, but I commonly see code like this:</p>
<pre><code class="language-ruby">class Vehicles
  def current_platforms(options = {})
    platforms = platforms.find(:all,
                        :conditions =&gt; 
                          [&quot;platforms.on_date &gt;= ? AND platforms.status IN (&apos;open&apos;, &apos;cancelled&apos;) AND platforms.cached_inventory_status != ?&quot;,
                            Date.today.to_s(:db), 
                            Platform.cached_inventory_status(:no_inventory)],
                        :order =&gt; &apos;on_date asc, time_note asc&apos;,
                        :include =&gt; {:models =&gt; :versions})
  
    if options[:skip_some_special_case]
      platforms.select { |platform| platform.versions.any? { |offer| !version.special_case} }
    elsif options[:skip_some_other_case]
      platforms.select { |platform| platform.versions.any?(&amp;:other_case?) }
    else
      platforms
    end
  end
end
</code></pre>
<p>This code is a great example of my problem with how most folks end up simplifying LoD violations. No where are we chaining methods &#x201C;too deep&#x201D; or as it gets simplified to are we &#x201C;using too many periods&#x201D;. We&#x2019;ve only used 1 period (because of a has_many :through =&gt;). However, in our if statements, we are tightly coupling our code to the behavior of a class that is 3 siblings away from the one we&#x2019;re working in. Nasty. Never should a Platform do operations on, or even know about, a Version.</p>
<p>So why is my example actually worse than something.try(:something_else).try(:a_third)? Well, lets get back to that * I left on &#x201C;(actually external [structure])&#x201D;.</p>
<p>Most people seem to classify the active_record generated attribute accessors of Rails model classes as &#x201C;internal structure&#x201D; (Avdi doesn&#x2019;t, I should state for correctness). These are most certainly external structure. You can override them and return whatever you&#x2019;d like and attributes[:foo] is actually the &#x201C;internal&#x201D; accessor for all active_record classes. External structure, in every project I&#x2019;ve ever worked in, has been the most consistent, least volatile part of the codebases. External structure almost <em>never</em> changes, and when it does, it&#x2019;s typically <em>very</em> easy to change (it&#x2019;s not even a refactoring, it&#x2019;s just changing the messages exchanged between classes).</p>
<p>My example relies on <em>behavior</em> of a class 3 classes away. If there&#x2019;s anything I&#x2019;ve learned, it&#x2019;s that behavior is always more volatile than structure, and as Avdi points out, LoD really starts hurting as code churns and whatever your LoD relies on changes and becomes more and more complex.</p>
<p>So the big question is, how do we fix this?</p>
<p>It&#x2019;s actually a theoretically simple fix, and similar to the fixes in Avdi&#x2019;s post: delegate the behavior down the object graph!</p>
<pre><code class="language-ruby">class Vehicle
  def current_platforms(options={})
    if options[:skip_some_special_case]
      platforms.reject(&amp;:special_case?)
    elsif options[:skip_some_other_case]
      platforms.select(&amp;:other_case?)
    else
      platforms.select(&amp;:regular_case)
    end
  end
end

class Platform
  def regular_case
    ...
  end
  def special_case?
    models.special_case?
  end
  def other_case?
    models.other_case?
  end
end

class Model
  def special_case?
    versions.special_case?
  end
  def other_case?
    versions.other_case?
  end
end

class Version
  def special_case?
    ...
  end
  def other_case?
    ...
  end
end
</code></pre>
<p>Now, Platform knows nothing about versions, versions can easily change what defines the &#x201C;cases&#x201D; without any changes to Platform and ironically, when I made this refactoring to the original source I got this derived example from, it&#x2019;s actually <em>more</em> efficient. Removing the explicit find that started the original method means that if we&#x2019;ve already loaded this object graph, even outside of this method, we can keep reusing it without going to the database.</p>
<p>I hope this helps, and for the love of Demeter, can we stop describing it as &#x201C;using too many periods&#x201D;?</p>
]]></content:encoded></item><item><title><![CDATA[Speaking of Turds (A Technological Term)]]></title><description><![CDATA[<p><a href="https://www.youtube.com/watch?v=yiJ9fy1qSFI&amp;ref=blog.scidept.com">https://www.youtube.com/watch?v=yiJ9fy1qSFI</a></p>
<p>I use the term &#x201C;turd&#x201D; often when talking about products, either hardware or software but I&#x2019;m not always sure people know what I mean.</p>
<p>A turd is something your company &#x201C;has to do&#x201D;. Sometimes they sink and</p>]]></description><link>https://blog.scidept.com/speaking-of-turds-a-technological-term/</link><guid isPermaLink="false">661aec324fb28d04d544090c</guid><category><![CDATA[product design]]></category><dc:creator><![CDATA[bjclark]]></dc:creator><pubDate>Mon, 14 Feb 2011 12:51:40 GMT</pubDate><content:encoded><![CDATA[<p><a href="https://www.youtube.com/watch?v=yiJ9fy1qSFI&amp;ref=blog.scidept.com">https://www.youtube.com/watch?v=yiJ9fy1qSFI</a></p>
<p>I use the term &#x201C;turd&#x201D; often when talking about products, either hardware or software but I&#x2019;m not always sure people know what I mean.</p>
<p>A turd is something your company &#x201C;has to do&#x201D;. Sometimes they sink and sometimes they float, but they are always mandatory.</p>
<p>A turd can be polished and it can be of any shape or size, but at it&#x2019;s core, it&#x2019;s still excrement.</p>
<p>Turds always come from somewhere. Sometimes, usually the ones that float, turds come from good things. The right things. Things like user needs, innovation, obvious holes in the market demanding to be filled. &#xA0;Many times, however, turds come from bad places, these are usually the ones that sink (and stink). Stinky turds come from fear, they come from reactions to competitors, they come from &#x201C;obligations&#x201D;.</p>
<p>Everyone makes turds. The iPod Touch is a floating turd. Apple was obligated to make it. How could they resist? They&#x2019;ve sold a ton because of the branding and the apps and the advertising, so it&#x2019;s a shiny turd, but a turd no less.</p>
<p>Most (all?) of the iPad &#x201C;killers&#x201D; are turds. They are reactionary. They aren&#x2019;t innovations, they are year late catchups powered by software that went from being something new to a turd the day the App Store launched.</p>
<p>The Facebook platform was, in it&#x2019;s inception, pretty awesome. It&#x2019;s turned in to a turd through, what I can only imagine has been, some epic bikeshedding, &#xA0;beauracracy and abuse. I bet Zuck would kill it if he could, but instead he&#x2019;s &#x201C;obligated&#x201D; to keep it going.</p>
<p>I don&#x2019;t even think turds are bad. Turds can be great. They can be just what a company needs. But lets call a spade, a spade, or a turd.</p>
]]></content:encoded></item><item><title><![CDATA[Things I have learned as an artist (no. 1)]]></title><description><![CDATA[<div id="_mcePaste">At the beginning of every project and the learning of any skill, you always believe you already know what perfection is.</div><div></div><div>This assumption is always false.</div>]]></description><link>https://blog.scidept.com/things-i-have-learned-as-an-artist-no-1/</link><guid isPermaLink="false">661aec324fb28d04d544090b</guid><dc:creator><![CDATA[bjclark]]></dc:creator><pubDate>Fri, 11 Feb 2011 20:36:43 GMT</pubDate><content:encoded><![CDATA[<div id="_mcePaste">At the beginning of every project and the learning of any skill, you always believe you already know what perfection is.</div><div></div><div>This assumption is always false.</div>
]]></content:encoded></item><item><title><![CDATA[Typography of web applications]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>One of the hardest things about designing web applications is presenting the <em>multitude of types</em> of information that is necessary at any one time. What do you display? What do you leave out? What information is more or less important than other information? If a piece of information is actionable,</p>]]></description><link>https://blog.scidept.com/typography-of-web-applications/</link><guid isPermaLink="false">661aec324fb28d04d544090a</guid><category><![CDATA[Design]]></category><category><![CDATA[new twitter]]></category><category><![CDATA[twitter]]></category><category><![CDATA[typography]]></category><dc:creator><![CDATA[bjclark]]></dc:creator><pubDate>Thu, 13 Jan 2011 14:55:08 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>One of the hardest things about designing web applications is presenting the <em>multitude of types</em> of information that is necessary at any one time. What do you display? What do you leave out? What information is more or less important than other information? If a piece of information is actionable, how do you visually inform the user of that?</p>
<p>Recently Twitter redesigned their interface using a new 2 panel layout where the sidebar dynamically changes, allowing for deeper inspection into the tweets that show up in your timeline. From a design standpoint there are a number of things that are great about this. The proportions (using the golden ratio) are excellent. The metaphor of a slide out panel is excellent. The exprience over &#x201C;old Twitter&#x201D; for reading conversation is vastly better.</p>
<p>However, there are 2 things that&#xA0;specifically bug me about the new design: &#xA0;what I&#x2019;d call the <em>over stylization</em> of the content and an over abundance of information.</p>
<p><a href="https://i1.wp.com/res.cloudinary.com/scidept/image/upload/v1527822943/4-Twitter-_-Home-2_ppjo6q.jpg?ssl=1&amp;ref=blog.scidept.com"><img src="https://i1.wp.com/res.cloudinary.com/scidept/image/upload/v1527822943/4-Twitter-_-Home-2_ppjo6q.jpg?resize=492%2C490&amp;ssl=1" alt="New Twitter conversation view." title="new twitter 1" loading="lazy"></a></p>
<p>This is a conversation in the side panel between two people I know. The first problem is that I think this is too much information. Here is what I see here: close link with icon, 3 tweets in two distinct styles with avatars, usernames, real names, timestamps, API client names and conversation links that link to the same conversation I&#x2019;m viewing. There is also a user profile, which is in the same style as a tweet except the user&#x2019;s bio is in italics. There is also links to use the original tweet in all the functions Twitter provides and the panel even goes on to list out other tweets from @bleything, however I have chosen to crop those out. Keeping in mind that my original intention was to view a conversation, and I came upon that conversation by clicking on a link in a original tweet, my goals are fulfilled but I&#x2019;m also bombarded with more extraneous information than the original conversation contained.</p>
<p>Second, although there are probably less than 1000 characters here, and less than 420 characters of the information I requested when I wanted to view the conversation, there are no less than 12 distinct combinations of font weight, color and size.</p>
<p><a href="https://i0.wp.com/res.cloudinary.com/scidept/image/upload/v1527822942/4-Twitter-_-Home-1-1_q2fpf9.jpg?ssl=1&amp;ref=blog.scidept.com"><img src="https://i0.wp.com/res.cloudinary.com/scidept/image/upload/v1527822942/4-Twitter-_-Home-1-1_q2fpf9.jpg?resize=492%2C487&amp;ssl=1" alt="Annotating a screen shot of new twitter to show the 12 distinct font styles." title="new twitter 2" loading="lazy"></a></p>
<p>Lets compare this with a &#x201C;conversation view&#x201D; from the Echofon Mac desktop app.</p>
<p><a href="https://i1.wp.com/res.cloudinary.com/scidept/image/upload/v1527822941/Echofon_wfdgf0.jpg?ssl=1&amp;ref=blog.scidept.com"><img src="https://i1.wp.com/res.cloudinary.com/scidept/image/upload/v1527822941/Echofon_wfdgf0.jpg?resize=491%2C251&amp;ssl=1" alt="Echofon conversation view" title="Echofon" loading="lazy"></a>I find Echofon&#x2019;s conversation much easier to read, and if I want more information, such as the API Client used to post the tweet or the user&#x2019;s bio, I don&#x2019;t mind digging deeper through the pathways I already know exist in the app. If I like to do something with one of the tweets, hidden controls appear when I mouse over. And even though there are graphics, the UI here is cleaner and only contains 2 text styles. &#xA0;Literally every piece of information or action provided in the new Twitter conversation is accessible via either 1 mouse click or hover.</p>
<p>Designing applications is always about more than what the app look like. It&#x2019;s how the app works, what information it presents, and making sure the user can easily and clearly achieve their goals.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Pro Tip: Encapsulate logic in Rails Views for maintainability]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>A Rails view anti-pattern is that they very quickly turn into a nasty tangle of conditional html blocks.</p>
<p>Example:</p>
<pre><code>&lt;code class=&quot;ruby&quot;&gt;
&lt;% if logged_in? &amp;&amp; @user == current_user %&gt;
</code></pre>
<p>Simple example, but what is the intention of that code? Why are you really</p>]]></description><link>https://blog.scidept.com/pro-tip-encapsulate-logic-in-rails-views-for-maintainability/</link><guid isPermaLink="false">661aec324fb28d04d5440908</guid><category><![CDATA[protip]]></category><category><![CDATA[rails]]></category><category><![CDATA[ruby]]></category><category><![CDATA[views]]></category><dc:creator><![CDATA[bjclark]]></dc:creator><pubDate>Wed, 12 Jan 2011 12:39:13 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>A Rails view anti-pattern is that they very quickly turn into a nasty tangle of conditional html blocks.</p>
<p>Example:</p>
<pre><code>&lt;code class=&quot;ruby&quot;&gt;
&lt;% if logged_in? &amp;&amp; @user == current_user %&gt;
</code></pre>
<p>Simple example, but what is the intention of that code? Why are you really checking for? Give that state a name.</p>
<p>Change that to:</p>
<pre><code>&lt;code class=&quot;ruby&quot;&gt;
def viewing_own_profile(user)
  logged_in? &amp;&amp; user == current_user
end

&lt;% if viewing_own_profile(@user) %&gt;
</code></pre>
<p>Now you can test that helper method without resorting to rendering a view and parsing it to check if elements exist, the state you care about is named and the intention is clear.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Jambox by Jawbone Review]]></title><description><![CDATA[<blockquote>
<p>&#x201C;Ohhhh! It&#x2019;s the hipster speaker!&#x201D; &#x2013; @didip</p>
</blockquote>
<p>That&#x2019;s what my co-worker said when he walked into the office this morning. Waiting for me when I got to work was the new Jambox by Jawbone. You may remember the <a href="http://www.youtube.com/watch?v=XgC3zjNH1oU&amp;ref=blog.scidept.com">video</a> for the Jambox that went</p>]]></description><link>https://blog.scidept.com/jambox-by-jawbone-review/</link><guid isPermaLink="false">661aec324fb28d04d5440906</guid><category><![CDATA[jambox]]></category><category><![CDATA[jawbone]]></category><category><![CDATA[photos]]></category><category><![CDATA[review]]></category><dc:creator><![CDATA[bjclark]]></dc:creator><pubDate>Mon, 15 Nov 2010 22:17:30 GMT</pubDate><content:encoded><![CDATA[<blockquote>
<p>&#x201C;Ohhhh! It&#x2019;s the hipster speaker!&#x201D; &#x2013; @didip</p>
</blockquote>
<p>That&#x2019;s what my co-worker said when he walked into the office this morning. Waiting for me when I got to work was the new Jambox by Jawbone. You may remember the <a href="http://www.youtube.com/watch?v=XgC3zjNH1oU&amp;ref=blog.scidept.com">video</a> for the Jambox that went around the interwebs that featured a hipster looking dude and set the tone that these speakers that could replace your stereo as well as your conference phone in your office. Well guess what? I tend to be on daily of conference calls (via IAX via Zoiper) and we really needed a stereo for our PDX Studio, so a pre-order was made and the Jambox was delivered!</p>
<p>[st flickr=<a href="http://api.flickr.com/services/feeds/photoset.gne?set=72157625397638016&amp;nsid=71881727%40N00&amp;lang=en-us&amp;ref=blog.scidept.com">http://api.flickr.com/services/feeds/photoset.gne?set=72157625397638016&amp;nsid=71881727@N00&amp;lang=en-us</a>]</p>
<p>More&#xA0;<a href="http://www.flickr.com/photos/robotdeathsquad/sets/72157625397638016/?ref=blog.scidept.com">photos of the Jambox</a> on my flickr.</p>
<p>The first thing you&#x2019;ll notice is that it comes in a shoe box (hipster) with a screen printed boombox on the top. I will admit, the design and packaging is very apple, but urban hipster instead of the modernist-chic of Jonathan Ivey, and it&#x2019;s pretty sexy. Upon taking the top off, I took out the Jambox and put it on the desk and tried to turn it on, nada. This thing doesn&#x2019;t seem to come with a charge. So I hooked it up and pushed the top button, again, nothing. Finally I noticed there&#x2019;s a sliding switch on the side, slid that on, and it announced it was ready to pair. The Jambox seems to have a few status messages that are spoken aloud to you. I like this.</p>
<p>I also love the size and weight. The Jambox is TINY! It&#x2019;s smaller than a chipotle burrito. It&#x2019;s lighter too!</p>
<p>It was pretty easy to get the Jambox to initially pair with my Macbook Pro (10.6.5 fwiw). I fired up iTunes and played some toons and it sounded terrible! I was a little bummed, but I soldiered&#xA0;on. My co-worker and I started trying to connect other devices, my iPhone, my MBP but using Zoiper to make a call, and in this process we figured out that we had the Jambox sitting on it&#x2019;s side! Looking back, I can see how they intend for you to use it, but my co-worker and I are pretty smart guys (heck, he&#x2019;s even got a CS degree!) and we had literally no idea which end was up. Here&#x2019;s the good news, when you do get the Jambox right side up, it sounds <strong>awesome</strong>.</p>
<p>Let me tell you a little about our office. It&#x2019;s got 16 foot ceilings, it&#x2019;s about 12 x 12 and it&#x2019;s one of the more echo-y places I&#x2019;ve ever been. Using my trusty Harmon Kardon iSticks, audio sounds pretty terrible in this office. However the Jambox actually lives up to it&#x2019;s marketing. For a tiny (this thing is just slightly longer than a sharpie), wireless, and battery powered&#xA0;speaker it sounds great! It&#x2019;s got so much bass, it makes my desk vibrate and will even dance across the table. And surprisingly enough, it&#x2019;s actually less echo-y in our little studio than the multi-hundered dollar, USB speaker system.</p>
<p>As a speaker phone, I haven&#x2019;t used it for any long meetings yet, but initial tests are great. In our cave, using the built in input and output of a MacBook Pro results in terrible echo and looping even in Apple&#x2019;s iChat (which does noise canceling). The Jambox exhibited none of this behavior. I&#x2019;ll tweet more about this when I use it tomorrow on a few hour-long calls. Certainly, the on-board echo canceling Jawbone is known for is very nice on this unit.</p>
<p>However, it&#x2019;s not all unicorns and rainbows: Bluetooth audio still kinda sucks.&#xA0;I spent a fair amount of time trying to reboot the Jambox, trying to get the computer to forget it so that the iPhone would notice it (when it did, it worked/sounded awesome), and quite a bit of time trying to make the MBP recognize the Jambox as an audio input/output device. This was not easy and led to much frustration which turned in to, at the end of the day, somehow having the bluetooth in my MBP completely&#xA0;turn off necessitating a reboot of the computer to get bluetooth to turn back on again (annoying when you&#x2019;re also using a bt mouse). By far, the biggest letdown of an otherwise satisfying user experience, is that using it wirelessly, with multiple devices, totally sucks. The other weird thing is that the Jambox shows up as 2 types of outputs, one a &#x201C;headset&#x201D; and one a &#x201C;speaker&#x201D;. I don&#x2019;t know when to use which, or what the ramifications are of doing either. Also, I had the absolute **worst **luck trying to get the Jambox to work with Zoiper. I think the final combination was, turn on the Jambox, pair with the macbook pro, choose it as an input/output, and finally start up Zoiper (with the Jambox already programmed as the input/output in the preferences). How this will work when I use Zoiper with headphones later on, we&#x2019;ll see.</p>
<p>Overall, is it worth $200? I&#x2019;d say the jury is still out. I find it hard to recommend it at this point, because the bluetooth stuff seems like completely voodoo to get working, but maybe after I better&#xA0;figure out pairing with different devices I&#x2019;ll change my mind. For the price, you can buy some seriously good speakers, and its hard to tell how Apple&#x2019;s Airplay technology is going to shake out on the speaker-system front (numerous manufacturers have announced support, but I haven&#x2019;t seen any products hit the market). I certainly would find wifi based speakers more appealing, but I doubt we&#x2019;ll see Airplay speakers that can also work as a noise canceling speaker phone for a small office/conference room.</p>
]]></content:encoded></item><item><title><![CDATA[From Zero to Rails Hero in 11 Easy Steps (Installing Rails on OS X 10.6.5)]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>This is the easiest, fastest and best-to-develop-in way to get a rails dev stack up and running on OS X 10.6 (Snow Leopard).</p>
<p>I actually find that it&#x2019;s pretty easy, if everything is done in the right order.</p>
<ol>
<li>Install <a href="http://developer.apple.com/devcenter/mac/login.action?ref=blog.scidept.com">XCode</a></li>
<li>Install Homebrew <code>$&#xA0;ruby -e &quot;$(curl</code></li></ol>]]></description><link>https://blog.scidept.com/from-zero-to-rails-hero-in-11-easy-steps/</link><guid isPermaLink="false">661aec324fb28d04d5440905</guid><category><![CDATA[installation]]></category><category><![CDATA[mysql]]></category><category><![CDATA[os x]]></category><category><![CDATA[rails]]></category><category><![CDATA[ruby]]></category><category><![CDATA[snow leopard]]></category><dc:creator><![CDATA[bjclark]]></dc:creator><pubDate>Sun, 14 Nov 2010 22:59:58 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>This is the easiest, fastest and best-to-develop-in way to get a rails dev stack up and running on OS X 10.6 (Snow Leopard).</p>
<p>I actually find that it&#x2019;s pretty easy, if everything is done in the right order.</p>
<ol>
<li>Install <a href="http://developer.apple.com/devcenter/mac/login.action?ref=blog.scidept.com">XCode</a></li>
<li>Install Homebrew <code>$&#xA0;ruby -e &quot;$(curl -fsSL https://gist.github.com/raw/323731/install_homebrew.rb)&quot;</code></li>
<li>Install git using homebrew <code>$ brew install git</code></li>
<li>Install mysql using homebrew <code>$ brew install mysql</code></li>
<li>Install rvm (and follow the instructions to set up bash and don&#x2019;t forget to open a new terminal window) <code>$ bash &lt; &lt;( curl http://rvm.beginrescueend.com/releases/rvm-install-head )</code></li>
<li>Install Ruby Enterprise Edition <code>$ rvm install ree</code></li>
<li>Make REE the default Ruby <code>$ rvm use ree --default</code></li>
<li>Tell rubygems to not install rdocs<br>
Put the following lines in ~/.gemrc<code> install: --no-rdoc --no-ri update: --no-rdoc --no-ri</code></li>
<li>Install Passenger <code>$ gem install passenger</code></li>
</ol>
<p>Now follow that up by running the install script (and follow the directions)</p>
<p><code>$ ./passenger-install-apache2-module</code></p>
<p>At the end of the install process it will give you instructions to add 3 lines to the &#x201C;Apache configuration file&#x201D;, but it won&#x2019;t tell you <em>where</em> your apache config file is. It&#x2019;s at /etc/apache2/httpd.conf<br>
10. Restart Apache<br>
At this point, if you&#x2019;re using 10.6.5, you might do a sudo /etc/apachectl restart and run into the following error:<br>
/usr/sbin/apachectl: line 82: ulimit: open files: cannot modify limit: Invalid argumentTo fix this, edit /usr/sbin/apachectl and change&#xA0;<span style="font-family: &apos;andale mono&apos;, &apos;lucida console&apos;, monospace; color: #525252;">ULIMIT_MAX_FILES </span>to an empty string.Now you can restart apache.<br>
11. Install PassengerPane 1.3&#xA0;<a href="http://www.fngtps.com/files/2/2009/09/PassengerPane-1.3.tgz?ref=blog.scidept.com">www.fngtps.com/files/2/2009/09/PassengerPane-1.3.tgz</a></p>
<p>BOOM! Done.</p>
<p>Well, for me, I had to <code>gem install isolate</code> and Rubymine and then I was done, but you get the idea. Just load up the Passenger Preference Pane, point at site at a rails project on your hard drive, and load it up in your browser. Assuming your rails app will boot, you should be good to go!</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Dev Nation Presentation: Dr. Strangelove or: How I learned to stop worrying and love HTML, CSS, and Javascript]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>I presented at Dev Nation Portland last weekend. These are my slides:</p>
<div id="__ss_4767945" style="width:425px">**[Dr. Strangelove or: How I learned to stop worrying and love HTML, CSS and Javascript](http://www.slideshare.net/RobotDeathSquad/dr-strangelove-4767945 &quot;Dr. Strangelove or: How I learned to stop worrying and love HTML, CSS and Javascript&quot;</div>]]></description><link>https://blog.scidept.com/dev-nation-presentation-dr-strangelove-or-how-i-learned-to-stop-worrying-and-love-html-css-and-javascript/</link><guid isPermaLink="false">661aec324fb28d04d5440903</guid><category><![CDATA[css]]></category><category><![CDATA[developers]]></category><category><![CDATA[html]]></category><category><![CDATA[Javascript]]></category><category><![CDATA[rails]]></category><dc:creator><![CDATA[bjclark]]></dc:creator><pubDate>Thu, 15 Jul 2010 18:13:59 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I presented at Dev Nation Portland last weekend. These are my slides:</p>
<div id="__ss_4767945" style="width:425px">**[Dr. Strangelove or: How I learned to stop worrying and love HTML, CSS and Javascript](http://www.slideshare.net/RobotDeathSquad/dr-strangelove-4767945 &quot;Dr. Strangelove or: How I learned to stop worrying and love HTML, CSS and Javascript&quot;)**<object height="355" id="__sse4767945" width="425"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=slides-100715200537-phpapp01&amp;stripped_title=dr-strangelove-4767945"><param name="allowFullScreen" value="true"><param name="allowScriptAccess" value="always"><embed allowfullscreen="true" allowscriptaccess="always" height="355" name="__sse4767945" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=slides-100715200537-phpapp01&amp;stripped_title=dr-strangelove-4767945" type="application/x-shockwave-flash" width="425"></object><div style="padding:5px 0 12px">View more [presentations](http://www.slideshare.net/) from [RobotDeathSquad](http://www.slideshare.net/RobotDeathSquad).</div></div>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Who should write tests?]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>The question seems pretty obvious, &#x201C;Who should be writing the acceptance tests for your software?&#x201D; I think most people will first answer with &#x201C;Programmers!&#x201D;. There might be a few &#x201C;testers&#x201D;&#x2018; maybe even a &#x201C;the customer and programer pair&#x201D;. These are all</p>]]></description><link>https://blog.scidept.com/who-should-write-tests/</link><guid isPermaLink="false">661aec324fb28d04d5440901</guid><category><![CDATA[acceptance testing]]></category><category><![CDATA[bdd]]></category><category><![CDATA[cucumber]]></category><category><![CDATA[rspec]]></category><category><![CDATA[testing]]></category><dc:creator><![CDATA[bjclark]]></dc:creator><pubDate>Mon, 28 Jun 2010 15:40:23 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>The question seems pretty obvious, &#x201C;Who should be writing the acceptance tests for your software?&#x201D; I think most people will first answer with &#x201C;Programmers!&#x201D;. There might be a few &#x201C;testers&#x201D;&#x2018; maybe even a &#x201C;the customer and programer pair&#x201D;. These are all fine answers. Unfortunately, I&#x2019;m starting to think they are wrong.</p>
<p>You are doing BDD right? So you already care about the &#x201C;b&#x201D; word: behavior. You care enough to differentiate yourself from the lowly TDD-ers. I&#x2019;ve got news for you, there is a whole group of folks that care <em>even more</em> about behavior than you do. These people are called Interaction Designers and you probably don&#x2019;t have one on your team. Don&#x2019;t get me wrong, everyone that has ever written software has done interaction design, you probably weren&#x2019;t conscious of it, or if you were, you probably did it poorly (unless you&#x2019;re an interaction designer, and then you probably don&#x2019;t read my blog).</p>
<p>Just who is doing IDx in your organization is easy to figure out. When you write a spec, you know, those &#x201C;it should. . . &#x201C;, &#x201C;When&#x201D; and &#x201C;Then&#x201D; statements, who fills in the blank? I&#x2019;d guess it&#x2019;s usually the developer (that&#x2019;s been the case every where I have worked). Sometimes you might ask the customer, product designer, product owner, project manager, designer, or someone else on your team. However, this is where I think we&#x2019;re doing it wrong. I&#x2019;m starting to get the feeling that the person that should be filling in these blanks should be the interaction designer (ID). IDs are the people that know your users, they know what your users want, what they need, and what their end goal is. They know where your users sit when they use your app. They know what time of day they use it, they know if they are bored or tired or in a hurry. And most of all, they know what &#x201C;it should&#x201D; do and they are <strong>right</strong>. Do you know this stuff? Do you care? I&#x2019;ve worked with programmers that were offended to even be in meetings where we talked about personas and end users!</p>
<p>I was recently involved in a little experiment we called &#x201C;Agile Up To Here&#x201D; which was (among other things) a 1 week agile bootcamp for Alan Cooper. You might recognize that name if you have ever heard of interaction design because Alan invented the term. He&#x2019;s written a couple books on the subject, <a href="http://www.amazon.com/gp/product/0672316498?ie=UTF8&amp;tag=givelist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0672316498&amp;ref=blog.scidept.com">The Inmates Are Running the Asylum</a><img src="http://www.assoc-amazon.com/e/ir?t=givelist-20&amp;l=as2&amp;o=1&amp;a=0672316498" alt loading="lazy"> and <a href="http://www.amazon.com/gp/product/0470084111?ie=UTF8&amp;tag=givelist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0470084111&amp;ref=blog.scidept.com">About Face 3: The Essentials of Interaction Design</a><img src="http://www.assoc-amazon.com/e/ir?t=givelist-20&amp;l=as2&amp;o=1&amp;a=0470084111" alt loading="lazy">. Anyway, after looking back at the week, I was trying to figure out what we could have done better. We were really agile. We could deploy from day 1, we had CI, we tested the shit out of everything, we paired all the time, we had the customer (Alan)&#xA0;in the room and on the team, it was sweet. But there was still something wrong.</p>
<p>Duh. We had an interaction designer in the room but he wasn&#x2019;t thinking about IDx, he was learning agile. So who decided what went after &#x201C;it should&#x201D; in our app? Programmers, the worse-case choice. And what happened? On Friday, our last day, one of Alan&#x2019;s IDs paired with Elizabeth Hendrickson and they finally started doing some real interaction design. But it was already too late, the damage was done. We had Interaction Design Debt&#x2122;.</p>
<p>But why do you need IDx? The job of an ID is to figure out what a user wants to accomplish and the to ensure the application does precisely that. Anything your app does that doesn&#x2019;t go to this need is waste, and any compromises are mistakes. Programmers, and I say this as someone who has almost solely as a programmer for the last 3-4 years, should be focused solely on figuring out the simplest code that could possibly work and implementing just that. The person that figures out &#x201C;what could possibly work&#x201D;, however, should be the ID. This must be a tight loop, and it must take place day in and day out.</p>
<p>Programmers are typically terrible at weighing the needs of the user against all the other things they have to keep in mind. If you don&#x2019;t believe me, you&#x2019;re either delusional or a programmer. Which is precisely the problem. This is something most people don&#x2019;t know they don&#x2019;t know. Or they don&#x2019;t know they are actually pretty bad at it. Visual designers can also be pretty bad at IDx. If your designer just hands over Photoshop files with no instructions of how things should behave, thats probably because they are a bad interaction designer.</p>
<p>&#x201C;Business people&#x201D; are also usually bad at it, but for almost the opposite reason. Typically I&#x2019;ve noticed that business people (which usually includes marketing folks) fall into 2 categories. Either they are too solution focused &#x201C;let&#x2019;s do it like so and so&#x201D; without thinking if that&#x2019;s actually the way it should be done for <em>their</em> users, or they don&#x2019;t actually care about the implementation. The first group are doing IDx poorly and the second group doesn&#x2019;t want to write specs. They don&#x2019;t want to work at the level of thinking required for IDx and programming. They have a business goal. Let&#x2019;s say it&#x2019;s that they &#x201C;want users to be able to sign up for a newsletter&#x201D;. That&#x2019;s the level they want to work at. The way the &#x201C;user does the sign up&#x201D;, &#x201C;What happens when they click the &#x201C;sign up&#x201D; button?&#x201D;, &#x201C;What is written on the button?&#x201D;, &#x201C;Does the user have to confirm their sign up?&#x201D;, and all the 100&#x2019;s of questions that go along with this feature isn&#x2019;t the level that most business people want to be involved. And when that is the case, why would &#xA0;you want them to be involved in writing ATDD tests? If the answer is &#x201C;because they are the ones that can answer that question&#x201D; then you&#x2019;re falling into the same trap that me and a lot of programmers have fallen into, because that just isn&#x2019;t true. You&#x2019;re actually looking for an interaction designer, not a business person.</p>
<p>Now that I&#x2019;ve, I hope, changed your mind about just who should be writing these &#x201C;tests&#x201D;, let me get into the part that I&#x2019;m not quite so confident about. Maybe what I&#x2019;m talking about shouldn&#x2019;t actually be expressed as &#x201C;acceptance tests&#x201D;. I mean, what happens and what a users sees when they sign up for a newsletter may not really be &#x201C;business rules&#x201D; or &#x201C;business logic&#x201D;, but isn&#x2019;t it just as or more important? It&#x2019;s important enough to me that I&#x2019;d like to test it and make sure that what I think my code is doing is actually doing what I think it should. In fact, in most of my experience, these types of things are usually much more important and a much larger part of the application than the &#x201C;business logic&#x201D;. If you look at something like Facebook, where is there <em>any</em> business logic in that application (is there even any business, I don&#x2019;t know)? I guess there could be some &#xA0;in the privacy/permissions area. However, wouldn&#x2019;t you want to test the multitude of things that happens when someone &#x201C;likes&#x201D; something? An interaction designer should be specifying what happens and a developer needs a way to be sure that their code does just that. What do we call those tests? How should we be doing that testing?</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[All the things we don't know that we don't know]]></title><description><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<p>[Paraphrasing] There are lots of things we don&#x2019;t know that we don&#x2019;t know about [the project we were working on]. Agile is how we optimize our process for learning those things. &#x2013; Ward Cunningham</p>
</blockquote>
<p>One of the things that really changed how I thought about building</p>]]></description><link>https://blog.scidept.com/all-the-things-we-dont-know-that-we-dont-know/</link><guid isPermaLink="false">661aec324fb28d04d54408ff</guid><category><![CDATA[Agile]]></category><category><![CDATA[bduf]]></category><category><![CDATA[dunning kruger effect]]></category><category><![CDATA[iterations]]></category><dc:creator><![CDATA[bjclark]]></dc:creator><pubDate>Tue, 22 Jun 2010 21:31:31 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<p>[Paraphrasing] There are lots of things we don&#x2019;t know that we don&#x2019;t know about [the project we were working on]. Agile is how we optimize our process for learning those things. &#x2013; Ward Cunningham</p>
</blockquote>
<p>One of the things that really changed how I thought about building software was learning about the Dunning-Kruger Effect. I didn&#x2019;t know that&#x2019;s what I was called, mind you, but I certainly had witnessed it and once it was explained, it made perfect sense. What is the Dunning-Kruger effect?</p>
<blockquote>
<p>&#x201C;people reach erroneous conclusions and make unfortunate choices but their incompetence robs them of the&#xA0;metacognitive&#xA0;ability to realize it.&#x201D; &#xA0;&#x2013; <a href="http://en.wikipedia.org/wiki/Dunning-kruger_effect?ref=blog.scidept.com">http://en.wikipedia.org/wiki/Dunning-kruger_effect</a></p>
</blockquote>
<p>What does that have to do with Agile? Well, some of the seeds for Agile, at least from Kent Beck and Ward Cunningham&#x2019;s influence came from the days when those two guys shared a lab and were partners in R&amp;D at Tektronix. I&#x2019;ve written about this before, but basically, their job was to come up with, every set period of time, some idea that Tektronix should pay a team of guys to develop out into a product or tool. So, KB and WC would come into work every morning and one of them would propose an idea and they would spend the morning trying to hack the idea into working software. If it wasn&#x2019;t working, they&#x2019;d go back to working on whatever was the last best idea, and then at the end of the time period, they always had something that worked that they could turn over as an idea. This is where some of the seeds of TDD, iteration, and other ideas that are now staples of Agile came from.</p>
<p>But why would you do that? Why would you essentially start over every morning? Well, as it turns out, humans are really bad at knowing what they don&#x2019;t know. So why not come up with an idea and just work on that idea until you had something? Let&#x2019;s explore that. . .</p>
<h2 id="bdufisforthosethatdontunderstandthedunningkrugereffect">BDUF is for those that don&#x2019;t understand the Dunning-Kruger Effect</h2>
<p>I don&#x2019;t feel like this is a very controversial topic (that might also be the other end of the K-D Effect) because I think this one has already won out. It certainly has in the ruby community. I&#x2019;ll go ahead an explain it though. BDUF stands for &#x201C;Big Design Up Front&#x201D; and most non-enterprisy, non-corporate software teams know, you can&#x2019;t design all of your code before you write your code. And the agilists out there will even say that the only way to write truly simple clean code is to write a test first. I hope this isn&#x2019;t a big shock to anyone. If we examine why this is true, we pretty quickly get to a point where you say &#x201C;we don&#x2019;t know enough about the code to design the code without first writing some code&#x201D;. In other words, we don&#x2019;t know what we don&#x2019;t know about the code yet, we have to learn what we don&#x2019;t know and adapt our application architecture as we learn. I guess if you get a CS degree, you&#x2019;ll run up against a whole set of folks that don&#x2019;t believe this, but I&#x2019;ll go out on a limb and say that most of those folks also don&#x2019;t write much software. Anyway, suffice to say, we&#x2019;ve got a whole set of practices, red-green-refactor, continuous integration and deployment, to optimize against doing BDUF (among other things, surely).</p>
<h2 id="specificationdocumentsareforthosethatdontunderstandthedunningkrugereffect">Specification Documents are for those that don&#x2019;t understand the Dunning-Kruger Effect</h2>
<p>Another example (I think more important and less widely accepted, and the real reason I wrote this post) of the optimization for all the &#x201C;things you don&#x2019;t know that you don&#x2019;t know&#x201D; in Agile is that we don&#x2019;t write spec docs. We don&#x2019;t start out a project with a giant document that spells out everything we&#x2019;re going to build. That&#x2019;s not to say no one knows what we&#x2019;re building, or has a vision of what it looks like when it&#x2019;s done, au-con-trair, that&#x2019;s definite a recipe for disaster (and, I think, most people&#x2019;s biggest fear that haven&#x2019;t participated in an Agile project). We spend the time to write all of this down in whatever format we would need to give it to a developer and walk away. Why? Well it&#x2019;s that damn Dunning-Kruger effect. You <em>can&#x2019;t</em> actually write a good spec, and not only that, those that don&#x2019;t know this are the ones that precisely think it&#x2019;s possible. No matter how many lines of code you&#x2019;ve written, or UI&#x2019;s you&#x2019;ve designed, or businesses you&#x2019;ve started, you will never know enough about what you don&#x2019;t know to write a document that will cover every edge case, angle, possibility, challenge and decision that has to be made to successfully create quality software.</p>
<p>I hear this lot when I tell people this: &#x201C;But you <em>can</em> change your spec&#x201D; or &#x201C;Good specs <em>allow</em> for learning&#x201D;. I&#x2019;m sure you can and I&#x2019;m sure they do. Change and learning is precisely what agile is all about and not just embracing change, but optimizing for it. You&#x2019;re <em>always</em> going to change that spec. Every project I&#x2019;ve ever been on, at one point or another, something was too hard or expensive to be worth it and we&#x2019;ve always changed what we&#x2019;re going to do. Most of the time, this something was a surprise. It wasn&#x2019;t what we <em>thought</em> would be hard or even something we <em>thought</em> we needed to do! I&#x2019;ll even go further to say that some of the more successful projects I&#x2019;ve been on, not only did we optimize for learning things early, we optimized for being able to change things easily.</p>
<p>The problem with writing a spec and then changing it, however, is that usually this renders part of the spec useless, or worse yet, it renders useless&#xA0;some &#x201C;real work&#x201D; you have already done. There&#x2019;s a million quips and anecdotes people use for this, &#x201C;Fail fast. . .&#x201D;, &#xA0;&#x201C;If you&#x2019;re not embarrassed when you launch your project, you waited too long&#x201D;, etc. The reason people say these things is precisely because they&#x2019;ve experienced the Dunning-Kruger effect. They&#x2019;ve written a spec or built software thinking they had their bases covered, that they knew things, but they didn&#x2019;t end up knowing everything and not all of what they thought they knew ended up being true. And many of these people have come to the conclusion that if they would have done less planning, and got to implementing even faster, they would have learned important information that they didn&#x2019;t know they didn&#x2019;t know earlier and saved themselves work. XP is about optimizing for this in a technical setting, &#x201C;The Lean Startup&#x201D; is about optimizing for this in a marketing and product development setting.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Summer Has Arrived]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Since the weather was so wonderful here in Portland today, my wife and I decided to make fajitas for dinner. Instead of your regular &#x201C;grill some chicken, fry some veggies&#x201D; fajitas, I decided to do a version I saw Alton Brown do on good eats.</p>
<p><a href="https://i0.wp.com/res.cloudinary.com/scidept/image/upload/v1527822945/img_0499_zhuh3g.jpg?ssl=1&amp;ref=blog.scidept.com"><img src="https://i0.wp.com/res.cloudinary.com/scidept/image/upload/v1527822945/img_0499_zhuh3g.jpg?resize=700%2C525&amp;ssl=1" alt="Skirt steak cooked directly on charcol" title="Steak on the coals" loading="lazy"></a></p>
<p>The interesting thing</p>]]></description><link>https://blog.scidept.com/summer-has-arrived/</link><guid isPermaLink="false">661aec324fb28d04d54408fe</guid><category><![CDATA[beer]]></category><category><![CDATA[cooking]]></category><category><![CDATA[culinary]]></category><category><![CDATA[dinner]]></category><dc:creator><![CDATA[bjclark]]></dc:creator><pubDate>Sun, 13 Jun 2010 18:53:17 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Since the weather was so wonderful here in Portland today, my wife and I decided to make fajitas for dinner. Instead of your regular &#x201C;grill some chicken, fry some veggies&#x201D; fajitas, I decided to do a version I saw Alton Brown do on good eats.</p>
<p><a href="https://i0.wp.com/res.cloudinary.com/scidept/image/upload/v1527822945/img_0499_zhuh3g.jpg?ssl=1&amp;ref=blog.scidept.com"><img src="https://i0.wp.com/res.cloudinary.com/scidept/image/upload/v1527822945/img_0499_zhuh3g.jpg?resize=700%2C525&amp;ssl=1" alt="Skirt steak cooked directly on charcol" title="Steak on the coals" loading="lazy"></a></p>
<p>The interesting thing here is that I&#x2019;m cooking the meat (skirt steak) directly on the charcoal. No grill, no foil, no pan, just meat directly to red hot glowing chunk charcoal. This develops and intensely smokey flavor in the meat. You can see there are large areas of &#x201C;burnt&#x201D; meat, but it&#x2019;s not actually burnt, it&#x2019;s just caramelized and full of flavor. I&#x2019;ve never had skirt steak so tasty, very caveman, in a good way.</p>
<p><a href="https://i2.wp.com/res.cloudinary.com/scidept/image/upload/v1527822944/img_0503_ym7ttq.jpg?ssl=1&amp;ref=blog.scidept.com"><img src="https://i2.wp.com/res.cloudinary.com/scidept/image/upload/v1527822944/img_0503_ym7ttq.jpg?resize=700%2C525&amp;ssl=1" alt title="Fajita Veggies" loading="lazy"></a></p>
<p>When the steak was done (3 minutes per side, don&#x2019;t even think about touching it while it cooks, and then let it rest 15 minutes), I put a cast iron skillet directly on to the coals and let it get smoking hot. I put the standard white onion and green/red pepper that I drizzled with a little olive oil and salt and pepper. The skillet was so hot the veggies instantly started to caramelize and you have to stir them almost constantly or you will get a little burning. Cooking the veggies takes less than 5 minutes (definately don&#x2019;t over cook them) and the flavor is also amazing. If you ever wonder why veggies take so much better in good chinese food, it&#x2019;s because they cook them super super hot like this. As a side note, if you want to make really great stir fry and don&#x2019;t have a really nice gas wok stove, this is actually a good way to do it.</p>
<p><a href="https://i2.wp.com/res.cloudinary.com/scidept/image/upload/v1527822943/img_0506_ijadhf.jpg?ssl=1&amp;ref=blog.scidept.com"><img src="https://i2.wp.com/res.cloudinary.com/scidept/image/upload/v1527822943/img_0506_ijadhf.jpg?resize=700%2C525&amp;ssl=1" alt title="Fajitas" loading="lazy"></a></p>
<p>Enjoy with a Cascadian Black Ale and plenty of guacamole, preferably on your beautiful patio with your bride.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[A trip to Baltimore in June]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>I&#x2019;m taking <a href="http://dplr.it/guest/837a017087a7e45bf67f?ref=blog.scidept.com">a trip to Baltimore</a> between June 7th and June 11th.</p>
<h1 id="railsconf">railsconf</h1>
<!--kg-card-end: markdown-->]]></description><link>https://blog.scidept.com/a-trip-to-baltimore-in-june/</link><guid isPermaLink="false">661aec324fb28d04d54408fd</guid><dc:creator><![CDATA[bjclark]]></dc:creator><pubDate>Thu, 03 Jun 2010 18:15:01 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I&#x2019;m taking <a href="http://dplr.it/guest/837a017087a7e45bf67f?ref=blog.scidept.com">a trip to Baltimore</a> between June 7th and June 11th.</p>
<h1 id="railsconf">railsconf</h1>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>