File-based Code Encapsulation

Discussion in 'Ruby' started by Trans, Jan 3, 2007.

  1. Trans

    Trans Guest

    Hi--

    I'm having a little debate with myself. On my current project I have a
    bunch of little reusable task scripts that a command line tool runs.
    The scripts are written as the top-level (although I actually simulate
    the top-level when running them). So for example a script would just be
    something like:

    # example.rb

    def example
    puts "This is an example!"
    end

    Then on the command line I would do:

    % mytool example
    This is an example!

    That's all well and good, but many of the scripts have generally useful
    routines and I would like them to be accessible by other programs too,
    not just my command line tool. So I thoght maybe it would be better if
    a module were required to wrap the defs.

    # another.rb

    module MyToolAnother

    def another
    puts "This is another!"
    end

    end

    That works, of course, but it adds an additonal layer of essentially
    redundant code, which IMHO is ugly.

    Then I got to thinking. Why don't we write resuable lib in this fashion
    anyway and just create our own containers on the fly when loading them?

    MyToolExample = load_as_module "example.rb"

    What intersting about that is then we could determine in what capacity
    it is to be used. For example:

    # adds module_function
    MyToolExample = load_as_function_module "example.rb"

    # adds self extend
    MyToolExample = load_as_self_extended_module "example.rb"

    Or even

    MyToolExample = load_as_class "example.rb"

    We could even have include and extend take a lib path.

    include "example.rb"

    Of course this effectively puts encapsulation, at least at the top
    level, on a per-file basis. But in many respects that seems kind of
    nice. It increases flexability and reduces configuration complexity.

    So what do your think? Is this technique worth promoting? Or am I being
    silly and should just wrap all my scripts in modules?

    T.
    Trans, Jan 3, 2007
    #1
    1. Advertising

  2. Trans

    Guest

    On Thu, 4 Jan 2007, Trans wrote:

    > Hi--
    >
    > I'm having a little debate with myself. On my current project I have a
    > bunch of little reusable task scripts that a command line tool runs.
    > The scripts are written as the top-level (although I actually simulate
    > the top-level when running them). So for example a script would just be
    > something like:
    >
    > # example.rb
    >
    > def example
    > puts "This is an example!"
    > end
    >
    > Then on the command line I would do:
    >
    > % mytool example
    > This is an example!
    >
    > That's all well and good, but many of the scripts have generally useful
    > routines and I would like them to be accessible by other programs too,
    > not just my command line tool. So I thoght maybe it would be better if
    > a module were required to wrap the defs.
    >
    > # another.rb
    >
    > module MyToolAnother
    >
    > def another
    > puts "This is another!"
    > end
    >
    > end
    >
    > That works, of course, but it adds an additonal layer of essentially
    > redundant code, which IMHO is ugly.
    >
    > Then I got to thinking. Why don't we write resuable lib in this fashion
    > anyway and just create our own containers on the fly when loading them?
    >
    > MyToolExample = load_as_module "example.rb"
    >
    > What intersting about that is then we could determine in what capacity
    > it is to be used. For example:
    >
    > # adds module_function
    > MyToolExample = load_as_function_module "example.rb"
    >
    > # adds self extend
    > MyToolExample = load_as_self_extended_module "example.rb"
    >
    > Or even
    >
    > MyToolExample = load_as_class "example.rb"
    >
    > We could even have include and extend take a lib path.
    >
    > include "example.rb"
    >
    > Of course this effectively puts encapsulation, at least at the top
    > level, on a per-file basis. But in many respects that seems kind of
    > nice. It increases flexability and reduces configuration complexity.
    >
    > So what do your think? Is this technique worth promoting? Or am I being
    > silly and should just wrap all my scripts in modules?
    >
    > T.


    wrap up the functionality into a lib, require that from your scripts, and make
    accessing instance methods from the command-line easy. i've used this pattern
    many times. here is an example from our NRT (near-real-time) system which
    allows me to call any module function from the command line:

    mussel: ~ > cat nrtlib.rb
    module NRT
    def self.foobar(*a) p a end

    # many, many, many lines of code
    end


    now i have a single command line program which loads this lib then takes the
    first command line argument as a method to send to the module. remaining
    command-line parms are parsed in a sensible way allowing ints, strings,
    floats, bools, lists, hashes, and combinations of those. whatever value is
    returned by the function is dumped on stdout. examples.


    mussel:~ > nrt foobar
    --- []

    mussel:~ > nrt foobar 42
    ---
    - 42

    mussel:~ > nrt foobar 1,2,3
    ---
    - - 1
    - 2
    - 3

    mussel:~ > nrt foobar 1,2,3 k:v
    ---
    - - 1
    - 2
    - 3
    - k: v

    mussel:~ > nrt foobar 1,2,3 k:v a:b
    ---
    - - 1
    - 2
    - 3
    - k: v
    a: b

    mussel:~ > nrt foobar 42.0 string
    ---
    - 42.0
    - string

    mussel:~ > nrt foobar 42.0 string key:val
    ---
    - 42.0
    - string
    - key: val


    now, yaml input is also allows by giving '--' as a commnad line arg

    mussel:~ > nrt foobar 42.0 string key:val | nrt foobar --
    ---
    - 42.0
    - string
    - key: val

    and the arg '-' indicates a simple unix style list, one element per line, on
    stdin:

    mussel:~ > printf "a \n b \n c \n" | nrt foobar -
    ---
    - a
    - b
    - c


    the result is that any library/module routine is instantly availible from the
    command line - makes testing a breeze!

    obviously not all routines are easy to use this way but, by sticking to simple
    interfaces/function call signatures many of them can be.

    it's a useful pattern.

    food for thought.


    -a
    --
    if you find yourself slandering anybody, first imagine that your mouth is
    filled with excrement. it will break you of the habit quickly enough. - the
    dalai lama
    , Jan 3, 2007
    #2
    1. Advertising

  3. Trans

    spooq Guest

    On 1/3/07, <> wrote:

    > now i have a single command line program which loads this lib then takes the
    > first command line argument as a method to send to the module. remaining
    > command-line parms are parsed in a sensible way allowing ints, strings,
    > floats, bools, lists, hashes, and combinations of those. whatever value is
    > returned by the function is dumped on stdout.


    Would it be possible for you to post this code?
    spooq, Jan 4, 2007
    #3
  4. Trans

    Guest

    On Thu, 4 Jan 2007, spooq wrote:

    > On 1/3/07, <> wrote:
    >
    >> now i have a single command line program which loads this lib then takes
    >> the
    >> first command line argument as a method to send to the module. remaining
    >> command-line parms are parsed in a sensible way allowing ints, strings,
    >> floats, bools, lists, hashes, and combinations of those. whatever value is
    >> returned by the function is dumped on stdout.

    >
    > Would it be possible for you to post this code?


    sure. i've been trying to organize it into a library, but it's hard to
    abstract. i'll see if i can gin up something later today.

    regards.

    -a
    --
    in the practice of tolerance, one's enemy is the best teacher.
    - the dalai lama
    , Jan 4, 2007
    #4
  5. Trans

    Trans Guest

    Loading, Python vs. Ruby [was: File-based Code Encapsulation]

    gabriele renzi wrote me with an interesting observation:

    > If you just add
    >
    > and a directory is a module, too so that
    > require 'foo'
    > loads module Foo
    > and
    > require 'foo/bar'
    > requires module Foo::Bar
    >
    > and you have the python's import system, which is a very good thing imo
    > and could reduce ruby's stdlib size of a 1/2% :)


    then i found this post from Guido van Rossum in 2003

    http://mail.python.org/pipermail/python-dev/2003-December/041065.html

    (did it ever happen?)

    this really gets me wondering, how do Ruby's and Python's loading
    mechanisms match-up? which do you think is better?

    T.
    Trans, Jan 5, 2007
    #5
  6. Trans

    Trans Guest

    wrote:
    > On Thu, 4 Jan 2007, Trans wrote:
    >
    > > Hi--
    > >
    > > I'm having a little debate with myself. On my current project I have a
    > > bunch of little reusable task scripts that a command line tool runs.
    > > The scripts are written as the top-level (although I actually simulate
    > > the top-level when running them). So for example a script would just be
    > > something like:
    > >
    > > # example.rb
    > >
    > > def example
    > > puts "This is an example!"
    > > end
    > >
    > > Then on the command line I would do:
    > >
    > > % mytool example
    > > This is an example!
    > >
    > > That's all well and good, but many of the scripts have generally useful
    > > routines and I would like them to be accessible by other programs too,
    > > not just my command line tool. So I thoght maybe it would be better if
    > > a module were required to wrap the defs.
    > >
    > > # another.rb
    > >
    > > module MyToolAnother
    > >
    > > def another
    > > puts "This is another!"
    > > end
    > >
    > > end
    > >
    > > That works, of course, but it adds an additonal layer of essentially
    > > redundant code, which IMHO is ugly.
    > >
    > > Then I got to thinking. Why don't we write resuable lib in this fashion
    > > anyway and just create our own containers on the fly when loading them?
    > >
    > > MyToolExample = load_as_module "example.rb"
    > >
    > > What intersting about that is then we could determine in what capacity
    > > it is to be used. For example:
    > >
    > > # adds module_function
    > > MyToolExample = load_as_function_module "example.rb"
    > >
    > > # adds self extend
    > > MyToolExample = load_as_self_extended_module "example.rb"
    > >
    > > Or even
    > >
    > > MyToolExample = load_as_class "example.rb"
    > >
    > > We could even have include and extend take a lib path.
    > >
    > > include "example.rb"
    > >
    > > Of course this effectively puts encapsulation, at least at the top
    > > level, on a per-file basis. But in many respects that seems kind of
    > > nice. It increases flexability and reduces configuration complexity.
    > >
    > > So what do your think? Is this technique worth promoting? Or am I being
    > > silly and should just wrap all my scripts in modules?
    > >
    > > T.

    >
    > wrap up the functionality into a lib, require that from your scripts, and make
    > accessing instance methods from the command-line easy.


    in this particluar case it's not suitable to separate the functionality
    into separate lib b/c it's important that these scripts be
    self-contained.

    > i've used this pattern
    > many times. here is an example from our NRT (near-real-time) system which
    > allows me to call any module function from the command line:
    >
    > [snip examples]
    >
    > the result is that any library/module routine is instantly availible from the
    > command line - makes testing a breeze!
    >
    > obviously not all routines are easy to use this way but, by sticking to simple
    > interfaces/function call signatures many of them can be.
    >
    > it's a useful pattern.
    >
    > food for thought.


    very cool. yea, i wondn't mind adding a tool like that to my current
    project. i wonder how extensive a tool like that could be. would it be
    possible to run arbitrary methods --even if they were in classes or
    non-function modules?

    T.
    Trans, Jan 5, 2007
    #6
  7. Re: Loading, Python vs. Ruby [was: File-based Code Encapsulation]

    On 1/4/07, Trans <> wrote:
    > then i found this post from Guido van Rossum in 2003
    >
    > http://mail.python.org/pipermail/python-dev/2003-December/041065.html
    >
    > (did it ever happen?)


    Yes.

    > this really gets me wondering, how do Ruby's and Python's loading
    > mechanisms match-up? which do you think is better?


    I prefer Python's, honestly. I also like that in Perl, the convention
    at least is that what you use is what the namespace is. So, if I use

    use File::Copy;

    Then the functions are in File::Copy::* by convention.

    Mind you, you'd typically use it like

    use File::Copy qw(move copy);

    And just call move() or copy() directly.

    In Ruby I guess that would be

    use File::Copy
    include File::Copy

    to achieve the same?

    Coming from Perl and Python, I did find Ruby's system confusing. The
    poor documentation makes it even more so.

    Mike
    --
    Michael P. Soulier <>
    "Any intelligent fool can make things bigger and more complex... It takes a
    touch of genius - and a lot of courage to move in the opposite direction."
    --Albert Einstein
    Michael P. Soulier, Jan 5, 2007
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. BLF
    Replies:
    4
    Views:
    1,277
    Mike Treseler
    Aug 7, 2004
  2. Andrew FPGA
    Replies:
    14
    Views:
    1,146
    Jim Lewis
    Oct 5, 2005
  3. Jack
    Replies:
    1
    Views:
    478
  4. Wayne Berke
    Replies:
    0
    Views:
    391
    Wayne Berke
    Sep 19, 2003
  5. Justin
    Replies:
    4
    Views:
    316
    Michael Fuhr
    Aug 27, 2004
Loading...

Share This Page