Hacker News new | ask | show | jobs
by richcollins 5934 days ago
I've been using Ruby since 2005 and I am a top 100 contributor to Rails (http://contributors.rubyonrails.org/). Rails design suffers for its heavy use of "keyword arguments".

positional arguments for more than two or so things creates connascence of position

Which is precisely the reason that you shouldn't pass more than two arguments to a method (unless you are creating a list or hash for their intended purpose). If you have more than two arguments to a method, it's a sign that you should reify them into an object.

Using block based DSLs so that you can break things down into small functions that each do their part is a good way around this

Why do people love making things complicated by misusing blocks. Just create an object and set slots on it. Blocks are best used for delaying computation, not setting up state.

I think that Zed Shaw's essay on the "Master" and the "Expert" is applicable here: http://www.zedshaw.com/essays/master_and_expert.html

1 comments

Wow, and this is exactly the kind of douchebaggery I was trying to get away from in my book. You know, I think on the first page I mention that the answer to "what the best way" to do something in Ruby is always "it depends". The notion that you can follow singular design principles in all situations is absurd, if you ask me.

Context is king, and what you've done is taken a single point from my book, ripped out its context, strawmanned it to death, and used it to bolster you're own "Top 100 rails" status.

I encourage readers to actually see what I had to say in the book by downloading the PDF before taking these arguments too seriously. If there are some constructive examples to be shown that seem promising and pass peer review, they'll definitely make it into the open source version.

It might even be worth it to write up a section describing the tradeoffs that richcollins has pointed out, but it's definitely not something as universal as he makes it sound.

used it to bolster you're own "Top 100 rails" status.

I've mostly stopped using Rails and Ruby in favor of Io, so I have no interest in bolstering my Rails status. I was just providing evidence to counter your assertion that I was a Ruby newb.

The notion that you can follow singular design principles in all situations is absurd, if you ask me.

I agree that "it depends", but using Hashes as arguments has become idiomatic Ruby, which is unfortunate in most cases.

I wasn't assuming you were a newb, just that you didn't have much exposure to what are commonly regarded as well designed Ruby libraries. It didn't occur to me that you'd have had that exposure and yet sound as if you were shocked and appalled about what is common practice.

I still would really like to see examples of well designed open source Ruby projects that follow what you consider to be decent design principles. I think that'd make a much stronger case for your argument, and might open my eyes to something that's been in a blind spot.

Personally, I feel like a certain amount of API design is bound to what consumers will expect. We can certainly stretch and shift their tendencies, but if we fly in the face of them, our perfection in a vacuum will never be appreciated.

Which libraries do you consider well designed? I'll let you know how I think that they could be improved.
I've already written an entire book on this and given it away for free. I suggest you read it and write a review. Be specific, and show good counterexamples. I'll be happy to link you when you do.

Until then, stop acting like you're some sort of authority (NOTE: This is not to claim I am -- because I'm not and no one is.) I just think it'd make sense to put your ideas into a bit of context so people can see that you're not just being critical for the sake of being critical.

    #from your book
    
    def distance(*points)
      case(points.length)
      when 2
        x1,y1,x2,y2 = points.flatten
      when 4
        x1,y1,x2,y2 = points
      else
        raise ArgumentError, "Points may be specified as [x1,y1], [x2,y2] or x1,y1,x2,y2"
      end
      Math.hypot(x2 - x1, y2 - y1)
    end

    puts distance(1, 2, 5, 6)
    puts distance([1, 2], [5, 6])

    # why would you choose to make a complicated interface that requires a complicated implementation?

    # simple, clear interfaces that allow for simple implementations
    # are almost always preferrable to complicated ones that save a
    # keystrokes through syntax

    class Point
      attr_accessor :x
      attr_accessor :y
  
      def initialize
        self.x = 0
        self.y = 0
      end
  
      def self.with(x, y)
        new.set(x, y)
      end
  
      def set(x, y)
        self.x = x
        self.y = y
        self
      end
  
      def distance_to(a_point)
        Math.hypot(a_point.x - x, a_point.y - y)
      end
    end

    puts Point.with(1, 2).distance_to(Point.with(5, 6))