GraalScript2 (GS2) Coding Conventions
This is a set of coding conventions and rules for use in GS2 programming. It is an adaptation of Crockford's document, http://javascript.crockford.com/code.html.
Over a script's lifetime, it will be handled by many people, making it very important to clearly communicate its structure and characteristics, making it less likely to break when modified in the never-too-distant future.
Indentation
The unit of indentation is 2 spaces. The code editor in Remote Control (RC) already handles this by changing a tab-stop to 2 spaces automatically.
Line Length
Avoid lines longer than 80 characters. If a statement won't fit on a single line, it may be better to break it up. Place the break after an operator, ideally after a comma. The next line should be indented 4 spaces.
Comments
Be generous with comments. It is useful to leave information that explains how your script works for others (possibly yourself) who will need to understand what you have done.
The comments should be well-written and clear, just like the code they are explaining. Occasional humor might be appreciated as well. Frustrations will not.
It is important comments be kept up-to-date. Incorrect comments can make programs harder to read and understand.
Make comments meaningful. Focus on what is not immediately visible. Don't waste the reader's time with stuff like:
i = 0; // Set i to zero.
Generally use line comments. Save block comments for formal documentation and for commenting out.
Variable Declarations
Variables should be declared before used. GS2 does not require this, but doing so makes the program easier to read.
The variable declarations should be the first statements in the function body.
It is preferred that each variable be given its own line and comment:
temp.currentEntry; // currently selected table entry temp.level; // current level temp.size; // size of table
Avoid using global variables. Variables that don't need to be accessed outside of the function should always have a temp. preceding them.
Always use the prefix even after originally declaring the variable for clarity.
Function Declarations
- There should be no space between the name of a function and the ( of its parameter list.
- There should be 1 space between the ) and the { that begins the statement body.
- The body itself is indented 2 spaces.
- The } is aligned with the line containing the beginning of the declaration of the function.
function doAwesome(a, b) { temp.x = 1; return temp.x+1; }
Inner Functions
Never use an inner function because it is not scoped and can be accessed outside of the outer function, for example:function outer() { function inner() { return 123; } outer2(); } function outer2() { echo (inner()); // echos 123 }
Using an inner function like that just makes things confusing in terms of scope, because it actually becomes a global function.
Anonymous Functions
If you are declaring an anonymous function, there should be 1 space between the word function and the (.If the space is left out, then it may seem that the function's name is "function", which is incorrect.
temp.distance = function (x1, y1, x2, y2) { return ((x2 - x1)^2 + (y2 - y1)^2)^.5; }; echo (temp.distance(2, 2, 1, 1));
Anonymous functions can unfortunately not be executed in the same statement they are declared in.
Names
Names should be formed from the 26 upper and lower case letters (A .. Z, a .. z) and the 10 digits (0 .. 9) and _.
Avoid other characters.
Do not use _ as the first character of a name. It is sometimes used to indicate privacy, but it does not actually provide privacy. Avoid conventions that demonstrate a lack of competence.
- Variables, functions, and classes should be set in camelCase, and start with a lower case letter. E.g., exampleFunction.
- Constants should be all UPPER case. The proper word delimiter is _. E.g., SPEED_OF_LIGHT.
Statements
Simple Statements
Each line should contain at most 1 statement. Put a ; at the end of every simple statement.Note that when declaring a variable as a function, it is still an assignment statement and must end with a semicolon.
Compound Statements
These are statements that contain lists of statements enclosed in { }.- The enclosed statements should be indented 2 more spaces.
- The { should be at the end of the line that begins the compound statement.
- The } should begin a line and be indented to align with the beginning of the line containing the matching {.
- Braces should be used around all statements, even single statements, when they are part of a control structure, such as an if or for statement. This makes it easier to add statements without accidentally introducing bugs.
return Statement
return is a statement, not a function, therefore it should not use ( ) around the value.
if Statement
The if class of statements should have the following form:
if (condition) { statements } if (condition) { statements } else { statements } if (condition) { statements } else if (condition) { statements } else { statements }
for Statement
A for class of statements should have the following form:
for (initialization; condition; update) { statements } for (variable : array) { if (filter) { statements } }
The first form should be used with loops of a predeterminable number of iterations.
while Statement
A while statement should have the following form:
while (condition) { statements }
do Statement
A do statement should have the following form:
do { statements } while (condition);
Unlike the other compound statements, the do statement always ends with a ;.
switch Statement
A switch statement should have the following form:
switch (expression) { case expression: statements default: statements }
Each case is aligned with the switch. This avoids over-indentation, but maintains the pattern of indenting all groups of statements.
Each group of statements (except the default) should end with break or return. Do not fall through.
Whitespace
Blank lines improve readability by separating sections of code that are logically related.
Blank spaces should be used in the following circumstances:
- A keyword followed by ( should be separated by a space.
while (true) {
- Each ; in the control part of a for statement should be followed with a space.
- Whitespace should follow every ,
Bonus Suggestions
Arrays
Use {} instead of new[0], for example:temp.someArray = {};
This keeps thing clear by avoiding using a constructor-specific syntax for creating a simple data structure.
Equality
Always use == instead of = when comparing variables, for example:if (a == b) {
Confusing Pluses and Minuses
Be careful to not follow a + with + or ++. This pattern can be confusing. Insert parenthesis between them to make your intention clear.temp.total = temp.subtotal + +temp.value;
is better written as:
temp.total = temp.subtotal + (+temp.value);
so that the + + is not misread as ++.
Code Placement
It is generally a bad idea to put code outside of an event block, unless you are joining another class.this.chat = "Hello"; function onCreated() { setimg("door.png"); }
is better written as:
function onCreated() { setimg("door.png"); this.chat = "Hello"; }
1. That is not what a closure is. True closures are impossible in GS, I've tried (although you've made some elegant workarounds, if I recall correctly)
2. Anonymous functions can be called on the same line they are declared, but in some sense they are not the sort of anonymous functions that Crockford was shooting for.
Re 2: I said "statement", and if you are referring to (temp.a = function () {})(), that would technically be another statement... I don't think I'd want such a thing to be encouraged in a conventions guide either way.
Something else I've noticed about anonymous functions is that if you start passing them around to other functions (higher-level functions), they sometimes stop working unless you call them like (@temp.f)(), which casts the function to its name in the global scope which is then called. Not sure if this should be noted or not.