some comments for Python 3000

Alex Martelli alex at magenta.com
Wed Aug 16 04:53:35 EDT 2000


"Courageous" <jkraska1 at san.rr.com> wrote in message
news:3999E27E.5A187A07 at san.rr.com...
> Aahz Maruch wrote:
> >
> > In article <8ncd4a0ih at news1.newsguy.com>,
> > Alex Martelli <alex at magenta.com> wrote:
> > >
> > >In Python I don't have to declare it even once.  In component based
> > >development, I prefer to write the declarations anyway, in IDL, after
> > >which any decent tool will generate the stubs in whatever language[s] I
> > >want to use to implement or consume the interfaces in question.  I like
> > >the separation of interface and implementation, which I don't see as
> > >"declaring twice".
> >
> > Interesting.  Bertrand Meyer seems to have a different POV in Software
> > Development Magazine, July 2000:
> > http://www.sdmagazine.com/uml/beyondobjects/s0007bo.shtml
>
> And he would seem to be correct, too. For example, in C#,
> Microsoft automagically generates your COM interfaces for
> you. In Java, if you're willing to pay a premium, Voyager
> will infer your RMI interface for your Java objects. IDL
> fairly well sucks, and not too many people much like it,
> IMO. Native language support for component software is the
> inevitable wave of the future.

Yes, that's definitely what developers appear to like and stentorously
require -- as a part, I believe, of the average developer's acute allergy
to using more than one language in a project.  I believe that allergy is
unwarranted, and good large projects are often best handled as multi
language _in general_ -- but the average programmer appears to
fixate on issues (to a surprisingly large extent, syntax-sugar level issues)
that make him or her loath such an approach.

But "extracting" as the to-be-published interface of a component whatever
it is that one implementation happens to expose is what strikes me as the
upside-down approach, not the reverse.  I *start* by designing the
interface.  If I wanted it to be "automatically extracted" from somewhere,
it would be from CLIENT code for the component -- the TEST code,
which I should write *as part of the design*, and should exercise ALL
exposed functionality of the component.  Extracting the interface from
the _implementation_ (ONE implementation!) is the LAST thing I want.

Languages designed for implementing and/or consuming components'
interfaces need not be optimal for the rather different purpose of
*specifying* those interfaces, and I claim that they are not, in fact,
anywhere close to optimal.  A few SMALL languages are a better
tack than ONE HUGE language, because language complexity grows
more than linearly with language size.  In a specification language, I
would want to be able to assert existential and universal quantifiers,
which need not be "implementable" or necessarily "checkable" but ARE
the _real_ semantics of my interface/ADT.  Such a general spec could
then be compiled down to concrete-language-specific stubs/facades in
several ways.


Consider a typical case, a "strict weak ordering" relationship as is
required for standard C++'s sorting-containers and sort templates.

Specifications for F(x,y) to be a strict weak ordering are:
    for any x, F(x,x) -> false
    for any x,y F(x,y) implies not F(y,x)
    for any x,y,z F(x,y) and F(y,z) imply F(x,z)

These are not sensibly runtime-checkable, given their generality,
but SO WHAT?  It's what I want to EXPRESS as a part of my
interface definition.  I want a language for the definition of interfaces
that will let me EXPRESS this, and clearly such a language has
nothing much to do with languages that will let me implement and/or
consume such interfaces.

A good compiler for such a language might, when courteously
asked, produce an extensive-detailed-checking-filter that, fed
with any implementation of such an F, will produce another F
implementation that will do as-thorough-as-possible runtime
checks, e.g., just impressionistically speaking:

class swo_checking_filter(checking_filter):
    def __init__(self, F):
        self.F=F
        self.cache={}
        checking_filter.__init__("strict weak ordering", F)
    def __call__(self,x,y):
        key=(copy.deepcopy(x),copy.deepcopy(y))
        if self.cache.has_key(key):
            return self.cache(key)
        self.cache(key)=result=self.F(x,y)
        if x==y and result:
            self.raiseAxiomViolation("F(x,x)->false",x,y)
        swappedkey=key[1],key[0]
        if self.cache.has_key(swappedkey):
            otherresult=self.cache[swappedkey]
            if result and otherresult:
                self.raiseAxiomViolation("F(x,y)->not F(y,x)",x,y)
        # check of transitivity left as exercise for the reader:-)

No, I don't truly expect to see such a generator of checks from
specs emerge anytime soon -- partly because, as you say, the
market is not really pushing for a *good* specification language,
but rather for the (IMHO inappropriate) use of implementation
languages as surrogates for specification languages.  "They" want
to code Visual Basic and have the interface specs be generated
automatically (and invisibly to "them") from whatever happens to
have in fact been implemented -0- just as, say, they don't want
to code good SQL, they want to get a cursor back ASAP and
just hack on it in VB, etc, etc.

Please note, however, that the same market/constituency has
repeatedly shown no tolerance for design-by-contract at any
level.  Even 'assert' is to be disabled in shipped production
software, etc -- these are the rules most development shops
live by.  DBC and interfaces-first design appear to be niches,
albeit non-insignificant ones; and I predict convergence for
them, at least if/when such major scholars as Meyer could
abandon their huge personal/professional/commercial ties to
the "one language fits all" meta-philosophy of development.


Alex






More information about the Python-list mailing list