<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Object Mentor Blog: Fudge anyone?</title>
    <link>http://blog.objectmentor.com/articles/2008/12/31/fudge-anyone</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description></description>
    <item>
      <title>Fudge anyone?</title>
      <description>&lt;p&gt;Back in September, when I was just staring the &lt;a href="http://fitnesse.org/FitNesse.TestSystems"&gt;Slim&lt;/a&gt; project, I made a crucial architectural decision.  I made it dead wrong.  And then life turned to fudge&amp;#8230;&lt;/p&gt;


	&lt;p&gt;The issue was simple.  Slim tables are, well, tables just like Fit tables are.  How should I parse these tables?  Fit parses &lt;span class="caps"&gt;HTML&lt;/span&gt;.  FitNesse parses wiki text &lt;em&gt;into&lt;/em&gt; HTML and delivers it to Fit.  Where should Slim fit in all of this?&lt;/p&gt;


	&lt;p&gt;Keep in mind that Fit &lt;em&gt;must&lt;/em&gt; parse &lt;span class="caps"&gt;HTML&lt;/span&gt; since it lives on the far side of the FitNesse/SUT boundary.  Fit doesn&amp;#8217;t have access to wiki text.  Slim tables, on the other hand, live on the &lt;em&gt;near&lt;/em&gt; side of the FitNesse/SUT boundary, and so have full access to wiki text, and the built in parsers that parse that text.&lt;/p&gt;


	&lt;p&gt;So it seemed to me that I had two options.&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Follow the example of Fit and parse wiki text into &lt;span class="caps"&gt;HTML&lt;/span&gt;, and then have the Slim Tables parse the &lt;span class="caps"&gt;HTML&lt;/span&gt; in order to process the tables.  &lt;/li&gt;
		&lt;li&gt;Take advantage of the built in wiki text parser inside of FitNesse and bypass &lt;span class="caps"&gt;HTML&lt;/span&gt; altogether.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;I chose the latter of the two because the Parsing system of FitNesse is &lt;em&gt;trivial&lt;/em&gt; to use.  You just hand it a string of wiki text, and it hands you a nice little parse tree of wiki widgets.  All I had to do was walk that parse three and process my tables.  Voila!&lt;/p&gt;


	&lt;p&gt;This worked great!  In a matter of hours I was making significant progress on processing Slim decision tables.  Instead of worrying about parsing &lt;span class="caps"&gt;HTML&lt;/span&gt; and building my own parse tree, I could focus on the problems of translating tables into Slim directives and then using the return values from Slim to colorize the table.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;Generating&lt;/em&gt; html was no problem since that&amp;#8217;s what FitNesse does anyway.  All I had to do was modify the elements of the parse tree and then simply tell the tree to convert itself to &lt;span class="caps"&gt;HTML&lt;/span&gt;.  What a dream.&lt;/p&gt;


	&lt;p&gt;Or so it seemed.  Although things started well, progress started to slow before the week was out.  The problem was that the FitNesse parser is &lt;em&gt;tuned&lt;/em&gt; to the esoteric needs of FitNesse.  The parser makes choices that are perfectly fine if your goal is to generate &lt;span class="caps"&gt;HTML&lt;/span&gt; and pass it to Fit, but that aren&amp;#8217;t quite so nice when you&amp;#8217;re goal is to use the parse tree to process Slim tables.  As a simple example, consider the problem of literals.&lt;/p&gt;


	&lt;p&gt;In FitNesse, any camel case phrase fits the pattern of a wiki word and will be turned into a wiki link.  Sometimes, though, you want to use a camel case phrase and you &lt;em&gt;don&amp;#8217;t&lt;/em&gt; want it converted to a link.  In that case you surround the phrase with literal marks as follows: &lt;code&gt;!- FitNesse-!&lt;/code&gt;.  Anything between literal marks is simply ignored by the parser and passed through to the end.&lt;/p&gt;


	&lt;p&gt;Indeed, things inside of literals are not even escaped for html!  If you put &lt;code&gt;&amp;lt;b&amp;gt;hi&amp;lt;/b&amp;gt;&lt;/code&gt; into a wiki page, it will escape the text you&amp;#8217;ll see &lt;code&gt;&amp;lt;b&amp;gt;hi&amp;lt;/b&amp;gt;&lt;/code&gt; on the screen instead of a bold &amp;#8220;hi&amp;#8221;.  On the other hand, if you put &lt;code&gt;!- &amp;lt;b&amp;gt;hi&amp;lt;/b&amp;gt;-!&lt;/code&gt; on a page, then the &lt;span class="caps"&gt;HTML&lt;/span&gt; is left unescaped and a boldfaced &amp;#8220;hi&amp;#8221; &lt;em&gt;will&lt;/em&gt; appear on the screen.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m telling you all of this because the devil is in the details&amp;#8212;so bear with me a bit longer.&lt;/p&gt;


	&lt;p&gt;You know how the C and C++ languages have a preprocessor?  This preprocessor handles all the &lt;code&gt;#include&lt;/code&gt; and &lt;code&gt;#define&lt;/code&gt; statements and then hands the resulting text off to the true compiler.  Well, the wiki parser works the same way!  Literals and &lt;code&gt;!define&lt;/code&gt; variables are processed first, by a different pass of the parser.  Then all the rest of the wiki widgets are parsed by the true parser.  The reason that we had to do this is even more devilishly detailed; so I&amp;#8217;ll spare you.  Suffice it to say that the reasons we need that preprocessor are similar to the reasons that C and C++ need it.&lt;/p&gt;


	&lt;p&gt;What does the preprocessor do with a literal?  It converts it into a special widget.  That widget looks like this: &lt;code&gt;!lit?23?&lt;/code&gt;  What does that mean?  It means replace me with the contents of literal #23.  You see, when FitNesse sees &lt;code&gt;!- FitNesse-!&lt;/code&gt; it replaces it with &lt;code&gt;!lit?nn?&lt;/code&gt; and squirrels &lt;code&gt;FitNesse&lt;/code&gt; away in literal slot &lt;em&gt;nn&lt;/em&gt;.  During the second pass, that &lt;code&gt;!lit?nn?&lt;/code&gt; is replaced with the contents of literal slot &lt;em&gt;nn&lt;/em&gt;.  Simple, right?&lt;/p&gt;


	&lt;p&gt;OK, now back to &lt;span class="caps"&gt;SLIM&lt;/span&gt; table processing.  There I was, in Norway, teaching a class during the day and coding Slim at night, and everything was going just great.  And then, during one of my tests, I happened to put a literal into one of the test tables.  This is perfectly normal, I didn&amp;#8217;t want some camel case phrase turned into a link.  But this perfectly normal gesture made a unit test fail for a very strange reason.  I got this wonderful message from junit: &lt;code&gt;expected MyPage but was !lit?3?&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;I knew exactly what this meant.  It meant that the value &lt;code&gt;MyPage&lt;/code&gt; had been squirreled away by the first pass of the parser.  I also knew that I had utterly no reasonable way of getting at it.  So I did the only thing any sane programmer would do.  I wrote my own preprocessor and used it instead of the standard one.  This was &amp;#8220;safe&amp;#8221; since in the end I simply reconvert all the colorized tables back into wiki text and let the normal parser render it into &lt;span class="caps"&gt;HTML&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;It was a bit of work, but I got it done at one am on a cold Norwegian night.  Tests passing, everything great!&lt;/p&gt;


	&lt;p&gt;Ah, but no.  By writing my own preprocessor, I broke the &lt;code&gt;!define&lt;/code&gt; variable processing &amp;#8211; subtly.  And when I found and fixed that I had re-broken literal processing &amp;#8211; subtly.&lt;/p&gt;


	&lt;p&gt;If you were following my tweets at the time you saw me twitter ever more frantically about literals.  It was the proverbial ball of Mercury.  Every time I put my thumb on it&lt;sup&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt; it would squirt away and take some new form.&lt;/p&gt;


	&lt;p&gt;I fell into a trap.  I call it the &lt;em&gt;fudge trap&lt;/em&gt;.  It goes like this:&lt;/p&gt;


	&lt;p style="text-align:center;"&gt;&lt;span style="color:chocolate;"&gt;&lt;code&gt;forever do {&lt;/code&gt;&amp;#8220;I can make this work!  Just one more little fudge right &lt;em&gt;here&lt;/em&gt;!&amp;#8221;&lt;code&gt;}&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;


	&lt;p&gt;I was in this trap for two months!  I was making progress, and getting lots of new features to work, but I was also running into strange little quirks and unexpected bizarre behaviors caused by the fudging I was doing.  So I&amp;#8217;d fudge a little more and then keep working.  But each little fudge added to the next until, eventually, I had a really nasty house of cards (or rather: pile of fudge) ready to topple every time I touched anything else.  I started to fear my own code&lt;sup&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt;.  It was time to stop!&lt;/p&gt;


	&lt;p&gt;I knew what I had to do.  I had to go back to my original architectural decision and make it the other way.  There was no escape from this.  The FitNesse parser was too coupled to the wiki-ness, and there was no sane way to repurpose it for test table processing.&lt;/p&gt;


	&lt;p&gt;I dreaded this.  It was such a big change.  I had built so much code in my house of fudge.  All of it would have to be changed or deleted.  And, worse, I needed to write an &lt;span class="caps"&gt;HTML&lt;/span&gt; parser.&lt;/p&gt;


	&lt;p&gt;I was lamenting to &lt;a href="http://www.8thlight.com/main"&gt;Micah&lt;/a&gt; about this one day in late November, and he said: &amp;#8220;Dad, there are &lt;span class="caps"&gt;HTML&lt;/span&gt; parsers out there you know.&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;Uh&amp;#8230;&lt;/p&gt;


	&lt;p&gt;So I went to google and typed &lt;code&gt;Html Parser&lt;/code&gt;.  Duh.  There they were.  Lots and lots of shiny &lt;span class="caps"&gt;HTML&lt;/span&gt; parsers free for the using.&lt;/p&gt;


	&lt;p&gt;I picked &lt;a href="http://htmlparser.sourceforge.net"&gt;one&lt;/a&gt; and started to fiddle with it.  It was &lt;em&gt;easy&lt;/em&gt; to use.&lt;/p&gt;


	&lt;p&gt;Now comes the good part.  I had not been a complete dolt.  Even when I was using the FitNesse parse tree, I ate my own dogfood and &lt;em&gt;wrapped&lt;/em&gt; it in an abstract interface.  No part of the Slim Table processing code actually &lt;em&gt;knew&lt;/em&gt; that it was dealing with a FitNesse parse tree.  It simply used the abstract interface to get its work done.&lt;/p&gt;


	&lt;p&gt;That meant that pulling out the wiki parser and putting in the &lt;span class="caps"&gt;HTML&lt;/span&gt; parser was a matter of re-implementing the abstract interface with the output of the new parser (which happened to be another parse tree!).  This took me about a day.&lt;/p&gt;


	&lt;p&gt;There came a magic moment when I had &lt;em&gt;both&lt;/em&gt; the wiki text version of the parser, and the &lt;span class="caps"&gt;HTML&lt;/span&gt; version of the parser working.  I could switch back and forth between the two by changing one word in one module.  When I got &lt;em&gt;all&lt;/em&gt; my tests passing with &lt;em&gt;both&lt;/em&gt; parsers, I knew I was done.  And then the fun &lt;em&gt;really&lt;/em&gt; began!&lt;/p&gt;


	&lt;p&gt;I &lt;span style="color:red;"&gt;&lt;em&gt;deleted&lt;/em&gt;&lt;/span&gt; ever stitch of that wiki parse tree pile of fudge.  I tore it loose and rent it asunder.  It was gone, never to darken my door with it&amp;#8217;s fudge again.&lt;/p&gt;


	&lt;p&gt;It took me a day.  A day.  And the result is 400 fewer lines of code, and a set of Slim tables that actually work the way they are supposed to.&lt;/p&gt;


	&lt;p&gt;Moral #1: &amp;#8220;Fudge tastes good while you are eating it, but it makes you fat, slow, and dumb.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;Moral #2: &amp;#8220;Eat the damned dog food. It&amp;#8217;ll save your posterior from your own maladroit decisions.&lt;/p&gt;


	&lt;p id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt; I do not recommend that you actually put your thumb on any Mercury.  Never mind that I used to play with liquid Mercury as a child, sloshing it around from hand to hand and endlessly stirring it with my finger.  Wiser heads than I have determined that merely being in the same room with liquid Mercury can cause severe brain damage, genetic corruption, and birth defects in your children, grandchildren, and pets.&lt;/p&gt;


	&lt;p id="fn2"&gt;&lt;sup&gt;2&lt;/sup&gt; Fearing your own code is an indicator that you are headed for ruin.  This fear is followed by self-loathing, project-loathing, career-loathing, divorce, infanticide, and finally chicken farming.&lt;/p&gt;</description>
      <pubDate>Wed, 31 Dec 2008 16:01:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:36578e35-eb79-4c39-bb15-e36e3acf4548</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2008/12/31/fudge-anyone</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>"Fudge anyone?" by brand clothing</title>
      <description>&lt;p&gt;I sometimes irritate people I&#8217;m pairing with because I&#8217;m too eager to jump to something&lt;/p&gt;</description>
      <pubDate>Sun, 27 Dec 2009 23:11:21 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:3477e9bc-101b-4ee4-b0a5-23a73fc3c29f</guid>
      <link>http://blog.objectmentor.com/articles/2008/12/31/fudge-anyone#comment-6335</link>
    </item>
    <item>
      <title>"Fudge anyone?" by long term drug rehabs</title>
      <description>&lt;p&gt;This was a great post. I think that I will be able to use this in getting a more widespread focus on drug addiction and rehab. Thank you for sharing this information.&lt;/p&gt;</description>
      <pubDate>Tue, 27 Oct 2009 14:43:59 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:f4c54018-02dc-444d-b421-bf970f2719b9</guid>
      <link>http://blog.objectmentor.com/articles/2008/12/31/fudge-anyone#comment-4905</link>
    </item>
    <item>
      <title>"Fudge anyone?" by ed hardy</title>
      <description>&lt;p&gt;Haha, I&#8217;m eager to jump to something else when the current tack isn&#8217;t working &amp;#8230;&lt;/p&gt;</description>
      <pubDate>Mon, 28 Sep 2009 10:22:02 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:35fd5c93-0f89-45e2-b237-582a29cfd17d</guid>
      <link>http://blog.objectmentor.com/articles/2008/12/31/fudge-anyone#comment-4277</link>
    </item>
    <item>
      <title>"Fudge anyone?" by Markus G&#228;rtner</title>
      <description>&lt;p&gt;I&amp;#8217;m currently counting how many times during the last year I fell into this pitfall. Interesting to get to know, that there are people out there trapping in the same traps as me.&lt;/p&gt;</description>
      <pubDate>Thu, 01 Jan 2009 18:07:50 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:9793c4b5-1f63-457d-9499-67f0fa535777</guid>
      <link>http://blog.objectmentor.com/articles/2008/12/31/fudge-anyone#comment-2307</link>
    </item>
    <item>
      <title>"Fudge anyone?" by Luis Sergio Oliveira</title>
      <description>&lt;p&gt;I had &lt;a href="http://argonauts-life.blogspot.com/2008/04/resolving-and-persisting-profile.html" rel="nofollow"&gt;a similar experience this year&lt;/a&gt;. So much work wasted, at least it was good to learn from it.&lt;/p&gt;</description>
      <pubDate>Thu, 01 Jan 2009 02:00:23 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:a8111ad5-ee49-43fb-bd8f-e5a56c3dab1a</guid>
      <link>http://blog.objectmentor.com/articles/2008/12/31/fudge-anyone#comment-2306</link>
    </item>
    <item>
      <title>"Fudge anyone?" by Fred Losi</title>
      <description>&lt;p&gt;Great blathering; I always enjoy your insights on our craft, Uncle Bob.&lt;/p&gt;


	&lt;p&gt;I learned about the new blog entry by viewing your Twitter content.  Thanks for your updates there.&lt;/p&gt;</description>
      <pubDate>Wed, 31 Dec 2008 22:09:11 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:33514e89-7acb-4286-9ff9-eac26c799570</guid>
      <link>http://blog.objectmentor.com/articles/2008/12/31/fudge-anyone#comment-2305</link>
    </item>
    <item>
      <title>"Fudge anyone?" by Curtis Cooley</title>
      <description>&lt;p&gt;Wow, this entry has the highest lesson density (lessons per word) that I ever read. So many good things to learn from this experiment. Thanks Uncle Bob!&lt;/p&gt;


	&lt;p&gt;And you playing with liquid mercury as a kid explains soooo many things ;)&lt;/p&gt;</description>
      <pubDate>Wed, 31 Dec 2008 17:36:59 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:016ec302-bead-4936-9280-d91880c12577</guid>
      <link>http://blog.objectmentor.com/articles/2008/12/31/fudge-anyone#comment-2303</link>
    </item>
    <item>
      <title>"Fudge anyone?" by MichaelFeathers</title>
      <description>&lt;p&gt;It sounds like the classic &amp;#8216;good money after bad&amp;#8217; scenario.  If anything, I sometimes irritate people I&amp;#8217;m pairing with because I&amp;#8217;m too eager to jump to something else when the current tack isn&amp;#8217;t working.&lt;/p&gt;</description>
      <pubDate>Wed, 31 Dec 2008 17:05:54 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:7221cf18-687b-4e8b-a89c-a0b5627ecf63</guid>
      <link>http://blog.objectmentor.com/articles/2008/12/31/fudge-anyone#comment-2302</link>
    </item>
  </channel>
</rss>
