Just A Summary : Category the-practice-of-programming, everything about the-practice-of-programming http://www.bofh.org.uk/articles/category/the-practice-of-programming.rss en-us 40 Piers Cawley Practices Punditry A quick Javascript formatting tip <p>IE&#8217;s a pain. The particular pain I want to write about is its pickiness about Javascript object literals. Consider the following Javascript object:</p> <div class="typocode"><pre><code class="typocode_default ">{ success: function () {...}, failure: function () {...}, }</code></pre></div> <p>If you&#8217;re used to programming in Perl or Ruby, that trailing comma&#8217;s perfectly fine, in fact leaving it there is sometimes considered good practice because it makes it easy to extend the hash, just add a new row and leave another trailing comma.</p> <p>The trouble is, it&#8217;s not strictly legal to do that in Javascript. Pretty much every implementation out there will allow it though.</p> <p>Except IE.</p> <p>So, I&#8217;ve taken a leaf out of Damian Conways <cite>Perl Best Practices</cite> and writing my object literals as:</p> <div class="typocode"><pre><code class="typocode_default ">{ success: function () {...} , failure: function () {...} }</code></pre></div> <p>By sticking the comma at the beginning of the line, I&#8217;m never going to make an object that breaks IE, and adding a new line to the hash is straightforward too. Just stick the cursor in front of the <code>}</code>, type my leading comma, space, attribute name, and hit return when I&#8217;m finished.</p> <p>I&#8217;ve also started using the same practice pretty much everywhere else that I&#8217;ve got a comma separated list of things:</p> <div class="typocode"><pre><code class="typocode_default ">var foo , bar , baz ; $.each( anArray , function () { ... } );</code></pre></div> <p>It looks weird at first, but trust me, it grows on you.</p> <h3>Update</h3> <p>In the comments, I make reference to tweaking Steve Yegge&#8217;s excellent <a href="http://code.google.com/p/js2-mode/">js2-mode</a> to handle leading comma style a little more gracefully. Since then, I&#8217;ve made it work and attached a diff to <a href="http://code.google.com/p/js2-mode/issues/detail?id=64">this issue</a> on the project&#8217;s issue tracker.</p> Wed, 16 Apr 2008 04:01:00 -0500 urn:uuid:43c91868-fede-47d2-8f9b-14fdce6dee88 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2008/04/16/a-quick-javascript-formatting-tip#comments The Practice of Programming javascript formatting tips http://www.bofh.org.uk/articles/2008/04/16/a-quick-javascript-formatting-tip Code is data, and it always has been <p>I&#8217;m just back from the first <a href="http://www.scotlandonrails.com">Scotland on Rails</a> conference, and a jolly fine conference it was too. Much kudos is due to <a href="http://www.alancfrancis.com">Alan</a>, <a href="http://woss.name">Graeme</a>, Abdel and <a href="http://merecomplexities.com/">Paul</a>. It was hard to believe that this was the first conference these guys have run and I think all my fellow delegates hope it won&#8217;t be the last. As I said in the Pub on Saturday night, I&#8217;d had a talk proposal knocked back and, in that situation, it&#8217;s terribly easy to find yourself sitting in a session thinking &#8220;Bloody hell, my talk would have been better than this!&#8221;, but not at this conference.</p> <p>A phrase that cropped up a couple of times was the old saw that &#8220;Data == Code&#8221; &#8211; it&#8217;s very hard to avoid the idea once you start talking about code generation or Domain Specific Pidgins, parsing&#8230; I first came across the idea in <a href="http://www.amazon.co.uk/exec/obidos/ASIN/0262510871/justasummary-21">The Structure And Interpretation of Computer Programs</a> where it&#8217;s elegantly phrased as &#8220;Data is just dumb code, and code is just smart data&#8221;. Traditionally, the idea seems to be attributed to <a href="http://en.wikipedia.org/wiki/John_McCarthy_%28computer_scientist%29">John McCarthy</a>, the inventor of Lisp. But it&#8217;s older than that. Way older than that. The idea is actually older than Computer Science. It lies at the core of <a href="http://en.wikipedia.org/wiki/Alan_Turing">Turing&#8217;s</a> original paper <a href="http://www.thocp.net/biographies/papers/turing_oncomputablenumbers_1936.pdf"><cite>On Computable Numbers, with an Application to the Entscheidungsproblem</cite></a> in which invents computer science on the way to proving that it&#8217;s impossible to decide algorithmically whether a given statement of arithmetic is true or false.</p> <p>In the course of the paper, Turing posits what has become known as the Halting Problem:</p> <blockquote> <p>Given a description of a program and a finite input, decide whether the program finishes running or will run forever, given that input.</p> </blockquote> <p>Turing&#8217;s proof runs something like this:</p> <p>Suppose we have a subroutine <code>halts?(code,data)</code> which solves the halting problem. Let&#8217;s use that to write something like:</p> <div class="typocode"><pre><code class="typocode_default ">def counter_example(code) if halts? code, code for (;;) end else return end end counter_example(File.read(STDIN))</code></pre></div> <p>and ask the question &#8220;What happens when we run <code>counter_example.rb &lt; counter_example.rb</code>&#8221;? If <code>halts?</code> reckons that <code>counter_example</code> would halt, given itself as input, then counter example will enter an infinite loop, but if <code>halts?</code> reckon that it would enter an infinite loop, then it would halt. Which is a contradiction. Which means that there can be no subroutine <code>halts?</code>, which means that maths is hard enough to be interesting and occasionally undecidable.</p> <p>Look at how the proof works &#8211; it&#8217;s built around the idea that code can be treated as data. In fact, you could say that the Turing Machine looks like it does because Turing was working backwards from this core idea to describe a sufficiently powerful machine that could obviously treat it&#8217;s own description as data. Certainly when you compare the clarity of his proof that the halting problem is undecidable (given the idea of the universal Turing machine) with the contortions required to make mathematics swallow its own tail in similar fashion so that Gödel could prove his Incompleteness Theorem.</p> <p>So, if you want to know who the idea that code is data is due to, the answer (as is so often the case in our field) is Turing.</p> <h3>Postscript</h3> <p>Incidentally, Turing is also responsible for the first ever bug &#8211; his original implementation of a Universal Turing Machine has a couple, one of which is probably a dumb typo (which even I could spot when I read the paper). Another is more subtle, but still fixable. Somewhat delightfully, a young grad student, (<a href="http://en.wikipedia.org/wiki/Donald_Davies">Donald W Davies</a>, who invented packet switching) spotted these bugs and told Turing:</p> <blockquote> <p>I &#8230; found a number of quite bad programming errors, in effect, in the specification of the machine that he had written down, and I had worked out how to overcome these. I went along to tell him and I was rather cock-a-hoop &#8230; I thought he would say &#8216;Oh fine, I&#8217;ll send along an addendum. But in fact he was very annoyed, and pointed out furiously that really it didn&#8217;t matter, the thing was right in principle, and altogether I found him extremely touchy on this subject.</p> </blockquote> <p>Nearly fifty years later Davies wrote and published a debugged version of the code, which you can find in <a href="http://www.amazon.co.uk/exec/obidos/ASIN/0198250797/justasummary-21">The Essential Turing</a>. One lesson to draw from the above is that getting annoyed at people pointing out trivial bugs in example code is also at least as old as computer science. Rather splendidly, there&#8217;s also a story of the chap who wrote the first ever assembler getting a serious telling off from Turing because the computer&#8217;s time was too valuable to waste it on converting symbols into machine code when humans were perfectly capable of doing it themselves. Who knows, maybe Turing&#8217;s contention was actually true back in the days of the Manchester Baby&#8230;</p> Mon, 07 Apr 2008 00:12:00 -0500 urn:uuid:1f6a68ac-944e-48e0-8802-6568a221bf71 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2008/04/07/code-is-data-and-it-always-has-been#comments Musings The Practice of Programming scotlandonrails turing compsci codeisdata http://www.bofh.org.uk/articles/2008/04/07/code-is-data-and-it-always-has-been Javascript scoping makes my head hurt <p>Who came up with the javascript scoping rules? What were they smoking. Here&#8217;s some Noddy Perl that demonstrates what I&#8217;m on about:</p> <div class="typocode"><pre><code class="typocode_default ">my @subs; for my $i (0..4) { push @subs, sub { $i } } print $subs[0]-&gt;(); # =&gt; 0;</code></pre></div> <p>Here&#8217;s the equivalent (or what I thought should be the equivalent) in Javscript:</p> <div class="typocode"><pre><code class="typocode_default ">var subs = []; for (var i in [0,1,2,3,4]) { subs[i] = function () { return i; } } alert subs[0]() // =&gt; 4</code></pre></div> <p>What&#8217;s going on? In Perl, <code>$i</code> is scoped to the <code>for</code> block. Essentially, each time through the loop, a new variable is created, so the generated closures all refer to different <code>$i</code>s. In Javascript, <code>i</code> is scoped to the <code>for</code> loop&#8217;s containing function. Each of the generated closures refer to the same <code>i</code>. Which means that, to get the same effect as the perl code, you must write:</p> <div class="typocode"><pre><code class="typocode_default ">var subs = []; for (var shared_i in [0,1,2,3,4]) { (function (i) { subs[i] = function () { return i; }; })(shared_i); } subs[0]() // =&gt; 0</code></pre></div> <h3>Dodgy Ruby scoping</h3> <p>I had initially planned to write the example &#8220;How it should work&#8221; code in Ruby, but it turns out that Ruby&#8217;s <code>for</code> has the same problem:</p> <div class="typocode"><pre><code class="typocode_default ">subs = []; for i in 0..4 subs &lt;&lt; lambda { i } end subs[0].call # =&gt; 4</code></pre></div> <p>Which is one reason why sensible Ruby programmers don&#8217;t use <code>for</code>. If I were writing the snippet in &#8216;real&#8217; Ruby, I&#8217;d write:</p> <div class="typocode"><pre><code class="typocode_default ">subs = (0..4).collect { |i| lambda { i } } subs[0].call # =&gt; 0</code></pre></div> <h3>My conclusion</h3> <p>Javascript is weird. Okay, so you already know this. In so many ways it&#8217;s a lovely language, but it does have some annoyingly odd corners.</p> Thu, 20 Mar 2008 11:41:00 -0500 urn:uuid:ab821d04-fe0e-40c5-a96f-9f879eff05f2 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2008/03/20/javascript-scoping-makes-my-head-hurt#comments Musings The Practice of Programming javascript http://www.bofh.org.uk/articles/2008/03/20/javascript-scoping-makes-my-head-hurt Joined up thinking: why your resources want links <p>Remember the good old days? The days before Google? The days before Altavista? The days when a 14k4bps modem was fast? Did I say <em>good</em> old days?</p> <p>In those days, the web had to be discoverable &#8216;cos it sure as hell wasn&#8217;t searchable. The big, big enabling technology of the web was the humble <code>&lt;a href='http://somewhereelse.com'&gt;Go somewhere else&lt;/a&gt;</code>. Placing the links right there in the body of the document turned out to be exactly the right thing to do.</p> <p>And it continues to be the right thing to do. Consider the two pieces of <span class="caps">YAML</span> below the fold.</p> <p>Here&#8217;s something close to what I&#8217;ve been generating at work (We generate <span class="caps">JSON</span>, but <span class="caps">YAML</span>&#8217;s easier to write out by hand):</p> <pre><code> location: http://site/users/pdcawley/tunes/99 name: Bill Norrie creator: name: Piers Cawley location: http://site/users/pdcawley duration: 360 image: http://s3.amazonaws.com/... stream: http://s3.amazonaws.com/... </code></pre> <p>Here&#8217;s that same snippet, recast in the <span class="caps">URL</span> free style that&#8217;s common in &#8216;RESTful&#8217; APIs:</p> <pre><code> id: 99 name: Bill Norrie creator: name: Piers Cawley id: pdcawley duration: 360 image: http://s3.amazonaws.com/... stream: http://s3.amazonaws.com/... </code></pre> <p>Which of those would you rather have served up to your <span class="caps">API</span> client? Obviously, the one with the URLs because then your client has to know so much less. If resources carry links within their body they&#8217;re discoverable, just like anything else on the web. A client only needs to know about a few resource directories and maybe a mechanism for searching, and most of the rest should follow from the RESTful principles<sup><a href="#fn1">1</a></sup>.</p> <p>If you wanted to write a client to make use of resources in the second form, you&#8217;d need to know that a tune&#8217;s <span class="caps">URL</span> is of the form <tt>/users/<var>creator.id</var>/tunes/<var>tune_id</var></tt>, that user urls have the form <tt>/users/<var>creator.id</var></tt> and so on. You&#8217;d curse the <span class="caps">API</span> designer who designed that <span class="caps">URL</span> scheme. You&#8217;d curse again when, having written the Ruby <span class="caps">API</span>, you sat down to write the Javascript version (modern sites need their <span class="caps">AJAX</span>, right?) and had to teach it all about the <span class="caps">URL</span> scheme all over again.</p> <h3>Don&#8217;t Repeat Yourself</h3> <p>If there&#8217;s one thing worse than violating the <span class="caps">DRY</span> principle, it&#8217;s forcing other people to do it. Structuring your APIs representations around IDs rather than URIs is doing just that. The complexity that you dodge by punting <span class="caps">URL</span> generation to the user is multiplied by the number of <span class="caps">API</span> client implementations (and, arguably, the number of client that don&#8217;t get written &#8216;cos your <span class="caps">API</span>&#8217;s a <span class="caps">PITA</span>).</p> <p>It&#8217;s worse than that though. You already <em>have</em> the code for mapping between resources and URLs. If you&#8217;re using Ruby on Rails, your mapper is bidirectional too<sup><a href="#fn2">2</a></sup>. Generating URLs within your representations should be a snap<sup><a href="#fn3">3</a></sup>. So, what are you waiting for? Start writing Joined Up APIs.</p> <p id="fn1"><sup>1</sup> For values of &#8216;the rest&#8217; that are concerned with the how of the <span class="caps">API</span>. You&#8217;re still going to have to document the what and the why. You can get a long way down that road with careful use of <code>&lt;link rel="ServiceDoc" href="/servicedocs/model" /&gt;</code> though.</p> <p id="fn2"><sup>2</sup> Catch me in the right mood and I can rant for ages about the awfulness of RoR&#8217;s routing system, but the bidirectional nature of them trumps almost all my complaints. It&#8217;s like Jamie Zawinski&#8217;s line that <a href="http://www.jwz.org/doc/java.html">Java doesn&#8217;t have <code>free</code></a>. Everything else about the routing system can suck almost as hard as it likes, but two way routing is a win.</p> <p id="fn3"><sup>3</sup> Not quite the snap it could be in Rails because rails is of the opinion that <span class="caps">URL</span> generation is something the controller does. Which is fine as far as it goes until you find yourself writing <code>Tune#to_json</code> without a controller in sight and you can&#8217;t change <code>to_json</code>&#8217;s signature because it&#8217;s a standard method. And you just want to cry. <code>Model.include ActionController::UrlWriter</code> is wrong, but <em>so</em> tempting&#8230; In fact I&#8217;ve succumbed, just to get the test to pass. I&#8217;m in the process of refactoring by introducing a <code>UrlPolicy</code> singleton that will do all that stuff and at least isolate the bits where my models get to play like controllers.</p> Fri, 22 Feb 2008 02:26:00 -0600 urn:uuid:89042495-f6bb-4639-9d93-ab87c0262fd2 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2008/02/22/joined-up-thinking-why-your-resources-want-links#comments The Practice of Programming rest http://www.bofh.org.uk/articles/2008/02/22/joined-up-thinking-why-your-resources-want-links Martin Fowler's big mouthful <p>Martin Fowler is writing a book about <a href="http://martinfowler.com/dslwip/">Domain Specific Languages</a> and, because you could never accuse Martin of a lack of ambition, he&#8217;s trying to write it in a reasonably (implementation) language agnostic fashion.</p> <p>It&#8217;s fairly easy to write an implementation language agnostic book about old school DSLs, what used to be called little languages &#8211; there&#8217;s a fairly well established literature and theory to do with lexing, parsing and interpreting. These are all about algorithms, and algorithms are implementation language neutral by their very nature.</p> <p>Where Martin has his work cut out for him is trying to talk about what he calls &#8216;internal DSLs&#8217; and what I&#8217;ve been calling &#8216;pidgins&#8217;. These are the sorts of languages where you don&#8217;t write a lexer or parser but instead build a family of objects, methods, functions or whatever other bits and pieces your host language provides in order to create a part of your program that, while it is directly interpreted by the host language, feels like it&#8217;s written in some new dialect.</p> <p>The Lisp family of languages can be said to be all about this. A good &#8216;bottom up&#8217; lisp programmer will shape a language to fit the problem space, essentially building a new lisp which makes it easy to solve the problem at hand. Lisp&#8217;s minimal syntax, powerful macros and the way it blurs the boundary between code and data really support this style.</p> <p>Once you move from Lisp to more &#8216;syntaxy&#8217; languages, things get hairier. As Martin himself <a href="http://martinfowler.com/bliki/BookCode.html">says</a></p> <blockquote> <p>Another issue with book code is to beware of using obscure features of the language, where obscure means for my general reader rather than even someone fluent in the language I&#8217;m using. [...] this is much harder for a <span class="caps">DSL</span> book. Internal DSLs tend to rely on abusing the native syntax in order to get readability. Much of this abuse involves quirky corners of the language. Again I have to balance showing readable <span class="caps">DSL</span> code against wallowing in quirk.</p> </blockquote> <p>He&#8217;s dead right. When I&#8217;m thinking about writing a pidgin in Ruby for instance, my first thought is usually to start with some kind of tabula rasa object which I can use to <code>instance_eval</code> a block. That lets me start to shape my language by lexically scoping the change:</p> <pre><code> in_pidgin do ... end </code></pre> <p>But, though it&#8217;s easy to illustrate what I&#8217;d <em>do</em> with my tabula rasa, the implementation is somewhat tricky, and the tricks needed are unique to Ruby.</p> <p>That sort of construct&#8217;s not really available to someone trying to write a pidgin in Java or Perl. In Perl, there are other odd corners of the language that can be abused to good effect. Dynamic scoping can let you &#8216;inject&#8217; methods into a block even though there&#8217;s no Perl equivalent to <code>instance_eval</code>, or you can do some quite staggering things with the otherwise really annoying Perl function prototypes. For instance, here&#8217;s part of a <a href="http://jifty.org/">Jifty</a> definition of a persistent object:</p> <pre><code> column title =&gt; type is 'text', label is 'Title', default is 'Untitled post'; column body =&gt; type is 'text', label is 'Content', render_as 'Textarea'; </code></pre> <p>Doesn&#8217;t look much like Perl does it? But it&#8217;s parsed and executed by perl with no source filters or <code>eval STRING</code> in sight. And there&#8217;s no unsightly <code>:symbols</code> scattered about the place either come to that.</p> <p>These things all work by making the language do something unexpected, and generally, the way to do that is by knowing your host language inside out and playing with it. One of Damian Conway&#8217;s more inspired moments in recent years was <a href="http://search.cpan.org/~dconway/List-Maker-v0.0.3/lib/List/Maker.pm">List::Maker</a>, in which the good doctor managed to find a corner of Perl where he could wedge a proper old school, complete with full on parser to build the <span class="caps">AST</span>, Little Language right in the heart of Perl without it <em>looking</em> like he was taking a plain old string and interpreting it. So, having found this odd little corner, he proceeded to implement a remarkably neat tool for building complex lists that are beyond the capabilities of Perl&#8217;s <code>..</code> operator.</p> <pre><code> @odds = &lt;1..100 : N % 2 != 0 &gt;; @primes = &lt;3,5..99&gt; : is_prime(N) &gt;; @available = &lt;1..$max : !allocated{N} &gt; </code></pre> <p>You may not think that&#8217;s all that sexy, but, and trust me on this, it&#8217;s just <em>gorgeous</em>. Yet more proof that Damian Conway is an (evil) genius.</p> <p>Frankly, once you&#8217;ve seen the best of the pidgins available in Perl, some of highly praised &#8216;DSLs&#8217; in Ruby start to look a bit ordinary. Ruby makes a great deal of stuff that a pidgin breeder needs to do really easy. In Perl it&#8217;s often rather hard with a huge amount of hoopage to deal with. But some of the things that are hard in Perl are impossible in Ruby.</p> <p>Anyhoo&#8230; coming back to my point. I do find myself wondering if Martin&#8217;s bitten off more than he can chew in attempting to write a book that covers implementing pidgins without getting bogged down in the nitty gritty of individual languages. The problem he&#8217;s facing is that different languages don&#8217;t just have different quirks, they have different idioms too. What reads naturally in the context of a Ruby program will read very weirdly in, say Java or a lisp. Any patterns of implementation beyond broad (but important) strokes like &#8220;Play to your host language&#8217;s strengths&#8221; will surely end up as language specific patterns. Designing and implementing a good pidgin is <em>hard</em>. Doing it effectively means getting down and dirty with your host language and its runtime structures. And that&#8217;s not the sort of thing you can cover effectively in a language agnostic book.</p> <p>Martin, if you&#8217;re reading this, good luck. I think you&#8217;re going to need it. I look forward to being proved wrong.</p> Fri, 18 Jan 2008 17:19:00 -0600 urn:uuid:85fbce77-14bf-44e5-ac34-b61f925d54b0 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2008/01/18/martin-fowlers-big-mouthful#comments Musings The Practice of Programming pidgin http://www.bofh.org.uk/articles/2008/01/18/martin-fowlers-big-mouthful Getting to grips with Javascript <p>I&#8217;ve been busily adding <span class="caps">AJAX</span> features to the work website, and I got bored of writing Form handlers. I got especially bored of attaching similar form handlers to lots of different forms on a page, so I came up with something I could attach to <code>document.body</code> and then plug in handlers for different form types as I wrote them.</p> <p>So, I wrote <code>FormSender</code> and set up my event handler like so:</p> <div class="typocode"><pre><code class="typocode_default ">FormSender.onSubmit = function (e) { if (canDispatch(e)) { YAHOO.util.Event.stopEvent(e); YAHOO.util.Connect.setForm(e.target); YAHOO.util.initHeader('Accept', 'application/javascript, application/xml'); YAHOO.util.Connect(e.target.method.toUpperCase(), e.target.action, callbackFor(e)); } }; jQuery(document.body).each(function () { YAHOO.util.Event.addListener(this, &quot;submit&quot;, FormSender.onSubmit); });</code></pre></div> I decided to mark any Ajax dispatchable forms using a class of &#8216;ajax&#8217;, the idea being that it would be a simple thing to check <code>jQuery(e.target).hasClass('ajax')</code>, but there was a snag. We had two sorts of forms on our pages, forms built using <code>form_for(..., :class =&gt; 'ajax')</code> and forms built using <code>button_to(..., :class =&gt; 'ajax')</code>, and they attached their classes in different places. In the <code>form_for</code> case, the class was on the form tag, but in the <code>button_to</code> case, it was on the generated form&#8217;s submit field. One option would be to monkey patch <code>button_to</code>, or roll my own <code>ajax_button_to</code>, but I ended up writing <code>canDispatch</code> like so: <div class="typocode"><pre><code class="typocode_default ">function canDispatch(e) { jQuery(e.target).find(':submit').andSelf().hasClass('ajax'); }</code></pre></div> <p>This uses jQuery to build a list of the form, and its submit button, and then checks to see if any member of that list has the class &#8216;ajax&#8217;.</p> <p>So, we can now tell if the source of a <code>submit</code> event is a form we should be doing <span class="caps">AJAX</span> dispatch with. The next trick is to work out what needs to be done with the results of sending the form. One option is the Prototype trick of simply evaluating the returned javascript, but it often makes sense to keep the behaviour clientside and just have the server return a datastructure. I decided that the way to do this would be by adding a second class to a form which used a none default handler, and then keep a hash of callback constructors keyed by class. This made <code>callbackFor</code> look like:</p> <div class="typocode"><pre><code class="typocode_default ">function callbackFor(e) { var candidates = candidateClasses(e.target); for (var i = 0; i &lt; candidates.length; i++) { if (FormSender.callbacks[candidates[i]]) { return new FormSender.callbacks[candidates[i]](e); } } return new FormSender.callbacks.ajax(e); }</code></pre></div> <p><code>candidateClasses</code> is, again, a little more complex than I&#8217;d like, by virtue of the differences between <code>button_to</code> and <code>form_for</code> differences, but still reasonably straightforward, thanks to jQuery:</p> <div class="typocode"><pre><code class="typocode_default ">function candidateClasses(element) { return jQuery(element).find(':submit').andSelf() .filter('.ajax').attr('className') .replace(/ajax/, '').trim().split(/ +/); }</code></pre></div> <p>JQuery gets the form and its submit button, then selects the tag that has the &#8216;ajax&#8217; class and pulls out the full <code>className</code> string. The <code>replace</code> gets rid of &#8216;ajax&#8217;, <code>trim</code> chops any useless whitespace off either end, and <code>split(/ +/)</code> turns it into an array of classnames. The <code>replace -&gt; trim -&gt; split</code> pipeline has the feel of something that must already exist in some <span class="caps">DOM</span> interface somewhere, but I&#8217;m not sure where, so I rolled my own.</p> <p>Once we have a list of classes it&#8217;s easy to just cycle through the candidates until we find one that matches a callback constructor, falling back to the default where nothing matches.</p> <p>For completeness, I&#8217;ll show you my current default handler, which I expect to be extending to deal with a couple more media types and, in the case of the failure handler, more failure statuses.</p> <div class="typocode"><pre><code class="typocode_default ">FormSender.callbacks.ajax = function (e) { var form = e.target; this.scope = form; }; FormSender.callbacks.ajax.prototype.success = function (o) { switch (o.getResponseHeader['Content-Type'].replace(/;.*/, '')) { case 'application/javascript': case 'application/x-javascript': case 'text/javascript': eval(o.responseText); break; default: YAHOO.log(&quot;Can't handle AJAX response of type &quot; + o.getResponseHeader['Content-Type']); } }; FormSender.callbacks.ajax.prototype.failure = function (o) { switch (o.status) { case 401: Authenticator.loginThenSubmit(this); break; default: switch (o.getResponseHeader['Content-Type'].replace(/;.*/, '')) { case 'application/javascript': case 'application/x-javascript': case 'text/javascript': eval(o.responseText); break; default: YAHOO.log(&quot;Can't handle AJAX failure response of type &quot; + o.getResponseHeader['Content-Type']); } } };</code></pre></div> <p>You&#8217;ll notice a reference to <code>Authenticator.loginThenSubmit</code> in the 401 handler, but that&#8217;s something I&#8217;ll save for another day.</p> <h3>A note on namespacing</h3> <p>Although I&#8217;ve been showing the various FormSender helper functions as if they were in the global namespace, in the real code they&#8217;re wrapped in a function call:</p> <div class="typocode"><pre><code class="typocode_default ">var FormSender = (function () { var candidateClasses = function (element) {...}; var callbackFor = function (e) {...}; ... var onSubmit = function (e) {...}; return {onSubmit: onSubmit, callbacks: {}}; })();</code></pre></div> <p>I love the <code>(function () {...})()</code> pattern &#8211; it&#8217;s a great way of keeping your paws out of the global namespace until you really, really need to.</p> <h3>FormSender Benefits</h3> <p>Aside from the obvious benefit of drastically reducing the number of <code>onSubmit</code> event handlers registered with the browser, I found that using <code>FormSender</code> has simplified some of my response handlers. For instance, one form would get a chunk of html back from the server and would use that to replace the div that contained the form. But the new div <em>also</em> contained a form that needed to have Ajax behaviour, so a chunk of the handler code was concerned with reregistering onSubmit handlers for the new form (or forms). No fun. By switching to a single, body level, form handler, that problem simply disappears &#8211; so long as the new forms have the right class, they automatically get the appropriate behaviour. Result.</p> <p>Obviously, FormSender is unobtrusive javascript, which is nice, and its pluggable nature means it&#8217;s easy to extend just by writing new response handlers and registering them with the FormSender object.</p> <h3>Future Directions</h3> <p>One obvious extension to FormSender is to pull out the meat of the <code>onSubmit</code> method into the callback object to allow for forms that don&#8217;t simply send themselves to the server. Another is to wrap my head around the workings of Javascript&#8217;s object model to make it easy to build handlers that don&#8217;t duplicate the behaviour of the default handler through the medium of copy and pasting code&#8230;</p> <h3>Your comments please?</h3> <p>I&#8217;m still very new to Javascript as a programming language and I&#8217;m sure I&#8217;m doing plenty of boneheaded things here. Please let me know if there&#8217;s things I can do to improve this, or point me at any libraries that already cover this ground.</p> Fri, 18 Jan 2008 02:30:00 -0600 urn:uuid:881e1181-5ea9-4ffb-af25-f468276dbaec pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2008/01/18/getting-to-grips-with-javascript#comments The Practice of Programming javascript http://www.bofh.org.uk/articles/2008/01/18/getting-to-grips-with-javascript Comprehensible sorting in Ruby <p>Here&#8217;s a problem I first came across when I was about 13 and helping do the stock check at the family firm. The parts department kept all their various spare parts racks of parts bins. Each bin was &#8216;numbered&#8217; with an alphanumeric id. We had printouts of all the bin numbers along with their expected contents and we&#8217;d go along the racks counting the bins&#8217; contents and checking them off against the print out. What confused me at the time was the way the printouts were organized. Instead of the obvious ordering, &#8220;A1, A2, A3, ..., <span class="caps">A99</span>&#8221;, the lists were ordered like &#8220;A1, <span class="caps">A10</span>, A11, ..., A2, <span class="caps">A20</span>, A21, ...&#8221;. After a bit of thought I realised that the computer was sorting the numeric bits of the bin numbers as if they were just sequences of strange letters. A bit more thought made me realise why, post computerisation, people were starting to use bin numbers like &#8220;A01, <span class="caps">A02</span>, ...&#8221;. Computers were more important than people so, in order to make sorting things easier, just add spurious leading 0s to make the number field a fixed width and Robert&#8217;s your parent&#8217;s brother.</p> <p>27 years later and computers are still crap at sorting things in a sensible fashion. Back before Moore&#8217;s Law was really kicking in, I suppose it was excusable, but surely we&#8217;ve moved past that now.</p> <p>Over on the <a href="http://blog.labnotes.org/2007/12/13/rounded-corners-173-beautiful-code/">labnotes</a> blog, there&#8217;s an example of some ruby code that attempts to do &#8216;human&#8217; sorting:</p> <div class="typocode"><pre><code class="typocode_default ">module Enumerable def sensible_sort sort_by { |key| key.split(/(\d+)/).map { |v| v =~ /\d/ ? v.to_i : v } } end end</code></pre></div> <p>It&#8217;s okay, as far as it goes. It certainly solves the parts bin problem I outlined above, but it&#8217;s not ideal. For example, you might expect <code>['-1', '1', '1.02', '1.1'].sensible_sort</code> to leave the order unchanged, but what you actually get is &#8216;1, 1.02, 1.1, -1&#8217;. Not ideal. Let&#8217;s rewrite sensible sort as</p> <div class="typocode"><pre><code class="typocode_default ">module Enumerable def sensible_sort sort_by {|k| k.split(/([-+]?\d+(?:\.\d+)?(?:[-+]?[eE]\d+)?)/).map {|v| Float(v) rescue v}} end end</code></pre></div> <p>That ugly regular expression should match a far wider selection of string representations of numbers. Certainly our &#8216;bad&#8217; list is now sorted correctly.</p> <p>But what about &#8220;a-1&#8221;, &#8220;a-2&#8221;. Using the implementation above, they&#8217;d get sorted as &#8220;a-2, a-1&#8221;, which can&#8217;t be right, can it? Let&#8217;s extend it a bit more and make sure we only worry about the &#8217;+&#8217; and &#8217;-&#8217; if they&#8217;re at the beginning of a line or preceded by whitespace.</p> <div class="typocode"><pre><code class="typocode_default ">module Enumerable def sensible_sort sort_by {|k| k.to_s.split(/((?:(?:^|\s)[-+])?\d+(?:\.\d+)?(?:[eE]\d+)?)/ms).map {|v| Float(v) rescue v}} end end</code></pre></div> <p>And that works fine, until you find that &#8220;B&#8221; sorts before &#8220;a&#8221;. Let&#8217;s catch that as well:</p> <div class="typocode"><pre><code class="typocode_default ">module Enumerable def sensible_sort sort_by {|k| k.to_s.split(/((?:(?:^|\s)[-+])?\d+(?:\.\d+)?(?:[eE]\d+)?)/ms).map {|v| Float(v) rescue v.downcase}} end end</code></pre></div> <p>Yay!</p> <p>Oh, wait a minute, what about version numbers? How should we sort, say &#8220;perl 5.8.0&#8221; and &#8220;perl 5.10.0&#8221;? The 5.8.0 form should definitely come first&#8230; Hmm&#8230;</p> <p>How about</p> <div class="typocode"><pre><code class="typocode_default ">module Enumerable def sensible_sort sort_by {|k| k.to_s.split(/((?:(?:^|\s)[-+])?\d+(?:\.\d+?(?:[eE]\d+)?(?:$|(?![eE\.])))?)/ms).map {|v| Float(v) rescue v.downcase}} end end</code></pre></div> <h3>How far down does this thing go?</h3> <p>I just noticed that &#8221;.1&#8221; sorts after &#8220;1&#8221;. Time for another tweak&#8230;</p> <div class="typocode"><pre><code class="typocode_default ">module Enumerable def sensible_sort sort_by {|k| k.to_s.split(/((?:(?:^|\s)[-+])?(?:\.\d+|\d+(?:\.\d+?(?:[eE]\d+)?(?:$|(?![eE\.])))?))/ms).map {|v| Float(v) rescue v.downcase}} end end</code></pre></div> <p>but that doesn&#8217;t work with version numbers like &#8221;.8.2&#8221;, &#8221;.10.2&#8221;...</p> <h4>Time passes&#8230; Thorin sits down and sings about gold</h4> <p>I was planning on giving an extension of the regex that caught this issue as well, but I&#8217;m afraid I&#8217;ve stumped myself &#8211; I can&#8217;t do it with a single regular expression unless I can use a fixed width lookbehind assertion, but they&#8217;re only available in Perl. Of course, it&#8217;s still possible to fix it, but doing so will take more thought than I have available to me at this time on a Sunday morning. And all this is before we get onto making sure that &#8220;1/2&#8221; sorts between &#8220;0&#8221; and &#8220;1&#8221;. And phone numbers. After all, &#8220;01915551238&#8221; is &#8216;obviously&#8217; the same as &#8220;0191 555 1238&#8221; and &#8220;0191 555-1238&#8221;, so they should end up next to each other in the sorted list.</p> <p>It looks like this is a &#8216;three pipe problem&#8217; after all. I shall probably return to this&#8230;</p> Sun, 16 Dec 2007 03:00:51 -0600 urn:uuid:a309756d-03d1-403e-99f6-c183d4509932 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/12/16/comprehensible-sorting-in-ruby#comments The Practice of Programming Ruby http://www.bofh.org.uk/articles/2007/12/16/comprehensible-sorting-in-ruby Can I get a witness? <blockquote> <p>Worrying about test coverage when you&#8217;re doing Test- or Behaviour-driven development is like worrying about the price of fish in Zimbabwe when you&#8217;re flying a kite.</p> </blockquote> <p>Your tests are there to help you discover your interface and to provide you with an ongoing stream of small bugs to fix. If you write them cleanly, and keep them well factored (you are refactoring your tests, aren&#8217;t you?) they will help to document your intent too. Ensuring that every code path is exercised might be intellectually satisfying but that satisfaction costs time, and time is money. And that&#8217;s before you start worrying about your code&#8217;s malleability. Cover the happy path and the edge cases you <em>know</em> how to deal with and move on. If you&#8217;ve screwed something up, it will get found during acceptance testing (or out in the wild) and you can write a few more tests to isolate the problem, fix it, and move on.</p> <p>If you deliberately add a test that passes without requiring you to write another line of code, ask yourself why you bothered with it. The test isn&#8217;t isolating a bug or specifying new behaviour. If you&#8217;re lucky, it merely confirms something you already know, and if you&#8217;re unlucky, you just introduced a bug in your test suite. Better to move on and either pull a new bug off the queue, or turn a feature request into a new bug &#8211; &#8220;Feature X doesn&#8217;t work!&#8221; &#8211; fix it, refactor and move on to the next. Further down the road, you may discover that the feature you were about to exhaustively test doesn&#8217;t even need to be there, or maybe it works differently than you expected. Aren&#8217;t you glad you didn&#8217;t worry about 100% coverage then? Maybe you will need to revisit the tests and cover more cases in the future. But future you knows more about the problem domain and can do a better job of working out what the behaviour needs to be. And if future you is likely to do a worse job than you right now, you may have bigger problems than the code to worry about.</p> Mon, 19 Nov 2007 13:17:21 -0600 urn:uuid:751d1619-fd46-4407-953d-fe794c06bf6d pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/11/19/can-i-get-a-witness#comments The Practice of Programming http://www.bofh.org.uk/articles/2007/11/19/can-i-get-a-witness Today's Noun is: Reticence <p>What does the <span class="caps">OED</span> say reticence is?</p> <blockquote> <p><ins>Reticence</ins>: Maintenance of silence; avoidance of saying too much or of speaking freely; disposition to say little.</p> </blockquote> <p>Pretty straightforward. When I chose reticence as one of my <a href="http://www.bofh.org.uk/articles/2007/08/20/five-nouns-for-programmers">five nouns for programmers</a> it was another reminder that objects are not the same as datastructures. Well designed objects keep their cards (instance variables) close to their chest. Client code tells objects what to do, it doesn&#8217;t ask them to kiss and tell. In <a href="http://www.amazon.co.uk/exec/obidos/ASIN/013476904X/justasummary-21">Smalltalk Best Practice Patterns</a>, (you don&#8217;t have a copy yet? Are you mad?) Kent Beck recommends that you put your accessor methods in the <code>private</code> protocol unless you have a <em>very</em> good reason for indicating that the accessors should be used by clients by putting the accessors in, say, the <code>accessing</code> protocol or some other, more suitably named, protocol. (In Smalltalk, all methods are public, but you can and should organize them into protocols/categories, either by choosing some existing protocol, or coming up with a new protocol name). In less flexible OO languages, you should probably at least mark your accessors as protected unless you have the aforementioned very good reason.</p> <h3>What about parameter objects then?</h3> <p>One obvious &#8216;exception&#8217; to the rule of reticence is the parameter object. Say you have an unwieldy method that takes a bunch of arguments and fills the screen with its implementation. Being a conscientious programmer, you want to apply the &#8216;composed method&#8217; pattern to the method so you&#8217;ll still end up with a screen&#8217;s worth of code, possibly more, but the individual methods will be much more focussed in what they achieve. What stops you is that bunch of parameters which are used through out the method. So, you introduce a parameter object. Bundle up the parameters into a single object, replace each parameter variable in the body of the code with an accessor call on the parameter object, and have at it. You can extract methods easily and you&#8217;ll only ever have to pass a single object.</p> <p>It&#8217;s tempting not to bother creating a &#8216;real&#8217; object, it&#8217;s very easy to just use an options hash, a la Ruby on Rails. And, because the options hash is a common pattern through your code, you can start adding helper methods like <code>with_options</code>, and you&#8217;ll get an awful lot of leverage out of it.</p> <p>However, what&#8217;s often missed in discussions of the parameter object pattern is that it&#8217;s a waystation, not a destination. It may be handy, but if you persist in treating it as a datastructure, you&#8217;re missing out on the good stuff. Now you have a parameter object, you can start to move <em>behaviour</em> onto the parameter object and before you know it you&#8217;ll end up with a real object doing real, testable (mockable?), work.</p> <h3>Homework</h3> <p>Find a method where you&#8217;re using an options hash. Try using that hash to build a parameter object and then apply the principle of reticence. What happens to it? Where does the behaviour go? If, like me, you&#8217;ve come to OO from procedural coding styles, making your objects reticent is not a natural thing to do, it can feel extremely odd. But the more you practice it, the better you&#8217;ll get at thinking in a truly object oriented fashion. Sometimes an options hash really is the way to go, but not as often as you&#8217;d think.</p> <p>Try it, maybe you&#8217;ll be converted.</p> Thu, 27 Sep 2007 18:30:29 -0500 urn:uuid:d915e393-cff4-4e70-86c1-710e4dd31958 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/09/27/todays-noun-is-reticence#comments Musings The Practice of Programming 5nouns http://www.bofh.org.uk/articles/2007/09/27/todays-noun-is-reticence My head hurts <p>During <span class="caps">DHH</span>&#8217;s keynote at RailsConf Europe it was apparent that there&#8217;s a great deal to like in edge rails, so I thought I&#8217;d have a crack at getting Typo up on it.</p> <p>Ow.</p> <p>I&#8217;d expected the pain points to be related to routing, but it seems that the rails routing system is approaching the level of the Excel calculation engine &#8211; nobody dares touch it for fear of breaking things, so typo&#8217;s custom routes seemed to work quite happily. There were a few things that have been deprecated, pluginized or moved out of the set of modules that&#8217;s automatically included when you do a <code>rake rails:freeze:edge</code>, but they were pretty easy to sort &#8211; the deprecation messages are a good deal more informative now than they were last time went deprecation squashing. There&#8217;s a surprising amount of stuff that&#8217;s been removed <em>without</em> any deprecation warnings though, which isn&#8217;t very sporting. <span class="caps">DHH</span> said there would likely be a 1.2.4 release (possibly a day before 2.0) with a bunch more deprecation warnings covering everything that&#8217;s <em>actually</em> going away, so if you&#8217;re thinking of moving a maturish app to Rails 2.0 it might make sense to wait for 1.2.4, install that, squash warnings, and move on up to 2.0.</p> <p>The real pain comes from themes. Typo&#8217;s themes rely on Rails internals working in a particular way, but they don&#8217;t work like that any more. In theory, the internals appear to be more theme friendly, related to allowing plugins to include views. The problem is, that it&#8217;s possible to change Typo&#8217;s theme without restarting the server, and the new themish internals don&#8217;t expect anything to change until the server&#8217;s restarted.</p> <p>So, I&#8217;ve been playing with plugins. The most promising approach appears to be that of the <a href="http://julik.textdriven.com/svn/tools/rails_plugins/themer/README">themer plugin</a>, which gets pretty close to doing what we need, and does it in a way that seems like it should work with both 1.2.3 and Edge Rails. It does appear to be making some radically different assumptions about the structure of the themes directory, but the basic framework is good and I should be able to make things work by making our current them object conform to Themer::Base&#8217;s interface and duck type my way to the sunny uplands of Edge Rails compatibility.</p> <p>Which will be nice.</p> <p>I like the themer approach a lot. Instead of monkeying about in the guts of rails, it monkeys about in <em>front</em> of Rails. It overrides <code>render</code> so that you can pass it a theme/lookup object. If it sees a lookup object, it uses that to rewrite the rest of the render arguments into a form that will render the right thing using the standard implementation of render. In a work project I&#8217;ve taken a similar approach to handling polymorphic routes for things like:</p> <div class="typocode"><pre><code class="typocode_default ">map.resources :pictures do |pics| pics.resources.comments end map.resources :users do |users| users.resources.comments end</code></pre></div> <p>I ended up with a <code>to_params</code> method defined on my <code>Comment</code> model, and stuck an extended <code>url_for</code> in front of the default Rails version, which looks something like:</p> <div class="typocode"><pre><code class="typocode_default ">def url_for_with_to_params(*arguments) if arguments[0].respond_to?(:to_params) with_options(arguments.shift.to_params) do |mapper| mapper.url_for_without_to_params(*arguments) end else url_for_without_to_params(*arguments) end end alias_method_chain :url_for, :to_params</code></pre></div> <p>Which is <em>so</em> much neater than the last time I attacked this particular problem (see the <a href="http://www.bofh.org.uk/articles/2007/01/25/initial-release-of-acts_as_resource">acts_as_resource</a> plugin).</p> <p>One of the nice things about Rails is that, although it&#8217;s opinionated and somewhat liberal with the syntactic vinegar for things the core team don&#8217;t think is the Right Way, they&#8217;re pretty good at leaving the door open for people like me who have other opinions. Both the themer plugin and my as yet unpluginized extension of <code>url_for</code> work by using existing capabilities in new ways and, because those <em>capabilities</em> are documented we can expect them to continue to work over multiple versions of Rails. Plugins that achieve similar effects by monkeying with Rails&#8217;s <em>internal</em> interfaces are hostages to fortune. Internal interfaces are free to change at any time, even between point releases, so a plugin can be left high and dry with surprising rapidity. Just ask the Rails Engines folk.</p> Sun, 23 Sep 2007 14:09:24 -0500 urn:uuid:1b4540f5-d2b4-4fac-b930-465f41608ca1 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/09/23/my-head-hurts#comments The Practice of Programming Ruby Typo http://www.bofh.org.uk/articles/2007/09/23/my-head-hurts A tiny ruby niggle <p>You know what? I&#8217;m starting to miss compulsory semicolons as statement terminators in Ruby.</p> <p>&#8220;What?&#8221; I hear you say. &#8220;But not needing semicolons is one of Ruby&#8217;s cardinal virtues! Are you mad?&#8221;</p> <p>I don&#8217;t think so, but maybe you&#8217;ll disagree after I explain further.</p> <p>Here&#8217;s a piece of code that I might write if semicolons were the only way of terminating a statement:</p> <div class="typocode"><pre><code class="typocode_default ">Category.should_receive(:find_by_permalink) .with('foo') .and_return(mock_category);</code></pre></div> <p>Or how about a complex find query</p> <div class="typocode"><pre><code class="typocode_default ">def find_tags_for(tag_maker, order = 'count') klass = tag_maker.class find :all , :select =&gt; 'tags.*, count(tags.id) count' , :group =&gt; Tag.sql_grouping , :joins =&gt; &quot;LEFT JOIN taggings ON &quot; + &quot; tags.id = taggings.tag_id &quot; + &quot;LEFT JOIN bookmarks ON &quot; + &quot; bookmarks.id = taggings.taggable_id &quot; + &quot; AND taggings.taggable_type = 'Bookmark' &quot; + &quot;LEFT JOIN #{klass.table_name} ON &quot; + &quot; #{klass.table_name}.id = bookmarks.#{klass.to_s.underscore}_id&quot; , :conditions =&gt; conditions_for(tag_holder) , :order =&gt; (order == 'count') ? 'count(tags.id) desc, tags.name' : &quot;tags.name&quot; , :readonly =&gt; true ; end</code></pre></div> <p>I first came across the idea of the leading comma in Damian Conway&#8217;s excellent <a href="http://www.amazon.co.uk/exec/obidos/ASIN/0596001738/justasummary-21">Perl Best Practices</a>. The idea is that, by leading with the comma it&#8217;s very easy to add a new argument to an argument list or hash specification without having to remember to stick a comma on the end of the preceding line if it was at the end, and also, the leading comma makes it very plain that the line is a continuation of its predecessor in some way.</p> <p>To make the examples work in Ruby, you have to add a <code>\</code> to the end of each line that has a continuation, so the first example has to be written:</p> <div class="typocode"><pre><code class="typocode_default ">Category.should_receive(:find_by_permalink) \ .with('foo') \ .and_return(mock_category);</code></pre></div> <p>Lining up the <code>\</code>s helps to stop them disappearing, but it&#8217;s an awful faff.</p> <p>What tends to happen (in the rails source especially) is that ruby programmers simply don&#8217;t break their lines up. A quick search of the rails source finds plenty of lines more than 160 characters long.</p> <p>Of course, some will argue that it doesn&#8217;t matter, that the old 80 column limit is a silly hangover from the days of steam when the only way to interact with your code was through an 80 column, green phosphor terminal. They have a point. An arbitrary line limit <em>is</em> silly, and we should get over it, especially in source code. However, unless you&#8217;re going to go around with every window open to its maximum width, lines <em>will</em> wrap, and they won&#8217;t do it nicely, or respect the indentation conventions of your language. Long lines are murder in diffs too, finding the point of difference is so much easier when your eye doesn&#8217;t have to scan an epic line.</p> <p>It&#8217;s a shame there&#8217;s no way of forcing ruby&#8217;s parser to <em>require</em> semicolons as statement terminators for those programmers like me who think that the restriction that a statement <em>must</em> end with a semicolon is worth the freedom to break lines where we like without needing to escape every line break. It&#8217;s a shame too that popular tools like Textmate are so clumsy when it comes to dealing with line breaks. I would attempt to hold Emacs up as a paragon in this respect, but its Ruby mode tends to get a wee bit bemused once you start breaking lines, so that&#8217;s no good.</p> <h3>Domino theory</h3> <p>It&#8217;s amazing how far reaching seemingly simple language design decisions can be isn&#8217;t it? Just getting rid of the need to terminate statements with a semicolon has an enormous effect on they way code in ruby looks. I&#8217;m just not sure that they look <em>better</em>.</p> <p>Maybe Smalltalk got it really right &#8211; they chose to use the most valuable syntactic character of all, the space, to denote sending a message. That freed up the <code>.</code> for use as a statement (sentence?) terminator. Then that freed up <code>;</code> for use in one of Smalltalk&#8217;s most distinctive patterns &#8211; the cascade. Where a Rails programmer might write:</p> <div class="typocode"><pre><code class="typocode_default ">form_for(@comment) do |f| f.input(:author) f.input(:title) f.input(:body) end</code></pre></div> <p>A Smalltalk programmer might eliminate the need for a temporary variable by doing:</p> <div class="typocode"><pre><code class="typocode_default ">Comment&gt;&gt;printOn: html (html formFor: self) input: #author; input: #title; input: #body.</code></pre></div> <p>All those <code>input: ...</code> messages get sent to the result of <code>html formFor: self</code>. Once you get the hang of it, it&#8217;s a really sweet bit of syntax.</p> <p>Incidentally, there&#8217;s been some discussion on the squeak mailing lists of a companion to the cascade, which would use a <code>;;</code> as a sort of &#8216;pipe&#8217;. The idea is to be able to replace code like:</p> <div class="typocode"><pre><code class="typocode_default ">((self collect: [:each | each wordCount) inject: 0 into: [:total :each| total + each]) printOn: aStream.</code></pre></div> <p>with</p> <div class="typocode"><pre><code class="typocode_default ">self collect: [:each | wordCount] ;; inject: 0 into: [:total :each | total + each] ;; printOn: aStream.</code></pre></div> <p>(NB: Please ignore what those code snippets <em>do</em>, because that&#8217;s gruesome. Concentrate on how they do it).</p> <p>Nobody&#8217;s quite proposed going as far as Haskell does with its Monads, which can be thought of as a magical land where the meaning of the semicolon changes according to what sort of Monad you&#8217;re in. (In an IO monad for instance, the semicolon imposes an evaluation order. In some other monad, the semicolon could just as easily denote a backtracking point). Then again, there&#8217;s nothing to <em>stop</em> the dedicated Smalltalker implementing something Monadish &#8211; every Smalltalk class can specify how its methods should be compiled after all&#8230;</p> <h3>In conclusion&#8230;</h3> <p>I&#8217;m not sure I&#8217;ve got a real conclusion for all this. I&#8217;m mostly musing. However, I do think it&#8217;s useful to think carefully about restrictions and what they free us to do as programmers. Lispers will wax lyrical about the way that their language&#8217;s pared down syntax lets them do amazing things with macros. Smalltalkers will defend to the death the idea that the only way to do anything is to send messages to objects. Pythonistas love their syntactic whitespace. Haskellers love their static typing (admittedly, they have an incredibly flexible notation for expressing type that leaves most other programming languages standing).</p> <p>And any English speaker with ears will know that a poem like Dylan Thomas&#8217;s <cite>Do Not Go Gentle Into That Good Night</cite> gains much of its power from it&#8217;s form, the villanelle, one of the most restricted forms of poetry there is. Two lines repeating through the poem and a staggering number of rhymes to find:</p> <blockquote> <p>Do not go gentle into that good night, <br/> Old age should burn and rave at close of day; <br/> Rage, rage against the dying of the light. <br/> Though wise men at their end know dark is right, <br/> Because their words had forked no lightning they <br/> Do not go gentle into that good night.<br/><br/> Good men, the last wave by, crying how bright <br/> Their frail deeds might have danced in a green bay, <br/> Rage, rage against the dying of the light.<br/><br/> Wild men who caught and sang the sun in flight, <br/> And learn, too late, they grieved it on its way, <br/> Do not go gentle into that good night.<br/><br/> Grave men, near death, who see with blinding sight <br/> Blind eyes could blaze like meteors and be gay, <br/> Rage, rage against the dying of the light.<br/><br/> And you, my father, there on the sad height, <br/> Curse, bless me now with your fierce tears, I pray. <br/> Do not go gentle into that good night. <br/> Rage, rage against the dying of the light.</p> </blockquote> <p>If that&#8217;s not making a virtue of a restriction, I don&#8217;t know what is.</p> Sun, 09 Sep 2007 02:51:00 -0500 urn:uuid:ab7799e2-e7d9-4802-b65e-07cecf9c03a1 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/09/09/a-tiny-ruby-niggle#comments Musings The Practice of Programming Ruby constraints smalltalk haskell poetry http://www.bofh.org.uk/articles/2007/09/09/a-tiny-ruby-niggle Today's Noun Is: Notation <p>Remember back when I wrote about <a href="http://www.bofh.org.uk/articles/2007/05/20/metaprogramming-programming">metaprogramming and programming</a> being the same thing?</p> <p>Well, Libraries, Domain Specific Languages, <a href="http://www.bofh.org.uk/articles/2007/05/19/domain-agnostic-languages">Domain Agnostic Languages</a>, Pidgins, <span class="caps">YAML</span>, .INI files and the like are all the same thing. They&#8217;re all notation.</p> <p>That&#8217;s the thing to remember. Good notation makes life easy. Bad (or inappropriate) notation makes it hard (or, in some cases, fun). There&#8217;s no point striving to write a pidgin or <span class="caps">DSL</span> if your problem can be solved easily enough with a well factored set of loosely coupled classes. After all, even the neatest and cleanest of domain specific languages has to be learned. Meanwhile a class library that&#8217;s respects the language of your problem domain can be easier to learn because the notation with which the library is implemented is plain old <acronym title="Your Favourite Language">YFL</acronym> and your team already knows that (and if it doesn&#8217;t, you have bigger problems). Learning the class library is like learning about the problem domain and vice versa. Learning one supports learning the other.</p> <p>I&#8217;m of the opinion that DSLs and pidgins are at their most when their domains are generic. So ActiveRecord&#8217;s most useful language like interfaces are related to general problems like expressing the relationships between objects or describing how to validate an object. Backus-Naur Form, Perl compatible regular expressions, parser combinators are all useful for solving the generic parsing and lexing problems that crop up everywhere. Data serialization notations like <span class="caps">YAML</span>, FASTA, <span class="caps">XML</span>, CSV, <span class="caps">JSON</span> and all the others are useful when you want a generic way to pass data between systems. All of these notations are narrow in their focus, but broad in the sense that the things that they focus on are ubiquitous.</p> <p>The most useful notation for your specific task is almost always a well factored set of classes or functions (depends on your language of choice) which reflects the language of your problem domain. Different parts of your program might well make use of a wide range of &#8216;donor&#8217; notations, but it&#8217;s a rare problem that&#8217;s going to require to you implement a full blown language in order to solve it.</p> <p>Don&#8217;t worry about whether something&#8217;s a <span class="caps">DSL</span>, pidgin or a library. What it is is notation. A better question is is &#8220;does this notation help me solve my problem?&#8221;. If the answer is no, find better notation. Or keep plugging on with what you&#8217;ve got, but don&#8217;t fool yourself about your reasons for using the notation &#8211; not everyone&#8217;s here for the hunting after all.</p> Tue, 28 Aug 2007 16:20:00 -0500 urn:uuid:c7833d62-3fb4-4e78-bbcd-c1689520a6c6 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/08/28/todays-noun-is-notation#comments Musings The Practice of Programming 5nouns http://www.bofh.org.uk/trackbacks?article_id=todays-noun-is-notation&day=28&month=08&year=2007 http://www.bofh.org.uk/articles/2007/08/28/todays-noun-is-notation Today's noun is: Reification <blockquote> <p>Reification: The mental conversion of a person or abstract concept into a thing. Also, depersonalization, esp. such as Marx thought was due to capitalist industrialization in which the worker is considered as the quantifiable labour factor in production or as a commodity. &#8211; <span class="caps">OED</span></p> </blockquote> <p>In the sense that the <span class="caps">OED</span> has it, I&#8217;m not what you could call a fan of reification. At work, we have a rule that anybody who starts talking about &#8216;resources&#8217; when they mean &#8216;people&#8217; gets a (verbal) slap.</p> <p>However, in OO circles (or maybe just in my head), reification is a good thing. It&#8217;s the process of taking something abstract and turning it into a &#8216;real&#8217; object. Usually, the word gets used for big things like turning an intractable method into an object as a step on the way to refactoring that method. I tend to use it in a slightly broader sense. For me, reification is the process of turning something (a method or a data structure usually) into a full blown object with its own behaviour.</p> <p>Back when I was working on Pixie (a cunning, but weird, object persistence tool written in Perl) we had a data structure which was used for keeping track of managed objects. It started life as a hash. Everything was fine at first, but over time we ended up with more and more code being repeated across the codebase that was concerned with manipulating the cache hash. So, we replaced the hash with a new object and pulled all the repeated code into methods on that object, which gave us cleaner code to extend, and a strong feeling that we should have turned the cache into an object much earlier in the game. (By leaving it so long, we had a lot more code to move about, some of it in fairly obscure places; tracking down the last bit took a while.)</p> <p>Data structures like hashes and arrays are really useful in languages that have them. The catch is, they have this habit of acquiring code. When this starts to happen, it&#8217;s time to reify &#8211; to replace the hash with a task specific object. In Ruby, it&#8217;s easy enough to inherit from <code>Hash</code>, but Hash comes with a pile of methods that probably aren&#8217;t relevant to your particular need. Generally it&#8217;s better to delegate. The first cut doesn&#8217;t have to be that complicated, just decorate the hash with a new class and initialize an instance of the class at the point where you had just made the hash.</p> <p>Once that&#8217;s done, you can go through your code and move the bits that treat the hash as a data structure onto your new class. As you gather all the common behaviour to the new class, you&#8217;ll start to see places where you can improve code quality by merging common behaviours, replacing complex conditionals with polymorphism (you&#8217;ll probably have to introduce a factory method if you do that) and pulling hash keys out into instance variables.</p> <h3>Stalled reification</h3> <p>Reifying your data structure isn&#8217;t an end in itself, it&#8217;s a step along the way as you refactor your code.</p> <p>There&#8217;s an example of a stalled reification to be found in ActionController::Routing::Resources. Consider the implementations of <code>map_resource</code> and <code>map_singleton_resource</code>, which are the worker methods used whenever you do a <code>map.resource</code> or <code>map.resources</code> in your <code>routes.rb</code>.</p> <pre><code>def map_resource(entities, options = {}, &#38;block) resource = Resource.new(entities, options) with_options :controller =&gt; resource.controller do |map| map_collection_actions(map, resource) map_default_collection_actions(map, resource) map_new_actions(map, resource) map_member_actions(map, resource) if block_given? with_options(:path_prefix =&gt; resource.nesting_path_prefix, &#38;block) end end end def map_singleton_resource(entities, options = {}, &#38;block) resource = SingletonResource.new(entities, options) with_options :controller =&gt; resource.controller do |map| map_collection_actions(map, resource) map_default_singleton_actions(map, resource) map_new_actions(map, resource) map_member_actions(map, resource) if block_given? with_options(:path_prefix =&gt; resource.nesting_path_prefix, &#38;block) end end end </code></pre> <p>There&#8217;s a lot of repetition there. The only differences are the classes of the resource object, name of the second function called in the <code>with_options</code> block. If we take a look at, <code>map_collection_actions</code> things start to look even fishier. Here&#8217;s <code>map_collection_actions</code>, for example:</p> <pre><code>def map_collection_actions(map, resource) resource.collection_methods.each do |method, actions| actions.each do |action| action_options = action_options_for(action, resource, method) map.named_route("#{resource.name_prefix}#{action}_#{resource.plural}", "#{resource.path};#{action}", action_options) map.named_route("formatted_#{resource.name_prefix}#{action}_#{resource.plural}", "#{resource.path}.:format;#{action}", action_options) end end end </code></pre> <p><code>resource.collection_methods.each</code>? Let&#8217;s see what happens if we the various <code>map_foo_actions</code> methods into methods on <code>ActionController::Resources::Resource</code>. While we&#8217;re about it, we can rename <code>map_default_collection_actions</code> to <code>map_default_actions</code> on Resource, and <code>map_default_singleton_actions</code> to <code>map_default_actions</code> on SingletonResource, which inherits from Resource. <code>map_collection_actions</code> becomes:</p> <pre><code>def map_collection_actions(map) collection_methods.each do |method, actions| actions.each do |action| map.with_options(action_options_for(action, method)) do |m| m.named_route("#{name_prefix}#{action}_#{plural}", "#{path};#{action}") m.named_route("formatted_#{name_prefix}#{action}_#{plural}, "#{path}.:format;#{action}") end end end end </code></pre> <p>(we move <code>action_options_for</code> onto resource as well, of course).</p> <p>Once we&#8217;ve moved the various mapping helpers onto the resource classes, we can revisit <code>map_resource</code> and <code>map_singleton_resource</code></p> <pre><code> def map_resource(entities, options={}, &#38;block) resource = Resource.new(entities, options) with_options(:controller =&gt; resource_controller) do |map| resource.map_collection_actions(map) resource.map_default_actions(map) resource.map_new_actions(map) resource.map_member_actions(map) end if block_given? with_options(:path_prefix =&gt; resource.nesting_path_prefix, &#38;block) end end def map_singleton_resource(entities, options={}, &#38;block) resource = SingletonResource.new(entities, options) with_options(:controller =&gt; resource.controller) do |map| resource.map_collection_actions(map) resource.map_default_actions(map) resource.map_new_actions(map) resource.map_member_actions(map) end if block_given? with_options(:path_prefix =&gt; resource.nesting_path_prefix, &#38;block) end end </code></pre> <p>And now, we no longer have two method bodies that look very similar, apart from the resource class, we have to methods that look <em>identical</em> apart from the resource class. So, if we pull out the common bits and put them onto Resource, like so:</p> <pre><code> class ActionController::Resources::Resource def install_routes_in(map, &#38;block) map.with_options(:controller =&gt; controller) do |m| map_collection_actions(m) map_default_actions(m) map_new_actions(m) map_member_actions(m) end if block_given? map.with_options(:path_prefix =&gt; nesting_path_prefix, &#38;block) end end end </code></pre> <p>Then <code>map_resource</code> and <code>map_singleton_resource</code> become</p> <pre><code> def map_resource(entities, options = {}, &#38;block) Resource.new(entities, options).install_routes_in(self) end def map_singleton_resource(entities, options = {}, &#38;block) SingletonResource.new(entities, options).install_routes_in(self) end </code></pre> <h3>Where&#8217;s the benefit?</h3> <p>Apart from making the <code>active_record/lib/resources.rb</code> a bit shorter (a laudable result in itself), where&#8217;s the benefit here?</p> <p>From my own experience of implementing <code>datestamped_resource</code>, a routing plugin that we use in Typo, it makes the life of anyone writing a resource like routing helper for Rails a great deal easier. With <code>datestamped_resource</code> I ended up subclassing ActionController::Resources::Resource, doing the refactoring I&#8217;ve outlined here, but leaving the original Rails methods where they were and just implementing the &#8216;moved&#8217; methods on DatestampedResource (well, not quite, <code>map_collection_actions</code> is pretty different from the default Resource implementation, but the other actions are pretty much the same.</p> <p>In another project I&#8217;m working on, I&#8217;m trying to retain meaningful urls with (potentially) deep resource nesting, and it&#8217;d be really handy to have an <code>inflected_resource</code> route helper. The problem with using a meaningful <code>to_param</code> on your models is, avoiding permalinks that share a name with your actions. You could set up validations so that, say, &#8216;new&#8217; is an illegal permalinks, but it&#8217;s clumsy.</p> <p>However, if you arrange things so that your URLs are inflected, you can always tell that a <span class="caps">URL</span> that begins <code>/resource/new</code> will be a particular resource, with the permalink &#8216;new&#8217;, and <code>/resources/new</code> will be the virtual new resource.</p> <p>If the resource system is factored as I outlined, this is almost trivial, you can introduce a InflectedResource subclass of Resource</p> <pre><code> class InflectedResource &lt; Resource def member_path @new_path ||= #{path_prefix}/#{singular}/:id end end </code></pre> <p>and you&#8217;re pretty much done. Admittedly, something like that (plus a small amount of copy and paste) would work with the current system, but then we&#8217;re looking at 3 substantially identical methods in ActionController::Resources and if it wasn&#8217;t time to refactor before, it&#8217;d definitely be time to refactor then.</p> <h3>Conclusions</h3> <p>Reification shouldn&#8217;t be something you do every day, but nor should it be something you do once a flood. Take a look at some of your projects and some of the places where you&#8217;re using hashes. Are those <em>really</em> hashes, or would they benefit from having some behaviour of their own? You can track down stalled reification by looking for anaemic classes; classes which have a lot of accessors but very little behaviour. Once you&#8217;ve found an anaemic class, look for all the places that instances of it get used. Try moving some of the client code into methods on your anaemic class. Do that a few times and you&#8217;ll end up with a real object.</p> <p>If you&#8217;re fussy about never putting <span class="caps">HTML</span> in your models, you could end up with a mediating builder/presenter object as well, but until you start wanting to render the same structured info in different formats, I&#8217;d suggest biting the bullet and living with <span class="caps">HTML</span> in the model as a lesser evil than structural code. Your mileage may vary.</p> Wed, 22 Aug 2007 18:22:00 -0500 urn:uuid:3eced011-aa22-4695-9c13-85f654d50792 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/08/22/reification#comments Musings The Practice of Programming Ruby 5nouns http://www.bofh.org.uk/articles/2007/08/22/reification Reading Beautiful Code <p>I&#8217;m reading <cite><a href="http://www.amazon.co.uk/exec/obidos/ASIN/0596510047/justasummary-21">Beautiful Code</a></cite> and it&#8217;s very good indeed. However, you have to feel sorry for <a href="http://www.tbray.org/ongoing">Tim Bray</a> &#8211; his chapter, &#8220;Finding Things&#8221; is excellent, as you&#8217;d expect. The only problem is, he&#8217;s following <a href="http://en.wikipedia.org/wiki/Jon_Bentley">Jon Bentley</a>, author of that perennial classic, <a href="http://www.amazon.co.uk/exec/obidos/ASIN/0201657880/justasummary-21">Programming Pearls</a>. It&#8217;s been a while since I (re)read anything by Bentley and I&#8217;d forgotten how good his <em>prose</em> was.</p> <p>Which isn&#8217;t to say that Tim Bray is a bad writer. Far from it. It&#8217;s just that Jon Bentley is a very good one indeed.</p> <p>Apart from that, <cite>Beautiful Code</cite> is a cracking book so far, and the royalties go to <a href="http://www.amnesty.org/">Amnesty International</a>. You should buy a copy.</p> Tue, 21 Aug 2007 18:49:57 -0500 urn:uuid:6de7ee7b-b1a8-4718-bf1b-31ff7880af37 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/08/21/reading-beautiful-code#comments The Practice of Programming Review http://www.bofh.org.uk/articles/2007/08/21/reading-beautiful-code Five nouns for programmers <ul> <li>Reification</li> <li>Notation</li> <li>Reticence</li> <li>Lucidity</li> <li>Intent</li> </ul> <p>Learn &#8216;em. Live by them.</p> <p>What did I miss? Which ones don&#8217;t belong on the list. What am I talking about?</p> Mon, 20 Aug 2007 18:45:00 -0500 urn:uuid:37876d17-6ed0-49fb-94e0-62592bfe0f13 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/08/20/five-nouns-for-programmers#comments Musings The Practice of Programming gnomicutterances 5nouns http://www.bofh.org.uk/articles/2007/08/20/five-nouns-for-programmers Domain Specific Pidgin <p>So, I&#8217;m busily writing an article about implementing an embedded little language in Ruby. It&#8217;s not something that&#8217;s going to need an entirely new parser, it borrows Ruby&#8217;s grammar/syntax but does some pretty language like things to the semantics and ends up feeling far more like at declarative language than the usual Ruby imperative OO style.</p> <p>Because I tend to <a href="http://www.oreillynet.com/onlamp/blog/2007/05/the_is_it_a_dsl_or_an_api_ten.html">chromatic&#8217;s view</a> of many ruby programmers&#8217; ability to cry <del>&#8220;Wolf!&#8221;</del> &#8220;DSL!&#8221;, I don&#8217;t want to claim that it&#8217;s a full blown Domain Specific Language, but it&#8217;s sufficiently language like that &#8216;API&#8217; doesn&#8217;t seem to fit as a description either.</p> <p>Then it hit me&#8230; it&#8217;s a pidgin.</p> <p>A pidgin can be thought of as a mashup of two languages, taking vocabulary from both its parents and its grammar (usually simplified) from one parent. Historically, pidgins have arisen to help with trade and colonization; grammars have tended to be lifted and simplified from the &#8216;native&#8217; language and then spiked with words from the colonizing language with a leavening of native words where they make sense. All quite politically incorrect nowadays, but they served their purpose. Pidgins are, by their nature, domain specific; fine if you wanted to talk trade or order your coolies about, but not what you&#8217;d write poetry in. Poetry tended to get written in the creoles that evolved from some pidgins. A creole is a general purpose language, with a grammar of its own; they seem to evolve from pidgin, getting invented by the kids of parents who speak that pidgin.</p> <p>In my little language, much of the vocabulary pinched from my problem domain&#8217;s language and the grammar and some terminology is lifted from ruby. Casting the problem domain as the colonial power and ruby as the native language, it&#8217;s obvious that I&#8217;ve invented a pidgin language.</p> <p>Let&#8217;s embrace that term. We&#8217;re not writing domain specific languages, we&#8217;re writing pidgins. ActiveRecord&#8217;s family of class methods isn&#8217;t a <span class="caps">DSL</span>, it&#8217;s database pidgin. RSpec is a testing pidgin, Parsec is a parsing pidgin, so are any number of APIs that make their host language feel like a new one.</p> <h3>Updates</h3> <p>In the comments, Aristotle Pagaltzis points out that Parse::RecDescent isn&#8217;t a parsing pidgin because it uses a full blown parser (itself, obviously) to parse any grammar declarations.</p> Wed, 08 Aug 2007 02:43:00 -0500 urn:uuid:b98b7846-546b-43f2-906f-cf2a883ca183 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/08/08/domain-specific-pidgin#comments Musings The Practice of Programming http://www.bofh.org.uk/articles/2007/08/08/domain-specific-pidgin Doing the fixture thing <p>Fixtures suck! Mocks rock! Don&#8217;t you <em>dare</em> let your tests touch the database!</p> <p>Well&#8230; yes&#8230; I suppose. Except, mocking can be a complete pain in the arse too (made slightly less of a pain in the arse if you use the null object options) &#8211; it&#8217;s awfully easy to end up with huge long setup methods that spend all their time faking out a mock object and about two lines testing what you need.</p> <p>I&#8217;m sure someone&#8217;ll be along to argue that this is evidence of lazy design on my part. Well, &#8220;Yah boo sucks!&#8221; to the lot of &#8216;em. Fixtures can be exceedingly useful.</p> <h3>Spooky action at a distance</h3> <p>The biggest problem I have with Rails&#8217; current implementation of fixtures is&#8230; oh, where to start&#8230; it&#8217;s probably the action at a distance aspect of them. Your test is here, but your fixture is defined some way over there, in a random collection of yaml files.</p> <p>Then there&#8217;s the problem of remembering <em>which</em> fixtures you need to have loaded for a particular test, and it all starts getting horrible very quickly.</p> <p><a href="http://errtheblog.com/post/7708">One way</a> of addressing this is to use fixture scenarios and fixture scenario builder, which works around the problem of remembering what to load and means you don&#8217;t have to write your fixtures in <span class="caps">YAML</span>. What it doesn&#8217;t work around is the action at a distance issue (but I&#8217;m betting it wouldn&#8217;t be too hard to repurpose the fixture scenario builder to let you declare the fixtures you need for a particular test/spec in the same place as you do the testing).</p> <p>At work though, we came up with another way of making it easy to build your fixtures right in the test file. Our current approach is still a little bit clunky, and it&#8217;s nowhere near the point where I can turn it into a library, but I think it&#8217;s worth discussing anyway.</p> <h3>Exemplars</h3> <p>The question to ask is, what do you use a fixture for? Most of the time, what a test needs is a mostly generic instance of your class which will pass the validations, and which has maybe a couple of attributes set to particular values.</p> <p>Let&#8217;s say you have a user class. As is common with such things, your user has a username, an email address and a password. As is so often the case, the usernames and email addresses must be unique, and the password must not be blank. Let&#8217;s say you&#8217;re working on a tagging system (isn&#8217;t everyone). Here&#8217;s the sort of specification you might write:</p> <div class="typocode"><pre><code class="typocode_default ">context &quot;A taggable object&quot; do setup do # makes a taggable object and a couple of users end it &quot;Should aggregate taggings&quot; do @first_user.tag(@taggable, &quot;tag&quot;) @second_user.tag(@taggable, &quot;tag&quot;) @taggable.save!; @taggable.reload @taggable.should have(1).tags end end</code></pre></div> <p>In this context, the only thing you need from those user objects is that they behave like @users, are distinct and valid. You could simply set up a couple of users your users.yml fixture, but the approach we took at work went something like this:</p> <div class="typocode"><pre><code class="typocode_default ">class User class &lt;&lt; self @@exemplar_count = 0 def exemplar(overrides = {}) @@exemplar_count += 1 with_options(:username =&gt; &quot;user#{@@exemplar_count}&quot;, :email =&gt; &quot;user#{@@exemplar_count}&quot;, :password =&gt; &quot;fredisabadpassword&quot;) do |maker| maker.new(overrides) end end def create_exemplar(overrides = {}) returning(exemplar(overrides)) {|user| user.save} end def create_exemplar!(overrides = {}) returning(exemplar(overrides)) {|user| user.save!} end end end</code></pre></div> <p>This lets us write setup code like:</p> <div class="typocode"><pre><code class="typocode_default ">setup do @first_user = User.create_exemplar! @second_user = User.create_exemplar! @taggable = ... end</code></pre></div> <p>In tests where you need an exemplar with a specific property, you can write <code>Model.exemplar(:tested_attribute =&gt; specific_value)</code> &#8211; the way the overrides work means you only have to describe the &#8216;interesting&#8217; bits and the obscuring dust involved in simply building a valid object is swept under the carpet.</p> <h3>Homework</h3> <ul> <li>If you&#8217;re familiar with the <a href="http://www.martinfowler.com/bliki/ObjectMother.html">Object Mother</a> pattern, this might seem a little familiar, with the wrinkle that, instead of having a factory class, we just push the exemplar builder directly onto the model class.</li> </ul> <ul> <li>If you start implementing exemplars yourself, you&#8217;ll probably spot a good deal of repetitive coding. I&#8217;ve not extracted a library yet because I&#8217;ve not quite come up with an interface that I like. Can you come up with a good way of doing it? Can you implement it?</li> </ul> <ul> <li>What did I miss?</li> </ul> Sun, 05 Aug 2007 02:39:00 -0500 urn:uuid:a5a3858c-741d-49e7-b4b9-a798f7dd27e9 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/08/05/doing-the-fixture-thing#comments The Practice of Programming Ruby http://www.bofh.org.uk/articles/2007/08/05/doing-the-fixture-thing Cheat all you want, but don't get caught <p>As far as I can tell, one of the Smalltalk optimizers&#8217; mottoes is &#8220;Cheat all you want, but don&#8217;t get caught&#8221;.</p> <p>Well, this morning, I caught Squeak with its hand in the till.</p> <p>One way I attempt to bootstrap myself towards understanding of code is to try and make it better, if that makes sense. So, I&#8217;d run SLint over the OmniBrowser package and was trying to shorten a method. One thing that struck me as rather ugly was a piece of code that ran like this:</p> <div class="typocode"><pre><code class="typocode_default ">|selection| ... selection := OBChoiceRequest prompt: nil labels: usersNames values: users. selection ifNotNil: [selection browse].</code></pre></div> <p>So I thought I&#8217;d tweak <code>ifNotNil:</code> so that, if its receiver isn&#8217;t nil, it will pass itself as an argument into the block, which will let me rewrite that ugly code with:</p> <div class="typocode"><pre><code class="typocode_default ">(OBChoiceRequest prompt: nil labels: usersNames values: users) ifNotNil: [:selection| selection browse].</code></pre></div> <p>So, I went to have a look at the implementation of <code>ifNotNil:</code> and found that it was already doing exactly what I was after.</p> <p>At this point, I had a slight premonition of danger, so I brought up a workspace and tried to print the result of running <code>10 ifNotNil: [:i| i + 10]</code> and got a compiler error, complaining that <code>ifNotNil:</code> takes a 0 argument block. Which isn&#8217;t what the implementation of <code>ifNotNil:</code> thinks.</p> <p>I&#8217;d caught Squeak&#8217;s optimizer cheating.</p> <p>What appears to happen is that Squeak catches conditional code and rewrites it before passing it to the compiler. The rewritten code uses VM level primitives where possible. I needed to fix it so that it would only rewrite any calls to <code>ifNotNil:</code> with a zero argument block.</p> <p>It took a while, but my local image now optimizes <code>ifNotNil:</code> correctly (the <code>ifNotNil:ifNil:</code> and <code>ifNil:ifNotNil:</code> forms are another matter though, but I shall live. Now, if I can just work out where to submit the changeset to&#8230;</p> <p>I have mixed feelings about this. On the one hand, I&#8217;ve just changed something in the workings of Squeak, on the other, it&#8217;s not been quite as easy as I&#8217;d expected it to be. It seems that, if you go poking around in methods that are defined on ProtoObject, don&#8217;t be surprised if changing things doesn&#8217;t quite do what you expect.</p> <p>Maybe I should have just written a <code>ifNotNilDo:</code> taking a single argument block, but that just felt ugly&#8230; Ho hum.</p> Wed, 20 Jun 2007 17:16:00 -0500 urn:uuid:9a1f0bdb-7908-4f39-9ec8-4e8091c5167d pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/06/20/cheat-all-you-want-but-dont-get-caught#comments The Practice of Programming Squeak smalltalk refactoring http://www.bofh.org.uk/articles/2007/06/20/cheat-all-you-want-but-dont-get-caught How I learned to stop worrying and love aggressive mockery <p>There&#8217;s something enormously liberating about writing an <a href="http://rspec.rubyforge.org/">RSpec</a> description that starts like:</p> <div class="typocode"><pre><code class="typocode_default ">describe ArticlesController, &quot;feeds:&quot; do before do @the_mock = mock('everything', :null_object =&gt; true) ActiveRecord::Base.stub!(:find).and_return(@the_mock) end it &quot;/articles.atom -&gt; atom feed&quot; do get :index, :format =&gt; 'atom' response.should render_template('_atom_feed') end ... end</code></pre></div> <p>The <code>:null_object</code> flag to rspec&#8217;s <code>mock</code> function is remarkably potent.The resulting mock will return itself from any method call that hasn&#8217;t got some other expectation set up. When I&#8217;m testing that my index methods render the appropriate views for the format, I don&#8217;t care that all the various variables have been set up correctly &#8211; I&#8217;ve already tested that in another description &#8211; I just want to get to the point where I&#8217;m about to render a template.</p> <p>What this does is decouple my tests. I can change the way that the index method fetches its stuff from the database and I&#8217;m only going to have to change the innards of the specs that test that.</p> <p>I tend to think of this as being analogous to the object oriented pattern of trying to write your methods at a single level of abstraction. Within a given spec, I should only be setting up expectations that are directly related to what I&#8217;m testing.</p> Wed, 06 Jun 2007 05:21:00 -0500 urn:uuid:2e16fe59-e574-4b39-9cd8-5f38bf91a873 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/06/06/how-i-learned-to-stop-worrying-and-love-aggressive-mockery#comments The Practice of Programming Ruby Typo http://www.bofh.org.uk/articles/2007/06/06/how-i-learned-to-stop-worrying-and-love-aggressive-mockery Metaprogramming == Programming <p>While I&#8217;m tilting a windmills, I should just like to tell all those people who bang on about &#8216;metaprogramming&#8217;.</p> <p>It&#8217;s all just programming.</p> <p>That is all.</p> Sun, 20 May 2007 11:21:00 -0500 urn:uuid:72672746-4514-41dd-8501-b1f33727c286 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/05/20/metaprogramming-programming#comments The Practice of Programming pontification windmilltilting http://www.bofh.org.uk/articles/2007/05/20/metaprogramming-programming Domain Agnostic Languages <p>Windmill tilting time again I&#8217;m afraid. Blame <a href="http://www.oreillynet.com/onlamp/blog/2007/05/the_is_it_a_dsl_or_an_api_ten.html">chromatic</a> and <a href="http://dablog.rubypal.com/2007/4/17/the-l-in-dsl-langue-ou-langage">David A. Black</a>.</p> <p>What is it that characterizes domain specific languages? Before you trot out something like &#8220;Programs written in them read like domain experts talk&#8221;, take a look at some examples of code written in domain specific languages:</p> <code><pre> /(?ms)"((?&gt;[^\\"]+)?(?&gt;\\.[^\\"]*)*)/ </pre></code> <code><pre> S3 R$* $: &lt; $1 &gt; R$+ &lt; $* &gt; &lt; $2 &gt; R&lt; $* &gt; $+ &lt; $1 &gt; R&lt;&gt; $@ &lt; @ &gt; R&lt; $+ &gt; $: $1 R@ $+ , $+ @ $1 : $2 R@ $+ : $+ $@ &lt;@ $1&gt; : $2 R$+ @ $+ $: $1 &lt;@ $2&gt; R$+ &lt; $+ @ $+ &gt; $1 $2 &lt;@ $3&gt; R$+ &lt;@ $+ &gt; $@ $1 &lt;@ $2&gt; </pre></code> <code><pre> &gt;gi|2501594|sp|Q57997|Y577_METJA PROTEIN MJ0577 MSVMYKKILYPTDFSETAEIALKHVKAFKTLKAEEVILLHVIDEREIKKRDIFSLLLGVAGLNKSVEEFE NELKNKLTEEAKNKMENIKKELEDVGFKVKDIIVVGIPHEEIVKIAEDEGVDIIIMGSHGKTNLKEILLG SVTENVIKKSNKPVLVVKRKNS </pre></code> <p>If you&#8217;re reading this on the front page, try and work out what the ones you recognise do before you dip below the fold&#8230;</p> <p>... Right, that&#8217;s scared the dilettantes off.</p> <h3>What do they do?</h3> <p>The first snippet is a regular expression. It should be an efficient matcher for double quoted strings which can span multiple lines and have backslash escaped internal quote marks. It&#8217;s not exactly easy to read because it&#8217;s optimized to reduce backtracking in failing cases. A simpler, but slower form would look like <code>/(?ms)"((?:\\.|[^\\"])*)"/</code>. I say &#8216;should&#8217; because I wrote it from first principles without recourse to the manual except to check on the syntax of <code>(?&gt;...)</code> &#8211; I&#8217;ve been using regular expressions for so long now, they&#8217;re getting pretty instinctive<sup><a href="#fn1">1</a></sup>. Every regular expression is a program written in a language whose domain is concisely expressing the rules to match strings. So long as what you&#8217;re matching doesn&#8217;t require you to worry about balancing bracket like things, a regex should suit you fine.</p> <p>The second snippet is a sample of sendmail.cf ruleset, this is the one that canonicalizes email addresses into a form that the rest of the rulesets can work on. Once upon a time I could have taken you through it line by line and explain what it did, but the world has changed since then. Sendmail&#8217;s domain was routing email back in the days when there were a mllion and one different email address formats and networks. Who uses addresses like <code>kremvax!ivan@ucbvax.UUCP</code>, <code>pdcawley@uk.ac.nott.cs</code> or (if you&#8217;re feeling sufficiently evil) <code>pdcawley@uk.org.bofh.org.uk</code> these days? Nowadays all email addresses look pretty much the same and routing is substantially less complicated, so tools like Postfix, Exim and qmail are far, far easier to configure because the domain has shrunk to the point where you can get away with a mere configuration file.</p> <p>The last one&#8217;s a <span class="caps">BLAST</span> query<sup><a href="#fn2">2</a></sup> which can be run against the genome of your choice. Again, if you&#8217;re a geneticist (or, more likely a geneticist&#8217;s computer), this makes perfect sense. If you&#8217;re not a geneticist however, it&#8217;s the next best thing to gobbledegook.</p> <h3>Searching for the odd one out&#8230;</h3> <p>What characterises Domain Specific Languages isn&#8217;t their readability, it&#8217;s their narrow focus on their domain. The sendmail config file&#8217;s the odd one out here because it turns out that you can implement a <a href="http://en.wikipedia.org/wiki/Universal_Turing_Machine#Universal_Turing_machines">Universal Turing Machine</a> in a <a href="http://okmij.org/ftp/Computation/sendmail-as-turing-machine.txt">sendmail.cf file</a> file. While Turing completeness might be fun to prove, it can be problematic in a Domain Specific Language. Ask James Duncan Davidson about accidentally making Ant Turing complete some time &#8211; there&#8217;s a reason he&#8217;s run away to be a photographer you know.</p> <h3>Domain Agnostic Languages</h3> <p>General purpose languages like Smalltalk, Lisp, Perl, Ruby, Python or &#42;spit&#42; Java aren&#8217;t domain specific languages in the same sense (unless you reckon that &#8216;writing general applications&#8217; is narrow enough to be their domain). Instead they&#8217;re domain <em>agnostic</em>. General purpose languages support programming &#8216;in the language of the domain&#8217;. So ActiveRecord&#8217;s combination of well designed class methods let you describe the relationships between database tables by describing the relationships between objects. Meanwhile in Perl, <a href="http://jifty.org/view/HomePage">Jifty</a> has similar capabilities and <a href="http://seaside.st/">Seaside</a> meanwhile morphs programming for the web into something that feels remarkably like programming for the desktop. <a href="http://www.paulgraham.com/">Paul Graham</a> would probably tell you that Arc does the same thing with Lisp (he was also the inspiration for Seaside).</p> <p>The more malleable of these languages let the cunning programmer embed full blown DSLs, complete with their own syntax and semantics within them. Lisp&#8217;s macros are the most obvious example of this, but Smalltalk has some pretty amazing tricks up its sleeve too &#8211; check out <a href="http://weblogs.media.mit.edu/llk/scratch/index.html">Scratch</a> or <a href="http://wiki.laptop.org/go/Etoys">Etoys</a>. As I understand it, you can have a different compiler for every browser window if you want. Compared to these languages, Ruby, Python, Perl et al speak the language of the domain with more or less thick accents.</p> <h3>Do I even have a point?</h3> <p>Well, sort of. It&#8217;s easy and tempting to rail against the way everything and its brother is a <span class="caps">DSL</span> now, but that ship has probably already sailed. We can hope that as the underlying idea of the <span class="caps">DSL</span> &#8211; the problem shapes the tool &#8211; gains wider currency people will incorporate it in their practice and become better at their craft as a result. We old farts will continue to chunter about the young folks of today not realising what it was like when we had to whittle our own bits and write a <span class="caps">DSL</span> to build the parser that would let us build the <span class="caps">DSL</span> we <em>really</em> wanted. But maybe it&#8217;s good that people get starry eyed. It&#8217;s a step down the road; even if they never take the next one, at least they&#8217;ve moved in a good direction.</p> <p>The moment you take a chunk of code and give it a name, you&#8217;re in the business of language design. Use your power wisely and the programming zeitgeist will beat a path to your <a href="http://www.rubyonrails.com/">door</a> &#8211; especially if you have <span class="caps">DHH</span>&#8217;s seemingly instinctive marketing nous. Use it less wisely and you&#8217;re welcome to your <a href="http://en.wikipedia.org/wiki/Big_ball_of_mud">ball of mud</a>.</p> <h3>Updates</h3> <p>With his usual aplomb (and in the very first comment), chromatic pointed out a glaring cock up in the original wording of this post so I&#8217;ve tightened it up a bit.</p> <p id="fn1"><sup>1</sup> I owe the vast bulk of my understanding of the guts of regex engines to reading the first edition of <a href="http://www.amazon.co.uk/exec/obidos/ASIN/0596528124/justasummary-21"><cite>Mastering Regular Expressions</cite></a>, Jeffrey Friedl&#8217;s masterly explanation of the subject. I understand it&#8217;s only got better with subsequent editions<sup><a href="#fn3">3</a></sup>.</p> <p id="fn2"><sup>2</sup> Oops, no it&#8217;s not. It&#8217;s &#8220;protein sequence in fasta format in which amino acids are represented by 1 letter codes. You can use it as a <span class="caps">BLAST</span> query but the options are endless. It is like a calling a comma separated text file as an Excel input only.&#8221; Thanks to Darked for pointing that one out to me in the comments. Remember kids, Google + a merely cursory knowledge of a domain will only get you so far. I&#8217;d maintain that fasta format can still be thought of as a domain specific language, but it has more in common with <span class="caps">XML</span> or <span class="caps">HTML</span> than, say <span class="caps">SQL</span>.</p> <p id="fn3"><sup>3</sup> I just noticed the first edition was published in 1997 and I bought it as soon as it came out. I feel old.</p> Sat, 19 May 2007 18:52:00 -0500 urn:uuid:c60ffc23-d4f5-4ffd-91d3-2ae2e593f93c pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/05/19/domain-agnostic-languages#comments The Practice of Programming DSLs pontification windmilltilting http://www.bofh.org.uk/articles/2007/05/19/domain-agnostic-languages Finally learning JavaScript <p>For years I&#8217;ve managed to dodge learning JavaScript. People have told me it&#8217;s a fine language with some dodge implementations. Friends have built an entire <a href="http://www.zimki.com/">business model</a> in the language, and I&#8217;ve continued to treat as if it were <cite>The Sound of Music</cite> (I&#8217;m 39 now and I have managed to completely avoid watching that film).</p> <p>Except, today I finally had a technical need that I couldn&#8217;t dodge by writing another <code>.rjs</code> file, so with the help of the <a href="http://www.prototypejs.org/">Prototype</a> docs, a <a href="http://www.crockford.com/javascript/private.html">helpful article</a> or two and healthy dose of cribbing from others, I was off.</p> <p>What do you know, it really is a fine language. I doubt I&#8217;m writing idiomatic code though &#8211; I&#8217;m leaning heavily on closures and private member functions, and I haven&#8217;t written a single <code>for</code> loop yet, but it seems to accommodate my style.</p> <p>Now, if I can just get my head round the innards of keyboard events I shall be a great deal happier.</p> Wed, 16 May 2007 17:17:00 -0500 urn:uuid:feab6aa5-bb1b-4445-80eb-c7de27eecdc4 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/05/16/finally-learning-javascript#comments The Practice of Programming javascript http://www.bofh.org.uk/articles/2007/05/16/finally-learning-javascript Why I love Smalltalk <p>From <a href="http://www.cincomsmalltalk.com/blog/blogView?showComments=true&#38;entry=3355580003">Extreme UI Testing</a>:</p> <blockquote> <p>Method wrappers. Easily possible in VW and Squeak since you can subclass CompiledMethod and much with the method dictionaries [...] Niall uses a strategy pattern to automatically wrap threads that get forked off by looking up the stack to see if the code is under test (and if it is, make sure to install a wrapper)</p> </blockquote> <p>So what if the language doesn&#8217;t give me the callbacks I need, I&#8217;ll just rejig the system classes until it does. Until Avi needed them for Seaside, Smalltalk didn&#8217;t have continuations, but it&#8217;s malleable enough that he could implement them.</p> <p>Malleability rocks (even though rocks aren&#8217;t exactly malleable.)</p> Wed, 02 May 2007 18:41:00 -0500 urn:uuid:8f5e0668-6ca0-471d-8812-6b76d475b0cc pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/05/02/why-i-love-smalltalk#comments The Practice of Programming http://www.bofh.org.uk/articles/2007/05/02/why-i-love-smalltalk That was fun <p>On Monday I was down in Brighton for a <a href="http://codingdojo.futureplatforms.com/vqwiki/jsp/Wiki?23-04-2007">Brighton Coding Dojo</a> where I had a crack at doing <a href="http://codekata.pragprog.com/2007/01/kata_four_data_.html">Kata four</a> in Smalltalk.</p> <p>It took a while to find the balance, but once we got going I think it went well.</p> <p>We stuck in what seemed like the strangest places though. At one point, I had a method that did almost exactly what I wanted for a new method I was writing so I called up the method in the browser, changed the selector and the few bits that needed fixing up and accepted the changes.</p> <p>Uproar! &#8220;Wha? What&#8217;ve you done to <code>testGetMnT</code>?&#8221;</p> <p>&#8220;It&#8217;s still there, look.&#8221; I said, pulling <code>testGetMnT</code> up in the browser.</p> <p>&#8220;But&#8230;!&#8221;</p> <p>People were impressed by OmniBrowser&#8217;s refactoring tools and slightly boggled by the sheer number of instance methods on Object.</p> <p>Because we dived straight in, people got a wee bit stuck on the syntax as well. Next time I do something like this, I&#8217;ll spend more time walking through what&#8217;s going on in each line of code, until people get a bit more secure, and I&#8217;ll start handing the keyboard off to other pairs <em>way</em> sooner. Once I did that, it became far more apparent which bits were sticking points.</p> <p>The session certainly confirmed my opinion that you can read all you like about Smalltalk, but you won&#8217;t really get it until you see it in motion.</p> <p>So, once I have some tuits of the appropriate shape, I&#8217;m planning on making a longish screencast of me running through Kata four, with commentary. It won&#8217;t be an exemplary example of a Smalltalk user getting the very best out of the toolset; I&#8217;m very much a beginner myself, but I hope it&#8217;ll give you a feel for why you should at least try Smalltalk for yourself. I also hope that any experienced Smalltalkers watching the screencast will be able to give me some tips on better ways of using the tool.</p> Wed, 25 Apr 2007 01:57:00 -0500 urn:uuid:348dfcd5-6867-4023-b48a-5d99cbe74f7d pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/04/25/that-was-fun#comments The Practice of Programming smalltalk codingkata katafour brightoncodingdojo http://www.bofh.org.uk/articles/2007/04/25/that-was-fun Rails, CRUD, REST and the importance of adjectives <p>Consider a web request:</p> <pre><code>GET /articles/2007/04/17/adjectives-rule;edit</code></pre> <h3>&#8220;What does it <em>mean?&#8221;</em></h3> <p>If we pass it through the prism of Rails routing, it breaks apart as follows:</p> <dl> <dt><code>GET</code></dt> <dd>The <code>:method</code>, sometimes called the verb.</dd> <dt><code>/articles</code></dt> <dd>The <code>:controller</code>, the thing that&#8217;s going to handle this request</dd> <dt><code>/2007/04/17/adjectives-rule</code></dt><dd>Parameters, passed to the controller method that handles this request</dd> <dt><code>;edit</code></dt><dd>The <code>:action</code>, some way of specifying what this request does</dd> </dl> <p>It&#8217;s certainly one way of looking at it, but if you do I think you&#8217;re limiting your understanding of what it means to program in a RESTful fashion. It&#8217;s an obvious fit for Rails where the dispatcher builds an appropriate controller and then does <code>controller.send params(:action)</code>[1] but it&#8217;s a very &#8216;imperative&#8217; view and that&#8217;s not necessarily a good view. The problem is that <code>:action</code> at the end.</p> <p>What&#8217;s happening is that Rails&#8217;s implementation is leaking into the abstraction that is the <span class="caps">URL</span>. If you let that happen you end up programming with <acronym title="Create, Read, Update, Delete">CRUD</acronym>dy blinkers.</p> <p>Let&#8217;s try another way of breaking that request up into &#8216;parts of speech&#8217;. Here&#8217;s what I think the request means: &#8220;Get me the editor for the article posted on 2007-04-17 called &#8216;adjectives-rule&#8217;&#8221;. <code>;edit</code> isn&#8217;t an action selector, it&#8217;s a <em>view</em> selector.</p> <h3>&#8220;Isn&#8217;t this just navel gazing?&#8221;</h3> <p>At the London Ruby Users&#8217; Group on Monday, there was an occasionally heated discussion of RESTful programming in which several people expressed the view that <span class="caps">REST</span> was limiting because they &#8220;needed more than 4 verbs&#8221; for their application.</p> <p>Much of the discussion of RESTful programming on Rails has been about how to break things down so that you can think of your application in <span class="caps">CRUD</span> terms, and that&#8217;s a terribly limiting way to view things.</p> <p>Let&#8217;s look at another request and see how to interpret it.</p> <code><pre> POST /articles/new;preview Content: article[title]=Adjectives+Rule; article[body]=... </pre></code> <p>If you break this request up along the lines suggested by rails, then it seems that this isn&#8217;t a RESTful request. It&#8217;s POSTing something, which means its creating a new resource, but that resource isn&#8217;t going in the datatabase. Wha?</p> <p>I think this is perfectly RESTful though. What we&#8217;re saying is &#8220;Make me a new preview of the article described in the body of the request&#8221;. The <span class="caps">POST</span> part of the request implies &#8216;make something&#8217;, the rest of the request describes what to make. Our controller knows that articles created for preview are not persistent, so they don&#8217;t go in the database. The preview you create and then throw away is just as much a resource as the finished article, the only difference being that every preview gets thrown away.</p> <p>Looked at like this, it&#8217;s apparent RESTful programming is much richer than the basic 4 <span class="caps">CRUD</span> actions. The important principles to bear in mind are:</p> <dl> <dt><span class="caps">GET</span> must not alter any resource</dt> <dd>This is the really, really, really big one. If you&#8217;re ever tempted to write a method that interprets a <span class="caps">GET</span> request and changes the state of the resource being fetched&#8230; well, think again.</dd> <dt>Statelessness</dt> <dd>This is the idea that the request itself contains all the information the server needs to build the response. No session cookies. There are those who argue for no cookies at all, but until browsers handle <span class="caps">HTTP</span> authentication better I think we&#8217;re stuck with cookie based authentication, but the cookie should really be self contained and not an opaque reference into a catch all session table.</dd> <dt><code>POST</code>, <code>PUT</code> and <code>DELETE</code> should act appropriately</dt> <dd><code>POST</code> makes new stuff, <code>PUT</code> changes old stuff, <code>DELETE</code> removes old stuff. Not that hard to understand. The only wrinkle is that browsers don&#8217;t know how to make <code>PUT<