As a company we have a rule that says: Work out of the OpenACS CVS tree as much as possible to prevent redundancy (and merge headaches afterwards). It also encourages us to be extra careful with what we work and always keep reusability in mind.
But how are we managing this with the high demands of clients that are not applicable broadly or may not be released?
Two methods:
- Overloading of procedure names. We do this only in the most dire circumstances and disable the "reload package" function on the production site. I don't encourage this, but it sometimes is the only way. BUT....
- since 5.2 we have CALLBACKS. And despite some arguments it is one of the best inventions OpenACS has seen in a long time. Because we can define callbacks and hooks in the packages like forums and have custom code hook in there. How can this be done:
- You want to add new custom fields to the data entry and it cannot be achieved by using Dynamic Types, Flexbase, AMS or whatever other functionality we come up with to add dynamic attributes to existing object_types. Add a package_key::form::create_form callback that allows you to extend the form with the desired elements. the package_key::form::submit_form callback will then trigger the callback implementation in your custom package that deals with the additional user input.
- You have a list and want to extend it with an additional bulk action (e.g. select files and folders and send the selected files/folders via E-Mail to a person. Look at file-storage/www/folder-chunk.tcl for the hook and contacts-callback-procs.tcl for the implementation). You create a hook right after setting the bulk_action_list variable (it is mandatory that you change your listbuilder code to work with preset variables instead of having a manual list in the -bulk_actions switch). This callback could be called fs::folder_chunk::add_bulk_actions and has the variables to path "-folder_id -bulk_action_var_name -export_var_list". The folder_id should be clear, the -bulk_action_var_name should be the name of the variable that holds the bulk actions and the var_list is the list that holds the variables to be exported. In your callback implementation (e.g. in contacts) you upvar the two passed variables as well as any custom variable you want / need to set. Then you just add the bulk action to your local var name for $bulk_action_var_name and off you go.
Another thing that has helped us a lot is the ability for application_link and application_data_links. An application link links to package_instances together. This is useful if you want to execute code in the callback only if there is a connection between the packages. The equivalent is true for application_data_links, though there the data items are related. I realized a little bit too late that we could probably have reused the functionality in related_items if we had thought about it a little bit more, but well, nobody is perfect :).
How does this help you to work out of CVS of OpenACS and why should you do it? First, you can get rid of most custom code in the packages using this methodology (even some UI changes are ammendable this way). Furthermore it (hopefully) prevents you from forking your code (if there are too many changes in your codebase). And last but not least development should be faster for all.
Special bonus for Project/Open (and others who want to build products on OpenACS code): You don't have to rewrite OpenACS code. You just add a callback hook in the OpenACS code and let your proprietary functions "hook" in there without a GPL violation. Now, if this isn't an argument for using OpenACS!
Enough from me for now, need to write more callbacks :). If you are interested in this and want to learn more I'm planning to have an online workshop explaining how to use these methods probably first weekend of July and /or first weekend in August. Furthermore, don't hesitate to tell me what I wrote is rubbish and does not work for customer code because ... (the because is important, so we can fine tune the approach and methods).