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

 <title>8th Light Blog</title>
 <link href="http://8thlight.github.com/atom.xml" rel="self"/>
 <link href="http://8thlight.github.com/"/>
 <icon>http://8thlight.github.com/favicon.ico</icon>
 <updated>2012-02-03T23:43:24-08:00</updated>
 <id>http://8thlight.github.com/</id>

 
 <entry>
   <title>Modules called, they want their integrity back</title>
   <category term="josh-cheek" />
   <link href="http://8thlight.github.com/josh-cheek/2012/02/03/modules-called-they-want-their-integrity-back.html"/>
   <author>
     <name>josh cheek</name>
   </author>
   <updated>03 Feb 2012</updated>
   <id>http://8thlight.github.com/josh-cheek/2012/02/03/modules-called-they-want-their-integrity-back</id>
   <content type="html">&lt;h2&gt;TL; DR&lt;/h2&gt;

&lt;p&gt;Rather than including modules and hooking into &lt;code&gt;.included&lt;/code&gt;, write a method that adds the behaviour (even if the method just includes and extends).&lt;/p&gt;

&lt;h2&gt;Introducing the pattern&lt;/h2&gt;

&lt;p&gt;It's common practice in Ruby these days to use modules for all kinds of crazy.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;IWishIWasAClass&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;included&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:include&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;InstanceMethods&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extend&lt;/span&gt;  &lt;span class=&quot;no&quot;&gt;ClassMethods&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;a href=&quot;https://github.com/rails/rails/blob/deb91690ae0883826950fa2cfb7c23944d7f03de/activerecord/lib/active_record/model.rb#L17-61&quot;&gt;Here&lt;/a&gt; is the most eye-widening example I've seen. You might think you're getting one thing, but you're not, you're getting all the things. &lt;a href=&quot;https://github.com/garybernhardt/base&quot;&gt;Base&lt;/a&gt;, anyone?&lt;/p&gt;

&lt;p&gt;So what's the problem?&lt;/p&gt;

&lt;h2&gt;Include has a meaning, and this changes its meaning.&lt;/h2&gt;

&lt;p&gt;When I include something, I expect to get the module's methods for my class' instances. Honestly, I know include is a method, but I think of it like a keyword. Until I realized this &quot;pattern&quot; was common, I was astounded when I would somehow magically have class methods, the class is a completely different object!&lt;/p&gt;

&lt;h2&gt;It pollutes the ancestry.&lt;/h2&gt;

&lt;p&gt;When you include a module, it creates a class with the module's methods and sets it as the superclass of the object. So first of all, it is pollutive (clutters up the ancestry when you are trying to look around) and second of all it is a performance hit. Whenever you invoke a method, it goes up the ancestry, one after the other, searching for the method in each of them. In this case, the module has no methods itself, it was just a way to include InstanceMethods and extend ClassMethods. An empty stop along the call chain. Even the Rails team has realized this and &lt;a href=&quot;https://github.com/rails/rails/commit/401393b6561adc1ce7101945163c9601257c057a&quot;&gt;stopped&lt;/a&gt; using the InstanceMethods side of the pattern.&lt;/p&gt;

&lt;h2&gt;It's unreliable and breaks module semantics.&lt;/h2&gt;

&lt;p&gt;When I want the module's methods on my instances, I include. When I want them on my class, I extend. Thus these two should be equivalent:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TheCommonWay&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;SomeModule&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TheEquivalentButUglyWay&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;
    &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;SomeModule&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;And they basically are equivalent, except if you start abusing hooks, consider:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;SomeModule&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;included&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;SomeModule was included in &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inspect&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;SomeModule&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# prints &amp;quot;SomeModule was included in #&amp;lt;Class:0x007fe17884f768&amp;gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;SomeModule&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;# nothing printed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;In the first example, the hook was invoked, in the second, it was not. So if you are relying on the hook to add the behaviour, then for it to behave correctly I must be aware of this and adjust my usage.&lt;/p&gt;

&lt;h2&gt;It's a problem of perception.&lt;/h2&gt;

&lt;p&gt;In his &lt;a href=&quot;http://www.confreaks.com/videos/646-gogaruco2011-the-problem-is-your-ruby&quot;&gt;talk&lt;/a&gt; at GoGaRuCo Why does Jeff Casimir&lt;a href=&quot;#footnote1&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; write this code?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/josh-cheek/images/2012-02-03-modules-called-they-want-their-integrity-back/included_hook.png&quot; alt=&quot;this&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Because he wants to use it like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/josh-cheek/images/2012-02-03-modules-called-they-want-their-integrity-back/code_i_wish_i_had.png&quot; alt=&quot;this&quot; /&gt;&lt;/p&gt;

&lt;p&gt;He knows he can extract the code with a module, so he has modules on his brain. And the way to use modules is to include them. I love around 7:19 when he says &lt;em&gt;&quot;I always use code before I write it. So I would write something like this where I would include the module&quot;&lt;/em&gt;. I consider that a best practice. But here, he isn't using the code before he writes it, it's already written in his brain. Which means the code that is supposed to use it (the code necessitating its existence) is written to the implementation he already has in mind.&lt;/p&gt;

&lt;p&gt;This just uses modules to dispatch methods. &lt;em&gt;There is absolutely no reason to include a module here&lt;/em&gt;. The module is mixed in because it will invoke the included method... which only needs to exist because that's how you hook into mixins. A regular method would work just fine. He could literally replace &lt;code&gt;include Contact&lt;/code&gt; with &lt;code&gt;Contact.included self&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;So what is the alternative?&lt;/h2&gt;

&lt;p&gt;We need to stop cargo culting module patterns. We can get behaviour any way we want. In the above example, we could use this alternative:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add_contact_associations_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ar_base_subclass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ar_base_subclass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:has_many&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:phone_numbers&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ar_base_subclass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:has_many&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email_addresses&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;add_contact_associations_to&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;name&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;last_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Company&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;add_contact_associations_to&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now I'm not advocating toplevel method definition, in reality I'd probably put it in a module as a &lt;em&gt;namespace&lt;/em&gt;. But this shows that the mixin was just an elaborate ruse to invoke a method that could be invoked directly, or replaced with something more expressive. Some say it's better to be &lt;a href=&quot;/josh-cheek/images/2012-02-03-modules-called-they-want-their-integrity-back/clear_over_clever.png&quot;&gt;clear over clever&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On &lt;a href=&quot;https://github.com/JoshCheek/deject&quot;&gt;Deject&lt;/a&gt; I just have a function with the same name as my module &lt;a href=&quot;#footnote2&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;. In one &lt;a href=&quot;https://github.com/JoshCheek/deject/blob/5bc94b05cfca045afebcb447170d9f549b9e4006/lib/deject/object_oriented.rb#L1-3&quot;&gt;implementation&lt;/a&gt;, it extends the class you pass it. Sure you could get the same thing by just saying &lt;code&gt;extend Deject&lt;/code&gt; but if it ever changes, then the interface will have to change, or I'll have to start abusing hooks. By having a method which is responsible for doing to the class whatever things need to be done, it does not change the meaning of include. In &lt;a href=&quot;https://github.com/JoshCheek/deject/blob/5bc94b05cfca045afebcb447170d9f549b9e4006/lib/deject/functional.rb#L11&quot;&gt;another implementation&lt;/a&gt;, it doesn't use modules at all, it just adds the desired methods.&lt;/p&gt;

&lt;p&gt;When you need both class and instance methods, give your module a descriptive method which will do the extending and including (or simply defining), there is no need to rely on the hook.&lt;/p&gt;

&lt;h2&gt;Here are some example alternatives&lt;/h2&gt;

&lt;p&gt;Define the method explicitly&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;M&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;m_ify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;add_class_method&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;add_instance_method&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add_class_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;class_method&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&amp;#39;some class method&amp;#39;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add_instance_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class_eval&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;instance_method&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;&amp;#39;some instance method&amp;#39;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m_ify&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class_method&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &amp;quot;some class method&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance_method&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &amp;quot;some instance method&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Include and extend implicitly&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;M&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ClassMethods&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;class_method&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&amp;#39;some class method&amp;#39;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;m_ify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ClassMethods&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:include&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;instance_method&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;some instance method&amp;#39;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m_ify&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class_method&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &amp;quot;some class method&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance_method&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# =&amp;gt; &amp;quot;some instance method&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;And of course, many things which modules are used for could actually be done with composition ;)&lt;/p&gt;

&lt;hr /&gt;

&lt;h2&gt;Footnotes&lt;/h2&gt;

&lt;p&gt;&lt;a name=&quot;footnote1&quot;&gt;1&lt;/a&gt; Jeff is a great guy and his talks always get me thinking and reconsidering, so I feel okay using him for my example. Though this is quite common across the Ruby community. Plus it's hard to resist when the name of the talk is &lt;em&gt;&quot;The Problem is Your Ruby&quot;&lt;/em&gt; :P&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;footnote2&quot;&gt;2&lt;/a&gt; In this example, &quot;deject&quot; is a verb so I felt okay making a method with the same name as the constant itself. I debated this a while, but ultimately was convinced by &lt;a href=&quot;http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html&quot;&gt;Execution in the Kingdom of Nouns&lt;/a&gt; that it was an acceptable decision.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Service Oriented Agony</title>
   <category term="uncle-bob" />
   <link href="http://8thlight.github.com/uncle-bob/2012/02/01/Service-Oriented-Agony.html"/>
   <author>
     <name>uncle bob</name>
   </author>
   <updated>01 Feb 2012</updated>
   <id>http://8thlight.github.com/uncle-bob/2012/02/01/Service-Oriented-Agony</id>
   <content type="html">&lt;p&gt;I sat down with a group of developers today to do a retrospective on a project.  They told me that project management has been complaining about their velocity.  It wasn&amp;#8217;t serious, but the developers felt bad because things &lt;em&gt;do&lt;/em&gt; seem to take longer than they should.  When I asked them why, they said that the system was very complex, and making changes to it was time consuming.&lt;/p&gt;
&lt;p&gt;I asked them to draw the system on the whiteboard.  Here&amp;#8217;s what they drew.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://dl.dropbox.com/u/4730299/blog_images/service-oriented-agony.jpg&quot; width=&quot;80%&quot;/&gt;&lt;/p&gt;
&lt;p&gt;The system has several front end processes, each is its own Rails app.  They talk to each other by throwing URLs at each other, and loading cookies, etc.  Pretty normal.&lt;/p&gt;
&lt;p&gt;Each of the front ends talks to some gems which act as interfaces for the services.  The services are individual Rails apps that communicate through &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; using &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt;.  These services each manage a backend database.&lt;/p&gt;
&lt;p&gt;I suspected the answer, but I asked the developers why this structure slowed them down.  They told me that every time there is a new feature to add, they have to add it in three different places.  They have to change the front end to add the UI gestures.  They have to add a new function to one of the gems in order to provide the UI with the new service interface.  Then they have to add a new &lt;span class=&quot;caps&quot;&gt;MVC&lt;/span&gt; triplet to one of the services that the gem will use to access the data.&lt;/p&gt;
&lt;p&gt;I asked them if this was true even if there weren&amp;#8217;t any schema changes; and they told me that it was because the gems and the services had evolved with the whole application, and only had functions for the current features.  New features often require new functions even though there&amp;#8217;s no schema change.&lt;/p&gt;
&lt;p&gt;This is a pretty typical structure.  I&amp;#8217;ve seen it many times before.  I&amp;#8217;ve seen it in Java apps, C++ apps, and now even Rails apps.  The structure seems obvious to system designers who have grown tired of single monolithic systems and want to break those systems up into components and services.  What could be more natural than to break the system along the lines of data base managment?&lt;/p&gt;
&lt;p&gt;Unfortunately this is a huge violation of the Single Responsibility Principle &amp;#8212; or its big brother the Common Closure Principle.  These principles tell us to group together things that change together, and keep apart things that change for different reasons.  Unfortunately the above design separates things that change for the same reasons, and groups together things that change for different reasons.  No wonder the developers feel like they are going slow!&lt;/p&gt;
&lt;p&gt;When you separate things that change for the same reasons, you have to make changes in many different places in the system.  If those places are in different applications, then you have to switch mental contexts for each change.  Testing the change is hard because you have to have all the components running to test it end-to-end.  And you have to make sure that all the interface points work as desired.  So it&amp;#8217;s a lot of work just to get &lt;em&gt;anything&lt;/em&gt; working.&lt;/p&gt;
&lt;p&gt;Moreover, when you group together things that change for different reasons, you expose the components of the system to collateral damage, thrashing, CM collisions, and a whole host of other problems.  Changing one of those gems, for example, has an impact on all the front ends, even though some of those front ends won&amp;#8217;t use the part of the gem that was changed.&lt;/p&gt;
&lt;p&gt;So what&amp;#8217;s the solution?  First of all, I question whether the system needed to be partitioned into services.  Services are expensive and complicated, you should only create them if you &lt;em&gt;absolutely&lt;/em&gt; need to.  It&amp;#8217;s always easier to live in a single process.  Remember Martin Fowler&amp;#8217;s first law of distributed objects:  &lt;em&gt;Don&amp;#8217;t distribute your objects.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s assume, however, that the system &lt;em&gt;did&lt;/em&gt; need to be partitioned into services.  Are these the right services?  Dividing a system into UI and DB services is a &lt;em&gt;physical&lt;/em&gt; partitioning.  What we should be looking for is families of &lt;em&gt;business rules&lt;/em&gt; that are separate from each other, and can be partitioned into true business services.&lt;/p&gt;
&lt;p&gt;Finally, let&amp;#8217;s assume that the physical partitioning was necessary for some reason.  Then we need to find a way to make the interfaces of the gems and DB services generic so that every new feature doesn&amp;#8217;t require a change throughout the whole system.&lt;/p&gt;
&lt;p&gt;Like I said, I see this kind of partitioning a lot; and it always has the same outcome.  It slows development because it smears features through many different layers.  Many systems could be streamlined, and development made much faster, if the system designers paid more attention to the Single Responsibility Principle.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>The Ruby Colored Box</title>
   <category term="uncle-bob" />
   <link href="http://8thlight.github.com/uncle-bob/2012/01/31/The-Ruby-Colored-Box.html"/>
   <author>
     <name>uncle bob</name>
   </author>
   <updated>31 Jan 2012</updated>
   <id>http://8thlight.github.com/uncle-bob/2012/01/31/The-Ruby-Colored-Box</id>
   <content type="html">&lt;p&gt;I recently read a &lt;a href=&quot;http://www.unlimitednovelty.com/2011/12/can-you-solve-this-problem-for-me-on.html&quot;&gt;blog&lt;/a&gt; about a guy who had a bad interview.  The blog was well written and pretty funny.  He metaphorically described the interview in terms of a mexican chef being grilled about how to make crème brûlée.  He made a bunch of interesting points about how unfair the interview was, and how you shouldn&amp;#8217;t ask a mexican chef how to cook pastry.&lt;/p&gt;
&lt;p&gt;The blog was in two parts, the mexican chef metaphor, and then a rant.  By the time I got to the end of the metaphor I was pretty much thinking that the author was a bit of a whiner.  OK, so the interview was unfair.  What interview isn&amp;#8217;t?  Why would any employer want to conduct a &amp;#8220;fair&amp;#8221; interview.  I&amp;#8217;m certainly not fair when I interview people.  I put them under all kinds of stresses, and throw lots of strange issues at them.  I want to see how they behave when confronted with unfamiliar problems.  I want to know if they can extrapolate their experience into a new domain.&lt;/p&gt;
&lt;p&gt;But I also understood his point.  I&amp;#8217;ve been to interviews where I&amp;#8217;ve bombed, and can remember thinking they were unfair at the time.  They weren&amp;#8217;t, it&amp;#8217;s just that interviewers aren&amp;#8217;t trying to find the first person who might fit.  They&amp;#8217;re trying to find the one person who stands out.  That means they&amp;#8217;re going to pass over a lot of good people.  That&amp;#8217;s just the breaks of the game.&lt;/p&gt;
&lt;p&gt;But then I got to the rant, and I read this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;My attitude is if I&amp;#8217;m a good Ruby programmer, and you&amp;#8217;re trying to hire me when the supply for Ruby programmers is low and demand is high, that before you even talk to me you&amp;#8217;ve spent at least 10 minutes Googling for my name, looking at my code, and figuring out who I am, rather than spending an hour subjecting me to a series of ad hoc programming questions in areas I may or may not specialize in. That 10 minutes of Google will tell you a lot more than asking me to come in and scribble stuff on a whiteboard.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;I think this process has left me a bit more discerning about the companies I&amp;#8217;ll actually interview with. When you&amp;#8217;re trying to hire talented developers in a scarce market, please do your due diligence and don&amp;#8217;t insult somebody skilled by asking them to do a degrading whiteboard interview instead of looking at code they have freely available on the Internet or just looking over their shoulder as they code on a computer, preferably their own, at least the first time you get to know them. You may even learn something.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The last thing I want is to hire someone who thinks I owe them a job.  Does this guy really think he&amp;#8217;s so hot that I&amp;#8217;m going to do research on him &lt;em&gt;before&lt;/em&gt; I meet him? Am I supposed to kneel down and kiss his sandals for granting me an audience?  Just who does he think he is?&lt;/p&gt;
&lt;p&gt;Oh!  He&amp;#8217;s a &lt;em&gt;Ruby Programmer&lt;/em&gt;!  That explains it!  Of course I should kiss his sandals.  He&amp;#8217;s a &lt;em&gt;Ruby Programmer&lt;/em&gt;.  He&amp;#8217;s on &lt;em&gt;GitHub&lt;/em&gt;.  Oooooohhhh!.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dear Employers in search of Ruby Programmers:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You don&amp;#8217;t need Ruby Programmers!  You just need programmers!  Any decent programmer can learn Ruby in a week.  And Rails only takes a little longer.  &lt;em&gt;Don&amp;#8217;t&lt;/em&gt; hire these prima donnas who think they&amp;#8217;re God&amp;#8217;s gift to Ruby shops.  They&amp;#8217;re not.  They&amp;#8217;re just generally inexperienced kids who happened to learn a pretty easy language and a pretty easy framework.&lt;/p&gt;
&lt;p&gt;Instead, find some programmers who have been around the block a few times.  They should know multiple languages, and be able to deal with many different and novel situations.  Don&amp;#8217;t worry if they don&amp;#8217;t know Ruby, they&amp;#8217;ll know it, and Rails, within a month.  If you like you can temporarily hire some super-expensive consultant to teach them if you like.  They&amp;#8217;ll learn quickly, with or without.&lt;/p&gt;
&lt;p&gt;What you are looking for, if I may drop back into the metaphor, are mexican chefs who don&amp;#8217;t panic when you ask them how to prepare crème brûlée.  It&amp;#8217;s ok if they don&amp;#8217;t know (though don&amp;#8217;t let &lt;em&gt;them&lt;/em&gt; know that!).  What you are looking for is whether or not they can extrapolate from their experience.  In other words, to drop back out of the metaphor, if you are interviewing a Ruby programmer, your first questions to him should &lt;em&gt;not be about Ruby&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Ask him something outside his comfort zone, and see if he can extrapolate.  Ask him, to write &lt;em&gt;The Sieve of Eratosthenes&lt;/em&gt; in C.  If he doesn&amp;#8217;t know C, give him a copy of K&amp;amp;R and come back in 20 min.  He won&amp;#8217;t have the right answer; but that&amp;#8217;s not what you are looking for.  You are looking to see whether or not he has the experience and resourcefulness to fruitfully attack the problem.  You are looking to see if he can think outside the Ruby colored box.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Effective Customer Consultant Relationships</title>
   <category term="dave-moore" />
   <link href="http://8thlight.github.com/dave-moore/2012/01/20/effective-customer-consultant-relationship.html"/>
   <author>
     <name>dave moore</name>
   </author>
   <updated>20 Jan 2012</updated>
   <id>http://8thlight.github.com/dave-moore/2012/01/20/effective-customer-consultant-relationship</id>
   <content type="html">&lt;p&gt;As a customer, how can you get the most out of your consultants? As a consultant, how can you deliver what your customers really want? I have been on both sides of this relationship and experienced both successful and unsuccessful results. In this post, I will go through the typical aspects of these types of relationships and identify action items that I have used to forge effective and lasting customer consultant relationships for both parties.&lt;/p&gt;

&lt;h2&gt;The Typical Process&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;The process I am about to outline is not the process for all software consulting firms. However I have seen this happen frequently and have run into this situation myself as a client and as a consultant.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The customer comes up with a general idea of an application that would bring value to a group of people. Then he/she finds a firm that has experience building software and hires them to build the application.&lt;/p&gt;

&lt;p&gt;The consulting firm takes a week or so to build a master plan based off of the customers ideas and shares it with the customer. Once the customer okays the plan, the consulting firm starts building the application. Since applications are very complex, the firm builds the application assuming basic details like user flow, page layouts, etc.&lt;/p&gt;

&lt;p&gt;After the firm has done a week or two of work, the customer has had more time to think about how their app should work. When they see what the firm has created so far, it doesn't quite match up with what the customer has envisioned in their head. So they give the consulting firm more specific information about their application. With the new specific information, the consulting firm fixes their improper guesses and adjusts their code to line up with the new information the customer has provided. The fixes took time away from development, so now the project is a little rushed.&lt;/p&gt;

&lt;p&gt;A couple weeks or months pass, and customer has come up with new ideas that will add tons of value to the application. So they share these ideas with their consulting firm. The consulting firm informs the customer that making these changes will add significantly to the development time because the system wasn't designed to support these new features. The customer is not happy to hear this, but this new idea is really important, so it has to go in. Now the project is over budget, over time, and rushed because the consulting firm has to change the structure of the application to accommodate the new idea.&lt;/p&gt;

&lt;p&gt;This process occurs because the business requirements of a project evolve over time as the customer learns what features add value to the application. In this scenario, whenever a business requirement evolves, the consulting firm has to backpedal to add it into the system.&lt;/p&gt;

&lt;h2&gt;How To Avoid Major Delays&lt;/h2&gt;

&lt;p&gt;A major fear customers have is that the project will take longer to develop than the original estimate suggested. At the same time, one of the hardest things to do as a consultant is to estimate how long a piece of software will take to develop. To minimize the variance in estimations, it is imperative that the development schedule be broken down into a prioritized series of fully-thought out minimum marketable features (MMF). Also, initially only the most important MMFs should be estimated and built out to form a minimum viable product (MVP). Additional features can be added on top of the app once market feedback has come in from the MVP.&lt;/p&gt;

&lt;p&gt;A MMF is defined as the smallest group of functionality that adds market value to an application. When a project's functionality gets broken down into MMFs, the project gets built in small working slices. Each slice can be demoed once it is done, and feedback is easier to give when the customer can play with a demo.&lt;/p&gt;

&lt;p&gt;A MVP is defined as the smallest group of MMFs that allow the application to be deployed. As the time and scope of a project gets larger, so does the amount of complexity. No matter how experienced a consultant is, he/she won't be able to clearly picture what the application will look like until relevant parts of it get developed. Therefore, it gets harder to estimate features as the project specs list get larger.&lt;/p&gt;

&lt;p&gt;Additionally, a tight feedback loop should be established. The customer's specialty is understanding the business requirements and the consultant's specialty is implementing functionality. Since the business requirements change over time, the customer and consultant have to work very closely to ensure that the consultant is implementing features that fulfill the current business requirements.&lt;/p&gt;

&lt;h2&gt;Customer Action Items&lt;/h2&gt;

&lt;h3&gt;Demand that your software gets built in short release cycles&lt;/h3&gt;

&lt;p&gt;You are more capable of giving quality feedback when you can play with a demo of your software (plus playing with your software is fun). Additionally, your consultants will spend less time guessing and more time developing when you can give great feedback every week.&lt;/p&gt;

&lt;h3&gt;Break apart your idea into minimum marketable features&lt;/h3&gt;

&lt;p&gt;When you create a MMF, it is easier to drill down into the specifics of what you want out of a certain aspect of your application. Additionally, it makes it easy for your contractors to build in short release cycles when they can simply implement a handful of MMFs per cycle.&lt;/p&gt;

&lt;h3&gt;Initially, only build enough features to create a minimum viable product&lt;/h3&gt;

&lt;p&gt;You won't know what actually brings value to your market until you can release something. When you put a MVP in a client's hands, they will be capable of giving you extremely valuable feedback that you couldn't get otherwise.&lt;/p&gt;

&lt;h3&gt;Be available all workday long for questions that your consultants come up with&lt;/h3&gt;

&lt;p&gt;It is more cost effective for you to answer questions that your consultants have, rather than them guessing an answer and you having to correct their mistake down the line.&lt;/p&gt;

&lt;h2&gt;Consultant Action Items&lt;/h2&gt;

&lt;h3&gt;Build software in short release cycles&lt;/h3&gt;

&lt;p&gt;Building software this way creates a tight feedback loop with your customer. Also, it pushes you to build an extensible architecture that can deliver business value amidst changing business requirements.&lt;/p&gt;

&lt;h3&gt;Persuade your customer to break up their idea into minimum marketable features&lt;/h3&gt;

&lt;p&gt;If they don't provide a MMF with specific acceptance criteria, then it will be extremely difficult for you to deliver value to them (unless you can read minds).&lt;/p&gt;

&lt;h3&gt;Don't estimate features that won't get implemented in the upcoming release cycle&lt;/h3&gt;

&lt;p&gt;No matter how smart you are today, you will always be smarter tomorrow. So don't waste your time estimating a feature that won't get implemented in the near future. Your estimation will change as you learn more about how the system should work.&lt;/p&gt;

&lt;h3&gt;Communicate with your client on a daily basis&lt;/h3&gt;

&lt;p&gt;Even if you only communicate with your client 5 minutes a day (excluding weekly product demos/meetings), your customer will feel in control of their project if he/she knows what is happening every day. Additionally, the more feedback you get from the customer, the less guessing/mind-reading you have to do.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;It is both the customer's and the consultant's responsibility to forge an effective relationship. Both parties should work together with an understanding that the business requirements WILL evolve. If they follow the action items that I outlined, their relationship will be extremely effective at building projects that produce value.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Fecophiles</title>
   <category term="uncle-bob" />
   <link href="http://8thlight.github.com/uncle-bob/2012/01/20/Fecophiles.html"/>
   <author>
     <name>uncle bob</name>
   </author>
   <updated>20 Jan 2012</updated>
   <id>http://8thlight.github.com/uncle-bob/2012/01/20/Fecophiles</id>
   <content type="html">&lt;p&gt;&amp;#8594;&lt;br /&gt;
I got an interesting email yesterday.   It contained the following paragraph describing an email he had sent to his co-workers about a refactoring he had done:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When I originally sent this email to my co-workers, I got the following reaction; 1 team member thought it was better &amp;amp; 2 team members thought it was harder to understand.  Of the 2 who thought it was worse; 1 thinks I should change it back, and the other is willing to put up with my change to shut me up :-)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here&amp;#8217;s the letter he sent to them, showing them the before and after of the code he had refactored.&lt;/p&gt;
&lt;pre&gt;
Subject: FW: Refactoring of the day

 
Am I missing something?  Or did I just refactor a 31 loc method to 2 loc?
 
------- before ------
public static string GetLtsCode(IventoryBinItem item)
{
    string ltsCode = null;
    if (!string.IsNullOrEmpty(item.ParentItemNo)) //child item
    {

        ltsCode = &quot;PzT&quot;;
        var isNfoOrDisc = item.IsNfoItem || item.IsDiscontinuedItem;
        //if (isNfoOrDisc &amp;amp;&amp;amp; item.ParentIsNfoOrDiscontinuedItem ||
        //    !isNfoOrDisc &amp;amp;&amp;amp; !item.ParentIsNfoOrDiscontinuedItem)
        if (!item.ParentIsNfoOrDiscontinuedItem)
        {
            ltsCode = &quot;PzT&quot;;
        }
        //else if (item.ParentIsNfoOrDiscontinuedItem &amp;amp;&amp;amp; !isNfoOrDisc)
        else if (item.ParentIsNfoOrDiscontinuedItem) //always capture demand for children of nfo (april19 change)
        //and childitem is not, then mark it as regular, otehrwise both PzT
        {
            ltsCode = null;
        }
    }
    else //parent
    {
        ltsCode = null;
        if (item.IsNfoItem || item.IsDiscontinuedItem)
        {
            //april 19 change
            //ltsCode = &quot;PzT&quot;;
            ltsCode = null;
        }

    }

    return ltsCode;
}
-----------------
 
---- after ------
public static string GetLtsCode(IventoryBinItem item)
{
    bool isPzT = item != null
              &amp;amp;&amp;amp; !item.ParentItemNo.IsNullEmptyOrWhiteSpace()
              &amp;amp;&amp;amp; !item.ParentIsNfoOrDiscontinuedItem;
    return isPzT ? &quot;PzT&quot; : null;
}
------------------
  
---- And later refactored to ----
public static string GetLtsCode(IventoryBinItem item)
{
    return IsPzT(item) ? &quot;PzT&quot; : null;
}

private static bool IsPzT(IventoryBinItem item)
{
    return item != null
       &amp;amp;&amp;amp; !item.ParentItemNo.IsNullEmptyOrWhiteSpace()
       &amp;amp;&amp;amp; !item.ParentIsNfoOrDiscontinuedItem;
}
------------------
&lt;/pre&gt;
&lt;p&gt;Now let me be clear.  The first code is crap.  Major crap.  I mean it&amp;#8217;s a really stinky brown and greasy pile of poop.  It looks like it came out of a very sick dog.&lt;/p&gt;
&lt;p&gt;I was astounded that anyone might think that crap was better than the rather nice refactoring.  I guess some people just like to smell poop.  I call them &lt;em&gt;Fecophiles&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I thought that perhaps there was something wrong with their noses.  After all, if you live in crap, you might just stop smelling it after awhile.  So I determined to shove their noses in the fetid pile by investigating the smell in all it&amp;#8217;s rich and pungent detail.  So I sent the following letter back to my friend.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Let&amp;#8217;s just walk through that previous code step by step and really &lt;em&gt;smell&lt;/em&gt; it!&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;We start out buy initializing ltsCode to null.  Fine.&lt;/li&gt;
	&lt;li&gt;Then we encounter a double negative (if not null/empty) and an indirection (item.ParentItemNo).  We need a comment to understand it.  Apparently if the ParentItemNo of the item is null or empty then it means that the item has no parent.  If we negate that, then the if statement is trying to say &amp;#8220;if this is a child&amp;#8221;  The comment tries to point this out, but the grammar is bad.  It would be nicer if the if statement were if(isChild(item)) or if (item.isChild()).&lt;/li&gt;
	&lt;li&gt;In the body of the if statement we are a child, so we set the ltsCode to PzT.&lt;/li&gt;
	&lt;li&gt;Ignore commented out code.&lt;/li&gt;
	&lt;li&gt;Set the var isNfoOrDisc to an interesting expression.  Oddly, I can&amp;#8217;t see any place where that variable is used.  It &lt;em&gt;used&lt;/em&gt; to be used, in the commented out code, so maybe someone just forgot to comment out that var too, eh?&lt;/li&gt;
	&lt;li&gt;A negative if statement (it&amp;#8217;s easy to miss that bang).&lt;/li&gt;
	&lt;li&gt;The if statement checks whether the parent is not nfo or discontinued.  If so, sets ltsCode to PzT if .  But ltsCode is &lt;em&gt;already&lt;/em&gt; PzT.  Maybe someone forgot to comment out this whole if statement too…. &amp;lt;bah!&amp;gt;&lt;/li&gt;
	&lt;li&gt;More commented out code. ugh.&lt;/li&gt;
	&lt;li&gt;Ah! Now in the else clause of the &amp;#8220;parent Not nfo or Discontinue&amp;#8221; if statement we check the boolean opposite.  Does this programmer not know how if/else works?  Why in hell is he checking a tautology.  We already &lt;span class=&quot;caps&quot;&gt;KNOW&lt;/span&gt;, in the else clause, that the parent is nfo or Discontinued.  Sheesh.&lt;/li&gt;
	&lt;li&gt;And in that else clause, we set ltsCode to null.  Wait…  Wasn&amp;#8217;t it already null?&lt;/li&gt;
	&lt;li&gt;(pant, pant, pant) ok, we&amp;#8217;ve reached an else.  What else is it?  It&amp;#8217;s the else from the double negative if statement in point 2 above.  Ah, so this is where we have an item with no parent.  That //parent comment is strange.  Does it mean that the item is a parent?  How would we know that.  All we know is that the item does not have non-null or empty parent item number.    So what&amp;#8217;s with the //parent comment?  It&amp;#8217;s a lie, or at least a wild mistruth.  I think that comment needs to be commented out.  (grrrr).&lt;/li&gt;
	&lt;li&gt;We set the ltsCode to null.  Hmmm.  Let&amp;#8217;s see.  What was the ltsCode be before we set it to null?  Why, I believe it must be null already!  Is there any pathway through this horrible rats nest of code that might set ltsCode to something other than null at this point?  No!&lt;/li&gt;
	&lt;li&gt;and now the coup-de-gras!  Another if statement that checks whether the item is nfo or Disconnected.  And what does this if statement do if that&amp;#8217;s so?  Why, it sets the ltsCode to … &lt;span class=&quot;caps&quot;&gt;NULL&lt;/span&gt;.  Of course!  &lt;span class=&quot;caps&quot;&gt;NULL&lt;/span&gt;. Brilliant!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Summary.  This code is a mess.  A whole-hearted unmitigated indisputable mess.  It&amp;#8217;s full of inaccurate and ambiguous comments, useless variables, if statements that have no purpose, and some truly convoluted logic.  And what was the goal?  The goal was:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;return PzT if the item exists and has a parent that is not nfo or Disconnected.  Otherwise return null.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;OR, to put it in simple code:&lt;/p&gt;
&lt;pre&gt;	
 public static string GetLtsCode(IventoryBinItem item) {
  return IsPzT(item) ? &quot;PzT&quot; : null;
 }

 private static bool IsPzT(IventoryBinItem item) {
  return item != null
    &amp;amp;&amp;amp; item.HasParent()
    &amp;amp;&amp;amp; item.ParentIsNotnfoOrDiscontinuedItem;
 }

&lt;/pre&gt;
&lt;p&gt;I am ashamed of anyone who thinks the original code is simpler and easier to understand.&lt;br /&gt;
&lt;hr/&gt;&lt;/p&gt;
&lt;p&gt;I don&amp;#8217;t know if they got the message.  But even if they did, and they could suddenly smell their home for the first time, it&amp;#8217;s a drop in the bucket.  There are lots and lots of fecophiles out there who need to take a step back and inhale deeply through their noses.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>8 Things You Ought to Know If You Do Not Know Anything About Hiring A Software Developer</title>
   <category term="angelique-martin" />
   <link href="http://8thlight.github.com/angelique-martin/2012/01/19/8-thing-you-ought-to-know.html"/>
   <author>
     <name>angelique martin</name>
   </author>
   <updated>19 Jan 2012</updated>
   <id>http://8thlight.github.com/angelique-martin/2012/01/19/8-thing-you-ought-to-know</id>
   <content type="html">&lt;h2&gt;“The one absolutely solid place to store your capital today — if you know how to do it –  is in software developers’ wallets.”&lt;/h2&gt;

&lt;p&gt;...is what Venkatesh Rao states in his thought provoking article &lt;a href=&quot;http://www.forbes.com/sites/venkateshrao/2011/12/05/the-rise-of-developeronomics/&quot;&gt;“The Rise in Developeronomics”&lt;/a&gt; published Dec 5, 2011 on Forbes. He argues that the future of our economy will be heavily dependent upon access to software development services as starting, growing, and running your business is bound to involve software nowadays.  So he makes the case that the best friend to have to face these challenges is... a software developer.&lt;/p&gt;

&lt;p&gt;I did not come to this industry with a software background.  I studied math, physics, business, then finance.  But over the past 12 years or so, I have learned quite a bit about how to pick a software... “friend”.  So let me share with you 8 things I would want to know if I was starting afresh.&lt;/p&gt;


		&lt;p&gt;&lt;b&gt;I would ask about the &lt;em&gt;development process&lt;/em&gt;&lt;/b&gt;.  I seem to take it for granted that all software shops operate on some type of “Agile” development methodology.  The reality is much different.  Beware of a once favorite software development process named the “Waterfall Model”, a sequential model in which steps are completed one after the other.  First the customer would specify ALL requirements, then the app would be designed and coded, then -- and lots of time is elapsing here as you’d progress thru the steps -- it would be tested; then deployed.  The drawbacks of this process is that it’s lengthy, unresponsive to change and yes, super costly.  So the process you want your software friend to abide by is an Agile one.  Because an Agile process calls for short  development “iterations”, you get value in short increments of time.  In a nutshell, it’s a collaborative process that delivers quickly  and enables you to adapt to change.&lt;/p&gt;

	&lt;p&gt;&lt;b&gt;I would ask about the &lt;em&gt;development practices&lt;/em&gt;&lt;/b&gt;.  Just like you would expect of your accountant to abide by certain Generally Accepted Accounting Principles, you ought to expect that your software “friend” abide by the following practices.&lt;/p&gt;

&lt;ol style=&quot;margin-left: 20px;&quot;&gt;
		&lt;li&gt;The first one on my list would be &lt;em&gt;TDD: Test Driven Development&lt;/em&gt;.  No later than yesterday, I produced a spreadsheet that summarizes how an amount of money gets allocated amongst different accounts.  In doing so, one could easily forget to include a cell.  To put TDD in perspective to the non developer, my test to avoid such a situation would be to have a cell in which the formula tests that the sum of the parts would equal the whole, before even starting the allocation.  A good software friend practices that as a reflex.  Before writing any code, he or she writes tests to ensure that the code to be written will produce the desired outcome.&lt;/li&gt;

		&lt;li&gt;The second one would be &lt;em&gt;pair programming&lt;/em&gt;.  If you have ever looked even remotely at code, it’s a lot of text.  To me it may be mostly gibberish, but it does not take much convincing to understand that two sets of eyes are better than one.  So hopefully, your friend has a friend, because, that will ensure less bugs.&lt;/li&gt;

		&lt;li&gt;The third one is those &lt;em&gt;short iterations&lt;/em&gt; we talked about earlier.&lt;/li&gt;

		&lt;li&gt;The fourth one is &lt;em&gt;continuous integration&lt;/em&gt;.  This means that your friend is diligent about integrating to the rest of the system as a whole.  It ensures that everybody’s work works together.&lt;/li&gt;
&lt;/ol&gt;


	&lt;p&gt;&lt;b&gt;I would ask how my potential software “friend” would &lt;em&gt;keep his or hers claws sharp&lt;/em&gt;&lt;/b&gt;.  Again, just as you would expect your accountant to be aware of the changes in tax laws, you should expect your software friend to be aware of the changes in the software industry.  My software friends usually go to conferences, read books, reflect on their work whether through blogging or presenting to others, and meet with other fellows in the field.  They know several languages and work across multiple platforms.  Better yet, they fear not learning a new one.  Above all, they are far from being the stereotypical isolated geek one could envision.&lt;/p&gt;

	&lt;p&gt;&lt;b&gt;I would ask for &lt;em&gt;proof of talent&lt;/em&gt;&lt;/b&gt;.  Although a degree from an ivy league university might do the trick for some, quality experience does set the good developer apart.  My developer friends have loads to show to testify for their talent.  For some, from past work done, for others, from apprenticeship projects, but for all, from hands on development.&lt;/p&gt;

	&lt;p&gt;&lt;b&gt;I would ask about how they &lt;em&gt;estimate&lt;/em&gt;&lt;/b&gt;.  Systems built nowadays have variable scope.  As a result, it can be difficult to estimate how long the project will take.  However, I would advise you to befriend a developer that gives you a reasonable estimate.  An estimate that could provide you with a bracket of possible values: one pessimistic, one optimistic, and one realistic.  I may even push it to ask with what confidence do past project estimations fall within a 95% accuracy within the aforementioned brackets.&lt;/p&gt;

	&lt;p&gt;&lt;b&gt;I would ask &lt;em&gt;how deadlines are met&lt;/em&gt;&lt;/b&gt;.   Deadlines are a critical variable for any business.   If I were to befriend a software developer I would expect to hear that since the development process relies on short iterations and prioritization of requirements, I (the customer) hold the key to deadlines.  I (the customer) would be the one prioritizing which features get attended first.  I (the customer) would hence have control on where my ROI would come from.&lt;/p&gt;

	&lt;p&gt;&lt;b&gt;I would ask about &lt;em&gt;cost&lt;/em&gt;&lt;/b&gt;.  Of the upmost importance, staying within one’s budget is a goal that short iterations can help to fulfill.  When getting value in short iterations, cost is easy to tame.  Prioritization ensures that the most financially critical decisions stay within the hands of the customer.  A good software development friend will bill at a certain frequency of iteration completions.&lt;/p&gt;

	&lt;p&gt;&lt;b&gt;I would ask about &lt;em&gt;change&lt;/em&gt;&lt;/b&gt;.  I would say to my potential friend: “How will my app be able to evolve overtime?” -- deeply concerned with the ever changing technologies, market requirements, and products I could offer.  I would expect him to state that he values feedback and collaboration.  A good software developer friend embraces change in requirements which are bound to happen overtime. Oh, and do I need to stress again that a good software friend develops in short iterations, which by itself, guarantees an adaptable progress?&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>The Letter</title>
   <category term="uncle-bob" />
   <link href="http://8thlight.github.com/uncle-bob/2012/01/12/The-Letter.html"/>
   <author>
     <name>uncle bob</name>
   </author>
   <updated>12 Jan 2012</updated>
   <id>http://8thlight.github.com/uncle-bob/2012/01/12/The-Letter</id>
   <content type="html">&lt;p&gt;We need to become a self-regulating and self-policing profession.  The stakes are simply too high to allow software to remain in the current ad-hoc limbo of hackers, heroics, and hermits.&lt;/p&gt;
&lt;p&gt;Consider how much software you interact with every day.  Your alarm clock, your cell phone, the television and cable box, the remote control, your toaster oven, your watch, your car, the train to work, the cash register at Starbucks, the coffee maker at Starbucks, the elevator you ride,  etc. etc.  The list is virtually endless.  Nearly every aspect of our daily lives, nearly ever corner of our civilization is somehow touched, controlled, managed, or influenced by software.&lt;/p&gt;
&lt;p&gt;Think about that again.  Virtually every aspect of our lives has a software component; and yet we exert absolutely no regulatory control over that writing of that software.  Any Harry Hacker with a &amp;#8220;J&amp;#8221; in his name can get hired to write Java code.  And the strongest likelihood is that Harry J. Hacker&amp;#8217;s code be crap, will be wrong, and will not be explicitly tested before it is shipped.&lt;/p&gt;
&lt;p&gt;Plumbers are regulated.  Electricians are regulated.  Architects, lawyers, and doctors are regulated.  Why aren&amp;#8217;t we?  Don&amp;#8217;t get me wrong, I don&amp;#8217;t want government to be the regulator; I want us to self-regulate.  But if we software developers don&amp;#8217;t figure out how to do that, then government will certainly step in.  And then life will get &lt;em&gt;really&lt;/em&gt; bad.&lt;/p&gt;
&lt;p&gt;Yesterday I received a very scary, letter that underscores this point rather dramatically.  I thought you&amp;#8217;d like to read it.  I worked with the developer to sanitize it so that the innocent people in this story are not punished.  I regret that I can&amp;#8217;t splash the guilty parties&amp;#8217; names all over twitter though.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hello &amp;#8220;Uncle Bob&amp;#8221;,&lt;br /&gt;
&lt;p/&gt;&lt;br /&gt;
I&amp;#8217;m  a 34 year old freelance programmer who has been developing software for 15 years.&lt;br /&gt;
&lt;p/&gt;&lt;br /&gt;
Some time ago I was hired as a team leader for a safety critical embedded system that controlled a medical surgery device.  Everything was fine during the first months.  I put a great deal of architectural effort into safety.  I used Active-Objects for safer threading, &lt;span class=&quot;caps&quot;&gt;UML&lt;/span&gt;-Generated State-Machines for stateful safety-checks, simulation, and lots of Unit-Testing (though not with full coverage). &lt;br /&gt;
&lt;p/&gt;&lt;br /&gt;
Oh, things weren&amp;#8217;t perfect.  We had been asked to finish a four year project in less than 1 year; so time pressure was very high. Even so I had a good feeling that the device would be safe for millions of treatments.&lt;br /&gt;
&lt;p/&gt;&lt;br /&gt;
Eventually it became clear that we could not deliver the full release on time.  When we told our manager, he began to worry about his bonus. (At least that’s my personal suspicion). When I told him we couldn&amp;#8217;t meet the schedule, he told me I was not allowed to make any more estimates. He shouted a lot all day long and forced everyone to work 7 days a week. He was in such a rage that he even scared the validation team into concluding the official medical validation after just a few days; which was far too early. &lt;br /&gt;
&lt;p/&gt;&lt;br /&gt;
He knew that safety was the most important issue for me, so he began to cut my responsibilities. He eventually gave full control of the project to the&lt;br /&gt;
youngest and most impressionable programmer on my team. I continued to code in the main-branch of the project; so the manager made his own code branch and, together with the rookie, produced his own version of the software.&lt;br /&gt;
&lt;p/&gt;&lt;br /&gt;
So I terminated my contract with the company.  &lt;br /&gt;
&lt;p/&gt;&lt;br /&gt;
A few days later the first bug occurred during a human trial. Fortunately, during the early days of the project, I had made the software robust enough that the bug didn’t harm the patient.  The device just stopped operating before starting the automated surgery. You&amp;#8217;d think that would have been a wakeup call, but the company didn’t even analyze the bug (not to mention stopping the unstable product). More bugs were found later. Even obvious bugs like mixing up the surgery directions (upwards/downwards) were found during the first human treatments. It is a real possibility, and one of my great fears, that tomorrow some patient will become severely disabled.&lt;br /&gt;
&lt;p/&gt;&lt;br /&gt;
The other programmers didn&amp;#8217;t quit.  They told me: “the boss is the boss – we just do what he tells us – it&amp;#8217;s his responsibility.”. So I figured I must have been crazy for quitting.  I felt weak and worthless, like I couldn&amp;#8217;t handle the pressure.  But lately I started reading “Clean Coder”. And it&amp;#8217;s made me consider that, perhaps, I’m not weak – but the opposite: strong.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I am, of course, furious about the manager who drove his organization to such unprofessional depths.  He is an idiot and a criminal, and I hope he winds up in prison.  But I am even angrier at the developers.  Not only were they accomplices to that criminal idiocy; they made the one guy who took a stand feel stupid and weak.  They are the ones who are stupid and weak.  They should not be programmers.  Programmers are better than that.&lt;/p&gt;
&lt;p&gt;Aren&amp;#8217;t we?&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Flipping the Bit</title>
   <category term="uncle-bob" />
   <link href="http://8thlight.github.com/uncle-bob/2012/01/11/Flipping-the-Bit.html"/>
   <author>
     <name>uncle bob</name>
   </author>
   <updated>11 Jan 2012</updated>
   <id>http://8thlight.github.com/uncle-bob/2012/01/11/Flipping-the-Bit</id>
   <content type="html">&lt;p&gt;There&amp;#8217;s a bit you need to flip in your head.  It&amp;#8217;s just one bit.  In this blog we&amp;#8217;ll call it &amp;#8220;&lt;span class=&quot;caps&quot;&gt;THE&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;BIT&lt;/span&gt;&amp;#8221;.  Some of you have already flipped &lt;span class=&quot;caps&quot;&gt;THE&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;BIT&lt;/span&gt;.  The rest of you need to flip &lt;span class=&quot;caps&quot;&gt;THE&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;BIT&lt;/span&gt; as soon as possible.&lt;/p&gt;
&lt;p&gt;Once you flip &lt;span class=&quot;caps&quot;&gt;THE&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;BIT&lt;/span&gt; your life will be easier, your code will be cleaner, you&amp;#8217;ll get done with software faster, your software will work better, and fuzzy bunnies will happily hop over hillsides overarched by double rainbows all the way!&lt;/p&gt;
&lt;p&gt;Before I tell you what &lt;span class=&quot;caps&quot;&gt;THE&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;BIT&lt;/span&gt; is, let me show you an example of an article produced without the benefit of &lt;span class=&quot;caps&quot;&gt;THE&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;BIT&lt;/span&gt; being flipped.  The article is &lt;a href=&quot;http://www.simple-talk.com/dotnet/.net-framework/unit-testing-myths-and-practices/&quot;&gt;here&lt;/a&gt;, and was written by someone named Tom Fischer.  As I write this blog, Fischer&amp;#8217;s article has been read eleven thousand times.  That&amp;#8217;s eleven thousand people who&amp;#8217;ve been influenced by the wrong polarity of &lt;span class=&quot;caps&quot;&gt;THE&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;BIT&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Fischer&amp;#8217;s article makes the point that unit testing isn&amp;#8217;t always necessary.  He uses graphs and charts with clever little colorings to support his arguments.  Those arguments are two-fold.&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Unit testing takes time and can delay projects causing them to lose money due to lost opportunity&lt;sup class=&quot;footnote&quot;&gt;&lt;a href=&quot;#fn1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;
	&lt;li&gt;Unit tests don&amp;#8217;t find all bugs because many bugs are &lt;em&gt;integration&lt;/em&gt; bugs, not bugs in the unit-tested components.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Fischer goes on to say that unit tests are great and can solve lots of problems, etc, etc, blah, blah.  But then he erases all those positive and friendly words by concluding with this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We can no longer rely on a general acceptance of the myth that unit testing is a universal panacea, but need to focus unit testing on aspects of development where it is most effective, and be prepared to actively justify its use.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Oh my goodness!  We have to be prepared to &lt;em&gt;actively justify unit testing?&lt;/em&gt;  Be warned!  The &lt;em&gt;Unit Test Compliance Squads&lt;/em&gt; will be making the rounds soon.  Anyone who cannot actively justify their unit tests will be duly punished! &amp;lt;&lt;em&gt;samuri scowl&lt;/em&gt;&amp;gt;&lt;/p&gt;
&lt;p&gt;Who&amp;#8217;s going to write unit tests if we have to &lt;em&gt;actively justify&lt;/em&gt; their use?  Who&amp;#8217;d be fool enough to take that risk?  So we can summarize Mr. Fischer&amp;#8217;s article with the following sentence:  &amp;#8220;Don&amp;#8217;t you dare write unit tests unless you &lt;span class=&quot;caps&quot;&gt;KNOW&lt;/span&gt;, and can &lt;em&gt;actively justify&lt;/em&gt;, that you have enough time.&amp;#8221;&lt;/p&gt;
&lt;p&gt;So the question is: &lt;em&gt;Who&amp;#8217;s got enough time?&lt;/em&gt;  Who, out there, has schedules that are so forgiving that you can &lt;em&gt;actively justify&lt;/em&gt; the risk of writing unit tests?   Who out there is working in an environment where opportunity costs and time-to-market aren&amp;#8217;t an issue?  Who out there has a cushy-dreamy-stress-free-unicorn-riding project in which you can safely absorb the terrible cost of unit tests?  Answer:  Unicorns and fuzzy bunnies.  But no humans that I am aware of.&lt;/p&gt;
&lt;p&gt;Therefore, the only real conclusion of Mr. Fischer&amp;#8217;s article is that nobody should ever write unit tests no matter how beneficial they might sometimes be, because the risk and cost is so great that you must &lt;em&gt;actively justify&lt;/em&gt; their use.  (Note, that there seems to be no need to actively justify their lack&amp;#8230;)&lt;/p&gt;
&lt;p&gt;Mr Fischer has not flipped &lt;span class=&quot;caps&quot;&gt;THE&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;BIT&lt;/span&gt; in his brain.  He still thinks that unit tests take time.  Apparently he thinks they take a &lt;em&gt;lot&lt;/em&gt; of time.  He still thinks that there are situations in which unit tests aren&amp;#8217;t helpful.  He hasn&amp;#8217;t flipped &lt;span class=&quot;caps&quot;&gt;THE&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;BIT&lt;/span&gt;.  What planet is he living on?&lt;/p&gt;
&lt;h2&gt;&lt;span class=&quot;caps&quot;&gt;THE&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;BIT&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;What is &lt;span class=&quot;caps&quot;&gt;THE&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;BIT&lt;/span&gt;?  &lt;span class=&quot;caps&quot;&gt;THE&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;BIT&lt;/span&gt; is the boolean variable within your subconscious that represents your belief that unit tests take time.  I want you to flip that bit so that your belief changes.  I want you to believe that &lt;em&gt;Test Driven Development saves time in every case and every situation without exception amen&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Notice that I did not say: &amp;#8220;Unit tests save time&amp;#8221;.  I said: &amp;#8220;&lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt; saves time&amp;#8221;.  I think that&amp;#8217;s an important distinction.  I don&amp;#8217;t want you believing that unit tests written after the fact are anywhere near as beneficial as the &lt;em&gt;discipline&lt;/em&gt; of &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s the test for &lt;span class=&quot;caps&quot;&gt;THE&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;BIT&lt;/span&gt;.  You can have a friend ask you these questions.  If you answer them as shown below, you&amp;#8217;ll know that &lt;span class=&quot;caps&quot;&gt;THE&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;BIT&lt;/span&gt; has been flipped:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Given a task, will you finish faster using &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt;?:  &lt;em&gt;&lt;span class=&quot;caps&quot;&gt;YES&lt;/span&gt;.&lt;/em&gt;&lt;/li&gt;
	&lt;li&gt;Are there any tasks that you can finish faster without using &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt;?: &lt;em&gt;NO.&lt;/em&gt;&lt;/li&gt;
	&lt;li&gt;I understand that &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt; might help in the long term, but what if the job is really short term?  Would you still use &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt;?: &lt;em&gt;Yes, because &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt; is faster even in the shortest term.&lt;/em&gt;&lt;/li&gt;
	&lt;li&gt;What if the schedule is really tight and the boss is breathing down your neck, would you still use &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt;?: &lt;em&gt;&lt;span class=&quot;caps&quot;&gt;YES&lt;/span&gt;.&lt;/em&gt;&lt;/li&gt;
	&lt;li&gt;In every case?: &lt;em&gt;&lt;span class=&quot;caps&quot;&gt;YES&lt;/span&gt;.&lt;/em&gt;&lt;/li&gt;
	&lt;li&gt;Is there any case where you would not use &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt;: &lt;em&gt;NO.&lt;/em&gt;&lt;/li&gt;
	&lt;li&gt;What if you were on the Starship Enterprise and the warp coil was seconds away from an anti-matter explosion and all you needed to do was invert one IF statement to save the ship.  Would you use &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt; for &lt;em&gt;that&lt;/em&gt;?: &lt;em&gt;Yes.&lt;/em&gt;&lt;/li&gt;
	&lt;li&gt;Why?: &lt;em&gt;Because I&amp;#8217;d get done faster.&lt;/em&gt;&lt;/li&gt;
	&lt;li&gt;Even for just one IF statement?: &lt;em&gt;Yes, even for just one IF statement.&lt;/em&gt;&lt;/li&gt;
	&lt;li&gt;Do you mean to tell me that there is no case, no case at all, in which you would not use &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt;?: &lt;em&gt;Well, I might not use &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt; if I needed the task to take a really long time to finish, and have lots of bugs.  But other than that?  No, no case at all.&lt;/em&gt;&lt;/li&gt;
	&lt;li&gt;What about GUIs?: &lt;em&gt;Ah, GUIs!&lt;sup class=&quot;footnote&quot;&gt;&lt;a href=&quot;#fn2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That&amp;#8217;s &lt;span class=&quot;caps&quot;&gt;THE&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;BIT&lt;/span&gt;.  When you have flipped &lt;span class=&quot;caps&quot;&gt;THE&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;BIT&lt;/span&gt; in your head, then when your boss tells you to stop writing tests because you don&amp;#8217;t have time, you&amp;#8217;ll refuse and tell him that without &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt; it will take you longer to get done &amp;#8212; and you&amp;#8217;ll believe it!  The more the pressure is on, the more you&amp;#8217;ll rely on the &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt; discipline.&lt;/p&gt;
&lt;p&gt;How do you flip &lt;span class=&quot;caps&quot;&gt;THE&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;BIT&lt;/span&gt;?  I can tell you how I flipped &lt;em&gt;my&lt;/em&gt; &lt;span class=&quot;caps&quot;&gt;BIT&lt;/span&gt;.  I used &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt; for a month or so; and my &lt;span class=&quot;caps&quot;&gt;BIT&lt;/span&gt; flipped.  That&amp;#8217;s all it took for me &amp;#8212; just doing it. Maybe that&amp;#8217;ll be enough for you.&lt;/p&gt;
&lt;p class=&quot;footnote&quot; id=&quot;fn1&quot;&gt;&lt;sup&gt;1&lt;/sup&gt; It seems to me that you can lose a lot of money by shipping code that doesn&amp;#8217;t work too, but &amp;#8212; oh well.&lt;/p&gt;
&lt;p class=&quot;footnote&quot; id=&quot;fn2&quot;&gt;&lt;sup&gt;2&lt;/sup&gt; We&amp;#8217;ll talk about GUIs in more detail later.  The short answer is: &lt;em&gt;Yes&lt;/em&gt;.  The medium answer is: &lt;em&gt;Yes, for all the dynamics.&lt;/em&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Hello iOS Development</title>
   <category term="eric-meyer" />
   <link href="http://8thlight.github.com/eric-meyer/2011/12/19/hello-ios-development.html"/>
   <author>
     <name>eric meyer</name>
   </author>
   <updated>19 Dec 2011</updated>
   <id>http://8thlight.github.com/eric-meyer/2011/12/19/hello-ios-development</id>
   <content type="html">&lt;p&gt;
  When first getting started with iOS development, there were very little resources to get up and started.  And with the strict NDA Apple had over the SDK, there were actually very little resources for any level of iOS development.  The goal of this tutorial is to walk you through building a simple app demonstrating the use of actions, outlets and controllers.
&lt;/p&gt;
&lt;p&gt;
  &lt;h3&gt;What you need to get started&lt;/h3&gt;
  &lt;ul&gt;
    &lt;li&gt;An Intel based Mac&lt;/li&gt;
    &lt;li&gt;Xcode 4 with the iOS SDK&lt;/li&gt;
    &lt;li&gt;A basic understanding of Objective C&lt;/li&gt;
    &lt;li&gt;An iOS Dev Center account (For testing apps on real devices and App Store Submission.  Not needed for this tutorial.)&lt;/li&gt;
  &lt;/ul&gt;
&lt;/p&gt;

&lt;h3&gt;Your First Project&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;p&gt;&lt;b&gt;Launch Xcode&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;
      Xcode is the IDE you will be using to development applications for an iPhone or iPad.  It comes with a simulator the two devices.  When you start up Xcode, one of the first things you will probably want to do is create a new project.
  &lt;/li&gt;
  &lt;li&gt;&lt;p&gt;&lt;b&gt;create a new xcode project&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;
      Here you are given a choice from different types of applications.  At the bottom of the screen there will be a short description of the selected application template, but here are some examples of different uses.  Navigation-based Applications would be used for Mail-like apps, Tab Bar Applications would be used for iTunes-like apps, and Split View-based Applications would be used for Mail-like apps but for the iPad.
    &lt;/p&gt;
    &lt;p&gt;
      For this tutorial, we will be using the View-based Application.
    &lt;/p&gt;
    &lt;p&gt;
      &lt;img src=&quot;/eric-meyer/images/ios_blog/01-project-templates.png&quot;
           alt=&quot;iOS Application Project Templates&quot;
           width=&quot;592&quot;/&gt;
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;b&gt;Choose View-based Application&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;
      Name the project &quot;HelloWorld&quot; and choose a location to save it.  Don't worry about including unit tests.
    &lt;/p&gt;
    &lt;p&gt;
      After creating the app, you will be shown a screen which is split into many different panes.  If any of the panes are hidden, there are buttons at the top-right of Xcode to toggle their display.
    &lt;/p&gt;
    &lt;p&gt;
      The left hand pane is the Navigator, which has multiple purposes.  Most commonly, it will be used to display your files arranged into groups (which do not correspond to directories on the filesystem).  It can also be set to show your compile errors or logs.
    &lt;/p&gt;
    &lt;p&gt;
      The bottom pane is the Debug Area, which will show log statements and exceptions.
    &lt;/p&gt;
    &lt;p&gt;
      The right pane is the Utilities Area, which is primarily useful when editing xib files.
    &lt;/p&gt;
    &lt;p&gt;
      The middle section is the main section and is where the current file will be displayed.
    &lt;/p&gt;
    &lt;p&gt;
      &lt;img src=&quot;/eric-meyer/images/ios_blog/02-new-view-based-app.png&quot;
           alt=&quot;View Based Application&quot;
           width=&quot;592&quot;/&gt;
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;b&gt;Edit HelloWorldViewController.xib&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;
      The gray box you are presented with is a WYSIWYG editor for your main view.  Drag a Label from the bottom of the Utilities pane onto the view and edit the text of the label.  If you don't see an option for Label in the list of elements, you might have to switch to a different tab on the Utilities pane.
    &lt;/p&gt;
    &lt;p&gt;
      You should also take this opportunity to make the label wider.  This will be important later in the tutorial.
    &lt;/p&gt;
    &lt;p&gt;
      &lt;img src=&quot;/eric-meyer/images/ios_blog/03-simple-label.png&quot;
           alt=&quot;Adding a Label&quot;
           width=&quot;592&quot;/&gt;
    &lt;/p&gt;
    &lt;p&gt;
      At this point, you could run the application by going to the Product Menu and choosing Run and be presented with the text of your label, but we aren't done yet!
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;b&gt;Edit HelloWorldViewController.h&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;
      What we are going to do here is to define two properties.  One UILabel and one UITextField.  You may notice the use of IBAction and IBOutlet in the method and property declarations.
    &lt;/p&gt;
    &lt;h4&gt;IBActions and IBOutlets&lt;/h4&gt;
    &lt;p&gt;
      The &quot;IB&quot; stands for Interface Builder.  An action is simply an event triggered by the user action, e.g. a button being pressed.  An outlet is an object in the view that is altered by a controller.  Labels are a common outlet, but even objects like buttons can be wired as outlets.  An example of this would be a on/off button, where you would toggle the text of the button between clicks.
    &lt;/p&gt;
    &lt;p&gt;
      The IBOutlet in the property declaration is a way to make the instance variables available to you in the xib file.  That way, when you make changes to label or text field in your code, it will show those changes in the view.  The IBAction in the method declaration where the return type would normally is not actually a return type, but instead makes this method available in the xib file as a target for an event.  The sender argument is an optional argument and will be the object that initiated the event.  In our case, it would be the instance of the UIButton that the user pressed.
    &lt;/p&gt;
    &lt;p&gt;
      You might receive some warnings until the next step is finished.  This is because we've defined methods in our header file but have not implemented them.
    &lt;/p&gt;
    &lt;p&gt;
      &lt;pre&gt;
        &lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;objectivec&quot;&gt;&lt;span class=&quot;lineno&quot;&gt; 1&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;        #import &amp;lt;UIKit/UIKit.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt; 3&lt;/span&gt;         &lt;span class=&quot;k&quot;&gt;@interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HelloWorldViewController&lt;/span&gt; : &lt;span class=&quot;nc&quot;&gt;UIViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4&lt;/span&gt;             &lt;span class=&quot;n&quot;&gt;UILabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;helloWorldLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5&lt;/span&gt;             &lt;span class=&quot;n&quot;&gt;UITextField&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nameTextField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6&lt;/span&gt;         &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7&lt;/span&gt;         &lt;span class=&quot;k&quot;&gt;@property&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nonatomic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;retain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;IBOutlet&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UILabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;helloWorldLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8&lt;/span&gt;         &lt;span class=&quot;k&quot;&gt;@property&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nonatomic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;retain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;IBOutlet&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UITextField&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nameTextField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;10&lt;/span&gt;         &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;IBAction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;sayHello:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;12&lt;/span&gt;         &lt;span class=&quot;k&quot;&gt;@end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13&lt;/span&gt;         
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

      &lt;/pre&gt;
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;b&gt;Edit HelloWorldViewController.m&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;
      Here we are synthesizing our properties and implementing our action, which returns nothing.  The sayHello action is doing a number of things in order.  It's taking the inputted name from the UITextField, prepending it with &quot;Hello &quot; and outputting that result to the UILabel.
    &lt;/p&gt;
    &lt;p&gt;
      At this point, you should be able to compile your application without any warnings.
    &lt;/p&gt;
    &lt;p&gt;
      &lt;pre&gt;
        &lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;objectivec&quot;&gt;&lt;span class=&quot;lineno&quot;&gt; 1&lt;/span&gt;         &lt;span class=&quot;k&quot;&gt;@implementation&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HelloWorldViewController&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2&lt;/span&gt;         
&lt;span class=&quot;lineno&quot;&gt; 3&lt;/span&gt;         &lt;span class=&quot;k&quot;&gt;@synthesize&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;helloWorldLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nameTextField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt; 5&lt;/span&gt;         &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;IBAction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;sayHello:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6&lt;/span&gt;             &lt;span class=&quot;n&quot;&gt;NSString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NSString&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;stringWithFormat:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;@&amp;quot;Hello %@&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nameTextField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7&lt;/span&gt;             &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;helloWorldLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8&lt;/span&gt;         &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9&lt;/span&gt;         
&lt;span class=&quot;lineno&quot;&gt;10&lt;/span&gt;         &lt;span class=&quot;c1&quot;&gt;// Remaining code below...&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11&lt;/span&gt;         
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

      &lt;/pre&gt;
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;b&gt;Back to HelloWorldViewController.xib&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;
      Our first version of this file only had a UILabel, so let's go ahead and add a Round Rect Button and Text Field to our view.  If we were to run the app now, we would see all of our UI elements, but wouldn't do anything, because we haven't wired them to our controller.
    &lt;/p&gt;
    &lt;p&gt;
      &lt;img src=&quot;/eric-meyer/images/ios_blog/04-complex-xib.png&quot;
           alt=&quot;Adding a UILabel and UITextField&quot;
           width=&quot;592&quot;/&gt;
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;b&gt;Wire Up The Outlets and Actions&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;
      This is where we link our UILabel and UITextField in the controller to their corresponding objects in the view.  Labels in the view correspond to instances of UILabel in the controller, Text Fields correspond to instances of UITextField in the controller, etc.
    &lt;/p&gt;
    &lt;p&gt;
      To see a list of available actions and outlets, right-click on the yellow cube, aka the &quot;File's Owner.&quot;  The File's Owner is simply the object that loaded up the xib file.  In this case, it will be the HelloWorldViewController.  Once you are in that menu, to wire up the label, drag from the circle to the right of helloWorldLabel to the label in the view.  Do the same for your nameTextField and the Text Field in the view.
    &lt;/p&gt;
    &lt;p&gt;
      &lt;img src=&quot;/eric-meyer/images/ios_blog/05-wiring-label.png&quot;
           alt=&quot;Wiring an IBOutlet to a UILabel&quot;
           width=&quot;592&quot;/&gt;
    &lt;/p&gt;
    &lt;p&gt;
      Wiring the action is a bit trickier but starts the same, with dragging the circle to the right of sayHello to the Round Rect Button.  The only difference is that at the end of dragging the action to the button, you will be presented with a different menu of the possible events that the UIButton can trigger.  For UIButtons, the most common event will be &quot;Touch Up Inside.&quot;  This event is fired when the user lifts their finger up inside of a button after that user pressed down the button.
    &lt;/p&gt;
    &lt;p&gt;
      &lt;img src=&quot;/eric-meyer/images/ios_blog/06-wiring-action.png&quot;
           alt=&quot;Åvailable Events for a Round Rect Button&quot;
           hie=&quot;592&quot;/&gt;
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;b&gt;Run It!&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;
      At this point, you should have a working app that allows you to type in a person's name and output it into a label.  A github repo with a working example can be found &lt;a href=&quot;https://github.com/ericmeyer/iOS-Hello-World&quot;&gt;here&lt;/a&gt;.
    &lt;/p&gt;
    &lt;p&gt;
      &lt;img src=&quot;/eric-meyer/images/ios_blog/07-done.png&quot;
           alt=&quot;Finished Application&quot;
           height=&quot;642&quot;/&gt;
    &lt;/p&gt;
&lt;/ol&gt;</content>
 </entry>
 
 <entry>
   <title>Fixed Feature</title>
   <category term="paul-pagel" />
   <link href="http://8thlight.github.com/paul-pagel/2011/12/16/fixed-feature.html"/>
   <author>
     <name>paul pagel</name>
   </author>
   <updated>16 Dec 2011</updated>
   <id>http://8thlight.github.com/paul-pagel/2011/12/16/fixed-feature</id>
   <content type="html">&lt;p&gt;
Time and materials vs. fixed bid is the classic duo of billing models in software services business.  Time and materials puts all the pressure on the client to make sure the work is completed.  They must have enough control and transparency to be satisfied the work is moving at the right pace and in the right direction.  Fixed bid projects put all the pressure on the services company to make their estimates for the whole project correct up front.  Since software is a craft with a close problem finding to problem solving loop, we can never anticipate what lies beneath a given problem set, making fix bid a high risk.
&lt;/p&gt;

&lt;p&gt;
8th Light uses a compensation model we call fixed feature which finds a middle ground between hourly and fixed bid compensation. Fixed Feature is an Agile method of fixed bid compensation that is unique in that clients only pay for the product they receive. At the beginning of an iteration we estimate using the &lt;a href=&quot;http://en.wikipedia.org/wiki/Program_Evaluation_and_Review_Technique&quot;&gt;PERT&lt;/a&gt; estimating technique.  After estimating we make a commitment to those estimates and use a predetermined price per point to calculate the cost.  At the end of the iteration we bill for the features that are accepted by the customer. 
&lt;/p&gt;

&lt;p&gt;
Because of this, clients do not have any obligation to manage personnel or hours, they get to focus on software features. Clients also know from the start exactly how much each feature will cost, regardless of the labor that goes into making it.  The metrics collected can be very important to the client specifics about where the cost of overall software is actually going.  From there they can iterate and effectively choose what features are most important to their business.
&lt;/p&gt;

&lt;p&gt;
This payment models didn't come without pain.  It made it transparent that our estimates were not very accurate.  We had to learn how to be really good at estimating features, which is described in the white paper &lt;a href=&quot;http://blog.8thlight.com/paul-pagel/FromEstimateToCommitment.pdf&quot;&gt;From Estimate To Commitment&lt;/a&gt;.
&lt;/p&gt;</content>
 </entry>
 

</feed>

