[Twisted-Python] Configuration, Final Spec

Glyph Lefkowitz glyph at twistedmatrix.com
Sun May 13 03:54:56 EDT 2001

On Sunday 13 May 2001 00:31, you wrote:
> On Sat, 12 May 2001, Glyph Lefkowitz <glyph at twistedmatrix.com> wrote:
> > In my humble (but correct) opinion, it is *always* bad API design to
> > force the caller to "promise" something.  (Sometimes, other design
> > concerns mitigate this decision, but I don't see one here.  However, I
> > have frequently joked about having a neon sign in my office, for design
> > discussions, that says "IT IS NOT THE CALLER'S RESPONSIBILITY" in
> > 10-foot-tall letters)
> >
> > I would much rather see a .getParameters() -> dict /
> > .setParameters(dict). It seems more symmetrical, and if you can "promise"
> > that (A) setParameters may be called some number of times and (B)
> > endParameters() will *always* be called afterwards, we can put that loop
> > into the config side of the code.
> >
> > Any reasons why it can't be done this way?
> Yes. In the usual case, where you don't need a .endParameters(), then the
> code will be *much* clearer. You also missed the place where I say
> ".endParameters() will not be called if it doesn't exist".
> See axiom 4 -- certainly
[snipped examples]

But if you declare setParameters as a member of the Configurable class, then 
you don't have to write every UI to deal with the possible existance or 
non-existance of endParameters.

I am strongly opposed to any API which requires validation on the caller's 
behalf, for several reasons.  A practical concern is that using an RPC like 
gloop (e.g. an asynchronous one) it is impossible to tell if the object you 
are calling "has the attribute" endParameters or not.  You just have to call 
it and hope for the best.

If setParameters is defined in Configurable (the default implementation being 
a 2-line loop which does setParameter and then endParameter) then the extra 
work you're talking about for the configurable author can be avoided.

Having an API which requires a garuantee on the caller's behalf (the "caller" 
in this case being the UI) in a language where exceptions are as common as in 
Python makes handling of errors somewhat tricky.  After all, if setting a 
bunch of parameters is a non-atomic operation, then what do you do when one 
of your parameters is invalid, and raises an exception?  Does endParameters 
still have to get called?

It seems to me that setParameters is an atomic operation, which should 
validate, then test.  validateParameters could be a method as well, to do 
extra validation if parameters are dependant upon each other.  However, you 
can then clearly say that setParameter may never raise an exception: if the 
call to validateParameters succeeds, but setParameter fails, then you are in 
a known-to-be-inconsistent state and can display an appropriate error 
message.  However, if some of your setParameter calls raise exceptions and 
others do not, should endParameters be called anyway?  Does every UI need to 
handle exceptions itself?

> > Another interesting open question (although not one I'm sure this code
> > has to address) is how to get the respective configuration interfaces to
> > represent object identity.  (e.g. I want to mount the *same* web resource
> > on /foo, on /bar)
> This code isn't the one that should address it -- this is UI's
> responsibility. Take *another* look at the way Zope does it.

Zope confuses the hell out of me, both in the UI and the code :)... but I 
agree that this code probably shouldn't have to deal with that.

> > However, I prefer the register(klass) way, both for clarity and
> > efficiency. Explicit is better than implicit.
> Indeed, I've decided I agree, for a different reason -- we do not want
> spurious options for the user.

Yay, agreement! :)

> I've thought about it, and decided against it -- since the UI needs to know
> so much about the validation anyway, I prefer to putting the knowledge in
> the UI. Sure, when we realized what is convinient for two UIs, we can have
> some nice functions to help UIs -- but *outside* the Parameter class.
> The classical example is that the UI might need to write the validation
> code in JavaScript, for DHTML forms. Surely, a method written in Python
> won't help...

It's not to help out the UIs, it's to prevent setParameter from being called 
incorrectly.  There are several points of failure here --

 * the user typed something incorrect (presumably, your JavaScript example)
 * something bad came from the transport (WebUI.validate)
 * there is a bug in/bad data from the UI (Parameter.validate)
 * there is a bug in the configurable (exceptions caught by Configurable on 

and I think each one has to be treated differently.

> > On the whole this looks like a good proposal, although I'm still not
> > entirely sure what the final end-user experience of configuration will
> > look like.
> Well, I've already gave an example of what it would look like with the
> command line. Mutatis-mutandis, we can pretty much imagine how to translate
> it into web-based. Of course, many options still remain, but I don't think
> I care about UIs: I've specified enough information for the UI -- now
> the UIs can compete. (We can have 10 different web-based UIs, and choose
> among them)

It's for this reason that I'd like as much thought to be given to making UIs 
easy to write as to making Configurable objects easy to write.  I think I've 
changed my mind about Configurable not providing much functionality;  The 
Configurable and Parameter classes should encapsulate as much common behavior 
as possible.  (Although, I admit that there is probably not *much* common 
functionality.)  If they don't for some reason (and I am still not convinced 
any such reasons exist), the "config" module should at least contain it all, 
and as a core part of the interface, not as an additional utility library for 

                      ______      __   __  _____  _     _
                     |  ____ |      \_/   |_____] |_____|
                     |_____| |_____  |    |       |     |
                     @ t w i s t e d m a t r i x  . c o m

More information about the Twisted-Python mailing list