On Mar 18, 12:59 pm, "Sean O'Halpin" <sean.ohal... / gmail.com> wrote:
>
> True enough. As I said, I'm only surmising what Trans is after. I'm
> not criticising your response to the concrete example (after all,
> it is both pragmatic and to the point). Rather, I'm taking the
> question Trans posed as an opportunity to discuss what I consider best
> practice in the more general case.

I'd like to present another example --a simpler one in a sense, of
direct extension vs. using modules. I will leave out most the code for
brevity sakes but consider, but here is an example where I took code
that was straight core extensions and "modulized" it:

  # -- random.rb

  # Can't modulize Kernel b/c of double module inclusion problem.

  module Kernel

    def maybe(chance = 0.5, &block)
      if block then
        yield if rand < chance
      else
        rand < chance
      end
    end

    ...
  end

  module Random

    def self.append_features(mod)
      if mod == ::Kernel # not needed
        mod.send(:include, Random::Kernel)
      elsif mod == ::Array
        mod.send(:include, Random::Array)
      elsif mod == ::Hash
        mod.send(:include, Random::Hash)
      elsif mod == ::String
        mod.send(:include, Random::String)
      else
        raise TypeError
      end
    end

    #

    module Array

      def at_rand
        self.at( rand( size ) )
      end

      ...
    end

    #

    module Hash

      def rand_key
        keys.at( rand(keys.size) )
      end

      ...
    end

    #

    module String

      def self.included(base)
        base.extend(Self)
      end

      module Self

        def random(max_length = 8, char_re = /[\w\d]/)
          # gmosx: this is a nice example of input parameter checking.
          # this is NOT a real time called method so we can add this
          # check. Congrats to the author.
          raise ArgumentError.new('char_re must be a regular
expression!') unless char_re.is_a?(Regexp)
          string = ""
          while string.length < max_length
              ch = rand(255).chr
              string << ch if ch =~ char_re
          end
          return string
        end

        def rand_letter
          (rand(26) + (rand(2) == 0 ? 65 : 97) ).chr
        end

      end

      def at_rand( separator=// )
        #separator = self.class.patterns( separator )
        self.split(separator,-1).at_rand
      end

      ...

    end

  end

  class Array
    include Random
  end

  class Hash
    include Random
  end

  class String
    include Random
  end

Other Ruby coder's might look at this and think, "clever". I look at
it and think, "obfuscated". First off there is Kernel, b/c of the
double module inclusion problem it can't participate in the whole
"clever" affair. Then there is Self and the included callback hack to
get the class-level methods in there. And on top of it all, there is
the simple fact that I had to create and include a bunch of new
modules and all the overhead that comes with them -- when all I want
to do add a few methods to the core classes/modules. To throw in a
little irony as well, the main reason I even bothered to do this, was
not to help avoid method clash (a fairly unavoidable problem really),
but to get better results for RDoc --and that fact really makes me
sick.

T.