On Writing Well: Exposition or Code

Posted by Jeremy Voorhis Tue, 29 Aug 2006 02:12:00 GMT

When I signed on with O’Reilly Media to write Rails In a Nutshell, I was sent a welcome package that included an audio recording of On Writing Well. One idea that On Writing Well stresses is that you can improve anything you write by cutting 50% of it. The recording even includes a stopping point where the listener is to stop and shorten the last thing he or she has written by 50%.

PuneRuby has posted an interview with Jean-Christian Fischer that I will quote:

I have the 50% rule as a measure of success: I’m usually able to reduce code I have written by 50% by applying better ruby techniques. I try to do that on my code and rejoice when I’m able to achieve that reduction.

I agree. Although some programmers might think this means obfuscation, Ruby offers many ways to cut your code and make it more acceptable. Some places to start:

  • Only use return when you really need multiple return paths.
  • Can you rewrite a conditional statement with a modifier?
  • Are you trapping an exception within a begin block? Do you really need that extra scope? Example: replace
    
      def catch_a_fish
        begin
          @line.cast
        rescue InsufficientBaitError
          @line.replenish_bait
        end
      end
      
    with
    
      def catch_a_fish
        @line.cast
      rescue InsufficientBaitError
        @line.replenish_bait
      end
      
  • Are you handling an exception? Can you use the rescue modifier? Example: replace
    
      def deep_copy
        @widgets.map do |w|
          begin
            w.dup
          rescue
            w
          end
        end
      end
      
    with
    
      def deep_copy
        @widgets.map { |w| w.dup rescue w }
      end
      
  • Can you rewrite a simple call to Enumerable#map with Symbol#to_proc? Rewrite
    
      @objects.map { |o| o.attribute }
      
    as
    
      @objects.map &:attribute
      

Ruby has many syntactical elements that help you write denser, more readable code. Experiment and see what matches your taste, and more importantly, contributes to readability.

Comments

  1. Kent said about 2 hours later:

    It always surprises me why the last example is considered more readable by Rails community. To me it is a clear example of code obfuscation.

  2. Josh H said about 4 hours later:

    Great stuff! I don’t remember the last time I learned so much Ruby from a single blog post. The last example could certainly be considered obfuscation since there’s so much going on behind the scenes. On the other hand, the point could be made that if it’s an accepted idiom, it’s not hard to read at all.

  3. Dr Nic said about 4 hours later:

    @Kent – I think once you are used to the syntax and its meaning it becomes very readable. So, use it 100 times and you’ll love it too :)

  4. JV said about 4 hours later:

    Dr Nic summarized my rebuttal fairly well, but to elaborate, I think Symbol#to_proc gives us a concise way of expressing bulk operations in Ruby. After using it a few times, I find it is very clear to select an attribute from each object within a structure in a declarative way; I forget that I am even iterating at all.

  5. Luke said about 18 hours later:

    I’m going to have to go with Kent. Symbol#to_proc is way to arcane for me. I think it’s one of the worst Perlisms in Ruby’s syntax.

  6. JV said about 21 hours later:

    Besides the punctuation marks, I see nothing perl-ish about it. It would seem more at home in a functional language; in fact, some would say It’s an incredibly elegant use of coercion and of closures.

  7. Sammy said 1 day later:

    Erk. Am I the only one who will stand up for explicit return statements, even if there’s only a single return path? I think it increases the readability of a function to have its return value explicit in the code.

    Unless it doesn’t return a value, of course, in which case nevermind.

  8. Jacob Fugal said 1 day later:

    I’m middle ground with Symbol#to_proc. I find the reduction of the block into a simple symbol argument very desirable, but don’t accept the mechanism as something I’d use in production code—even if I do think it’s nifty and clever.

    We can have the best of both worlds, I think by defining a new method, e.g. Enumerable#extract:

    module Enumerable
      def extract(attribute)
        # I'll cheat and use
        # Symbol#to_proc for the
        # implementation here
        self.map attribute.to_proc
      end
    end
    @users = User.find(:all)
    @names = @users.extract(:name)

    This sort of helper method I would be very happy to use in production code…

  9. Joe said 1 day later:

    I agree with Jacob F. Much more readable.

  10. Rob Sanheim said 2 days later:

    Hmm, I responded on my blog and trackback’ed, but it didn’t take. So here are my thoughts.

(leave url/email »)