File-based Code Encapsulation

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.

On 1/3/07, [email protected] [email protected] 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?

On Thu, 4 Jan 2007, Trans wrote:

def example
not just my command line tool. So I thoght maybe it would be better if
end
it is to be used. For example:

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

On Thu, 4 Jan 2007, spooq wrote:

On 1/3/07, [email protected] [email protected] 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

gabriele renzi wrote me with an interesting observation:

and could reduce ruby’s stdlib size of a 1/2% :slight_smile:
then i found this post from Guido van Rossum in 2003

[Python-Dev] Relative import

(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.

On 1/4/07, Trans [email protected] wrote:

then i found this post from Guido van Rossum in 2003

[Python-Dev] Relative import

(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

[email protected] wrote:

example.rb

That’s all well and good, but many of the scripts have generally useful
end

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.

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.