Object Orientation

Posts tagged with "Object Orientation."
  • 30


    Objectified Beer

    I got another thing out of my recent conversation with Katrina Owen: a will-not-let-go itch to try a programming exercise that she mentioned. I'm such a sucker for a challenge.

    Katrina spoke of an assignment that her and Sandi Metz have used in their object orientation trainings. She said that they build an OO implementation of the 99 Bottles of Beer song, "mainly removing ifs and such." There may be more to the actual task than this, but I ran with that brief explanation.

    As I often say, you'll probably learn more by trying the exercise for yourself before you read through my thoughts about it. Give it a go if you can spare the time.

    Diff Driven Development

    I decided to throw some scaffolding into the master branch of a Git repository. I figured I could then branch off of that with each idea, to keep trying things out.

    I started by constructing a trivial framework for running and verifying the song. That consisted of an executable:

    #!/usr/bin/env ruby -w
    require_relative "../lib/bottles_of_beer"
    verses = ARGV.first =~ /\A\d+\z/ ? ARGV.shift.to_i : 99

    Read more…

  • 21


    Decorators Verses the Mix-in

    It is a neat time to be involved in the Ruby community, if you ask me. A large portion of us are currently studying the techniques for doing good object oriented development. We are looking at the ideas that have come before and trying to decide the best ways to apply those ideas to our favorite language. This leads to blog posts, forum threads, and conference talks about what we are learning. No matter what, we all gain from explorations like this. Everybody wins as our collective knowledge grows. We all deserve gold stars.

    So far, there's one point pretty much everyone agrees on: composition should typically be preferred to inheritance. The trickier part of that discussion though is deciding what composition looks like in Ruby. Generally you see Rubyists comparing the merits of decorators and mix-ins. [Note: the comments correctly pointed out that this was a bad use of the word "composition" on my part, to describe mix-ins.] There's a very representative thread on the excellent Objects on Rails mailing list.

    Read more…

  • 1


    Single Method Classes

    [Update: I've changed my mind about some of the following due to this excellent counter argument.]

    In the words of Dennis Miller, "I don't want to get off on a rant here, but…"

    There's something that drives me crazy and I see it in so much Ruby code. I see it in the documentation for our key projects; I see Rubyists of all skill levels doing it; it's just everywhere.

    Let's talk about when the use of a Class is and is not appropriate.

    The Chained new()

    Here's an example of one form of code that bugs me:

    class Adder
      def add(n)
        40 + n
    p Adder.new.add(2)

    The problem here is that a Class has been used, probably because as Rubyists that's always our default choice, but it's the wrong fit for this code. A Class is for state and behavior. The example above is just using behavior. No state is maintained.

    A handy tip for sniffing out this problem is watching for a call to new() in the middle of method chaining as we have here. If you always use a Class like that, it's not really a Class. Put another way, if an instance never gets assigned to a variable, something has likely gone wrong with the design.

    Read more…

  • 21


    Learn to Love Mix-ins

    The road to mastering Ruby is paved with understanding some key Ruby concepts. Mix-ins are one of those concepts. I'm sure everyone reading this knows the mechanics of how mix-ins work, but it pays to spend some time really thinking about all that mix-ins imply. Let's do just that.

    Adding a Type

    One of the primary reasons that Ruby needs mix-ins is that it does not support multiple inheritance. That leaves mix-ins as our only option for modeling hybrid objects. It's the way Ruby programmers can add another type.

    That's a good way to think about it too: adding a type.

    Take pagination, for example. Pagination methods are usually defined to return an object like this:

    class PaginatedCollection < Array
      # ... paginated helpers defined here ...

    That's never really felt right to me though.

    First, inheriting from Ruby's core classes can come back to bite you in some scenarios. The reason is that Ruby makes some performance tradeoffs to keep the core classes fast, but those tradeoffs mean that those classes don't always perfectly follow Ruby's rules.

    Read more…

  • 1


    The Right Ruby Mix

    Ruby is a melting pot language. It borrows ideas from many things that came before. It combines several different programming philosophies.

    This aspect of the language can be a plus. It means that Ruby is suited to multiple applications. It also opens up some pragmatic shortcuts. Even better, it sometimes encourages us to think about problems using a different lens of thought.

    Of course, this cuts both ways. Ruby living at the intersection of many ideas does have some downsides. First, there's more to learn than you find with some simpler languages. There's a cost for the extra knowledge we have to track. Even worse though, in my opinion, is that it's sometimes hard to know exactly what Ruby's style really is.

    Going Off Script

    One culture Ruby borrowed heavily from is that of the so called "Scripting Languages." The main source of these features was Perl, in my opinion, but you can also find influences from Bash and other sources. I found this comforting since I came to Ruby from Perl, but the truth is that it bothers some people.

    Read more…

  • 20


    Infinite Streams

    I've tried to summarize this chapter a couple of times now, but I keep getting tripped up over syntax. So, let's talk about that…

    Functional Perl

    Obviously, the examples in the book can be more or less directly translated. Here's a sample from the first couple of pages:

    #!/usr/local/bin/ruby -w
    ### Stream Methods ###
    def node(head, tail)
      [head, tail]
    def head(stream)
    def tail(stream)
      tail = stream.last
      if tail.is_a?(Proc)
    def drop(stream)
      head                 = head(stream)
      stream[0], stream[1] = Array(tail(stream))
    def show(stream, limit = nil)
      while head(stream) && (limit.nil? or (limit -= 1) > -1)
        print drop(stream), $, || " "
      print $/
    ### Examples ###
    def upto(from, to)
      return if from > to
      node(from, lambda { upto(from + 1, to) })
    show(upto(3, 6))  # => 3 4 5 6
    def upfrom(start)
      node(start, lambda { upfrom(start + 1) })
    show(upfrom(7), 10)  # => 7 8 9 10 11 12 13 14 15 16

    Read more…

  • 4


    Pathname and Enumerator

    I'm always digging around in Ruby's standard library looking for new toys. It's one-stop-shopping for geeks. I love it.

    There really are some great tools in there that can help you do your work easier. Let me tell you a little about two I am using on a current application.


    Pop Quiz: Which would you rather work with?

    if File.exist? some_dir
      data = File.read( File.join( File.dirname(some_dir),
                                   File.basename(some_file) ) )
      # ...


    if some_dir.exist?
      data = (some_dir.dirname + "another_dir" + some_file.basename).read
      # ...

    If you prefer the second version, the Pathname library is for you.

    Ruby's file manipulations are usually fine for normal work, but anytime I start messing with directories I really start feeling the pain. For that kind of work, I find Pathname to be a superior interface. My current project makes great use of the methods in the above example as well as Pathname#entries, Pathname#relative_path_from, and more.

    Read more…