[PEAK] And so it begins... (generic function migration)
Phillip J. Eby
pje at telecommunity.com
Thu Nov 11 00:07:11 EST 2004
Here are some current candidates for potentially switching from interfaces
to single-dispatch generic functions:
* binding.IComponentKey -- findComponent()
* binding.IAttachable -- setParentComponent()
* binding.IBindingNode -- getParentComponent(), getComponentName()
* config.IStreamSource -- getFactory()
* naming.IBaseURL -- joinURL()
* naming.IReferenceable -- getReference()
* net.IClientSockAddr -- connect_addrs()
* net.IListenSockAddr -- listen_addrs()
* running.ICheckableResource -- checkResource()
* security.IAuthorizedPrincipal -- checkGlobalPermission()
* security.IPermissionChecker -- checkPermission()
* security.IGuardedObject -- getPermissionForName() [full GF?]
* web.IViewTarget -- registerWithProtocol()
* Virtually all peak.model interfaces [full GF's]
* running.IExecutable and friends
This is a preliminary list, and some items on it might get
eliminated. Essentially, these are interfaces that are "stateless", where
the interface usually doesn't inherit from another interface, nor do other
interfaces inherit from it. Also, the interfaces are usually mostly
implemented as adapters, rather than as methods of the target
classes. Often, the functionality is accessed via an existing functional
API such as 'binding.getParentComponent()', or could be.
Currently, my thought regarding these is to start with the most recently
introduced items: config.IStreamSource and naming.IBaseURL. Also,
naming.IReferenceable isn't actually used in the core currently, so it
should probably just be deleted! (Assuming nobody's using it out there.)
I'd like to then do the 'binding' interfaces, because they are all backed
by API functions already, and don't appear to be used outside the
core. I'm wavering a bit on IComponentKey, though, because
'lookupComponent()' supports 'adaptTo' and 'suggestParent' operations that
would have to be duplicated in each method of a 'lookupComponent' generic
function. On the other hand, creating a 'findComponent()' generic
function, that's then used by 'lookupComponent', would also work, at the
cost of having another visible API. Then again, in the long run, it'll be
balanced by one less interface.
There is of course the question of whether some of these are even worth
touching. I have strong, concrete use cases only for IAttachable,
IBindingNode, IStreamSource, IBaseURL, and the model, security and web
stuff. I have some vague use cases for the 'running' stuff.
So I guess that sums up the priorities, at least for single-dispatch
stuff. I'm not sure if I'll actually migrate the security stuff to
single-dispatch as a first step, or just go straight for multi-dispatch,
which we *really* need in order to have decently reusable security metadata
and rules.
In separate posts, I'll start laying out more detailed designs for how
we'll start implementing general metadata for classes and their attributes
using generic functions, and specific plans for refactoring peak.security
to use generic functions, and peak.binding to allow general annotations to
be supplied as part of attribute bindings. peak.web will also have its
view system refactored to use full generic functions, and site maps will
add an attribute to allow you to specify conditions on views, so that e.g.
you can say, when account balance is less than some amount, show this view,
otherwise show this other view. (Or, "if user is logged in, show the
welcome box, otherwise show the login box".)
Somewhere in the midst of all this, I'll be writing the peak.model
replacement, tentatively called peak.schema. The schema package will
basically re-implement what's in peak.model now, but using separate
metadata "aspects" to handle security, parsing, CORBA info, relationships,
etc. The core of peak.schema will thus be quite simple: mostly simple
attribute descriptors plugged into generic functions that are methods of a
workspace object. (With a default "null workspace" object for objects used
outside a workspace.) By subclassing the basic workspace and adding
metadata or new methods, you'll be able to completely customize the
behavior of objects created and used in that workspace, including custom
validation constraints and the triggering of arbitrary actions in response
to changes in model objects. Er, schema objects. :)
Some of these features will require sophisticated method combination for
generic functions, as I laid out in a previous post here. So, at some
point I'll have to go back to add those. (peak.web will need those
features also at some point, in order to do menus.)
While peak.schema is being built, peak.model will remain as-is. That's
because peak.schema isn't going to support all of peak.model's features
initially. For example, I'm unlikely to focus on syntax (parse/format) at
first.
Once enough of the schema stuff is there, I'll go back to working on the
"workspace" concept I posted a few months ago, using generic functions to
help implement many of the hairier bits that I've been avoiding to
date. The workspace concept will actually be the culmination of a big
piece of the original vision for TransWarp: backend-specific "markup" of
domain model classes to implement an efficient mapping to any storage
mechanism, be it in-memory or in-database, while still being able to
customize and override aspects of the mapping for a specific application.
Exciting days are ahead!
More information about the PEAK
mailing list