The ENVY/Developer Cookbook

Copyright (c) 1995 - 2000 by Joseph Pelrine. All rights reserved.

Last update: June 24, 2000.

This cookbook is meant to serve as a quick reference for the main steps in working with ENVY. It's meant to help Smalltalkers get up to speed quick. It's not really meant for the gurus out there; you guys know all this stuff already. I had originally put this together for my consulting customers in order to avoid answering the same questions over and over. As a service to the Smalltalk community, I'm putting it up on the Web.

NOTE: This is still a draft version. Comments and criticism are appreciated. E-mail me at: jpelrine@acm.org.


Table of contents

This cookbook consists of the following sections:

  1. Creating software components
  1. Creating a new application
  2. Creating a new Subapplication
  3. Creating a new class
  4. Defining a class
  5. Extending a class
  6. Creating a new method
  7. Creating a new ConfigurationMap
  1. Preload initialization
  2. Postload initialization
  3. Preunload de-initialization
  4. Postunload de-initialization
  5. setToBeLoadedCode
  6. Error recovery
  1. Versioning Classes and Applications
  2. Releasing Classes and Applications
  1. Application Manager
  2. Class Owner
  1. Extending existing classes
  2. Changes to system classes
  1. Method comments
  2. Class comments
  3. Application comments
  4. ConfigurationMap comments


Creating software components

Creating a new application

Creating a new Subapplication

Subapplications should only be used under a small number of clearly defined circumstances. It is not a good idea to structure a project as one application with many subapplications. For guidelines, consult Bobby Woolf's ENVY page.

Creating a new class

ENVY distinguishes between class definitions and class extensions.  An ENVY class definition is a standard Smalltalk definition, consisting of name, superclass, instVars, classVars, pools, and methods. Class extensions consist solely of methods. While the class may be defined only once, in a single Application, it may be extended many times. Definitions and extensions must be contained in different ENVY Applications, and the Application containing the definition must be declared as a prerequisite for any Application extending the class.

Defining a class

Extending a class

Creating new methods

Creating new ConfigurationMaps

ConfigurationMaps are non-defining collections of Applications. Non-defining means that one Application can appear in a number of different ConfigurationMaps. ConfigurationMaps may also have prerequisites declared. In many organizations, the Library Supervisor is responsible for creating ConfigurationMaps, and for this reason we will not go into detail about the process here.


Initialization

In order to be a good citizen, every Application should set up any necessary state on loading, and remove any changes upon unloading. ENVY provides protocol for Application classes to accomplish this.

Preload initialization

Initializations which should be performed before an Application is loaded (such as global and variable declarations) can be stored as a Smalltalk-evaluable string in the repository. Upon loading, the Compiler evaluates the string. The string is stored by sending the method #toBeLoadedCode: to the Application. The following is an example:

myApplication toBeLoadedCode: '
  Smalltalk 
    declareVariable: ''MyGlobal'';
    declarePoolDictionary: ''NewPool'';
    declare Variable: ''PoolConstant'' poolName: ''NewPool''.'

The declare.. methods do not overwrite an existing declaration. Any variables that already are defined are not altered. The source string is stored with the Application edition, and only the Application Manager can change it.

It is customary to define a setToBeLoadedCode method in the Application, as explained below.

Postload initialization

Initialization which must be performed after an Application has been loaded should be defined in a #loaded method in the Application. This method is sent to an Application after it has been loaded or reloaded.

loaded
 
  Foobar initialize.
  System updateTranscriptMenus.
   

Preunload de-initialization

De-initialization which must be performed before an Application can be unloaded should be defined in a #removing method in the Application. In this method, the Application should remove any instances of its defined classes contained in the image, and remove any changes it has made to the System menu. This method is sent to an Application before it is to be unloaded.

removing
 
  Foobar reset.
  System updateTranscriptMenus.
   

Postunload de-initialization

After unloading, an Application should be a good citizen, and remove any pool dictionaries, globals, etc. that it has defined. The code to perform these actions can be stored as a Smalltalk-evaluable string in the repository. After removal, the Compiler evaluates the string. The string is stored by sending the method #wasRemovedCode: to the Application. The following is an example:

  myApplication wasRemovedCode: '
    Smalltalk 
      undeclare: ''NewPool'';
      undeclare: ''MyGlobal''.'

setToBeLoadedCode

If you use the #toBeLoadedCode: and #wasRemovedCode: methods, it is customary to send them in the context of a #setToBeLoadedCode: method. This technique has the added advantage of giving you an edition history of your declarations.

setToBeLoadedCode
    "self setToBeLoadedCode"

  self toBeLoadedCode: '
    Smalltalk 
      declareVariable: ''MyGlobal'';
      declarePoolDictionary: ''NewPool'';
      declare Variable: ''PoolConstant'' poolName: ''NewPool''.'

  self wasRemovedCode: '
    Smalltalk 
      undeclare: ''NewPool'';
      undeclare: ''MyGlobal''.'

Error recovery

If you attempt to remove an Application which contains classes with existing instances, or with subclasses defined elsewhere which would be left orphaned, your unloading will fail. Since this can leave the image in an inconsistent state, ENVY sends the method failedRemove if an error occurs while unloading. The default implementation is to mark the Application as a scratch edition; if you have added loaded code, it is best to reinitialize it.

failedRemove

  self loaded.


Versioning

Versioning is the process of freezing and naming a component. A version of a component cannot be changed, and can be uniquely identified.  Good naming conventions and very important, and play a major role in successful, productive development. Do not use the default names; rather, ensure that the version name adheres to the naming conventions.

Releasing is the process of defining which version of a component belongs in a larger component. The Class Owner releases his classes into the enclosing Application or Subapplication; the Subapplication Manager releases his Subapplications into the enclosing Application, and the ConfigurationMap Manager releases Applications into the ConfigurationMap. Components must be versioned before they can be released, and all enclosed components must be versioned and released before the enclosing component can be versioned.

Versioning Classes and Applications

Releasing Classes and Applications


Prerequisites

All dependencies to other Applications should be explicitly listed as Application prerequisites. ENVY ensures the proper loading and functioning by means of prerequisites, and the Packager uses the prerequisite structure to calculate the inclusion set for the run-time executable. Transcript messages when loading an Application, or "...should not reference..." messages upon compiling a method, are signs that the prerequisite structure is not correct.


Ownership

Application Manager

Class Owner

Any developer who is listed as a group member of an application can create an edition of a class in the application and subsequently version it. One developer, though, is designated as class owner, and has the responsibility for maintaining the consistency of the class. The class owner is responsible for merging any changes made to the class by different developers. Only the class owner can:

The scope of class ownership is limited to a single application edition. The owner of a class in the application in which it is defined is not necessarily the owner of the class in another application, where the class is extended. Also, the owner of a class in one version of an application is not necessarily the owner of the class in another version.


Changes

Extending existing classes

See Extending a class above.

Changes to system classes

Since changes to system classes can affect all developers, it is important to be able to estimate the consequences of any such change. For this reason, such changes should be left to the Library Supervisor or an experienced Smalltalker.


Comments and Notes

It should be obvious that comments are necessary in order to communicate the developer's intentions to the reader of the code. ENVY allows comments above and beyond the quotation marks at the beginning of a method.

ENVY differentiates between comments and notes. Comments are unique for a software component (they are inherited from a previous edition of the component), while notes are bound to a specific version of the component. Neither comments or notes are historicized; if you want a history of a component's comments or notes, you need to implement it as a string or comment in a method.

Both comments and notes are stored as User Fields, and are available for all software components. The browsers offer a simple interface to the commenting mechanism by way of the three-state button in the bottom right part of the browser. Comments and notes may be accessed programmatically as well. This technique is useful for automatic documentation tools.

Users have no comment; nevertheless, it is no problem to add an inherited user field for comments about a user ;-)

Method comments

#comment

Class comments

#comment

Application comments

#applicationComment

ConfigurationMap comments

#comment


User Fields

This section is under construction.

 

comment

"Return the comment entered for the receiver. The comment is

inherited from the previous edition of the receiver."

 

^EmImageSupport textFilter filter:

(self record inheritedUserFieldAt: 'comment')

description

"Return the description entered for the receiver. The description

is not inherited from the previous edition of the receiver."

 

^EmImageSupport textFilter filter:

(self record localUserFieldAt: 'description')


Recovery

This section is under construction.


Tips and tricks

This section is under construction.


Resources

This section is under construction.


Acknowledgements

The author wishes to acknowledge the following people, who have strongly influenced the way he (and many others) uses ENVY: Alan Knight of the Object People, Jan Steinman of Bytesmiths, and both Adrian Cho & Stefan Bosshard of OTI.


Legal Stuff

Disclaimer

This FAQ is to aid in informing the public about ENVY/Developer, a product of Object Technology International (OTI). Joseph Pelrine claims NO responsibility regarding ANY activity concerning this FAQ, or indirectly related to this FAQ. The information contained in this FAQ only reflects OTI indirectly, and questioning OTI regarding any information in this FAQ is not recommended.

Trademark information

All specific names included herein are trademarks and are so acknowledged: ENVY/Developer, VisualWorks, VisualAge. Any trademarks not mentioned here are still hypothetically acknowledged.

Copyright notice

This article is Copyright (c) 1995-2000 by Joseph Pelrine. All rights reserved.

You are granted the following rights:

I. To make copies of this work in original form, so long as

II. To distribute this work, or copies made under the provisions above, so long as

 

You may not distribute this work by any non-electronic media, including but not limited to books, newsletters, magazines, manuals, catalogs, and speech. You may not distribute this work in electronic magazines or within computer software without prior written explicit permission. These rights are temporary and revocable upon written, oral, or other notice by Joseph Pelrine.

If you would like additional rights beyond those granted above, write to the author at jpelrine@acm.org on the Internet.

You found this document at http://www.daedalos.com/~j_pelrine/envyfaq.htm.