<?xml version="1.0" encoding="iso-8859-1"?>
<?xml-stylesheet href="http://www.reiersol.com/blog/styles/rss.css" type="text/css"?>
<rss version="2.0" 
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
>
 <channel>
  <title>PHP in Action</title>
  <link>http://www.reiersol.com/blog/1_php_in_action</link>
  <description></description>
  <pubDate>Tue, 06 Jan 2009 15:06:22 -0800</pubDate>
  <generator>http://www.lifetype.net</generator>
    <item>
   <title>How code comments deteriorate</title>
   <description>
    &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;http://www.reiersol.com/blog/plugins/plogeshi/styles/plogeshi.css&quot; /&gt;&lt;p&gt;
There was a lot of disagreement on the value of code comments after my earlier post &lt;a href=&quot;http://www.reiersol.com/blog/1_php_in_action/archive/174_comments_considered_harmful.html&quot;&gt;Comments considered harmful&lt;/a&gt;.
Perhaps the most important objection that was raised was the idea that it&#039;s OK to improve the code, but it&#039;s even
better to keep the comments in addition to the improved code.
&lt;/p&gt;
&lt;p&gt;
As one of the critics expressed it:
&lt;/p&gt;
&lt;blockquote&gt;
  No, comments are there to comment. Period.&lt;br /&gt;
  That has nothing to do with how good is your code.&lt;br /&gt;
  You can write perfectly clean code and add good comments to it. Nothing wrong with that.
&lt;/blockquote&gt;
This is one of those ideas that seem obviously true in theory, but fail to work in practice.
The reason is that comments get out of sync with the code. The comments rot, or rather, their
meaning does. They become more and more misleading as the code gets changed and the comments
are not adequately updated.
&lt;p&gt;
Let me give you an example.
But first, I want to make it clear that I don&#039;t think code comments are always a bad thing. Sometimes, they are necessary.
But much less often than people think.
&lt;/p&gt;
&lt;p&gt;
API documentation is often indispensible, but that&#039;s really a different matter.
When API documentation is generated from comments in front of each method,
the primary purpose is to explain how the code can be used, not how it works.
In fact, you might say they are code comments only in a syntactical sense.
&lt;/p&gt;
&lt;p&gt;
On to the example. One of the comments to my blog post presented a code snippet that illustrates my point well. It&#039;s supposed
to be a example of a useful inline comment in code.
&lt;/p&gt;
&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;co1&quot;&gt;// first handle the case where no records were found&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;re1&quot;&gt;$records&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kw2&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;
&lt;p&gt;
&lt;p&gt;
Is this really an case of good commenting? I don&#039;t think so.  If it&#039;s hard to
understand that $records == 0 means that no records were found, we can change
the code to make it easier.  The simplest way to do it is to rename the
variable to something like $numberOfRecordsFound or $numRecordsFound. Or
extract a method. But typically, it&#039;s possible and preferable to avoid this
kind of check altogether.
&lt;/p&gt;
&lt;p&gt;
Anyway, the comment is unnecessary. But as I only realized
a while later, it&#039;s also misleading. Does the code &quot;handle the case
where no records were found&quot;? No, it leaves it to the calling function to
handle the case. The one line that returns &lt;tt&gt;false&lt;/tt&gt; is not handling anything, it&#039;s just
passing a message.
&lt;/p&gt;
&lt;p&gt;
So the comment is already misleading, never mind what will happen when someone
changes the code and neglects to update the comment. For example, let&#039;s say the
next programmer to work on this code is in hurry to fix a bug. Now maybe the
code will look like this:
&lt;/p&gt;
&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;co1&quot;&gt;// first handle the case where no records were found&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;re1&quot;&gt;$records&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;re1&quot;&gt;$state&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;==&lt;/span&gt; ACTIVE&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kw2&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;
&lt;p&gt;
&lt;p&gt;
The programmer wonders briefly whether the comment is still fully appropriate,
is unsure, and decides to do nothing about it (or postpones the decision and
forgets about it). Now, perhaps (we can&#039;t quite tell without the full context), the comment is even more misleading. 
&lt;/p&gt;
&lt;p&gt;
In the next round, yet another programmer comes along, makes some more code changes
and wonders: &quot;Should I update the comment? It looks all wrong to me, but it was
probably written by someone with deeper insignt into the code. Better leave
it alone.&quot;
&lt;/p&gt;
&lt;p&gt;
The code would have been better off without the comment, but no one wants to
delete it, especially since they have been told that comments are so important.
It&#039;s a downward spiral: the code changes make the comments misleading
less chance that they will 
&lt;/p&gt;
&lt;p&gt;
Comments that lie are worse than no comments, and in practice they tend to big liars.
&lt;/p&gt;
   </description>
   <link>http://www.reiersol.com/blog/1_php_in_action/archive/176_how_code_comments_deteriorate.html</link>
   <comments>http://www.reiersol.com/blog/1_php_in_action/archive/176_how_code_comments_deteriorate.html</comments>
   <guid>http://www.reiersol.com/blog/1_php_in_action/archive/176_how_code_comments_deteriorate.html</guid>
      <dc:creator>dagfinn</dc:creator>
      
    <category>Application design</category>
      
    <category>PHP</category>
      
    <category>Refactoring</category>
         <pubDate>Sun, 04 Jan 2009 03:24:12 -0800</pubDate>
   <source url="http://www.reiersol.com/blog/1_php_in_action/feeds/rss20">PHP in Action</source>
     </item>
    <item>
   <title>How harmful is &quot;harmful&quot;?</title>
   <description>
    &lt;p&gt;
    Conflict is not a bad thing. That is, if it leads eventually towards
    clarity and understanding rather than confusion and misunderstanding.  And
    it&#039;s almost always better to have a conflict openly than to sweep it under
    the rug. Fear of conflict is the second of the &lt;a href=&quot;http://en.wikipedia.org/wiki/The_Five_Dysfunctions_of_a_Team&quot;&gt;five
      dysfunctions of a team&lt;/a&gt;.
    &lt;/p&gt;
    &lt;p&gt;
    And even though anger tends to cloud people&#039;s judgment, it need not be
    terribly destructive. If the angry person can manage to cool down and
    eventually keep an open mind in spite of it, it&#039;s not so bad. The problem
    is that people often get stuck trying to prove that they&#039;re right, placing
    blame and defending whatever position they started with at all
    costs.
    &lt;/p&gt;
    &lt;p&gt;
    One factor that exacerbates this is when different discussions get mixed
    up.  When discussions get heated, you will often you get a discussion about
    the discussion mixed up with the original discussion. A debate about a
    technical matter may be conducted in parallel with an altercation that
    addresses the relationship between the participants. This is confusing in
    itself.  Keeping these discussion apart will help maintain clarity.
    &lt;/p&gt;
    &lt;p&gt;
    In this vein, let me address the criticism I got in &lt;a href=&quot;http://www.reiersol.com/blog/1_php_in_action/archive/174_comments_considered_harmful.html&quot;&gt;my
      latest blog post (&quot;Comments considered harmful&quot;)&lt;/a&gt; regarding the
    appropriateness of the &quot;considered harmful&quot; idiom. This is not a technical
    issue, so let me give it a separate treatment.
    &lt;/p&gt;
    &lt;p&gt;
    A response I got was:
    &lt;/p&gt;
    &lt;blockquote&gt;
      If ever there was a posting to which the &lt;a href=&quot;http://meyerweb.com/eric/comment/chech.html&quot;&gt;&quot;Considered Harmful&quot;
        Essays Considered Harmful posting&lt;/a&gt; applied, it&#039;s this one.
    &lt;/blockquote&gt;
    &lt;p&gt;
    To quote my own reply:
    &lt;/p&gt;
    &lt;blockquote&gt;
      &lt;p&gt;
      I have read that before. I fully understand the argument and agree with
      it in general terms. In particular, I agree with the idea that &#039;the
      writing of a &quot;considered harmful&quot; essay often serves to inflame whatever
      debate is in progress..&#039;
      &lt;/p&gt;
      &lt;p&gt;
      In this case though, there seems to be no debate in progress in the first
      place. I am trying to make my point strongly enough that people will at
      least notice it.
      &lt;/p&gt;
      &lt;p&gt;
      If the rest of the blog post had been over the top, then I would probably
      have been shooting myself in the foot.  I don&#039;t think it is, though.
      &lt;/p&gt;
    &lt;/blockquote&gt;
    &lt;p&gt;
    I find the idea of &quot;considered harmful considered harmful&quot; valid, but over-generalized.
    Sometimes, a little conflict is needed to wake people up. Sometimes, you need to have
    two opposed camps for a while to make the difference of opinion clear before you
    can come to agreement.
    &lt;/p&gt;
    &lt;p&gt;
    When it comes down to it, it&#039;s an empirical question. I choose to measure
    the success, or lack of it, of my provocative title by the actual responses
    I get. Few of the commentators seem to have been derailed by the title. Some had
    specific technical objections, and that&#039;s fine even when I don&#039;t agree with the objections. Some asked me
    how specifically comments might be harmful. That also is totally relevant
    and, in fact, helpful.
    &lt;/p&gt;
    &lt;p&gt;
    Let me try to be even more precise. My aim in using this kind of title is
    not primarily to provoke, but to (over)simplify the message to make it easy
    to get some idea of the content by reading the title.  If I had said
    &quot;comments are not always useful&quot;, it would be so vague that anyone could
    embrace it. I would rather make it clear that I&#039;m pushing a point of
    view that many are going to disagree with. Maybe I&#039;ll choose differently
    the next time, but I&#039;m not promising anything.
    &lt;/p&gt;
   </description>
   <link>http://www.reiersol.com/blog/1_php_in_action/archive/175_how_harmful_is_harmful.html</link>
   <comments>http://www.reiersol.com/blog/1_php_in_action/archive/175_how_harmful_is_harmful.html</comments>
   <guid>http://www.reiersol.com/blog/1_php_in_action/archive/175_how_harmful_is_harmful.html</guid>
      <dc:creator>dagfinn</dc:creator>
      
    <category>PHP</category>
         <pubDate>Fri, 26 Dec 2008 05:14:15 -0800</pubDate>
   <source url="http://www.reiersol.com/blog/1_php_in_action/feeds/rss20">PHP in Action</source>
     </item>
    <item>
   <title>Comments considered harmful</title>
   <description>
    &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;http://www.reiersol.com/blog/plugins/plogeshi/styles/plogeshi.css&quot; /&gt;&lt;p&gt;
    There is too much old advice in PHP. A recent case comes from the PHP
    Advent calendar. &lt;a href=&quot;http://phpadvent.org/2008/commenting-on-comments-by-eli-white&quot;&gt;Eli
      White&lt;/a&gt; is a strong believer in commenting code, including inline
    comments inside functions.
    &lt;/p&gt;
    &lt;p&gt;
    Unfortunately, he&#039;s at least 10 years too late. This used to be good advice, but not any more.
    &lt;/p&gt;
    &lt;p&gt;
    Up to a point, he&#039;s right. Making code as easy to understand as possible is
    essential and can save a huge amount of time later. And adding comments to
    unreadable code is better than leaving it the way it is.
    &lt;/p&gt;
    &lt;p&gt;
    There is a better way, though. Refactor your code so it&#039;s easy to
    understand even without comments. I&#039;m just reading Robert C. Martin&#039;s
    recent book&lt;i&gt;Clean Code&lt;/i&gt;.  He is very clear on this point.
    &lt;blockquote&gt;
      Clear and expressive code with few comments is far superior to cluttered
      and complex code with lots of comments. Rather than spend your time
      writing the comments that explain the mess you made, spend it cleaning
      that mess.
    &lt;/blockquote&gt;
    &lt;/p&gt;
    &lt;p&gt;
    The principle is simple: if you have an inline comment in a method (or
    function), take the chunk of code that the comment refers to and extract it
    into a separate method. Give the method an intention-revealing
      name. Typically, you won&#039;t need the comment afterwards.
    &lt;/p&gt;
    &lt;p&gt;
    I&#039;m sure we need an example. Here&#039;s a small excerpt from a method taken from Zend Framework.
    &lt;/p&gt;
    &lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;    protected &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt; _doUpdate&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
    &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span class=&quot;sy0&quot;&gt;...&lt;/span&gt;
        &lt;span class=&quot;coMULTI&quot;&gt;/**
         * Execute cascading updates against dependent tables.
         * Do this only if primary key value(s) were changed.
         */&lt;/span&gt;
        &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;a href=&quot;http://www.php.net/count&quot;&gt;&lt;span class=&quot;kw3&quot;&gt;count&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;re1&quot;&gt;$pkDiffData&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
            &lt;span class=&quot;re1&quot;&gt;$depTables&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;re1&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;_getTable&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;getDependentTables&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;!&lt;/span&gt;&lt;a href=&quot;http://www.php.net/empty&quot;&gt;&lt;span class=&quot;kw3&quot;&gt;empty&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;re1&quot;&gt;$depTables&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
                &lt;span class=&quot;re1&quot;&gt;$db&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;re1&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;_getTable&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;getAdapter&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;re1&quot;&gt;$pkNew&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;re1&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;_getPrimaryKey&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;re1&quot;&gt;$pkOld&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;re1&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;_getPrimaryKey&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;kw1&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;re1&quot;&gt;$depTables&lt;/span&gt; &lt;span class=&quot;kw1&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;re1&quot;&gt;$tableClass&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
                    try &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
                        &lt;span class=&quot;sy0&quot;&gt;@&lt;/span&gt;Zend_Loader&lt;span class=&quot;sy0&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;me2&quot;&gt;loadClass&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;re1&quot;&gt;$tableClass&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt; catch &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;Zend_Exception &lt;span class=&quot;re1&quot;&gt;$e&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
                        &lt;span class=&quot;kw1&quot;&gt;require_once&lt;/span&gt; &lt;span class=&quot;st0&quot;&gt;&#039;Zend/Db/Table/Row/Exception.php&#039;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
                        throw &lt;span class=&quot;kw2&quot;&gt;new&lt;/span&gt; Zend_Db_Table_Row_Exception&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;re1&quot;&gt;$e&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;getMessage&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
                    &lt;span class=&quot;re1&quot;&gt;$t&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw2&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;re1&quot;&gt;$tableClass&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;a href=&quot;http://www.php.net/array&quot;&gt;&lt;span class=&quot;kw3&quot;&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;db&#039;&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;re1&quot;&gt;$db&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;re1&quot;&gt;$t&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;_cascadeUpdate&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;re1&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;getTableClass&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;re1&quot;&gt;$pkOld&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;re1&quot;&gt;$pkNew&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
            &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
        &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;
&lt;p&gt;
  &lt;p&gt;
  By changing some temporary varibles into instance variables and extracting a couple of methods, 
  we can get code like this:
  &lt;/p&gt;
    &lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;      &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;re1&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;primaryKeyValuesHaveChanged&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
          &lt;span class=&quot;re1&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;executeCascadingUpdatesOnDependentTables&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;
&lt;p&gt;
  &lt;p&gt;
  Or even, by extracting a couple of classes, making objects out of two of the concepts involved, we might end up with something like this.
  &lt;/p&gt;
    &lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;      &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;re1&quot;&gt;$primaryKeys&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;valuesHaveChanged&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
          &lt;span class=&quot;re1&quot;&gt;$dependentTables&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;executeCascadingUpdates&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;
&lt;p&gt;
  &lt;p&gt;
  This uses most of the words from the original comment, but it&#039;s superior for
  several reasons. First and foremost, the section of code as a whole is clearer.
  Second, comments have a tendency to get out of sync with the code. By
  expressing the message in the code itself instead, we can avoid that.
  Third, the extraction itself has the positive side-effect of making it possible
  to test the extracted method in isolation.
  &lt;/p&gt;
  &lt;p&gt;
Improving the code itself is harder than writing comments, but it&#039;s worth it.
.&lt;/p&gt;
   </description>
   <link>http://www.reiersol.com/blog/1_php_in_action/archive/174_comments_considered_harmful.html</link>
   <comments>http://www.reiersol.com/blog/1_php_in_action/archive/174_comments_considered_harmful.html</comments>
   <guid>http://www.reiersol.com/blog/1_php_in_action/archive/174_comments_considered_harmful.html</guid>
      <dc:creator>dagfinn</dc:creator>
      
    <category>Application design</category>
      
    <category>PHP</category>
         <pubDate>Tue, 23 Dec 2008 11:11:54 -0800</pubDate>
   <source url="http://www.reiersol.com/blog/1_php_in_action/feeds/rss20">PHP in Action</source>
     </item>
    <item>
   <title>The one-line web framework</title>
   <description>
    &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;http://www.reiersol.com/blog/plugins/plogeshi/styles/plogeshi.css&quot; /&gt;&lt;p&gt;
The core of your average web framework is a Front Controller. Front Controllers
are commonly considered complex and esoteric.  That&#039;s a myth. I
sometimes brag that I can construct a Front Controller in 15 minutes. Actually,
it&#039;s doesn&#039;t take quite that long. In PHP, a Front Controller can be simplified to
just one line of code:
&lt;/p&gt;

&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;a href=&quot;http://www.php.net/call_user_func&quot;&gt;&lt;span class=&quot;kw3&quot;&gt;call_user_func&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;re1&quot;&gt;$_REQUEST&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;action&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;
&lt;p&gt;

&lt;p&gt;
&lt;b&gt;Warning: Do not use this in a real application.&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
There is one and only one good reason why you shouldn&#039;t:
it&#039;s totally insecure. Except for that, it&#039;s simple but perfectly viable.
Your actions will be just plain functions, which is pretty simplistic and will
be hard to handle if you build many of them. But it&#039;s a huge improvement over the
average PHP script with no systematic handling of the PHP request.
&lt;/p&gt;

&lt;p&gt;
If you want to do something more like the frameworks such as Zend Framework, you want
your actions as methods grouped into classes (called Controllers in ZF).
&lt;/p&gt;

&lt;p&gt;
Now you need two lines. The following script demonstrates this:
&lt;/p&gt;

&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;co1&quot;&gt;// Pretend we have an HTTP request&lt;/span&gt;
&lt;span class=&quot;re1&quot;&gt;$_REQUEST&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;=&lt;/span&gt; &lt;a href=&quot;http://www.php.net/array&quot;&gt;&lt;span class=&quot;kw3&quot;&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;controller&#039;&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;st0&quot;&gt;&#039;Contacts&#039;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;st0&quot;&gt;&#039;action&#039;&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;st0&quot;&gt;&#039;edit&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&amp;nbsp;
&lt;span class=&quot;co1&quot;&gt;// Front controller&lt;/span&gt;
&lt;span class=&quot;re1&quot;&gt;$controller&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw2&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;re1&quot;&gt;$_REQUEST&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;controller&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&lt;a href=&quot;http://www.php.net/call_user_func&quot;&gt;&lt;span class=&quot;kw3&quot;&gt;call_user_func&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;a href=&quot;http://www.php.net/array&quot;&gt;&lt;span class=&quot;kw3&quot;&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;re1&quot;&gt;$controller&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;re1&quot;&gt;$_REQUEST&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;action&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&amp;nbsp;
&lt;span class=&quot;co1&quot;&gt;// The action controller class&lt;/span&gt;
&lt;span class=&quot;kw2&quot;&gt;class&lt;/span&gt; Contacts &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt; edit&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt; 
        &lt;a href=&quot;http://www.php.net/echo&quot;&gt;&lt;span class=&quot;kw3&quot;&gt;echo&lt;/span&gt;&lt;/a&gt; &lt;span class=&quot;st0&quot;&gt;&amp;quot;ok&lt;span class=&quot;es0&quot;&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;
&lt;p&gt;

&lt;p&gt;
You can start with something like it (assuming that security has been taken care of)
and add features as you need them.
&lt;/p&gt;

&lt;p&gt;
In case you&#039;re wondering how to what exactly the security issues are, the most
obvious problem is the fact that any user can run any method in any class that
is available to this script. The way to avoid that append or prepend some fixed
string to the class and the method name. For instance, in Zend Framework, the
action name edit will activate the method editAction().
&lt;/p&gt;

&lt;p&gt;
Beyond that, the security problems are the usual ones. You need to &lt;a href=&quot;http://shiflett.org/articles/input-filtering&quot;&gt;filter input&lt;/a&gt;, And in
general you should beware of $_REQUEST, since it can also contain cookie data.
&lt;/p&gt;
   </description>
   <link>http://www.reiersol.com/blog/1_php_in_action/archive/172_the_one-line_web_framework.html</link>
   <comments>http://www.reiersol.com/blog/1_php_in_action/archive/172_the_one-line_web_framework.html</comments>
   <guid>http://www.reiersol.com/blog/1_php_in_action/archive/172_the_one-line_web_framework.html</guid>
      <dc:creator>dagfinn</dc:creator>
      
    <category>Application design</category>
      
    <category>PHP</category>
      
    <category>Frameworks</category>
         <pubDate>Sun, 14 Dec 2008 05:53:49 -0800</pubDate>
   <source url="http://www.reiersol.com/blog/1_php_in_action/feeds/rss20">PHP in Action</source>
     </item>
    <item>
   <title>How to test everything</title>
   <description>
    &lt;p&gt;
They say there&#039;s no free lunch, but at least there&#039;s free breakfast. Last week I
attended a &quot;breakfast seminar&quot; with Robert C.
Martin (Uncle Bob). There really was free food.
&lt;/p&gt;
&lt;p&gt;
Anyway, Uncle Bob held an extremely entertaining and useful introduction to
the &lt;a href=&quot;http://fitnesse.org/&quot;&gt;FitNesse&lt;/a&gt; testing tool. He got me
hooked on it, but I&#039;m even more fascinated by something else. I asked him,
&quot;what is the nature of the test API [you&#039;ve been talking about]?&quot; He
answered that question, and also another, more general one: What is a good
strategy for complete automated integration and acceptance testing of an
application? That was the question I really wanted to ask, only I wasn&#039;t
quite aware that I wanted to ask it. And, impressively, he answered it anyway.
&lt;/p&gt;



&lt;p&gt;
As I understood it, the strategy he outlined was as follows.
The diagram is probably only a mild perversion of the one he drew on the blackboard.
&lt;/p&gt;
&lt;img style=&quot;margin: 5px;&quot; alt=&quot;&quot; src=&quot;http://www.reiersol.com/blog/gallery/1/totaltest.jpg&quot; /&gt;



&lt;ul&gt;
  &lt;li&gt;Test all features through a test API just underneath the user
  inteface. These are the main acceptance tests; the ones that are used to
  decide whether a feature is &lt;b&gt;done&lt;/b&gt; or not done yet.&lt;/li&gt;
  &lt;li&gt;Test the user interface in isolation, running calls to a fake system underneath.&lt;/li&gt;
  &lt;li&gt;Run just a &lt;i&gt;few&lt;/i&gt; tests all the way through the application to
  test the plumbing between the user interface and the rest of the
  system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
The reason why we don&#039;t want all our acceptance tests to go through the
user interface is that the user interface has a tendency to change often,
and changes in the user interface tend to breaks lots of tests.
&lt;/p&gt;
&lt;p&gt;
This resonates reasonably well with my experience, although I think testing &quot;everything&quot; through the user
interface can work sometimes, if the user interface is a very plain one.
&lt;/p&gt;
&lt;p&gt;
In addition, we want unit tests for each small piece of the application. The tests
outlined above are just catch the few bugs that are not detected by the
unit tests.
&lt;/p&gt;
   </description>
   <link>http://www.reiersol.com/blog/1_php_in_action/archive/171_how_to_test_everything.html</link>
   <comments>http://www.reiersol.com/blog/1_php_in_action/archive/171_how_to_test_everything.html</comments>
   <guid>http://www.reiersol.com/blog/1_php_in_action/archive/171_how_to_test_everything.html</guid>
      <dc:creator>dagfinn</dc:creator>
      
    <category>Application design</category>
      
    <category>Testing</category>
      
    <category>PHP</category>
         <pubDate>Thu, 27 Nov 2008 14:19:04 -0800</pubDate>
   <source url="http://www.reiersol.com/blog/1_php_in_action/feeds/rss20">PHP in Action</source>
     </item>
    <item>
   <title>Zend_Test</title>
   <description>
    &lt;p&gt;
I admit I don&#039;t follow Zend Framework very closely, since I haven&#039;t been using it for any serious work.
But I did write a piece about &lt;a href=&quot;http://www.reiersol.com/blog/1_php_in_action/archive/70_testing_a_zend_framework_action_controller_with_view_helpers.html&quot;&gt;testing a Zend Framework action controller with View Helpers&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
This might need updating, since the testing capabilities of the Zend Framework have grown substantially since then. In particular, there is now a component called &lt;a href=&quot;http://framework.zend.com/manual/en/zend.test.html&quot;&gt;Zend_Test&lt;/a&gt;. I haven&#039;t had time to study it closely yet, but I hope to do so soon.
&lt;/p&gt;
   </description>
   <link>http://www.reiersol.com/blog/1_php_in_action/archive/170_zend_test.html</link>
   <comments>http://www.reiersol.com/blog/1_php_in_action/archive/170_zend_test.html</comments>
   <guid>http://www.reiersol.com/blog/1_php_in_action/archive/170_zend_test.html</guid>
      <dc:creator>dagfinn</dc:creator>
      
    <category>Testing</category>
      
    <category>PHP</category>
      
    <category>Frameworks</category>
         <pubDate>Tue, 18 Nov 2008 14:45:54 -0800</pubDate>
   <source url="http://www.reiersol.com/blog/1_php_in_action/feeds/rss20">PHP in Action</source>
     </item>
    <item>
   <title>More beautiful code</title>
   <description>
    &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;http://www.reiersol.com/blog/plugins/plogeshi/styles/plogeshi.css&quot; /&gt;&lt;p&gt;
I got some interesting comments to my previous post on &lt;a href=&quot;http://www.reiersol.com/blog/1_php_in_action/archive/168_beautiful_code.html&quot;&gt;&quot;beautiful code&quot;&lt;/a&gt;.
Some were pretty strong disagreements.
&lt;/p&gt;
&lt;p&gt;
So am I wrong? Did I get carried away? Did my critical faculty go on vacation somewhere nice and sunny? I admit that sometimes I deliberately
look at the positive and ignore the negative. (And sometimes I do the opposite; It&#039;s a good exercise if you&#039;re careful.)
&lt;/p&gt;
&lt;p&gt;
I wasn&#039;t drunk, anyway. But let me take a closer look at the particular line of code I was praising:
&lt;/p&gt;
&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;re1&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;assertThat&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;re1&quot;&gt;$form&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;hasSelect&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;withName&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;statusConfirm&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;hasValues&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;,&lt;/span&gt;
    &lt;a href=&quot;http://www.php.net/array&quot;&gt;&lt;span class=&quot;kw3&quot;&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;Yes&#039;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;No&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;
&lt;p&gt;
&lt;p&gt;
My main point is that it&#039;s close to plain English. Not everyone agrees that that&#039;s a good thing, but I argue that
we&#039;re built (genetically wired, in fact) to understand natural languages, not program code. Therefore code should be easier to understand when
it approximates natural language and expression. And we&#039;re trying to create or approximate a Domain Specific Language (DSL), which should express exactly what&#039;s required for the domain and not the demands of the technical implementation.
&lt;/p&gt;
&lt;p&gt;
So for this experiment, let&#039;s translate this one into a (plain English sentence:
&lt;/p&gt;
&lt;p&gt;
Assert that Form (this particular one) has a select menu with the name &quot;statusConfirm&quot; and values &quot;yes&quot; and &quot;no&quot;
&lt;/p&gt;
&lt;p&gt;
Translating back into code, it might look more like this:
&lt;/p&gt;
&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;re1&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;assertThat&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;re1&quot;&gt;$form&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;hasSelect&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;withName&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;statusConfirm&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;andValues&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;yes&#039;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;no&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;
&lt;p&gt;
&lt;p&gt;
To me, this is even more natural than the other one. I think we&#039;ve gotten rid of some syntax that has to do with
implementation details rather than making the API simple to use.
&lt;/p&gt;
&lt;p&gt;
It also seems clear to me how this could be implemented. All of the method calls could be to an assertion object that would take all these various inputs and always return itself at the end of the method so you can chain the calls in what&#039;s known as a fluent interface.
&lt;/p&gt;
   </description>
   <link>http://www.reiersol.com/blog/1_php_in_action/archive/169_more_beautiful_code.html</link>
   <comments>http://www.reiersol.com/blog/1_php_in_action/archive/169_more_beautiful_code.html</comments>
   <guid>http://www.reiersol.com/blog/1_php_in_action/archive/169_more_beautiful_code.html</guid>
      <dc:creator>dagfinn</dc:creator>
      
    <category>Application design</category>
      
    <category>Testing</category>
      
    <category>PHP</category>
         <pubDate>Fri, 07 Nov 2008 20:34:42 -0800</pubDate>
   <source url="http://www.reiersol.com/blog/1_php_in_action/feeds/rss20">PHP in Action</source>
     </item>
    <item>
   <title>Beautiful code</title>
   <description>
    &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;http://www.reiersol.com/blog/plugins/plogeshi/styles/plogeshi.css&quot; /&gt;&lt;p&gt;
    Max Horwath has published his slides on &lt;a href=&quot;http://www.maxhorvath.com/2008/10/slide-for-ipc-session-on-making-selenium-test-writing-easier-using-a-dsl-online.html&quot;&gt;Making
      Selenium Test Writing easier using a DSL online&lt;/a&gt;from &lt;a href=&quot;http://it-republik.de/php/phpconference/&quot;&gt;IPC 2008&lt;/a&gt;. Let me
    quote the whole short description:
    &lt;/p&gt;
&lt;blockquote&gt;
Implementing automated tests by using Seleniums API methods has several
drawbacks. Selenium is great for what it does, providing a generic framework
for testing a generic application. Using the Testing_SeleniumDSL framework, I
will show you how to create your own Domain Specific Language (DSL), which
would allow you to write tests in the language of your business rather than in
Seleniums language. 
&lt;/blockquote&gt;
&lt;p&gt;
I&#039;m quite impressed by the examples he presents, such as:
&lt;/p&gt;
&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;re1&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;assertThat&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;re1&quot;&gt;$form&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;hasSelect&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;withName&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;statusConfirm&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;hasValues&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;,&lt;/span&gt;
    &lt;a href=&quot;http://www.php.net/array&quot;&gt;&lt;span class=&quot;kw3&quot;&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;Yes&#039;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;No&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;
&lt;p&gt;
&lt;p&gt;
This is truly expressive, readable code. I&#039;ve refactored web test code in this direction many times, but I admit I 
never got quite this far.
&lt;/p&gt;
&lt;p&gt;

The DSL is planned as an open source release. It would be interesting to try something 
similar for the SimpleTest web tester, which is my favorite for testing web interfaces without too much JavaScript.
(Based on &lt;a href=&quot;http://www.reiersol.com/blog/1_php_in_action/archive/25_paparrazzi_testing.html&quot;&gt;the paparrazzi principle&lt;/a&gt;.)
&lt;/p&gt;
   </description>
   <link>http://www.reiersol.com/blog/1_php_in_action/archive/168_beautiful_code.html</link>
   <comments>http://www.reiersol.com/blog/1_php_in_action/archive/168_beautiful_code.html</comments>
   <guid>http://www.reiersol.com/blog/1_php_in_action/archive/168_beautiful_code.html</guid>
      <dc:creator>dagfinn</dc:creator>
      
    <category>Application design</category>
      
    <category>Testing</category>
      
    <category>PHP</category>
      
    <category>Refactoring</category>
         <pubDate>Mon, 03 Nov 2008 04:36:56 -0800</pubDate>
   <source url="http://www.reiersol.com/blog/1_php_in_action/feeds/rss20">PHP in Action</source>
     </item>
    <item>
   <title>Refactoring is design</title>
   <description>
    &lt;p&gt;
Refactoring is by definition a design actitivity, since the definition of
refactoring is &quot;improving the design of existing code&quot;. But is this generally
and fully recognized? After attending my friendly local agile conference
(&lt;a href=&quot;http://smidig.no/smidig2008/&quot;&gt;Smidig2008&lt;/a&gt;&amp;mdash;sorry, it&#039;s in Norwegian), I&#039;m getting more of a feel for how different people think about
it. And I&#039;m wondering whether the use of metaphors such as &quot;cleaning&quot; makes
refactoring seem too much like unskilled labor.  After all, physical cleaning
jobs are seen that way.
&lt;/p&gt;
&lt;p&gt;
The analogy between cleaning and refactoring is useful for making the
non-developers understand that refactoring is absolutely necessary. But beyond
this pragmatic similarity, are the two really similar in deep and meaningful
ways? I don&#039;t think so. Refactoring is not unskilled labor. It&#039;s a task that
both requires and builds design skill and experience.  While anyone can see
that a floor is dirty, identifying &lt;a href=&quot;http://en.wikipedia.org/wiki/Code_smell&quot;&gt;code smells&lt;/a&gt; is non-obvious, tricky and
demanding.  This is true even of the simplest code smell, duplicated code. Although spotting code duplication is sometimes easy, at other
times, the duplication is too subtle to be easily identifable.  When you clean
a floor, the goal is well-defined and easy to visualize. When refactoring, you
may know what you&#039;re aiming for at each small step, but just a few moves
further ahead you may end up with a structure you hadn&#039;t imagined.
&lt;/p&gt;
   </description>
   <link>http://www.reiersol.com/blog/1_php_in_action/archive/165_refactoring_is_design.html</link>
   <comments>http://www.reiersol.com/blog/1_php_in_action/archive/165_refactoring_is_design.html</comments>
   <guid>http://www.reiersol.com/blog/1_php_in_action/archive/165_refactoring_is_design.html</guid>
      <dc:creator>dagfinn</dc:creator>
      
    <category>Application design</category>
      
    <category>PHP</category>
      
    <category>Ruby</category>
      
    <category>Java</category>
      
    <category>Refactoring</category>
      
    <category>Smidig2008</category>
         <pubDate>Sat, 11 Oct 2008 14:41:24 -0700</pubDate>
   <source url="http://www.reiersol.com/blog/1_php_in_action/feeds/rss20">PHP in Action</source>
     </item>
    <item>
   <title>Get links with XPath</title>
   <description>
    &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;http://www.reiersol.com/blog/plugins/plogeshi/styles/plogeshi.css&quot; /&gt;&lt;p&gt;
There&#039;s a tutorial that appeared recently called &lt;a href=&quot;http://www.phpro.org/examples/Get-Links-With-DOM.html&quot;&gt;Get Links With DOM&lt;/a&gt;. Planet PHP lists the author as Kevin Waterson, although his name is not mentioned on the page itself. Anyway, he claims:
&lt;/p&gt;
&lt;blockquote&gt;
Perhaps the biggest mistake people make when trying to get URLs or link text from a web page is trying to do it using regular expressions. The job can be done with regular expressions, however, there is a high overhead in having preg loop over the entire document many times. The correct way, and the faster, and infinitely cooler ways is to use DOM. 
&lt;/blockquote&gt;
&lt;p&gt;
Yes, of course it&#039;s cooler. But I&#039;m a little bit surprised at the claim that it&#039;s the &quot;correct&quot; (only) way, since there&#039;s at least one more that I find even cooler: XPath. Admittedly, it&#039;s slower, yet it&#039;s a more powerful language.
&lt;/p&gt;
&lt;p&gt;
In his example, we just need to add a line to create an XPath object after we&#039;ve created the DOM object:
&lt;/p&gt;
&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;re1&quot;&gt;$xpath&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw2&quot;&gt;new&lt;/span&gt; DOMXpath&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;re1&quot;&gt;$dom&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;
&lt;p&gt;
&lt;p&gt;
Then, instead of the DOM call:
&lt;/p&gt;
&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;/*** get the links from the HTML ***/&lt;/span&gt;
&lt;span class=&quot;re1&quot;&gt;$links&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;re1&quot;&gt;$dom&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;a&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;
&lt;p&gt;
&lt;p&gt;
we can use an XPath query:
&lt;/p&gt;
&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;/*** get the links from the HTML ***/&lt;/span&gt;
&lt;span class=&quot;re1&quot;&gt;$links&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;re1&quot;&gt;$xpath&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;//a&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;
&lt;p&gt;
&lt;p&gt;
That&#039;s all. So why is that cooler? Because you can do more powerful searches easily. The DOM just happens to have a simple call to find all elements with a certain tag name, so there&#039;s not much difference in this case. But more complex stuff is something else. For instance, we can get just the URLs with a single expression:
&lt;/p&gt;
&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;re1&quot;&gt;$links&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;re1&quot;&gt;$xpath&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;//a/@href&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;
&lt;p&gt;
&lt;p&gt;
Or we can get just the URLs of just the links whose CSS class is &quot;bookmark&quot;:
&lt;/p&gt;
&lt;/p&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;re1&quot;&gt;$links&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;re1&quot;&gt;$xpath&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;me1&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;//a[@class=&#039;bookmark&#039;]/@href&amp;quot;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;
&lt;p&gt;
&lt;p&gt;
I&#039;ve been using this for ages when testing web pages. Then there&#039;s the not quite official SimpleTest DOM tester, which uses CSS selectors to specify paths. But I won&#039;t go into that right now.
&lt;/p&gt;
   </description>
   <link>http://www.reiersol.com/blog/1_php_in_action/archive/162_get_links_with_xpath.html</link>
   <comments>http://www.reiersol.com/blog/1_php_in_action/archive/162_get_links_with_xpath.html</comments>
   <guid>http://www.reiersol.com/blog/1_php_in_action/archive/162_get_links_with_xpath.html</guid>
      <dc:creator>dagfinn</dc:creator>
      
    <category>PHP</category>
         <pubDate>Mon, 06 Oct 2008 12:53:11 -0700</pubDate>
   <source url="http://www.reiersol.com/blog/1_php_in_action/feeds/rss20">PHP in Action</source>
     </item>
   </channel>
</rss>