Sw4   >   Tools   >   Programmer Workbench

Programmer Workbench

This information on the Programmer Workbench is being documented to help me (Doug K) remember the structure and strategy for cascading updates and saving module data.

Module Data

All of the cached lists which you edit/update in the Programmers Workbench are saved to the oModuleData objects in the various libraries.

StudioWorks always to keep each module (library) portable, so that it can easily be copied from one StudioWorks app to another. The cached lists are therefore split and stored in the various oModuleData objects based on each line's home library.

The oModuleData object in each library is used to store the various cached lists applicable to that library. The $userinfo property of the oModuleData object is used to store the cached lists. A row variable, with one column for each cached list is copied to the $userinfo property.

The oModuleDataTool object class in swBase4 is the central access point for saving and getting cached lists.

Here are the cached lists used by StudioWorks:

  1. Schema classes meta-data
  2. Schema columns meta-data
  3. Query classes meta-data
  4. Query columns meta-data
  5. Window instances list
  6. Navigation Menu list, Groups list, Subgroups list
  7. Window Menu Lines list
  8. String Tables list
  9. Icons list
  10. Report Instances list

Cascading Updates

Changes made to schema meta-data can cascade to other schema meta-data, query meta-data, string tables, window instances, navigation menus, and window menus.

Changes made to window instances can cascade to navigation menus, and window menus.

Because of these cascading dependencies a structure needs to be in place to ensure that changes are properly cascaded from one cached list to another.

If a developer uses the VCS, this adds complexity to cascading updates. A schema class in one library and the oModuleData object class in that library might be checked out of the VCS, but a query class in the same or another module that contains columnns of the schema class might not be checked out of the VCS.

When a cascading update occurs the classes that are not checked out will be a problem. We won't know about the problem till we get to down to that class in the cascading updates chain. We therefore need to be able to emulate manual transactions, with commit and rollback ability for all of the cached lists.

Save/Commit/Rollback

To be able to emulate manual transactions with commit/rollback capability each cached list is set to be a smartlist immediately after it is built/loaded. The smartlist property is then used for tracking changed lines and thereby allowing us to know which module data needs to be saved. The smartlist also gives us the opportunity to rollback ($undowork) in the event of a problem, or commit ($savelistwork) if all goes well.

Each model has 3 public methods that relate to saving changes made to the model:

  1. $saveChangedData_manualtrans - This method really only tests to make sure the required oModuleData objects can be modified. It doesn't actually execute saving the modified cached list lines to the various oModuleData objects.
  2. $saveChangedData_commit - This method actually saves the modified cached list lines to the required oModuleData objects and issues a $savelistwork to the applicable smartlists.
  3. $saveChangedData_rollback - This method issues a $undowork to all of the applicable smartlists, reverting them to their previous state. Because the $saveChangedData_rollback reverses all previous changes it is vitally important to do a save and commit or rollback immediately after each modification.

None of the other method in the models can issue or call a save.

Knowing when and where to save, commit or rollback is very confusing at the model level because one model property method might call several other model property methods, which then in turn might call a few other model property methods. Any of those properties could cascade updates to other models. You can never be sure at the model level which property method was the first one to be called.

The only way to I can figure to avoid a tangled web of knowing when and where to save/commit/rollback is to control it from the source method in the Programmer Workbench cached list editors. The $event method where the value is modified triggers assigning the first cached list property... the chain of cascading updates can then go as far as it likes, eventually returning to the $event method.

If we only issue the saves from the view when the view changes a value (#MODIFIED), we can be sure that only one save/commit/rollback will be executed when a value is changed by the developer in the Programmer Workbench.

A $saveChangedDataAndCommitOrRollback method is added to each controller. The controller sends a $saveChangedData_manualtrans(bCascade=kTrue) message to the appropriate task variable, The task variable then forwards the message to its model(s). If changes to a task's models cascade to other models, then the task variable also forwards the message to the task variables which instantiate those models. To avoid looping, when one task variable forwards the message to another task variable the bCascade parameter is set to kFalse. If the manual save is successful the controller immediately issues a $saveChangedData_commit. If the manual save is not successful the controller immediately issues a $saveChangedData_rollback.

When a value is changed by a view, it sends a $saveChangedDataAndCommitOrRollback message to its controller. If all the saves are successful the flag is returned true. If the not, the changes are rolled back and flag false is returned to the sender method in the view and the view prompts the user with the appropriate error message. (The error will likely be a class that needs to be checked out of the VCS, if the VCS is being used by the developer.)