Tutorial :What's an example of Ruby code that's “too clever”? [closed]



Question:

I was having a discussion with some programmer friends who said that they see Ruby programmers (in particular) producing a lot of code that's "too clever". So I'm wondering what would that look like? I'm referring to the unnecessary use of an obscure language feature in a context in which something straightforward would have worked just as well or better. Know any good Ruby examples of this?


Solution:1

After giving a straight answer to your question, I'd like to also dispute the premise; whenever a group of programmers characterizes the users of another language in this way, the odds are that they are telling you more about themselves than about the community they are describing.

You could, for example, accuse c programmers of being too obsessed with low level details, or haskell programmers with being blinded by their desire for functional purity; perl mongers for brevity, etc. But you would, IMHO, by getting the causality backwards when you do so.

When I want to write a program that is best expressed in a certain style, I try to choose a language that supports that style. Sometimes you want a tool that lets you do unusual things, and for such a task having a language such as ruby is as valuable as having mathematica for math or javascript for browser manipulation in your toolkit. If I want to play with typography I hop into postscript because that's what it's best at.

It's like saying "Have you ever noticed that people who use power drills are always poking holes in things?" It's true, but it kind of misses the point.


Solution:2

class Tree    def initialize*d;@d,=d;end    def to_s;@l||@r?"<#{@d},<#{@l}>,<#{@r}>>":@d;end    def total;(@d.is_a?(Numeric)?@d:0)+(@l?@l.total: 0)+(@r?@r.total: 0);end    def insert d      alias g instance_variable_get      p=lambda{|s,o|d.to_s.send(o,@d.to_s)&&        (g(s).nil??instance_variable_set(s,Tree.new(d)):g(s).insert(d))}      @d?p[:@l,:<]||p[:@r,:>]:@d=d    end  end  


Solution:3

The double-bang: !!something

I'm not gonna write what it does. Forget that you ever saw this syntax.


Solution:4

The output phase of yaml.rb; that's why I co-authored zaml.rb. The standard yaml version does all sorts of metaprogramming (it was originally written by why-the-lucky-stiff, who I generally admire) but by replacing it with a straight forward hierarchical version that directly maps to the class tree we were able to eliminate several O(n^3) cases, resulting in a factor of ten speedup for cases of interest, fix several bugs, and do so in a fraction of the code.

Plus, even people who aren't ruby gurus can see what it does.


Solution:5

Many of the examples in this article would seem to qualify:

21 Ruby Tricks You Should Be Using In Your Own Code.

The title of the article was a bit of a giveaway, given that it reads "Should" instead of "Should Not". Code "should" be transparent. Code "should not" be tricky.


Solution:6

Any use of metaprogramming without having thought damn hard about whether there's a better way to acheive this using the normal, non-'meta' idioms of the language, I tend to find annoying.

An obsession with "DRY" (don't repeat yourself) where some fiendish piece of metaprogramming spaghetti is invoked to avoid repeating yourself, say, twice in a simple and actually-more-straightforward-and-readable-than-the-alternative fashion.

Any use of 'eval' in particular. As metaprogramming goes, this one should be your absolute last resort after trying everything else. eg a lot of rubyists appear not to have heard of Class#define_method.


Solution:7

I'm not sure if this qualifies as "too clever," but I have seen code that made me wonder if the author was either a genius or an idiot. One developer seemed to have a rule that no method should have more than two lines of code. That pushed the call stack very deep and made debugging rather difficult. The upside is that his overall design was very abstract and even elegant from a distance.


Solution:8

Cucumber (or RSpec Stories)

Quoted from the above RSpec Stories link:

Based around plain text descriptions of application behaviour, it lets you write integration tests with good reuse and good diagnostic reporting.

For example, here's a story I wrote to check the login process.

Story: login as an existing user      As an unauthenticated user      I want to log in to Expectnation      So I can see my account details        Scenario: login details are correct              Given an event provider              And my test@example.org account              When I log in with email test@example.org and password foofoo              Then I will be logged in              And I will be shown the account page  

The words such as "Given", "When" and "Then" are cues to the story runner to execute some code. Behind the story sits a collection of steps. Here's a couple of steps from this test:

  Given "my $email account" do |email|      @user = find_or_create_user_by_email({:email => email,        :password => 'foofoo',        :password_confirmation => 'foofoo'})    end      When "I log in with email $email and password $password" do |email, password|      post '/user/account/authenticate',        :user => {:email => email, :password => password}    end  

Notice how a clever bit of string matching allows you to pass parameters from the story prose.

With a small bit of bolting together, the prose stories are then run as code and the tests executed.


Solution:9

It depends. (I love "it depends" questions)

It depends on the knowledge of the writer and reader. I used to think the use of Symbol#to_proc in Rails was unnecessarily arcane, for example, preferring

a.map { |e| e.downcase }  

to

a.map(&:downcase)  

Now I'm happy when I read it, although I still don't think to write it.

There are areas of libraries (Rails and others) where I have felt excessive and self-indulgent metaprogramming may have occurred but again the division between "too clever" and "really very clever indeed" is often paper-thin. DSLs are a good area: the ways in which "macros" are made available within classes (think of all that declarative goodness in things like ActiveRecord::Base or ActionController::Base) is very hard for a relative novice to understand and would probably seem like over-cleverness. It did to me. Now I find myself referencing the same code for guidance as I implement similar capabilities.


Solution:10

method_missing can be abused and it's one of those things that may cause you to pull your hair out when you have to fix a bug 3 months after you've written code.


Solution:11

Take a look at the source of Markaby. Insanity.


Solution:12

You shouldn't have to go from method to method to method to try to figure out what in the hell something is doing, for the sole purpose of not repeating a few lines of code. Being too focused on the LOC count and ultra-skinny methods might feel cool at the time but is time-consuming for someone else trying to debug or follow the code (and that someone may be you months later).


Solution:13

compare:

if MODELS.keys.inject(true) {|b, klass| b and klass.constantize.columns.map(&:name).include? association.options [:foreign_key]} then     # ...   end  

1 line (if), 132 chars, 132 avg len, 22.9 flog

vs

fk = association.options[:foreign_key]   columns = MODELS.keys.map { |key| key.constantize.columns.map { |c| c.name } }   if columns.all? {|column| column.include? fk} then     # ...   end  

4 lines, 172 chars, 43 avg chars, 15.9 flog

much faster too.

Original author actually argued maintainability for the first version.


Solution:14

Recently uncovered this monster:

def id    unless defined?(@id)      @id = if id = local_body.to_s[/(?:#\s*|@[[:punct:]]?)#{URL_REGEX}/,1]              id.to_i            end    end    @id  end  

Not that I disagree with caching a calculation, it could just be far more clear.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »