Forum OpenACS Development: Re: XoTCL interface for Objects (aka. extending methods for objects)

Malte,

I think we need to decide first if the xotcl-core package is part of OpenACS core.

I think a serious design of what the core object API would look like is very important. I explored mimicing the Generic CrClass for plain objects but quickly got out of my depth.

Right now I have a hard time following HOW to use the various bits of the classes provided by xotcl-core. Just adding an object oriented API to objects won't produce better code without a very clear path to good use of the features.

That said I totally agree is the right way to go, but I don't have a good plan of developing this API. Right now we can use dynamic types as an API to any object type. It provides similar features to xotcl-core including managing object types and forms.

So overall I want to make sure any new APIs 1) provide a clear path to proper use of the APIs. THis generally means the naming and design of the interaction of the APIs makes sense just by reading the nams of the procedures etc. THis is REALLY hard to do well. and 2) allows new developers to learn the system. If 1 is done right, 2 should follow naturally.

Does anyone have a good idea how to accomplish this?

What exactly are the new methods? Is this just for getting and setting objects in a database? Somehow I thought this was figured out a while ago. Does anyone remember query-writer? Pretty much nobody was interested in it because it was a different way of doing things, and maybe it was better to only have one way. A few years have passed, and still there is no fully supported way to access acs_objects. Yet query-writer takes a table name and (via a wizard) creates insert/update/delete/reset methods for acs_objects or even regular database tables. The methods are tcl methods, which all look the same, but each object can use pgplsql or tcl code to do the actual database call. Most importantly, you can group any set of objects and attributes into a 'group' and assign set,new,del permissions on each member. In general you submit any form to a single page to process the form. It handles any number of operations as efficiently as possible. There is also a Tcl API which can be used with library code or on tcl pages for the same methods.

One thing missing, by design, are select methods. I never could figure out a great way to handle this so that joins could be used, along with order by and where clauses. Replacing SQL seemed like a step backward. I also enjoy writing select queries, whereas there is nothing interesting about processing a form, validating inputs, etc. for every object type. Although there are no select methods, there is meta-data on each attribute/object in a group. It can be used to skip presentation of certain form elements which are restricted. So you can reuse a form for admin and regular users.

I'm not suggesting anyone use query-writer, but any system which wants to provide generic access to objects will have to provide this type of functionality and more, otherwise it will fail to encourage developers to use it. Whenever a gap is found, each developer will find their own way of handling it, and of course, it will have to be programmed by hand.

There has also been package builder which allowed you to define the objects along with their attributes and it created automatically a package with create, access, edit and list functionality, so you could quickly start a new package by defininig it's objects.

So, yes, I do agree, it is a pitty that we only have the functionality which deals with content items and not with objects per se, but this is how it is. You still have to write you custom insert statements, you custom add/edit/delete procedures, pretty much what package builder and query writer (if I read you correctly) have been trying to automate for you.

< future >The beauty of generic classes for acs-objects is that you can define the class definition of you own acs-object type, and, as it is inheriting from the generic object class, it will automatically provide you with the methods for add edit delete without you having to write them (just define the class). It also deals with additional attributes (inserting into the appropriate tables as given for the object type) and allows you to access the attributes anytime you like (set my_object [$object_type instantiate $object_id]; set myvalue [$myobject set myvalue]) . Additionally none of your old select queries will break as the new API is using the same information as stored in acs_objects, acs_object_types, acs_attributes and custom object tables. So you can easily create the class and get the information how to do it out of the acs_object_type table and improve the readability of your code (also by getting rid of your custom procedures for add/edit/new, which, remarkably, are not following the naming convention in all packages). Done using [$myobject save]. < /future >

Okay, so much for the blurb once we get the functionality written. And take this only as an idea / guideline. It is very crude and comes from the top of my head. Also, as this is a project for 5.5 (not 5.4), maybe we should not invest too much energy into it right now but focus on the summer release with bug-tracker enhancements, site-node improvements and, my personal favourite, new e-mail handling.

I've been working on a vastly simplified class/object data model. Probably one of the most fundamental concepts used to simplify programming is to use abstractions and avoid special cases as distinct building blocks. As an example, a number of the base tables in OpenACS are not object tables, so code which deals with them are special. In my model, I have an object table, a class table and a mapping table (and optionally an object extension table). Classes are objects, and every object has a class. (Object 1 is of class 'class', it is self referential). The maps are not objects, several fields are used as the primary key. This simple model supports versioning, tagging, multiple hierarchies per object, archiving, logging, etc. These features can be applied after the fact, or removed. You can join objects in new ways without changing the class models. You can attach any object to any other object, so it would be easy to add a comment class and use it with every other object class.

Anyway, I just had a thought, more for myself I'm sure, but until now I was thinking how incompatible this model is with OpenACS, in other words, what would be the point of creating an OpenACS package with this datamodel. But maybe I could reverse things a bit and make a few changes to OpenACS so that everything sits on top of this model. Probably not too much code would be required to add a 'create object' function for the acs_objects table, which would get its id from my object table. Then I could use my system to create objects distinct from OpenACS, but still use the features when necessary.

The XoTCL code would have an easy time with this datamodel, as the whole point is to leverage generic methods for reuse. Of course, the same will be true for Tcl and pl code...

I totally agree with you Dave. And I know that Gustaf still has some ideas on how to improve xotcl-core over the summer, so I would not suggest making it core until he wants to.

With regards to documentation, I am going to train someone on using XoTCL with OpenACS, based on the experiences of I had lately with it (including turning packages without acs-objects into XoTCL CrItems (which makes sense in the context, the original developer was very old school).

Additionally I will look at other code I have been developing, especiallly project manager, and clean up the code by introducing CrItem dependend classes. A howto will be generated out of this experience as well.

Still, what we should do is write down which methods we want to have executeable by default on objects. I am fairly certain we can mimick a lot from the content::item and content::revision procedures combined with the CrItem class to come up with

a) The functionality provided by the methods
b) The name of the methods to be self explanatory

One thing which bothers me a lot with ::Generic:: is the lack of documentation with some core methods, so I will try to improve that whenever I see it. I just hope my documentation will be correct, but in case it is not, Gustaf will hopefully be ready to correct it (and me for that matter).

Last but not least, do not change the datamodel when adding the functionality.