The Simple Library: details

Package contents and structure

Each Simple Library package is a collection of namespaces, commands, variables, errors and aliases which together provide a differentiated functionality. All Simple Library packages are defined in child namespaces of the ::Simple namespace. Each command has one access type, either exported, public or private: See the SimplePackage package for more details.

Some Simple Library packages behaviour can be configured through package options. These options are modified via the configure command in the package main namespace and queried via the cget command in the same namespace.

Each Simple Library package is a single Tcl file. Each file is divided into two sections: the package definition and the regression testing sections. The package definition contains the package declaration together with its options, variables, errors and procedures. The regression testing section contains a collection of test cases intended to fully test the functionality provided by the package. More sections may be added in the future, for exaple one for benchmarking the package.

Each package file is structured as follows:

if {[string compare $::SIMPLE(PackageMode,package) test]} {
   Package definition section
} else {
   Regression testing section
}

where package is the name of the package. This way, either the regression testing or the package definition section is exposed depending on whether the package mode (stored in the global array SIMPLE, first index PackageMode, indexed through the second index by package name) is definition or test, respectively. The Simple Library pkgIndex.tcl file sets each element of the package mode array to definition or test depending on whether the required package is named package or package-test, respectively, as expected by simpletest, the regression testing utility.

Program, package and command headers

Each Simple Library component (program, package or command) contains a header. What follows is the ordered list of the tags which may appear in each component header:

Component
 Tag   Program   Package   Command   Description 
 program 
X
     Program name 
 package   
X
   Package name 
 command     
X
 Command name 
 version 
X
X
X
 Component version 
 purpose 
X
X
X
 Component one line description 
 access     
X
 Command access mode [1
 alias     
X
 Command alias 
 overview 
X
X
X
 Component multi-line overview 
 usage 
X
X
X
 Component usage [2
 arguments     
X
 Command arguments 
 returns     
X
 Command return value 
 keywords 
X
X
X
 Component keywords 
 examples 
X
X
X
 Examples on how to use the component 
 namespaces   
X
   Package list of namespaces 
 commands   
X
   Package list of commands 
 variables   
X
   Package list of variables 
 options   
X
   Package list of options 
 requires 
X
X
   Component list of required packages 
 assumes 
X
X
X
 Component assumptions 
 resources 
X
X
X
 Resources required by the component 
 limitations 
X
X
X
 Component limitations 
 effects     
X
 Command effects [3
 diagnostics 
X
     Program list of error messages and explanations 
 details 
X
X
X
 Component implementation details 
 seealso 
X
X
X
 Component references 
 remarks 
X
X
X
 Component important remarks 
 todo 
X
X
X
 Component to do list 
 bugs 
X
X
X
 Component known bugs 
 history 
X
X
X
 Component history 
 copyright 
X
X
X
 Component copyright notice 
 [1] Exported, public or private.
 [2] A short usage message for programs, a longer usage description for packages and commands.
 [3] Command effects outside its package scope, such as variables modified thorugh upvar, those of evaluated scripts, or items (command, variables, namespaces, aliases, ...) creations or deletions.

Coding style

The Simple Library Tcl code follows extrict coding style rules:
  1. Naming conventions:

    1. Identifiers: made of letters, numbers, hyphens and underscores only. The percent sign is reserved for Simple Library internal usage. The space is used for subcommand procedure identifiers, between the base command and the subcommand names (as in command subcommand).

    2. Variables:

      1. Global variables: all uppercase, words separated by underscores: FOO_BAR_GEE.

      2. Local variables: use of the camel convention (all identifier words joined, with the initial letter of the second and following words capitalized), first letter lowercase: implicitCheckType.

      3. Namespace variables: use of the camel convention, first letter uppercase: ArgumentNames.

    3. Namespaces: use of the camel convention, first letter uppercase: ::Simple::ScriptHead.

    4. Procedures: all lowercase, words separated by hyphens: parse-qualify-name.

    5. Subcommands: all lowercase, no separation between words: importedinto.

    6. Packages: use of the camel convention, first letter uppercase: SimpleExtProc.

    7. Package options: all lowercase with a starting hyphen, no separation between words: -storedetails.

  2. No line exceeds 80 characters.

  3. Verbose comments are extensively used, many times referring even to a single line of code. Although this is sometimes considered bad practice, I do like this style. Most comments start by a triple hash (###), and the code is commented in such as way that each procedure pseudocode is exposed when deleting everything in its body but the triple hash comments.

  4. Double quotes or curly brackets are used only when necessary (for grouping); set foo bar is used instead of set foo "bar".

  5. Curly brackets are used for grouping, unless double quotes are necessary (for substitution); set foo {bar gee} is used instead of set foo "bar gee" (but, of course, set foo "bar $gee").

  6. All commands and variables are used in their fully-qualified form; the Tcl variable command is never used.

  7. No Simple Library command is named after a Tcl intrinsic command. There are information and move commands resembling the info and rename Tcl intrinsic commands.

  8. Some care has been taken to separate between lists and strings. In particular, set foo [list] is used when an empty list is needed, but set foo {} when the null string is wanted.

  9. string compare is used to check the equality of strings instead of ==.

  10. [llength $list] == 0 is used to check for an empty list.

  11. The format command is sometimes used to escape from quoting hell. For example,

    set subexpression [format {$%s == %s} $number $atom]

    instead of

    set subexpression "\$$number == $atom".

    (for a much better example, see the ::Simple::Subcommand::Priv::create-base-command in the SimpleSubcommand package, where some twenty lines of code are escpaed with this method). Although this is slower, the improved legibility pays off in non-critical procedures

  12. The use of return is avoided unless strictly necessary. Most procedures return to its caller by exiting through the end of its body, that is, multiple return points are avoided.

    When a value must be returned, the return value of the procedure body last command is implicitely used. Many times a local variable named answer is set to contain the procedure return value, and the last command of the procedure body is set answer. This is also against what is generally considered good style, but return is slow, and I prefer to avoid it.

Last update: 23 april 2000