InterfaceContract distilled :: how to implement (mostly)

Discussion in 'Ruby' started by T. Onoma, Nov 22, 2003.

  1. T. Onoma

    T. Onoma Guest

    Distilled:

    1. An InterfaceContract is a guarentee that a class provides
    required "respond_to" methods. Ruby can verify this
    on either defining or constructor events. So it is a strong
    promise with reasonably low overhead.

    2. An InterfaceContract may also specify the types of method
    parameters. But this requires extra syntax, and Ruby can't
    verify these at constructor or defining moments. So it is only
    a weak promise, anyway.

    3. To overcome the later a runtime TypeChecker is required.
    This provides strong promise, but has higher overhead.
    To improve performance this could be an option
    that can be switched on or off either on the command line
    or inline.

    4. InterfaceContracts will require type definitions
    to specify the base Interfaces. And it has been proposed
    that standard built in Ruby classes be used as that basis.

    6. Using these base classes amounts to providing a set of
    correspoding hollow, immutable replicas of the base classes.
    Classes that Implement these are checked to verify that
    they fulfill the role of a complete superclass of the
    implemented immutables.

    Thoughts:

    1. If there is too much coding overhaed for defining
    InterfaceContracts it will get little use. This would
    make it rather obscure and thus perhaps not worth
    the effort.

    2. But this can be addressed by not having special
    Interface types. We can just use existing classes.
    If we say: implement Klass (in contrast to mixins)
    then we are saying that our new class must fullfill
    the role of a superclass of Klass, prior to the
    instantiation of our new class, or it is not valid.

    3. When #implements is invoked a new frozen subclass
    of Klass is created, the Interface, and a mixin
    is inserted in our new class. So when our new class
    is substantiated, the use of super calls the initialize
    method of the mixin module which compares the
    Interface to self. If it doesn't check-out an
    ImplementationError is thrown.

    4. This design is not as light weight as the one Sean
    has put forth because it checks the interface everytime a
    new object, that implements an interface, is created. But the
    advantage is that no special hooks are required for dealing
    with the dynamic adding or removing of methods to our classes
    working to continue to ensure the contract is being kept.
    The dynamic nature of Ruby remains intact. Also I think
    that if we subsequently freeze our class, we could
    have this mixin removed, as it would no longer be needed.
    in an enviornemt where InterfaceCnntracts are bing used
    freezing calss definition make a lot of sense, and could be
    common place. Although this feature would have to be
    added to core ruby itself.

    5. This design dosen't account for parameter types b/c they
    would have only a weak promise any way. So this is best
    reserved for a Euphoria like type checker as I have descibed
    elsewhere, or :pre and :post assertion methods as descirbed
    by James. Each has advantages and disadvantges. The
    Euphoric system has one major advantage in that it can
    be integrated with InterfaceContracts such that the types
    defined could double for Interface classes, which seems
    useful considering the next point.

    6. One problem becomes quite appearent when using this tool. That of
    Granularity. Ruby's built in classes have too many methods for
    this to be very useful. This may indicate that Ruby's classes,
    somehow, need to be broken into smaller meaningful chunks, even
    if it is merely a matter of namespace dividers inside the class that
    have no effect on the class other then to group related methods,
    and, of course, a means to reference them from the outside.

    Implementation:

    class ImplementationError < StandardError
    end

    module InterfaceContracts
    end

    class Module
    def implements(*klasses)
    klasses.each do |klass|
    InterfaceContracts.class_eval %Q{
    unless #{klass} === Class
    class #{klass} < #{klass}; end
    #{klass}.freeze
    end
    }
    end
    ifc_str = '[' +
    klasses.collect {|k| "InterfaceContracts::#{k.name}" }.join(',')+']'
    ifm = Module.new
    ifm.module_eval %Q{
    def initialize(*args)
    #{ifc_str}.each do |k|
    umeths = k.public_instance_methods(true) - self.public_methods
    if umeths != []
    raise ImplementationError, self.class.name + " as " +
    k.name + "\n" + umeths.sort.join(', ')
    end
    end
    super
    end
    }
    class_eval { include ifm }
    end
    end

    Example 1:

    # this may seem trival but it is a guaranteed super class of String.

    class MyClass < String
    implements String
    def initialize
    super
    p "I promise to quack like a String."
    end
    def extra; p "extra"; end
    end
    m1 = MyClass.new # => "I promise to quack like a String."
    m2 = MyClass.new # => "I promise to quack like a String."

    Example 2:

    # show that the methods of Integer have not been implemented.

    class MyClass < String
    implements String, Integer
    def initialize
    super
    p "I promise to quack like a String and Integer."
    end
    end
    m1 = MyClass.new # => ImplementationError (see below)

    MyClass as InterfaceContracts::Integer (ImplementationError)
    +@, -@, abs, ceil, chr, coerce, div, divmod, downto, floor, integer?,
    modulo, nonzero?, prec, prec_f, prec_i, quo, remainder, round, step,
    times, to_int, truncate, zero?

    # notice that the unimplemented methods are listed.

    -t0
    T. Onoma, Nov 22, 2003
    #1
    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. Rogue Chameleon
    Replies:
    0
    Views:
    469
    Rogue Chameleon
    Oct 18, 2004
  2. sloan
    Replies:
    2
    Views:
    393
    Alan Silver
    Jun 19, 2006
  3. =?iso-8859-1?q?S=E9bastien_Boisg=E9rault?=

    (mostly-)POSIX regular expressions

    =?iso-8859-1?q?S=E9bastien_Boisg=E9rault?=, May 27, 2006, in forum: Python
    Replies:
    6
    Views:
    358
    Anthony
    May 29, 2006
  4. Radu
    Replies:
    2
    Views:
    43,302
  5. Simon Wittber

    Python Distilled

    Simon Wittber, Nov 6, 2006, in forum: Python
    Replies:
    8
    Views:
    304
    The Eternal Squire
    Nov 7, 2006
Loading...

Share This Page