From: James Edward Gray II Date: 2005-03-23T08:48:49+09:00 Subject: Re: Any guides for good coding in Ruby? On Mar 22, 2005, at 4:41 PM, vruz wrote: > An rpa guide to decent API design: > > http://rpa-base.rubyforge.org/wiki/wiki.cgi?GoodAPIDesign I just read this collection of very good tips. Thanks for the link! One section does bother me there though: > Put methods where they belong > > It's not a Ruby API design idiom, but anyway (perhaps we should split > this page in two: Ruby API idioms and design advices). > > Classes are supposed to reflect reality. Thus, you should generally > put your methods where they belong, to reduce coupling. For example, > typical "data classes" should not have "actions", but methods to > access their data. > > Example: > # > # Bad API > # > class GraphicElement > def draw(canvas) > raise "Implement me!" > end > end > class Circle < GraphicElement > def draw(canvas) > # Draw directly into the canvas > # (couples Circle with the canvas, as Circle > # follows this particular canvas API) > end > end > > # > # Good API (definitely better than above, perhaps not the best) > # > class GraphicElement > def to_canvas(resolution) > raise "Implement me!" > end > end > class Circle < GraphicElement > def to_canvas(resolution) > # Convert circle to an array of arrays of pixels, > # taking into account the resolution parameter > end > end > class CanvasPainter > def paint(elmt, canvas, color=Color::BLACK, > centerX=0, centerY=0) > elmt.to_canvas.each do |x,y| > canvas.put(centerX+x, centerY+y, color) > end > end > end I can't decide if it's just the example or the whole section, but this one just doesn't feel right to me. I would much rather have a class rendering itself (who better qualified?), then providing accessor like data for others to do it. Push, don't pull, right? An excellent book on this topic is Holub on Patterns, if you're interested. Anyway, just wanted to share. I really did love the page. James Edward Gray II