- Joined
- Sep 26, 2009
- Messages
- 9,521
JPAG - JASS Proper Application Guide
Bettering the cause of readable source code
Naming Conventions
Indentation
Documentation
Configuration
Initialization Priorities
Math Operators
Bettering the cause of readable source code
If you are building a map you want to submit for review, building a
spell or system to submit for public use, this guide can help to establish a
general formula for making good, readable code. The more people that
follow this, the easier it will be to read code because you know to expect
certain things and not get weird surprises like a STRUCT_NAME_LIKE_THIS.
The reason I have chosen these rules is that JASS standards defined
by Blizzard in the original form, while they still had the opportunity
to style the language in any format they chose, they chose to do it this
way. If we are to have a standard, then Blizzard's standard makes the
most sense.
These rules help to do something similar for writing your JASS code.
There has been a standard in the past for JESP, but this revives the
topic and makes points more clear. Henceforth we can refer to this
tutorial format as the JPAG format.
spell or system to submit for public use, this guide can help to establish a
general formula for making good, readable code. The more people that
follow this, the easier it will be to read code because you know to expect
certain things and not get weird surprises like a STRUCT_NAME_LIKE_THIS.
The reason I have chosen these rules is that JASS standards defined
by Blizzard in the original form, while they still had the opportunity
to style the language in any format they chose, they chose to do it this
way. If we are to have a standard, then Blizzard's standard makes the
most sense.
These rules help to do something similar for writing your JASS code.
There has been a standard in the past for JESP, but this revives the
topic and makes points more clear. Henceforth we can refer to this
tutorial format as the JPAG format.
Naming Conventions
CONSTANT_NAMES are all capital letters and each new word
is indicated by being seperated from the rest by an underscore.
TEXTMACROS are good to write in this format, though it is not
a requirement. "constant <type> CONSTANT_NAME", however,
should follow this format, as well as the "key" type. Constant functions are an
exception, as they should still adhere to the FunctionName syntax.
FunctionNames start with an uppercase and each new word is
indicated by a new capitalitzed letter. FunctionName. StructNames,
ModuleNames, LibraryNames and ScopeNames should
also follow this format. FunctionInterface names and InterfaceNames
for lack of better placement should just be treated the same as
StructName. Though the use of either is highly discouraged because
interfaces double the code length and add unnecessary handles to your
map which in some cases also drastically slow CPU performance.
The reason why these non-JASS names should be capitalized is
just for English-language syntax and syntax of many languages.
Names are always capitalized in English. Save for variable names
and method names (reasons outlined below), keeping to this
convention is ideal if we want a uniform standard. There is also
the idea of "this is a property of 'that'" in which case it makes more
sense to write "StructName.memberName" than to write something
like "structname.MemberName" or "StructName.MEMBER_NAME"
although sometimes the latter is unavoidable but please try your
best to avoid it because it's really ugly Nestharus.
variableNames and methodNames should begin with a
lowercase letter and each new word seperated by a new capitalized
letter. This is called camelCasing. variableNames, this was designed
by Blizzard. methodNames are typically formatted like this in most
mainstream languages like C and are also formatted in such a way
with most of vJass resources, it makes sense that this should also
be the standard.
Also, short variable names are generally discouraged. A variable
should have a name that has some semblence to its purpose. If
it is for general purpose, simply writing "data" or "value" is only
fine if there is no other "general purpose" variable that might also
share such a name.
AMENDMENT: Added on 25 Feb 2016 by Bribe:
Creation and destruction of artificial types should match the naming conventions set by Blizzard and Vexorian. Struct methods should be named "create" or "destroy". Other functions which try to serve the same purpose should begin with Create or Destroy.
There is another naming convention which should be encouraged: adding and removing. These should be reserved for container-type syntax. In JASS, you have
is indicated by being seperated from the rest by an underscore.
TEXTMACROS are good to write in this format, though it is not
a requirement. "constant <type> CONSTANT_NAME", however,
should follow this format, as well as the "key" type. Constant functions are an
exception, as they should still adhere to the FunctionName syntax.
FunctionNames start with an uppercase and each new word is
indicated by a new capitalitzed letter. FunctionName. StructNames,
ModuleNames, LibraryNames and ScopeNames should
also follow this format. FunctionInterface names and InterfaceNames
for lack of better placement should just be treated the same as
StructName. Though the use of either is highly discouraged because
interfaces double the code length and add unnecessary handles to your
map which in some cases also drastically slow CPU performance.
The reason why these non-JASS names should be capitalized is
just for English-language syntax and syntax of many languages.
Names are always capitalized in English. Save for variable names
and method names (reasons outlined below), keeping to this
convention is ideal if we want a uniform standard. There is also
the idea of "this is a property of 'that'" in which case it makes more
sense to write "StructName.memberName" than to write something
like "structname.MemberName" or "StructName.MEMBER_NAME"
although sometimes the latter is unavoidable but please try your
best to avoid it because it's really ugly Nestharus.
variableNames and methodNames should begin with a
lowercase letter and each new word seperated by a new capitalized
letter. This is called camelCasing. variableNames, this was designed
by Blizzard. methodNames are typically formatted like this in most
mainstream languages like C and are also formatted in such a way
with most of vJass resources, it makes sense that this should also
be the standard.
Also, short variable names are generally discouraged. A variable
should have a name that has some semblence to its purpose. If
it is for general purpose, simply writing "data" or "value" is only
fine if there is no other "general purpose" variable that might also
share such a name.
AMENDMENT: Added on 25 Feb 2016 by Bribe:
Creation and destruction of artificial types should match the naming conventions set by Blizzard and Vexorian. Struct methods should be named "create" or "destroy". Other functions which try to serve the same purpose should begin with Create or Destroy.
There is another naming convention which should be encouraged: adding and removing. These should be reserved for container-type syntax. In JASS, you have
GroupAddUnit, GroupRemoveUnit, ForceAddPlayer, ForceRemovePlayer
and others. The naming convention should contain the words add and/or remove when you are working with structures like linked list, linear stacks, Tables and any other "containing" element which may be utilized or invented.Indentation
Indentation is four spaces in JASS and every block is required
to be indented, with the rare exception of indenting the contents of
an all-encompassing library or scope because it's usually obvious
then.
Sometimes people make "exitwhen" on the same indentation as
"loop", or make "local" on the same indentation as "function". Neither
way used endorsed by Blizzard, though there are compelling arguments
to support it, if you so desire. Though I encourage to do it the Blizzard
way, doing it this other way is also permitted.
to be indented, with the rare exception of indenting the contents of
an all-encompassing library or scope because it's usually obvious
then.
Sometimes people make "exitwhen" on the same indentation as
"loop", or make "local" on the same indentation as "function". Neither
way used endorsed by Blizzard, though there are compelling arguments
to support it, if you so desire. Though I encourage to do it the Blizzard
way, doing it this other way is also permitted.
Documentation
A resource should document all of its public interface at the top
of the script, and if it has library requirements it should provide
a link to those requirements.
Obviously, in the JassHelper manual there are established
"scope" and "library" keywords. because it is controversial and
this is a global standard, I will only make the following clear:
If it is a resource that will not be required by others, for example
a spell or a fully-automatic system are not required by any other
library, it is OK if it is a scope as long as its requirements are
still linked to and declared.
Obviously if it is to be required by others, containing any form
of public API, it needs to be a library.
Use your best judgment with outlining the public API at the top
of your library.
of the script, and if it has library requirements it should provide
a link to those requirements.
Obviously, in the JassHelper manual there are established
"scope" and "library" keywords. because it is controversial and
this is a global standard, I will only make the following clear:
If it is a resource that will not be required by others, for example
a spell or a fully-automatic system are not required by any other
library, it is OK if it is a scope as long as its requirements are
still linked to and declared.
Obviously if it is to be required by others, containing any form
of public API, it needs to be a library.
Use your best judgment with outlining the public API at the top
of your library.
Configuration
If your resource has things that are able to be configured, like
spell duration or FX art path, damage amount or whether to even
deal damage, they need to be easily configurable either through
dedicated functions or through dedicated constants. Some other
creative approaches to configuring your resource are sometimes
also allowed, depending on a few factors like presentation, ease
of use and with a lesser emphasis on efficiency.
spell duration or FX art path, damage amount or whether to even
deal damage, they need to be easily configurable either through
dedicated functions or through dedicated constants. Some other
creative approaches to configuring your resource are sometimes
also allowed, depending on a few factors like presentation, ease
of use and with a lesser emphasis on efficiency.
Initialization Priorities
NOTE: Users of Cohadar's JassHelper can ignore this next
step for the most part as initialization is much more intuitive
in his version.
This is not clear enough to most, but here is how the order of
initialization fires in the realm of JASS:
Rather than letting all initializers in one library or scope fire first,
initializers fire in that above sequence.
Because a modules initialize first, you should try to do everything
from within a module initializer if it initializes public API. Spells,
however, can get away library, scope, struct, InitTrig_ or Map
Initialization. A unit casting a spell from within an initializer may
bug your resource but it is too much to ask for everyone to use
module initializers for everything.
However, systems that create things which might be used by the
the public during initialization (such as a hashtable) need to use
modules to initialize, just in case. Its API is horrendous but it is
reliable.
step for the most part as initialization is much more intuitive
in his version.
This is not clear enough to most, but here is how the order of
initialization fires in the realm of JASS:
- Module Initializers
JASS:module M private static method onInit takes nothing returns nothing endmethod endmodule struct S extends array implement M endstruct
- Struct Initializers
JASS:struct S extends array private static method onInit takes nothing returns nothing endmethod endstruct
- Library Initializers
JASS:library L initializer Init private function Init takes nothing returns nothing endfunction endlibrary
- Scope Initializers
JASS:scope S initializer Init private function Init takes nothing returns nothing endfunction endscope
- InitTrig_ Initializers
JASS:function InitTrig_MyTrigger takes nothing returns nothing endfunction
- "Event - Map Initialization" GUI Initializers
-
MyTrigger
-
Events
- Map Initialization
- Conditions
- Actions
-
Events
-
MyTrigger
- 0-seconds game time (happens after map has finished loading)
JASS:call TimerStart(CreateTimer(), 0, false, function OnLoad)
Rather than letting all initializers in one library or scope fire first,
initializers fire in that above sequence.
Because a modules initialize first, you should try to do everything
from within a module initializer if it initializes public API. Spells,
however, can get away library, scope, struct, InitTrig_ or Map
Initialization. A unit casting a spell from within an initializer may
bug your resource but it is too much to ask for everyone to use
module initializers for everything.
However, systems that create things which might be used by the
the public during initialization (such as a hashtable) need to use
modules to initialize, just in case. Its API is horrendous but it is
reliable.
Math Operators
Formatting math operators has been pretty freestyle for a long
time, however I owe this new addition to the guide to Nestharus
as he proposed a pretty logical way to organize operators:
One space between addition/subtraction operators, and no spaces
between multiplication/division operators. This clearly shows the
precedence of the operations.
time, however I owe this new addition to the guide to Nestharus
as he proposed a pretty logical way to organize operators:
One space between addition/subtraction operators, and no spaces
between multiplication/division operators. This clearly shows the
precedence of the operations.
JASS:
1 + 1 * 3 + 6 - 2 / 1 * 6
1+1 * 3+6-2 / 1 * 6
1+1*3+6-2/1*6
1 + 1*3 + 6 - 2/1*6 //Correct
Last edited: