Version 6, last updated by Sean Connelly at April 26, 2009 01:29 UTC

SC - Note, these standards / conventions are for writting GT.m code for an easyM library such as core. Maybe we need a seperate wiki page for a more general "Recommended Coding Conventions for M".

One of the objectives of easyM is to encourage the use of coding standards. These coding standards will provide benefits such as

  • Avoiding code collisions
  • Readability and Conistancy
  • Automatic documentation of code
  • Unit Testing

 

1. Naming Conventions

Routines should be logically organised into a related groups of code. These groups should all share the same prefix. If the routine is part of an easyM library then that prefix should start with a small z. For instance, all routines that are part of the core library should be prefixed with zcore, i.e.
zcoreString
Globals should also be grouped and prefixed in the same way. Globals that are part of the easyM library should also start with a small z.
Function names should be self describing.
Variables should use self describing long names with the exception of iterators that can use the single characters i,j,k...
All names should be in camelCase starting with a lower case alpha character.

? AW - Looks like the character "z" is being reserved as a root prefix, was expecting zcore*

SC - Agreed, zcore for the zcore lib, z?* for other libs.

? AW- "z" global on many M applications is mapped to a non-journalled, temp area. It is assumed that temp databases can be dropped or purged without impact to a deployment. If z data contains some kind of data dictionary or configuration data this would cause problems. Maybe a % prefix globals would be better?

SC - Agreed but not sure about using %. Maybe make it a more unique prefix such as "xm" (extended m). And "zxm" for temp.
e.g. ^xmCoreDocs for core documentation.

? AW- Do we have a searchable source controlled document that lists what routine names have already been use and short summary of usage.

SC- No. We could get the documation profiler to do this. Or, maybe use RE/m!


2. Comments

Code should be clear and self describing. The use of comments within the body of code should be kept to a minimum. Comments should be primarily used to describe the routine and how to use its public functions.
easyM will include a code profiler that will automatically generate documentation from its comments. The convention for automated comments will require two leading semicolons.
Automated comments should describe the routine and each public function, how to use the function and its arguments. There is no need to add authors or dates to routines, these can be derived from SVN.
The start of each function should be clearly marked with a solid line of comments. This helps to clearly divide functions for readability.
Example...

mathsFunctions
    ;;this routine contains maths functions

    ;;________________________________________________________
    ;; adds two integers together
    ;; int1 : the first integer value
    ;; int2 : the second integer value
add(int1,int2)

    quit int1+int2

    ;;________________________________________________________
    ;; subtracts two integers
    ;; int1 : the first integer value
    ;; int2 : the second integer value
subtract(int1,int2)
    quit int1-int2

? AW -Note on location and structure of the standard version header for VCM.

? AW- Source versioning scheme. [MajorRelease].[MinorRelease].[BugfixIncrement].[BuildNumber]

For example: 1.3.15.1.

? AW -Can we agree a format for maintenance and header:

  ;;-------------------------------------------------------

  ;; Developer | Version      | Date             | History

  ;; Fred           | 1.3.15.1      |2009-01-21 | Added subroutine XYZ to support new functionality

? AW - What Date format do we use in documentation for source control

SC - I would prefer to keep the header comments simple for now and automate it later. As Terry suggested we could get SVN to do this for us. In the mean time SVN provides this information in its audit. Note, we should also add a link to easyM licence terms as well.

3. Code

In most instances we should use the long form of all keywords. Functions such as $Order are just as readable in short form.
We should avoid in most instances the temptation to put lots of code on one line.
In some instances, it's accepted that small chunks of optimised code are condensed into a few lines. In these instances it's ok to use short form.
Code that's all in lower case looks cleaner and is easier on the eye.

? AW -In the comments example above you have used lowercase names for subroutines. I'm wondering whether routine and line labels would benifit from camel case. Note that casing of the routine name is significant on Linux.

First code label is same name as mumps file name.

This label only contains summary and maintance history.

Use "p" prefix on label arguments eg:

CodeExample;

  ;; Some usage

  quit

LabelA(pArg1, pArg2)

  new localvar

  set localvar = pArg1 _ pArg2

  quit localvar

SC - I prefer camel case starting with a lower case. Anyone else with a view on this?

SC - Agreed, using the "p" prefix would be clearer for anyone else reading the code.

 

4. Unit Testing

All common functions, especially those in the core library should be unit tested. The original author of a function should be responsible for creating a sufficient quantity of unit tests for that function. All unit tests should be organised within a function called unittest within the same routine as the function. A profiler will recognise this function and will add it to it internal unit test list. Tools will be generated to visualise and automate these tests. A wiki page detailing unit testing will be added here soon.

Suggestion AW - Instead can we use annotations to indicate unit tests for example:

@UnitTest_Fixture - placed above the first line label of a routine

@UnitTest_SetUp - Argumentless line label called before running any tests in a fixture

@UnitText_TearDown - Argumentless line label called after completing one or more tests on a fixture

@UnitTest_Test - Argumentless line label called for unit test

Also would like to support for RowTest

 @UnitTest_Row

 @UnitTest_RowTest(1,"ABC")

 @UnitTest_RowTest(2,"DEF")

LabelTest12(pNum, pString)

 ;; Some functionality

 Quit

Test code needs to exist independently in a seperate version controlled mumps source file. This allows unit test to be written at the level of modules or at system level. A specific module test may be valid for many versions of source code.

SC - Would prefer to keep this a classic M solution just now (needs a compiler, compiler needs core, chicken and egg...).

quick dump of assertion tests...

assertEqual(a,b)
assertEqualIgnoreCase(a,b)
assertNotEqual(a,b)
assertIsNull(a)
assertIsNotNull(a)
assertIsTrue(a)
assertIsFalse(a)
assertGreater(a,b)
assertGreaterOrEqual(a,b)
assertLess(a,b)
assertLessOrEqual(a,b)
assertContains(a,b)
assertMatches(a,b)
assertStartsWith(a,b)
assertEndsWith(a,b)
assertFileEquals(a,b)

depending on the mode, running a test will either report to the command line, or build a global report for a GUI.