[development] object.module - part 2

Edgar Whipple drupaladmin at misterwhipple.com
Sun Jan 21 06:17:15 UTC 2007

[Continued from part 1]

I was saying I believe your [Nedjo's] table {objects} and the more
fundamental half of your {object_type} correspond to my layers 0, 1 and
2. The more complex aspects of correspond to {object_type}are spread
across layer 2 and part of 3. The rest of my 3, and layer 4, are the
part that I think you may have implied, or at least had silently in
mind, but didn't mention out loud.

    Reduce the fundamental type of storable data to an irreducible "nude
node". It has unique, database-specific (non-portable) object ID, the
class identifier that you called 'type_id', universal housekeeping info
like timestamps, *and nothing else*. This type could be actually
instantiated by higher layer's function, if that's ever useful, but the
type doesn't actually record any useful data.

    I'm calling this layer "0" because there's no software associated
with it. It's just a principle present in the design of the programmable

    This is where we put logic for defining data fields. No actual,
instantiable field *types*, just abstract logic--and the API
specification--for defining individual fields. That is, their names,
their basic database-level data types, their validation parameters or
handers, and so on.

    It would be logically consistent to leave defining basic field types
to a bunch of API calls in the reference implementation's installation.
And, unless that produces unreasonably long installation times, I think
we should, so everyone can see how it works. Perhaps it would make sense
to provide predefined primitive field-types as simple INSERT data in the
core download, but also provide the programs that called the API to
produce that data. (My goal is to avoid hand-written startup data as
much as possible.) This will help ensure the core download is entire
consistent with the whole design, and it will let everyone see how it
was all done, using the concrete example of the reference implementation.

    Two logical parts at this level. On the left hand, the mechanism for
bundling field types together into the named node-type-components I
described above. Specifically, the API at this level lets you gather
several defined field types together under a single name, and associate
handler functions with it. The basic bundles that we've become
accustomed to as Drupal's "built-in" types would be reference
implementation, just like the fields for Layer 1.

    On the right hand is the seemingly unrelated mechanism for actually
storing node data in the database. However, these two things have to be
together. There's no point being able to store data in the database if
you can't define how it's organized. And there's no point defining how
to organize data if you can't store that information in the database.

    Everything Drupal does could be accomplished with the API layers
I've described, but it would be a major pain. The typing would be
tedious and error prone, and the learning curve would be too steep.
Therefore, it is useful for some node types to have a type-specific API,
as they do now. However, it is *not* useful for those API's to all be
unique, and it is *not* useful for for every module to have one. This is
quintuply true if we really do make everything a module.

    Many modules operate on only one node at a time, and the standard
hooks are fully sufficient. Others, like many of the taxonomy-related
modules, require something more elaborate, although we may be able to
accomodate that with standard callbacks. And, some of the node types
semantics are so different that it's useful to give them special
function names, even if what those different functions do is all alike.
So, the Layer 3 API will provide tools for defining those higher-level

    For example, these two hypothetical function calls, with appropriate
values, would have exactly the same meaning and effect:
           populate_node_field($node_id, $node_type, $field_name,
           assign_taxo_term($node_id, $vocabulary, $term);
But one of them makes a lot more sense, as users of the current API's
can no doubt attest.

    What Layer 3 should provide is a *standardized* means for defining
shortcuts like this, for bypassing standard callbacks with lower-level
API calls when necessary, and even for declaring that the standard APIs
are bypassed altogether, when necessary. HOWEVER, by using the API to
set that up, and requiring that contrib developers do the same, we can
some of avoid the horrible database issues and
merely-awful-but-bad-enough namespace issues and incompatibility that
strike here and there.  (Think node-type table name collisions in CCK
issues, or [as much as I like the module] trying to integrate just about
anything with Category.)
    The point is, a modules would use *this* API to declare its *custom*
API. Ideally, anyone reading it should understand in lower-API terms
exactly what that module is trying to accomplish, without having to
grovel through the implementation of that custom API. (Some of this
layer's "API" might really just be further deveopment of the current
.info file requirements.)

    I think this is also the appropriate layer of abstraction for the
API's for admin pages, input filters, and a lot of the stuff that
happens outside of actual nodes. (But not all; I think you'll be surprised.)

    Layers 1 through 3 create the engine. Layer 4 is where, in a very
real sense, we create Drupal itself. These are the high-level API's that
module developers declare using Layer 3, and possibly using the lower
layers. That's both the high-level API's for Drupal's core node types,
and all the contrib modules' special-purpose API's (*when needed*, and
we need to be strict about that).

    A side note: Some of my words might seem like a call to do away with
the hooks API. I do, in fact, think the hooks idea should be reexamined,
if only just in case something better presents itself. However, I'm not
advocating a change like that here. I believe this model will
accommodate the hooks structure. More importantly, I strongly believe
that this approach will facilitate creating a legacy-support API that
fully implements the hooks system for the benefit of D-5 modules.

    There is no layer 5, unless you want to count printable
documentation. :-D

Part 3 of this <ahem> manifesto will describe examples of using this
approach, Part 4 will look at some implications for contrib-level
development, and Part 5 will go into the new module-loading mechanism I
alluded to.

[Continued in Part 3]

More information about the development mailing list