In the "old days" many of us used to include basic_additions and basic_changes in our custom Magik code to indicate core classes and methods that we were enhancing or changing. Sometimes we needed to change or patch core methods because we needed to do it quickly to meet a customer business requirement. The problem with this approach is that it these basic_* folders were scattered all over the source tree and made it more difficult than necessary to upgrade the core code at a later time.
I would like to suggest a different methodology that uses the core patching mechanism. It is one that I have seen used at some customer sites and have adopted for my ongoing work for other customers.
Many methods in the Smallworld core product are classified as not redefinable or even restricted. According to protocol, customizers may not modify restricted methods or really any method that is not classified as redefinable. The reality is that often times to meet a customer business need we do need to modify such methods. This adds to future code upgrade efforts because we now have introduced code that we must manually inspect for changes at each upgrade by comparing it to the core-upgraded version of that code.
It can be argued that changing a non-redefinable method is actually fixing a defect in the code. If the code does not do what a customer expects it to do, that is a defect. And if it is a defect, then it should be reported to the GE Smallworld Helpdesk. The helpdesk may not be able to produce a patch for you in the time period your project needs it for. In that case, you need to patch the defect yourself and have some kind of mechanism in place to revisit that patch once the next TSB is released for that product.
The following steps outline a process that could be followed. We refer to an example of an actual Smallworld-FME defect.
identify the defect
e.g., FME zero-length sectors incorrectly identified as donut holes. The problem was found in fme_tics_client.geom_field_for()
report the defect to GE Smallworld Helpdesk
report at http://supportcentral.ge.com
if Helpdesk can supply patch
install it per their instructions. In this example they were unable to so we created our own patch
if Helpdesk cannot supply patch
determine what module (and module version) your magik class is part of
determine what product your code is part of and where that product directory exists
Ensure that that product has a source/patches_z_proposed folder
NOTE: the "z" in z_proposed is not a spelling mistake. All the "patches_*" folders in a product's source folder are loaded alphabetically. We need the "z" in z_proposed in order to have our patches loaded last. Because the core SW products already have patches, it is possible that we may be "patching a patch". The only way for this to be effective is to load our patches last.
get new patch number
Unless you have been assigned a range of patch numbers by Smallworld, the patch number you use will possibly overlap one that was already used by Smallworld. You can get around this by assigning a version to it that has a string in it unique to your organization.
For example, at Red Planet Consulting (RPC), we started our patches at 1. Therefore, the patch file might have been labeled as p1_1.magik. This patch probably existed for Smallworld at one time, so to make our patch unique, we change the file to p1_1rpc.magik. A corresponding entry in the file itself declares the patch as unique, too...
You will want to create a patch list or log for your organization so that you do not get duplicate patch numbers with your unique organization identifier.
create patch file
using the newly-logged patch number, create a patch file in the product's source/patches_z_proposed folder.
e.g., create E:\projects\customer\fme400\source\patches_z_proposed\p1_1rpc.magik.
be sure to add a reference to this file in the patch_list.txt for that folder.
You can look at any existing patch file for a template of how to create a patch file. The important parts to include are:
# at the top of the file, declare which module this patch fixes.
# This is important because the patch mechanism attempts to load ALL
# patch files regardless of the relevance of their code to the current
# image. Putting a sw!patch_software() call at the top of the file will
# prevent your patch from loading if it is not relevant to the current image.
# the very last line of the patch file should be the patch declaration.
sw!declare_patch(1,"1rpc","FME zero-length sectors incorrectly identified as donut holes")
The benefits of this approach include:
- Smallworld is notified of "defects" to the code. This feedback loop is important to improve the product
- Customers are given a more robust solution to introducing core fixes identified by the customizer even before the next TSB. An added benefit of a patch-based approach is that patches can be easily "backed out" of an environment if they are deemed to be causing problems in that environment.
- At TSB/upgrade time, there are fewer folders to review for changes. Each time a TSB or upgrade is released, someone will need to look at all the patches_z_proposed folders and files to either remove or modify the files depending on what core code has been update by that TSB or upgrade. It is easier to maintain core patches in one folder per product as opposed to changes in one folder (eg., basic_changes) per module.