Category: VisualWorks


When a Customer wants to upgrade to a newer version of Cincom® ObjectStudio® or Cincom® VisualWorks®, I and other members of our Smalltalk Support team here at Cincom will suggest that they review the Release Notes—not only for the version that they are upgrading to, but also for all the releases that came after their current version. While this will give customers an overview of the things that have changed, the individual specific changes usually can only be seen by reviewing the actual changes in the code that happened between the versions.

In Chapter 2 of our Source Code Management Guide, we suggest publishing the VisualWorks base code into a company’s Store repository.¹ If that is done, the Package Comparison tool can be used during development to see if any changes or overrides have been made to the base code. As an added benefit, the Package Comparison tool can then be used to review the changes that have happened between versions of VisualWorks.

During many upgrade projects, there are phases when it is beneficial to include a review of what base code has changed, was added or removed. Focusing on just those individual types of changes at any one time can be difficult in the Package Comparison tool because it combines all of the types into one presentation.

To help reduce the friction during that phase of an upgrade project, I’m introducing the Filtered Store-Code Comparison Contributed Package for Cincom ObjectStudio 8.4 or Cincom VisualWorks 7.9 and above.

Click for a lager Image of Package Comparison Tool with the new options.

When loaded, this package adds three Checkboxes to the Package Comparison Tool that allow the user to control what types of comparisons are to be shown or hidden:

Image of the new options at the bottom of the Compare Packaged tool.

When any of these new options are turned on (checked), the comparison view will be updated so that those types of comparisons are no longer shown. The hidden comparisons can be shown again by turning off any of the options (unchecking a checked option).

The new options are made possible in part by wrapping the existing Tools.PackageComparisonTool within instances of PackageComparisonToolWithFiltering—a new ApplicationModel provided by this package. Doing this required overriding a couple of existing methods in the image, but I tried to keep the number of overrides to a minimum. The majority of the functionality was enabled by adding and keeping flags in the properties dictionary that already exists in every instance of VisualPart.² Also, since not every kind of AbstractComparisonRollupView kept track of what kind of comparison it represented, the code has been extended so that every comparison view can answer if it represents an addition, a change or a removal.

If you wish to explore how the extensions and overrides work, additional technical details can be found in the comments for the package and in all of the added methods. I’ve done my best to explain my design decisions, along with noting any compromises, which I felt were needed.

The current version of the Filtered Store-Code Comparison package can be downloaded from the Contributed Components section of our website:

http://www.cincomsmalltalk.com/main/community/product-portal/contributed/


1. Publishing the base code is recommended in “Chapter 2 − Beginning to Use Store” of our Source Code Management Guide documentation. (Overall page 27 of 168 in the latest version of the document.)

2. The properties dictionary was first added as an instance variable of VisualPart in VisualWorks 7.6. For more information, see the Release Notes for 7.6 or the instance variable documentation in the class comments of VisualPart.

Posted by: James T. Savidge

Introducing BrowseOverrides

The BrowseOverrides is a new contributed package designed to help users quickly review any methods in an image that have been overridden by extensions in other packages.

While working on the Senders of Deprecated browser, our customers have told me and other members of our Smalltalk Support team here at Cincom that they have difficulties in managing the overridden methods in their images. Because the existing Override Editors¹ are restrained by the limitations of the Change List Tool², most of our customers work with overridden methods within the confines of the standard Refactoring Browser.

When a method is overridden in the code browsers, we only show the code for that method in the package that contains the most recently loaded or edited version of the override. Some of our customers agree that this is the right thing to do, but others want the overridden version of the methods to also be shown in the package(s) where the original methods resided. Our Engineering team is in the process of finding a way to give our customers something that will accommodate all of those needs, but it may take a while before that work is ready to be released.

To provide some short-term help in this area, I’m introducing the BrowseOverrides Contributed Package for Cincom® ObjectStudio® 8.1 or Cincom® VisualWorks® 7.6 and above. Included are extensions to the VisualLauncher and Override classes that are designed to help you quickly review any methods in your image that have been overridden by extensions in other packages.

Loading the package will add an Overridden Methods submenu and submenu items to the “Browse” menu in the Launcher window:

Click for a lager Image of the Overridden Methods Browser Menu

Each of the submenu items will open a method list browser on a list of methods based on the following criteria:

  • All          -> Any methods that have an Override.
  • Single     -> Any methods that have only one (a single) Override.
  • Multiple  -> Any methods that have more than one Override.

Click for a lager Image of the OverriddenMethods BrowserSince a standard method list browser is used, the code editing pane will have an active red-colored “Overridden” tab for each of the methods in the list. This tab has the same functionality of the “Overridden” tab in the code editing panes of the standard Package/Class Refactoring browsers. Please note that the look and functionality of the “Overridden” tab will be somewhat different in versions of VisualWorks prior to 7.7.1.³

If you wish to explore how the extensions work, additional technical details can be found in the comments for the package, and in all of the added methods. I’ve done my best to explain my design decisions along with noting any compromises I felt I had to make along the way.

Starting on December 9, the current version of the BrowseOverrides package can be downloaded from the Contributed Components section of our website:

http://www.cincomsmalltalk.com/main/community/product-portal/contributed/


1. Override Editors are described in “Chapter 3 – Override Editor” in our Tool Guide documentation.

2. Change List Tools are described in “Chapter 5 – Change List” in our Tool Guide documentation.

3. Please see the “Override Code Tool gets a facelift” section from the Release Notes for VisualWorks 7.8 , Page 1-20, about the Override tab in the code browsers.

Posted by: James T. Savidge

Introducing the Senders of Deprecated Browser

The Senders of Deprecated browser is a new contributed package for Cincom® ObjectStudio® 8.6 or Cincom® VisualWorks® 8.0 and above.Click for a lager Image of the Senders of Deprecated Browser

I created it to help developers track down, evaluate, and hopefully eliminate any places in their code that call methods which have been marked as deprecated by the Engineering team at Cincom, or by anyone else.

After loading the package, the browser can be opened by picking the “Browse -> Senders of Deprecated” menu item from the VisualWorks Launcher window, or by executing the following code:

    Smalltalk.DeprecatedSendersBrowser openDeprecatedSenders.

As the browser opens, it searches the image to collect all of the methods that send >>deprecated:. It then attempts to find the methods that call any of those deprecated methods. The list of deprecated methods is displayed in the upper list pane, and when one of those methods is selected, the second list pane below it is filled with the methods that are believed to be senders of the deprecated method in the upper list. If a method in the second list pane is selected, then below it is a standard code pane where the source of that sending method is shown and can be edited.

Because of the inherent performance compromises in MethodCollector and MethodFilterReference, there will be some false positives in the list of methods collected. Methods in the lower list pane can be removed from that list by using the standard “Method -> Remove From List” menu item. Deprecated methods in the upper list pane can be removed from that upper list by using the new new “Deprecated -> Remove From List” menu item. (If there are any senders still left in the lower list pane for the selected deprecated method, then those will be removed from the lower list pane at the same time.)

Image of the new Deprecated menu

The new Deprecated menu is much like the existing Method menu, but the items have been pared down to items that make sense for a method list which does not have a corresponding code pane where source can be viewed and edited.

If you wish to explore how the browser works, additional technical details can be found in the comments for the package, the classes, and in all the methods. I’ve done my best to explain my design decisions, along with noting any compromises I felt I had to make along the way. Hopefully, you can jump into any place that interests you, and the comments should help you understand how it is connected to other parts of the browser, and to the rest of the system.

The current version of the BrowseDeprecated package can be downloaded from the Contributed Components section of our website:

http://www.cincomsmalltalk.com/main/community/product-portal/contributed/

On a historical note, I started work on this browser when one of our Customers wrote about how difficult and time-consuming it was for them to verify that none of their code calls any of our deprecated methods. I targeted this browser to make it easier to focus on and complete that process for any ObjectStudio or VisualWorks project.

There are numerous improvements that can be made to the browser, but I would like to get some feedback from real users before deciding what to work on first. After working with the new browser, please tell me what features are useful to you, and what your team needs to make it even more valuable during your projects.

Posted by: James T. Savidge

F-Spot, Glorp and VisualWorks

I’ve been using Linux as my primary desktop platform for some years now. I generally try to keep up with the releases and stick with the default choices as much as possible. Recently I tried to use F-Spot because it’s the default photo manager for GNOME now. It’s got some nice features and is generally OK, although not very flexible. Very much in the spirit of today’s UI design dogmas (“You can’t handle flexibility!”). Anyway, I noticed that F-Spot uses sqlite3 as its database, so I wasn’t too afraid to spend some effort tagging pictures etc.

Recently, as I was upgrading my computers, I decided to move the pictures to a different location. Unfortunately F-Spot doesn’t seem to provide a way to update its database accordingly. Poking around in the database it seemed to be fairly simple database update, so I decided to whip up a quick, Glorp based, database mapping and do the update with a script.

The database has a PHOTOS table with following definition:

CREATE TABLE photos (
	id			INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
	time			INTEGER NOT NULL, 
	base_uri		STRING NOT NULL, 
	filename		STRING NOT NULL, 
	description		TEXT NOT NULL, 
	roll_id			INTEGER NOT NULL, 
	default_version_id	INTEGER NOT NULL, 
	rating			INTEGER NULL, 
	md5_sum			TEXT NULL
);

The path to the picture is stored in the base_uri field, usually looking something like ‘file:///home/user/Photos/…’. I needed to change all of them to something like ‘file:///pub/photos….’ instead. So, first I created a Photo class with a simplified version of the above:

	id  database id
	time  time taken
	base_uri  location of the photo
	filename  location of the photo
	description  any notes

Mappings are defined on subclasses of DescriptorSystem, so I created one and started with description of the class model:

classModelForPhoto: aModel

	aModel newAttributeNamed: #id.
	aModel newAttributeNamed: #time type: Timestamp.
	aModel newAttributeNamed: #base_uri type: String.
	aModel newAttributeNamed: #filename type: String.
	aModel newAttributeNamed: #description type: String.

then the table description.

tableForPHOTOS: aTable

	(aTable createFieldNamed: 'id' type: (self fakeSequenceFor: aTable)) bePrimaryKey.
	(aTable createFieldNamed: 'time' type: platform int4) beIndexed.
	aTable createFieldNamed: 'base_uri' type: platform varchar.
	aTable createFieldNamed: 'filename' type: platform varchar.
	aTable createFieldNamed: 'description' type: platform text.

and finally the mapping between the two:

descriptorForPhoto: aDescriptor

	| table |
	table := self tableNamed: 'PHOTOS'.
	aDescriptor table: table.
	(aDescriptor newMapping: DirectMapping) from: #id to: (table fieldNamed: 'id').
	(aDescriptor newMapping: DirectMapping) from: #base_uri to: (table fieldNamed: 'base_uri').
	(aDescriptor newMapping: DirectMapping) from: #filename to: (table fieldNamed: 'filename').
	(aDescriptor newMapping: DirectMapping) from: #time to: (table fieldNamed: 'time').
	(aDescriptor newMapping: DirectMapping) from: #description to: (table fieldNamed: 'description').

 

With these in place I could try to connect to the database. For that I needed to provide the connection information, so I added 2 class side methods:

newLogin

	^(Login new)
		database: SQLite3Platform new;
		connectString: (PortableFilename named: '$(HOME)/.config/f-spot/photos.db') asFilename asString.

newSession

	^self sessionForLogin: self newLogin

With this I could invoke #newSession and get a connected session back. Time to start experimenting with the database.

Reading a photo is easy:

	session readOneOf: Photo.

To figure out what are all the places from which I’ve imported pictures I used this:

	query := (Query read: Photo) retrieve: [ :e | e base_uri ].
	(session execute: query) asSet.

It reads all the base_uri values and puts them into a Set. A smarter database query can do this more efficiently, but this was fine as well in my database of about 6k pictures. I found out I imported pictures from two locations. I decided to deal with them one by one. To perform the update I ran the following:

	photos := session read: Photo where: [ :p | p base_uri like: '%home/mk/Photos%' ].
	session modify: photos in: [
		photos do: [ :p | p base_uri: (p base_uri copyReplaceAll: 'home/mk/Photos' with: 'pub/photos') ] ].

It reads each photo with the selected location in base_uri and updates it with the new one. Then I did the same for the second location. The entire update operation took less than 20 seconds. Later I found out that there’s a plugin for F-Spot for this sort of migration, but its comment said that it can take a few hours. I don’t know how big a database they had in mind, but that sounds a bit excessive still.

Since then I fleshed out the mappings, created a Glorp Workbook so that it’s more convenient for quick experiments (you get a toolbar button for easy access) and packed it all up. I published the package to the public repository as F-Spot, hoping it might be useful to someone else too. As far as future plans go, there really aren’t any beyond finishing the mapping layer. One thing I’m considering is that I find the imports into F-Spot excruciatingly slow. I might use this package for that task instead.

– Posted by Martin Kobetic