Thursday, May 27, 2010

MDT on Smallworld 4.2

In recent MDT news from ASTEC, I noticed an article that stated that "MDT will be included in new Smallworld CST 4.2". Basically, during the Smallworld installation process you will be able to choose whether you want to use Emacs or MDT. As far as I can tell, you will initially be able to evaluate MDT for 30 days and then have to purchase a licensed version to continue using it.

For those of you who don't know, MDT (Magik Development Tools) is a visual Integrated Development Environment for Smallworld developers that is based on the Eclipse framework. You can read more about the details here.

I think that it promises faster familiarization with Magik particularly for those developers just getting started. I have to admit that it took me quite a while to get comfortable with Emacs.

I haven't used the tool much myself, but would love to hear from users that have made the switch from Emacs to MDT to learn about their experiences.

Thursday, May 13, 2010

FME and Smallworld Text Join fields

Smallworld ignores data from FME that is destined for text_join fields.

Smallworld has a data type called "text_join" which allows you to store a string of indefinite length on a Smallworld record. Under the hood, this data type is actually modeled as a join relationship to an internal table that stores chunks of finite-length strings that can be added to each other to emulate an indefinite-length string. So a text_join is actually considered a join field and not a physical field.

This becomes a problem when you want to copy data into one of these text_join fields. This is not an unusual requirement. Many Smallworld objects have at least one text_join field (e.g., Electric Office objects have a "Remarks" field; other datamodels might have a "Comments" field). Not being able to import attribute values via FME into those Smallworld objects is not an insignificant limitation.

I raised a case with GE about this recently and was told that this was a duplicate of a same case that I had raised a few years ago. I knew that there had been something familiar with this issue, but I couldn't remember that I had already encountered it a few years ago. Because there is no patch in sight any time soon for this issue, I present to you the fix I made. Like most of the FME/Magik tweaks I have had to make, the implementation is fairly easy.

(click on image to enlarge)

Debugging Smallworld-FME Error Messages

Sometimes, when I am importing data into Smallworld using FME, I get a Smallworld error message in the FME log. Unfortunately I get only the condition string and not the accompanying traceback so it is usually very difficult to debug. The traceback is also not written out to the Magik standard output.

This simple hack will cause any error conditions raised during an FME import to have a traceback dumped to the Magik standard output.

(click on image below to enlarge)

Monday, May 3, 2010

Update Triggers Fired Unnecessarily

Recently, I was working on some performance profiling on some QAQC scripts in Electric Office. It turns out that the big bottleneck was in the trigger and business rule code that was being called during the QAQC routine run. In my review of the business rules, I saw that a lot of the business rules were being called unnecessarily. That is, the update triggers were being called on objects where no material change had occurred to their attributes. If you call record_transaction.new_update(proposed_values).run() and the proposed_values are all the same as the existing values for those attributes, the triggers and business rules will still be fired. Because some of the business rules called code that was expensive to run, this added unnecessary time to the whole process.

Please be aware of this whenever you write code with record_transaction.new_update() and make sure that you only update attributes where the value has actually changed. The record_transaction API will not optimize your proposed_values list for you.

If you compile the following code into your image and then run any “slow” process, you will be notified of all the times a record gets updated with nothing new, causing the business rules to be fired unnecessarily…


_pragma(classify_level=basic)
_method record_transaction.new_update( record, values, _optional description )
##
## Creates an instance which specifies the update of a record.
##
## RECORD - the record to be updated
##
## VALUES - a property_list keyed on field name.
## The elements of this property_list provide proposed values
## for physical, geometry and simple valued join fields, and
## information for updating multi valued join fields.
##
## DESCRIPTION - String description on transactions to be used
## for undo messages.
##

# BEGIN CHANGE
# DO NOT PERMANENTLY PUT THIS INTO PRODUCTION CODE!!!! THIS IS
# FOR DEBUG PURPOSES ONLY.
_local anything_changed? << _false
_for k,v _over values.fast_keys_and_elements()
_loop
_if record.perform(k) <> v
_then
anything_changed? << _true
_endif
_endloop

_if _not anything_changed?
_then
write("Nothing changed for: ",record)
print(values)
# put a traceback in here to figure out which code is calling
# unnecessary new_update()
#!traceback!()
_endif
# END CHANGE

>> _clone.init( :update, _unset, record, values, description )

_endmethod
$