Fourth World Logo Fourth World Media Corporation
  Embassy Services Products Resources   About Fourth World Contact  
logo


Fourth World Scripting Style Guide

Adapted from The Michael and Richard Style Guide
Copyright © 1994-2001 Fourth World
Portions Copyright © 1994-1996 Michael Silver and Barnacle Software

This document may be distributed freely only in its complete, unmodified form, including this header and copyright information.
Revision 1.2(4/4/97)
Revision 1.3(4/21/97)
Revision 1.4(9/4/98)


Whereas it is in the interest of all programmers to write code in a consistent, readable style, Richard Gaskin of Fourth World and Michael Silver of Barnacle Software have collaborated to produce a style guide for programming in SuperTalk, HyperTalk, and related scripting languages.

There are many reasons to use good style practice when writing code. Some of these reasons are:

  • More easily read and understood code.
  • Consistency in a multiple-author environment.
  • Clues to the author as to the function of a variable or call.
  • Impress the chicks (or hunks).

It may take a little discipline at first, but a good style becomes natural very quickly and soon you will look at your old code and wonder who wrote it.

The authors, along with Ken Ray, Mark Hanrek, and others, have, in their courses of writing lots and lots of code, independently adopted or evolved most of the same conventions, and thus we concur that they must be pretty good. We have taken the few small differences between our styles and made what we feel is the better choice to give you, our guest, a well-thought-out, stable style that will serve you for years to come. You will be happy and all your dreams will come true.

You may have developed your own stylistic practices which you feel are better in some regards than what we present here. And they probably are. And while these are only guidelines, the more people stick to them, the more easily people will exchange code happily and live in peace. And in the end, isn't that all we really want?

Having said all that, it is never worthwhile to rewrite existing code simply to conform to these restrictions. Nor is it worthwhile to stick to a guidelines where the function or efficiency of the code is compromised. There is a fine line between maintaining more maintainable code and more efficient code. It is up to you to decide where that line is in your own code.

This document is a work in progress. We use it here in the course of teaching and working with contractors, and accordingly it is always being ammended and enhanced as experience dictates and time permits. If you have suggestions for tips and techniques which you would like to see included here, please email them to me.

Oh, and one last comment: the code in the examples may seem pointless. They are examples. That said, here is what you really came for.


1. Handler Descriptions

If a description of a handler or function is needed, it preceeds the handler with sufficient comment lines to link it visually with the handler definition.

Example:

--
-- doExample (give an example) 
--
-- This is an example of a handler definition.
--
on doExample
   global gMyGlobal,gAnotherGlobal
   ...
end doExample



2. Other Comments

Use comments liberally if you are not concerned about the script size. SuperCard, HyperCard, and Director currently have a 32K limitation for any single script, so scripts often run into this limit, and, unfortunately, comments may add considerably to the problem. Hopefully this limitation will be removed soon. Then comment liberally always.

If you must comment sparingly, be sure to comment places where the code is unusual: for example, workarounds. You may need to initialize a variable in two places or set the lockScreen to false (although it was never set to true) to workaround an engine problem. If so, you will probably not remember why that strange line of code is there the next time around until you delete it and break something.

NOTE: SuperCard users should remember that comments are removed when using Standalone Maker's encryption option. The same applies to Director users when compiling to Lingo's byte code.

 

3. Capitalization

  • Use all lower case, except where noted.
  • Capitalize the first letter in all but the first word of any compound word (e.g. doubleClickList). This applies to handler and function names, variables (except constants), and lexicon of the language you are using.
  • Capitalize the first letter in all words of an XFCN/XCMD (e.g. BitAnd), as well as your own custom hander names.
  • Avoid using underscores to separate words (e.g. my_ugly_handler_name). These are harder to work with since the entire work cannot be selected with a double-click.

Example:

on myHandler
   global gFilePath 
   put cd fld "Names" into tNames
   get Directory(gFilePath,"MDOC") -- XFCN call
   put convertDirectory(it) into tDirectory
   if tNames = tDirectory then pass myHandler
end myHandler



4. Variable Naming

In this section we advocate liberal use of what is commonly referred to as Hungarian notation, in honor of the famous Microsoft programmer Charles Simonyi, who is said to follow this practice obsessively. The value of Hungarian notation is that it provides a consistent method for determining the use and nature of a given container right in the name, without having to refer to the global declarations or parameter list. To varying degrees, this style has been adopted by many scripters in recent years, as is reflected in the product documentation for Allegiant products and others.

Here's how we apply Hungarian notation to scripting languages:

  • Use a miniscule "g" before all globals.
  • Use a miniscule "t" before all locals (for "temporary").
  • Use a miniscule "k" before all constants. Most scripting languages do not provide a true contant variable type, but there may be cases where you will want to define a global variable only once and use that value as if it were a constant throughout the rest of your code.In such cases, using a preceeding "k" will help you identify these special-case global variables.
  • Use a miniscule "p" before locals which are passed into handlers and functions as parameters.
  • Use a miniscule "u" before the names of user-defined properties.
  • Declare all globals in the first line(s) of your code.
  • Use globals sparingly. Using many globals slows down your code, and code written with globals often has problems which are difficult to find since the globals can be touched anywhere. However, if you need to use a global, you need to use a global.
  • Always use variable names that are descriptive. Stay away from names like "temp," "var1," and other names which have no meaning. Use instead names like "tProjPath."
  • The exception to the previous rule is counters which serve no other function except as an index within a loop. Traditionally, counters begin with the variable "i" and procede through the alphabet (next use "j," then "k," then "l.") You do not need to use "j", &c., unless you are building a nested loop.
  • The exception to this exception is the case where the increment counter is used within the handler as a part of an object reference (e.g, "card <counter> of ..."). Since such cases are often nested, it is recommended to use the first letter of the object type, as in "button b of card c of wd w of proj tMyProj")

Example:

on myHandler pNumPeople,pNames
   global gFilePath 
   global kMaxPeople,kMinPeople -- constants
   if pNumPeople > kMaxPeople then exit myHandler
   if pNumPeople < kMinPeople then exit myHandler
   repeat with i = 1 to the num of items in pNames
      put item i of pNames & cr after tFileData
   end repeat
   open file gFilePath
   write tFileData to file gFilePath
   close file gFilePath
end myHandler



5. Other Considerations

  • Use spelled-out words for literals such as "comma" and "colon" where the language provides them. These are parsed more quickly by the interpreter.
  • Name all objects (cd flds, grcs, wds, &c.). Stay away from using numbers unless your script depends upon that technique (and even so, you should still name them. I often use names like "Bookmark 1," "Bookmark 2", &c.).
  • Many words in scripting languages can be abbreviated. Always use abbreviations; you'll save typing and your users will save space.
  • Use parentheses to group logical or arithmetic expressions or to clarify code:
if (the vis of wd "myWindow") then

instead of:

	if the vis of wd "myWindow" = true

MetaTalk, SuperTalk and some other languages also requires parantheses for some special cases such as substituting a variable name where it expects a literal. One-word literals do not have to be in quotes, except in some special cases. Which leads us to our next rule:

  • Always put string literals in quotes, even one-word literals. Never put numeric literals in quotes (unless the language requires it). This improves parsing speed, since otherwise the interpreter must check its list of variables for a match before determining that the string is to be used literally.
  • Break your code up into logical handlers/functions. It is often better to split out sections of code into separate handlers even if they are only called once within a handler because it can make the code much easier to understand and debug. But if a handler is called often, such as in a tightly-nested loop, it is probably better to not split it out.
  • I always use the () form of functions (unless SuperTalk only support the "the" form). The "the" form is ever-so-slightly faster, but I find the () form much easier to read. Whichever you choose, just be consistent.
  • Optional "the" (e.g. "put short name of cd fld 1" vs. "put the short name of cd fld 1"). I always use it because I find the code easier to read.
  • Always use "=" for comparisons except special cases such as "the commandKey is down" or "the mouse is up".
  • & & &&: Always use && for inserting a space between concatenated expressions. (e.g. "myVar1 && quote & "the thing" && tCounter & quote".)
  • Always use Latin numbers instead of textual numeric constants. (e.g. "put myVar - 10 into cd fld "myField"", not "put myVar - ten into cd fld "myField"")