Ask a Question related to Ruby, Design and Development.

  1. #41

    Default Re: "stereotyping"

    > From: Rasputin [mailto:rasputin@idoru.mine.nu]
    > It seemed like you were more interested in a way to know how an API
    > will use your object. Why not send in a probe?
    >
    > Pass a custom object in that has a method_missing? method that does
    > a ludicrous amount of debugging of how its called. That would tell you
    > how an API is actually using your object, what methods it calls and how.
    Below is a quick hack to do that. Needs work. Needs redirection of IO. But
    its kinda cute.. Has issues with side effects, of course, and printing
    crapola all over the place.

    # Usage:
    # ins = ObjectProbe::Inspector.new( SomeObject.new )
    # ins.probe
    module ObjectProbe

    class Inspector
    def initialize( object )
    @object = object
    end

    def target_class
    @object.class
    end

    def target_methods
    @object.methods - Object.new.methods
    end

    def probe
    puts "Probing: #{target_class}"
    target_methods.each do | method |
    meta = MetaMethod.new( method.intern, @object )
    print " Method: #{method}( "
    meta.args.each do | arg |
    print "[ #{arg.___requires.join(', ')} ], "
    end
    puts
    end
    end
    end

    class MetaMethod
    def initialize( method, object )
    @method = method
    @object = object
    end

    def symbol
    @method
    end

    def arity
    m = @object.method( @method )
    m.arity
    end

    def args
    result = []
    arity.times { result << DummyArgument.new }
    begin
    @object.send( @method, *result )
    rescue
    puts $!.to_s
    end
    result
    end
    end

    class DummyArgument
    attr_reader :___requires

    def initialize
    @___requires = []
    end

    def DummyArgument.clean_out_methods
    methods_list = Object.new.methods
    methods_list.each do | m |
    meth = m.intern
    # keep the important fns, and keep __send__ and __id__ to prevent
    warnings.
    next if( meth == :method_missing || meth == :__send__ || meth ==
    :__id__ )
    module_eval <<-"end_eval"
    alias_method :__#{meth.to_i}__, #{meth.inspect}
    def #{meth.id2name}(*args, &block)
    method_missing( :#{meth}, *args )
    __#{meth.to_i}__(*args, &block)
    end
    end_eval
    end
    end

    def method_missing( symbol, *args )
    @___requires << symbol
    end

    clean_out_methods
    end
    end


    David Naseby Guest

  2. Similar Questions and Discussions

    1. "stereotyping" (was: Strong Typing (Managing metadata about attribute types) )
      On Thu, 20 Nov 2003 14:52:17 +0900, Thien Vuong wrote: Again: why? Why do you need intrinsic interface validation? As Michael Campbell noted, if...
    2. "stereotyping" (was: Strong Typing (Managing metadata about attribute types)
      On Thu, 20 Nov 2003 14:08:51 +0900, Simon Kitching wrote: You're right. Drb uses Marshal#dump and Marshal#load. YAPC uses YAML which has...
    3. "stereotyping" (was: Strong Typing (Managing metadataabout attribute types)
      Simon, there is another way, the classes can be substantiated only on the remote end and all messages are routed to the remote object. the local...
    4. "stereotyping" (was: Strong Typing (Managing metadataabout attribute types)
      Simon, yes, i understood that the first time. (sorry, i just spent a couple of hours reading through hugely verbose posts that tended toward...
    5. "stereotyping" (was: Strong Typing (Managing metadata about attribute types) )
      On Thu, 20 Nov 2003 08:21:34 +0900, Sean O'Dell wrote: So does the existing one: foo.backend NoMethodError: undefined method `backend' for...
  3. #42

    Default Re: "stereotyping"

    Sean O'Dell wrote:
    >>But again, its less hassle to document your API than to do rigourous
    >>argument checking.
    >>
    >>
    >
    >No, it's more hassle. To update a document, you have to open a different
    >file, and if you make a typo or just plain write it wrong, there is nothing
    >to stop you from doing so. Interfaces can be described in the same source
    >file as your class definition, so it's easy to find and update, plus, you
    >can't update it wrong, or your code gives you errors.
    >
    >
    You always have to update documentation when you change something.
    Having an interface checking
    system doesn't mean that you don't have to document your code. So in
    effect, having interfaces means
    you have to update two different places when you make an interface
    change (three, actually, if you
    count the code that uses the interface), and there's more things that
    can get out of sync.

    Besides, with systems like RDoc you can make all documentation
    annotations in your source and
    generate the documentation from there, so it's really no more or less
    convenient than having an
    interface definition in your source, at least for documentation purposes.

    - Dan


    Dan Doel Guest

  4. #43

    Default Re: "stereotyping"

    On Friday 21 November 2003 01:50 pm, Dan Doel wrote:
    > Sean O'Dell wrote:
    > >>But again, its less hassle to document your API than to do rigourous
    > >>argument checking.
    > >
    > >No, it's more hassle. To update a document, you have to open a different
    > >file, and if you make a typo or just plain write it wrong, there is
    > > nothing to stop you from doing so. Interfaces can be described in the
    > > same source file as your class definition, so it's easy to find and
    > > update, plus, you can't update it wrong, or your code gives you errors.
    >
    > You always have to update documentation when you change something.
    Not always. If you provide code to others and are responsible enough to do
    so, sure. On team projects, documentation happens very sporadically. RAA is
    full of non or poorly documentation code. It is a good habit to have, but
    humans often don't keep up with as well as they should.
    > Having an interface checking
    > system doesn't mean that you don't have to document your code. So in
    > effect, having interfaces means
    > you have to update two different places when you make an interface
    > change (three, actually, if you
    > count the code that uses the interface), and there's more things that
    > can get out of sync.
    Or, you could argue, the interface description could serve as the source for
    your API documentation. I'm going to add that to the wiki; the idea just
    occurred to me. Automatic documentation generation would be extremely easy
    if you had interface objects to query.
    > Besides, with systems like RDoc you can make all documentation
    > annotations in your source and
    > generate the documentation from there, so it's really no more or less
    > convenient than having an
    > interface definition in your source, at least for documentation purposes.
    That much is a plus, but the biggest problem I have with that is the same as
    the problem I had with defining interfaces through classes: methods are
    spread out by the code inside them. Browsing a class is not all that
    pleasant because of that. Smaller source files aren't so bad, but when a lot
    of code sits in a source file, everything gets really spread out.

    Sean O'Dell



    Sean O'Dell Guest

  5. #44

    Default Re: "stereotyping"

    On Friday 21 November 2003 02:42 pm, Dave Brown wrote:
    > In article <200311201143.59231.sean@celsoft.com>,
    >
    > Sean O'Dell <sean@celsoft.com> wrote:
    > : Q: Okay. We have to look to code quite often in lieu of project
    > : documentation, and normally we look to the description of
    > : classes, and the declarations of function parameters to
    > : determine how to make calls and to understand how classes are
    > : designed that are unfamiliar to some of the programmers on the
    > : team. Type checking would help us to know what parameters are
    > : used by certain methods at-a-glance, which saves us from having
    > : to spend time studying source code to figure things out.
    >
    > Of course, the simple answer to that is to use
    > properly-descriptive parameter names.
    I know. I agree, too. Doesn't happen as often as I wish.
    > It generally doesn't matter what something is made of--what
    > matters is what it *is*.
    I disagree here. It's a nomenclature issue, I suppose, but I am personally
    only concerned about what an object does, not what it is. I can't use an
    object passed to me that is a string, if it gives me no way to make use of
    it. I need access, so to me the most important thing is what it does.

    Also, objects do things in different ways. I could have an object that is a
    Report object. If it uses text files, great, that's easy. If it uses MySQL,
    okay, let me go set up a table it can use somewhere, or make the connection
    to an existing one. It's what it does that determines there is an issue.

    But, then again, you can say that with something like an interface, you're
    making both statements. Interfaces are immutable, and you can't partially
    implement one. When fulfilled, you can say "this object is this" as well as
    "this object does this" pretty clearly.
    > In other words, if it's Java you're looking for, you know where to
    > find it. Ruby "market share" isn't something I think is even
    > worth considering. It's a wonderfully handy tool and it makes my
    > life easier, and that's all I ask of it.
    Yeah, I know people feel that way. The problem I have with that point of view
    is that not caring about market share sounds a lot like not caring about
    anyone outside the Ruby community. Getting programmers to use Ruby is not
    about gaining market share, it's about being able to say "Ruby is here to be
    the best programming language we can make it, no more and no less." If you
    decide that features from Java aren't worth putting in simply because Java
    has it, that's prejudice that I don't think is at the heart of Ruby. Ruby is
    about adopting what works. Interfaces work in lots of places. Directing
    people away from Ruby to get a feature like this doesn't seem to me what the
    Ruby community historically has done. It's packed with lots of cool features
    taken from here and there. If interfaces can be done with finesse and makes
    Ruby stronger, it should be adopted. As things progress, it seems like we've
    found a way to do it without a lot of back-breaking work which doesn't break
    Ruby now, and which also doesn't look like a third eye growing out of its
    elbow. It could be just another quietly tucked away feature that gets used
    by some, ignored by others.
    > I don't care what management thinks of Ruby: I only care about
    > getting the job done. When something needs to be done, I use
    > whatever tools are at my disposal and are most effective. Ruby
    > doesn't need to be "promoted"; it just needs to be used. Let it
    > promote itself by demonstrating results. Leave the bulleted
    > feature lists to the likes of Microsoft Word.
    Being able to put something on a feature list is not a reason to discount it,
    though, either. It has value in itself. If people have been asking for
    something, and you've found a cool way to do it that fits right in with the
    language, then you put it on the list. But that's not WHY you do it, to put
    it on the list. You do it because there are real reasons for it, and the
    reward is yet another really cool feature on the list.

    Ask yourself: why does Ruby have iterators? You could do loops lots of other
    ways. It's there because it was the coolest, smoothest way that could be
    conceived of at the time and it endures today.

    This is what I think we can achieve. Something cool and smooth and which will
    endure and will make Ruby just that one little bit better.

    Sean O'Dell



    Sean O'Dell Guest

  6. #45

    Default Re: "stereotyping"

    Hi,

    In message "Re: "stereotyping""
    on 03/11/22, gabriele renzi <surrender_it@rc1.vip.ukl.yahoo.com> writes:

    |il Fri, 21 Nov 2003 08:11:17 -0700, "Ara.T.Howard"
    |<ahoward@ngdc.noaa.gov> ha scritto::

    |>tcl is the worlds greatest language, but ousterhout is a very bright guy.

    |mh.. based on this we must hope that matz is really really stupid :)

    Don't worry. I am.

    By the way, where should I put "not" in the above statement, Ara?

    matz.


    Yukihiro Matsumoto Guest

  7. #46

    Default Re: "stereotyping"

    "David Naseby" <david.naseby@eonesolutions.com.au> wrote:
    > Below is a quick hack to do that. Needs work. Needs redirection of IO.
    > But its kinda cute.. Has issues with side effects, of course, and
    > printing crapola all over the place.
    Is this or something like it on the RAA? Perhaps a slightly more general
    mechanism to proxy messages to the "real" object and call a
    hook/callback?

    --
    Greg McIntyre ======[ [email]greg@puyo.cjb.net[/email] ]===[ [url]http://puyo.cjb.net[/url] ]===
    Greg McIntyre Guest

  8. #47

    Default Re: "stereotyping"

    On Sat, 22 Nov 2003, Yukihiro Matsumoto wrote:
    > Hi,
    >
    > In message "Re: "stereotyping""
    > on 03/11/22, gabriele renzi <surrender_it@rc1.vip.ukl.yahoo.com> writes:
    >
    > |il Fri, 21 Nov 2003 08:11:17 -0700, "Ara.T.Howard"
    > |<ahoward@ngdc.noaa.gov> ha scritto::
    >
    > |>tcl is the worlds greatest language, but ousterhout is a very bright guy.
    >
    > |mh.. based on this we must hope that matz is really really stupid :)
    >
    > Don't worry. I am.
    >
    > By the way, where should I put "not" in the above statement, Ara?
    >
    > matz.

    loop { self.mouth << self.foot } if clr?


    for the record:

    tcl is not the worlds greatest language, but ousterhout is a very bright guy.
    ^^^
    ^^^
    ^^^

    wouldn't want to offend ousterhout!

    ;-)

    -a
    --

    ATTN: please update your address books with address below!

    ================================================== =============================
    | EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
    | PHONE :: 303.497.6469
    | ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
    | STP :: [url]http://www.ngdc.noaa.gov/stp/[/url]
    | NGDC :: [url]http://www.ngdc.noaa.gov/[/url]
    | NESDIS :: [url]http://www.nesdis.noaa.gov/[/url]
    | NOAA :: [url]http://www.noaa.gov/[/url]
    | US DOC :: [url]http://www.commerce.gov/[/url]
    |
    | The difference between art and science is that science is what we
    | understand well enough to explain to a computer.
    | Art is everything else.
    | -- Donald Knuth, "Discover"
    |
    | /bin/sh -c 'for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done'
    ================================================== =============================

    Ara.T.Howard Guest

  9. #48

    Default Re: "stereotyping"

    and i thought it was so radical when i wrote it yesterday

    # notice if TypeErrors woud return offending respond_to? method
    # in error message then it would continue to probe

    class DuckHunter

    def initialize
    @a_r_g_s = {}
    end

    def a_r_g_s
    @a_r_g_s
    end

    def d_u_c_k_c_a_l_l
    begin
    yield
    rescue TypeError => e
    self.send(e.message)
    retry
    end
    end

    def method_missing(aSym, *args)
    # This will happen the first time
    aSymStr = aSym.to_s
    @a_r_g_s["#{aSymStr}"] = [ args.collect { |a| "#{a.class}" } ]
    begin
    d = %Q{
    def self.#{aSymStr}(*args)
    # This will happen the subsequent time
    @a_r_g_s["#{aSymStr}"] } + %q{.concat [ args.collect { |a|
    "#{a.class}" } ]
    self
    end
    }
    instance_eval d
    rescue SyntaxError
    puts "TypeError induced SyntaxError! TypeError must return respond_to
    method!"
    raise
    end
    self
    end

    end

    # example

    class TypeTest
    def ameth(x)
    big4 x
    #---
    puts x.to_i
    puts x.jump(4)
    puts x.do_what_ever("Duck can take it!", /\w+/)
    puts x.do_what_ever("Duck can take it!", /\w+/, 42)
    end
    end

    t = TypeTest.new

    puts "\nDUCK QUACKS"

    dh = DuckHunter.new
    dh.d_u_c_k_c_a_l_l do
    t.ameth(dh)
    end

    # show args
    puts "\nameth:"
    dh.a_r_g_s.each { |name, argpat| argpat.each { |args| puts "\t#{name}
    (#{args.join(',')})" } }

    # -----------

    On Saturday 22 November 2003 12:52 am, Greg McIntyre wrote:
    > "David Naseby" <david.naseby@eonesolutions.com.au> wrote:
    > > Below is a quick hack to do that. Needs work. Needs redirection of IO.
    > > But its kinda cute.. Has issues with side effects, of course, and
    > > printing crapola all over the place.
    >
    > Is this or something like it on the RAA? Perhaps a slightly more general
    > mechanism to proxy messages to the "real" object and call a
    > hook/callback?
    late could be added




    T. Onoma Guest

  10. #49

    Default Re: "stereotyping"

    Sorry I forgot to post results of DuckHunter examples. (DuckHunter itself is
    also included below).

    DuckHunter is a concise probe providing the functionality of #duck_signature,
    and has a unique feature that suggests how Ruby might proceed to cleaning up
    some of its code: If a type error returns the method that was not implemented
    in the error message then DuckHunter will fix and continue to probe. Using
    this on a number of libraries I have discoverd that ruby has a problem in
    that it allows TypeError to be raised for any reason whatsoever. There needs
    to be a tighter system for raising TypeErrors, including returning the
    offened method. I believe that one of the first things that needs to happen
    to improve Ruby's type mechanics is to ensure that a signature probe can run
    without fail on any method.

    Results:

    DUCK QUACKS

    big4:
    succ()
    to_i()
    >()
    >(Fixnum)
    DUCK QUACKS
    #<DuckHunter:0x402a8738>
    #<DuckHunter:0x402a8738>
    #<DuckHunter:0x402a8738>
    #<DuckHunter:0x402a8738>

    ameth:
    succ()
    jump(Fixnum)
    to_i()
    to_i()
    >()
    >(Fixnum)
    do_what_ever(String,Regexp)
    do_what_ever(String,Regexp,Fixnum)

    -t0


    On Saturday 22 November 2003 02:22 am, T. Onoma wrote:
    > and i thought it was so radical when i wrote it yesterday
    >
    > # notice if TypeErrors woud return offending respond_to? method
    > # in error message then it would continue to probe
    >
    > class DuckHunter
    >
    > def initialize
    > @a_r_g_s = {}
    > end
    >
    > def a_r_g_s
    > @a_r_g_s
    > end
    >
    > def d_u_c_k_c_a_l_l
    > begin
    > yield
    > rescue TypeError => e
    > self.send(e.message)
    > retry
    > end
    > end
    >
    > def method_missing(aSym, *args)
    > # This will happen the first time
    > aSymStr = aSym.to_s
    > @a_r_g_s["#{aSymStr}"] = [ args.collect { |a| "#{a.class}" } ]
    > begin
    > d = %Q{
    > def self.#{aSymStr}(*args)
    > # This will happen the subsequent time
    > @a_r_g_s["#{aSymStr}"] } + %q{.concat [ args.collect { |a|
    > "#{a.class}" } ]
    > self
    > end
    > }
    > instance_eval d
    > rescue SyntaxError
    > puts "TypeError induced SyntaxError! TypeError must return respond_to
    > method!"
    > raise
    > end
    > self
    > end
    >
    > end
    >
    > # example
    >
    > class TypeTest
    > def ameth(x)
    > big4 x
    > #---
    > puts x.to_i
    > puts x.jump(4)
    > puts x.do_what_ever("Duck can take it!", /\w+/)
    > puts x.do_what_ever("Duck can take it!", /\w+/, 42)
    > end
    > end
    >
    > t = TypeTest.new
    >
    > puts "\nDUCK QUACKS"
    >
    > dh = DuckHunter.new
    > dh.d_u_c_k_c_a_l_l do
    > t.ameth(dh)
    > end
    >
    > # show args
    > puts "\nameth:"
    > dh.a_r_g_s.each { |name, argpat| argpat.each { |args| puts "\t#{name}
    > (#{args.join(',')})" } }
    >
    > # -----------
    >
    > On Saturday 22 November 2003 12:52 am, Greg McIntyre wrote:
    > > "David Naseby" <david.naseby@eonesolutions.com.au> wrote:
    > > > Below is a quick hack to do that. Needs work. Needs redirection of IO.
    > > > But its kinda cute.. Has issues with side effects, of course, and
    > > > printing crapola all over the place.
    > >
    > > Is this or something like it on the RAA? Perhaps a slightly more general
    > > mechanism to proxy messages to the "real" object and call a
    > > hook/callback?
    >
    > late could be added

    T. Onoma Guest

  11. #50

    Default Re: "stereotyping"

    * Sean O'Dell <sean@celsoft.com> [1115 21:15]:
    > On Friday 21 November 2003 12:48 pm, Rasputin wrote:
    > > * Sean O'Dell <sean@celsoft.com> [1144 19:44]:
    > > This seems to be using interface implementation to flag a class
    > > as suitable for use in a particular way. Thats just as much an agreed
    > > protocol between the method and the argument as a respond_to? approach,
    > > but respond_to? doesnt require such a fundamental change to the
    > > language (and thats what it would have to be, if it was really to be
    > > useful - I dont think an optional feature would please anyone).
    > The difference is: simply stating a class' purpose is easy. You do it once
    > and that's pretty much it. As you develop, though, the interface changes.
    > Keeping up with specific method documentation is much more labor-intensive.
    > If you have an interface description that you had to adhere to, you wouldn't
    > have the option of falling behind on updating it. Your code simply wouldn't
    > work until you did.
    Right, but thats no different to enforcing a respond_to? and
    arity check coupled with an assert. I'm not saying thats a better
    way, just it gives you the same assurance (IMO) without
    such a big change to the language.
    > > But again, its less hassle to document your API than to do rigourous
    > > argument checking.
    > No, it's more hassle. To update a document, you have to open a different
    > file, and if you make a typo or just plain write it wrong, there is nothing
    > to stop you from doing so. Interfaces can be described in the same source
    > file as your class definition, so it's easy to find and update, plus, you
    > can't update it wrong, or your code gives you errors.
    My main doubt about this is, unless I misunderstand it,
    this only makes APIs easier to use if the author decides to
    use interface declarations.
    But the choice 'to doc or not to doc' is no different to
    'to interface or not to' for a lazy sod (I speak as one myself).
    Unless you enforce it across the language, which would get you
    burnt at the stake, you've potentially forked the language and you may
    not even see a benefit.

    It seems to me that when working around lazy b*stards like
    me, its easier to doc a third party library than to retrofit
    interfaces onto it.
    > > It seemed like you were more interested in a way to know how an API
    > > will use your object. Why not send in a probe?
    >
    > Because probes can sometimes cause damage, and the errors reported deep inside
    > may not be easily understood. It's a hit-or-miss proposition in there; some
    > people have no trouble diving in and reading someone else's code. I do it as
    > a last resort because I find it's a terribly inefficient way to debug.
    I agree, and I have found several promising APIs unusable because the
    documentation was non-existent. My point was there are ways and means in
    Ruby that the typed languages dont have, that feel more Rubyish than
    a bolt-on feature.
    In this case (investigating an alien object) we can verify an
    object passed as an argument( respond_to? and arity checks) has methods
    we expect, and callers of our methods can also see how methods they pass in
    are being used by us (by use of a probe object).
    I dont think an interface check can do any more. Admittedly someone has
    written 'this object is for Xing' on it, but 99% of the time knowing there
    is a method doX(objectA,objectB) does that job. There are edge cases
    (using RMI systems, etc) but personally I'd prefer to dissect the remote
    object rather than trust a flag on it if I didnt trust the source - and if
    I knew where it came from, I'd rather unit test it.

    I've started talking personal prefs, so I'll stop posting after this -
    thats my 2p, anyway.
    > Well, since classes can implement interfaces, the test can also check that
    > methods are being passed object that fulfill the interface contract. So, a
    > sort of type checking can be performed.
    But thats no different from probing the objects you are passed as arguments.
    > > I think I share some of both sides viewpoint, but I dont want a
    > > Java'ed Ruby, and it seems that this interface idea is coming from
    > > that angle.
    Incihentally, my opposition to this isnt 'not invented here', its simply
    that interfaces in Java *increase* flexibility, whereas in Ruby they
    seem to be a restriction.

    --
    Truth is the most valuable thing we have -- so let us economize it.
    -- Mark Twain
    Rasputin :: Jack of All Trades - Master of Nuns

    Rasputin Guest

Posting Permissions

  • You may not post new threads
  • You may post replies
  • You may not post attachments
  • You may not edit your posts

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139