Coding Styles/Methodology

Encapsulation

  • Generally any specific SQL commands should be placed in PGSQLDAM or any other DAM that is being used. Avoid using direct SQL where possible. Exceptions can be made where performance is a concern.
  • Put most ‘work’ methods in the main table classes so that they are accessible from all parts of Theatre Manager (Windows, Web, Reports, Future Features). If a query/table class requires the functionality it should inherit from the main table class and add appropriate fields to do so. For example, a method that calculates subscription prices is stored in tF_SUBSCRIPTION because that is the database table that stores the subscription.

Looping

  • The For list.$line to list.$linecount step 1 form is generally preferred for loops for the best blend of efficiency and readability. While…End While and Repeat…Until are slower and should only be used when required. In performance sensitive areas the construct below is preferred.

    If using this construct, at the end of the loop, you must do a 'set current list' as a guard action and the setting of the list must be in a reversible block.

  • Any long running loops should be nominated for conversion or re-factoring into SQL stored procedures if they perform any database access.

    Method coding and placement

    • One should avoid, where possible, putting behavior code in events under objects on a window. It is preferred to have a public or private method in the window class that an event calls, rather then putting the code directly under an event. This allows for encapsulated functionality and allows the behavior to be called for other purposes. For example, a button that opens the patron window should have the same code whether it opens from a toolbar button, or a push button -- This would be located in $clickBtnOpenPatronWindow of the class and called from both the push button $event and the toolbar button $event.
    • Avoid writing code in window methods where possible. Window method code should only contain interface and interaction. If and code deals with database, the approach to be used is:
      • to put that code into a table class
      • invoke it from the window class by doing 'do list.$doMyMethod(parameters)'
    • A comment in all methods is essential. At the very least a comment section should include what the method is expected to do based on what inputs.
    • When altering existing code within a method, the developer should put a comment indicating what version the code was altered in as well as the initials of the developer altering it. E.g. ; V90000 DM (Version 9.00.00 [D]avid [M]cKeone)

    Parameter Passing

    • Throughout TM, the TMObjs.$makeparamrow() and TMObj.$loadparamvars() functions are used for passing parameters between objects. This method is favoured over passing individual parameters to a top-level class, especially when a large number of the parameters are optional. See wModeless.$construct for an example.
    • When over-riding any method:
      • always put the parameters in place that the superclass has:
        • in the same order (verify the order always)
        • document with the same parameter definitions
        • copy whatever documentation from the superclass and augment with why you are over-riding the class if it is not obvious
    • All parameters are to have an initial value specified for default case. 0, kTrue, Kfalse or #NULL is acceptable if no value is wanted

    Table Classes (SQL database)

    • All foreign key relationships should be in $buildChildRecordList of the appropriate main table class. E.g. All relationships for the F_CLIENT database table are in the tF_CLIENT table class.
    • All F_APPLICATION replaceable variables (indicated by a ‘g’ prefix). Should be specified in the $getReplacementSelectNames. Use $getReplacementSelectNames where possible:
      • To avoid setting values in the omnis list - for performance reasons
      • To add functions to replace gVars, especially where there may be multiple parent records to a relationship (eg sold by, changed by, printed by all connect to employee)
      • To obtain key customer data like Primary Phone, email address and other data that varies depending on the outlet (department) of the employee who is logged in. Example: the primary address for patron 1 made be different for outlet A and B
      • In reports so that there is limited record looping in the detail section of report (again for performance)
    • Any validation on a table should be done in $verifyRecord of the main table class for that database table.

    Tidying Up Code

    After completing code changes and final testing of any code class, always:
    • Remove unused variables from the Local variables
    • Remove unused variables from the Instance Variables. If a variable is not used in a superclass class, but is used in a number of subclasses, then in the superclass, in the construct, after the quit method, calculate the variable as itself so it will not show up as unreferenced.
    • Check the class variables and see if they are used and remove if not