[TransWarp] PEAK Applications Code and Concepts

Ulrich Eck ueck at net-labs.de
Wed Feb 26 15:09:23 EST 2003

Hi Phillip,

thank you very much for your exessive comment on our first steps with peak.

I'm still working on modifying our example to use as many of your suggestions
as possible.

first there is a typo in model/elements.py in line 502:

        def _doGet(ob):
            value = oldGet(ob)
            if isinstance(value,LazyLoader):
                ^^^^^^^^^^^^^^^^ -> d should probably be ob ??
                return oldGet(ob)
            return value

> * model.Package is deprecated; I'd suggest getting rid of the IMAPModel and just putting all its classes into the
> module, and using the module itself in place of the IMAPModel class.


> * The acmgr.connection.imapmodel.MessageHeaderField class has some issues.  First, you're breaking persistence
> notification by modifying a stored mutable, unless the mutable itself is Persistent.  Second, the proper place to
> perform format conversions of this sort is in the DM _load() method, either by performing the computation or
> inserting a LazyLoader.  Third, you're breaking validation/observation capabilities by bypassing _link()/_unlink() -
> this might be okay if you know that the 'data' attribute is implementing all the validation and observation you need.
> Fourth, if you *really* need to redefine how an object stores its bindings, you can always override '_setBinding()'
> in the element class.  All in all, the MessageHeaderField class is very bad for separation of implementation issues
> from the domain model.

Not Done: I'm not 100% shure how i should handle this situation... message-header is basically like a dict
that has standard + optional keys. if i restrict the Element to From/To/Subject/+xxx Features i can easily
load the data into the state-attributes one for each - but then i loose the capability to access optional
header fields ..

a Dict-Like Feature is basically missing :) but i have no clue how to make such a thing real, if it would
be possible and make sense ...

> * Most of your features don't declare a 'referencedType'.  *This will break soon*.  I expect to add a validation hook
> to the StructuralFeature._link() method soon, that will expect to call a 'mdl_normalize()' class method on the
> referenced type, to normalize the value of a supplied input object.  This will let you do things like:

Partly Done

hmm .. what type should e.g. a collection of messages get ???
or the message.data (if it'll stay alive) that is an email.Message object ??

do i need to define a type for each new feature .. will you accept contributions ??

e.g. type that i miss:
- DateTime (preferable with the new datetime module)
- List/Collection Type (does this make sense ??)
(had more in mind while coding .. i'll post when i remember)

how to handle "References" to e.g. Parents that could be of different type ??

> * I recommend the idiom 'isChangeable = False' for clarity, in place of using '0' for false.  I'm also curious
> whether the status fields should really be represented as derived attributes or methods instead of as read-only
> attributes, but I don't know/remember enough about IMAP to give an informed opinion.

what exactly are derived attributes ( perhaps my (still limited) english vocabulary prevents me from understanding ...)

> * I would like to caution against the excessive use of '../foo/bar' type name paths.  I prefer to keep these
> infrequent for components that are potentially more separable and reusable, as most of the connection.imap module is.
> I'd suggest that instead you use 'connection = binding.bindTo(IIMAPConnection)', for example, so that you simply
> connect to the nearest available IMAPConnection.  In this way, somebody who wants to reuse your component can simply
> drop an instance of it into their context, without having to hard-wire/override the 'connection' attribute of your
> component.  The object that owns the connection simply does (for example):

Done .. but Question on that:

Why doesn't a binding provide an Interface automatically it the instance bound defines one ??

> * Nice style on the 'stateForMessage()' method; by that I mean giving the DM a common way to extract an object's
> state, so that the method can be shared by query DM's that collaborate with it.  I'll have to remember that trick to
> use myself!  Maybe even write it up as a standard technique.

yup .. proven to be useful :)

> * You might want to create a "TxnUnsafeDM" base class (or maybe I should add one to PEAK!) to use as a base for your
> EntityDM's.  The idea would be that it would raise an error on transaction abort if 'saved' were non-empty, as we
> discussed on the list earlier this week.  Right now, if a transaction rollback is attempted following a flush() or
> commit attempt, there will be no indication that the transaction partially committed.

Not yet done

> * Speaking of flush(), I don't recall seeing any of your IMAP DM's calling flush() on the EntityDM they get their
> records for during _load().  This means that if a user (for example) adds a folder during a transaction, and then
> looks at the parent folder's child list, they will not see the new folder unless the parent's folder list had been
> viewed before the add occurred.  In general, it's best to have QueryDM's flush their corresponding EntityDM's before
> executing a query against external state.

Not done

you're right .. i do not call flush manually anywhere. will have a look on this

> * I notice that overall you've emulated the style of PEAK itself, with regards to naming and structuring conventions.
> Please make sure that this is appropriate for your application; I'm not saying it's not, mind you, but I've done
> little application development with PEAK as yet and don't know how *I* feel about using the same style.  I expect
> that when I do application code, for example, I will be more likely to used MixedCaseNames for modules, because
> brevity will be less important than clarity for an app versus a framework.  I also expect to use flatter package
> hierarchy than in PEAK, because most apps aren't as big as PEAK!  And I expect there to be many other such style
> differences, either more or less subtle than the preceding.  So, I encourage everyone to be diverse in their styles,
> so that people don't get the impression that if you use PEAK, your code's got to look like PEAK.  :)

as peak, twisted and zope3 use lowercase for the module names i decided to do it for my own modules as well.
the from api import * style is nice as well .. that's why we just copied your layout and are happy :))

> Note that you could also get away from this issue by using a single LDAP_DM which looked at the 'objectclass' field
> of records it retrieved, in order to determine what class to assign them.  This is the route I plan to go with my own
> apps, because I need the ability to reference objects by DN regardless of type, in order to implement certain LDAP
> features (e.g. the 'seeAlso' field, which doesn't tell you what kind of object you're supposed to "see also") and
> also to support cross-db references from relational databases pointing to LDAP objects.

today we started work on the generic LDAPEntityDM - wouldn't that one belong to peak.storage when finished and
our code quality/implementation is acceptable ??

(note on LDAPConnection: the case of keys e.g. objectclass vs. objectClass in LDAP is making life hard,
 would it make sense to store ldap-keys in the result allways lower case for example ??)

I also started a prototype of a SQLEntityDM that get's a field/index-spec and build the needed queries
(once). it's inspired by PyDO (from skunkweb) .. and i have a question on this:

peak tries hard to decouple different ascpects of your app.
wouldn't it make sense to give the SQLConnections some more methods that hide implementation details
like Sequences, ParameterPlaceholders or StoredProcedure-Calls that are not defined in the python dbapi2.

This would again decouple storage-implementation details from Datamanagers (if developers stay with
mostly standard way of using SQL-RDBMS) .. if someone uses more advanced features .. he cannot just
switch the database without modifying his Datamanagers .. others probably could ...

what do you think about this ???

again .. thanks and keep going this project and poke on us if you have tasks where we could help.


Ulrich Eck
net-labs Systemhaus GmbH
Ebersberger Str. 46
85570 Markt Schwaben
fon:   +49-8121-4747-11
fax:   +49-8121-4747-77
email: ueck at net-labs.de

More information about the PEAK mailing list