Announcing the Global SNUG Board of Directors. Learn more here

Help
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Maik Skoddow
Tera Patron
Tera Patron

find_real_file.png

 

Table of Contents

In the several thousand questions I've answered here in the community, as well as in my customer projects over the last few years, I've seen a lot of JavaScript code. And in most cases, it was difficult to read and to understand, because for the authors, these JavaScript codes were just what they ended up being in ServiceNow: fragments that serve to complement the configurations of the artifact in which they are embedded. It is only important that the code works somehow, but whether it is well readable and thus maintainable, is only of secondary importance.

In this article, I have picked out many internationally recognized naming conventions and enriched them with my own best practices, based on over 30 years of programming experience by now.

 

Why do we need naming conventions?

You think, if you're the only person to be involved in application development, there does not necessarily have to be a naming convention? Usually this is not the case. There comes a time when your source codes have to be handed over to someone else (support, new team members, your successor). Bugs have to be fixed or additional code must be woven in to for implementing new requirements. Then you will see how understandable and maintainable your source code is. 

Naming conventions, ideally written down somewhere in the project documentation, improve code readability and thus allow new developers to get started quickly. They also reduce the risk of broken code, as enriching the identifiers with semantics leads to better understanding and minimizes confusion.

 

How to enforce naming conventions?

At this time, I am not aware of any tool or framework that detects the violation of naming conventions fully and reliably. All the identifier will still work technically - no matter if they are just an incomprehensible letter or a descriptive word. A few violations can be detected with scanners (for example, the use of gr as variable name). However the only way to enforce naming conventions is pair programming and regular code reviews. It is important to have an experienced developer in the project who can guide the less experienced team members. In addition, there must be a climate of constructive and open error culture, otherwise permanent quality improvement will not have a chance.

 

 

 

Common rules

 

Notation

 

Although JavaScript cannot be compared to the high-level language "Java" despite the similarity in name, it is common practice to use its naming conventions in JavaScript as well. And in the most common sense, the underlying basis of all naming conventions is the so-called Camel Case notation. In simplified terms, several partial words are visually separated from each other by the use of capital letters:

Natural Language Camel Case Notation
several words separated by spaces severalWordsSeparatedBySpaces

 

 

And depending on how the first letter is written, two versions of the Camel Case notation are distinguished:

Example Type Remarks
AbstractStringHelper Upper Camel Case also known as "Pascal Case"
calculateDistance Lower Camel Case  

 

 

The identifiers should use only ASCII letters, maybe digits and in a few cases (see chapter Constants) also underscores.

Also abbreviations have to follow the camel case notation - even if this may look unusual at first:

bad good
objXMLHTTPRequest objXmlHttpRequest
strSysID strSysId
supportsIPv6OnIOS supportsIpv6OnIos

 

 

Semantic

 

The name should describe the information represented by the identifier. An identifier name should tell you precisely in words what the identifier stands for.

bad good
strName strUserFullName
numPrice numTotalCarPrice
objUser objCurrentUser

 

When writing your code, prioritize ease of reading over speed of writing. Do not worry about saving horizontal space, as it is far more essential to make your code immediately understandable by a new reader.

Adopt standard conventions from your domain for naming, so you can make one global decision instead of multiple local decisions.

 

Do not use abbreviations that are ambiguous or unfamiliar to readers outside your project, and do not abbreviate by deleting letters within a word. For example, "ACL" is well-know in the context of ServiceNow, but "TTL" is probably not.  

 

Find names that are visually distinct enough from each other to avoid mix-ups. In particular, this means extending a name with a number or a plural "s" is not enough. A good indicator for the optical difference is the so-called Levenshtein distance which should have at least a value of "3":

  name 1 name 2 Levenshtein distance
bad strFieldName strFieldNames 1
good strFieldName strAllFieldNames 4

 

ℹ️ You can calculate the Levenshtein distance by youself on https://planetcalc.com/1721/ 

 

 

 

Variables

 

Variables are the most essential element of a programming language, which is why particular attention should be paid here to the observance of naming conventions.

 

Notation

 

Variable names should always start with a lower case letter (Lower Camel Case). Starting variables names with an upper case char can cause a lot of confusion!

 

A pure syntactic feature is the prefixing of a variable name with the dollar sign, for example $scope. Syntactically this is allowed, but should be avoided in your own source codes, because such identifiers represent important predefined variables from a framework (for example JQuery or AngularJS).,

 

Unlike Java, JavaScript is not a data-type-safe programming language. As a result conversions between data types are constantly being made under the hood. Therefore you can never be sure whether a variable still represents the data type it was originally intended for. As an aid for the developer as well as for the reader of the source code, the so-called Hungarian notation can be used here, where each variable is prefixed with a meaningful abbreviation. That way, it is easy to understand what the intended data type was originally. And having several variables with different data types in one expression, you can recognize the implicit data type conversions better. The following tables represent just my personal best practices, and you may find your own schemes.

 

 

Primitive Data Types / Simple Objects / Arrays

Examples Data Type Remarks
strHeadline String Internally represented as a set of "elements" of 16-bit unsigned integer values.
numSize Number Internally this data type is stored as double-precision 64-bit binary format.
intAge Number Indicating that an integer value can be expected, but JavaScript don't know Integer values under the hood!
isEnabled
hasChildren
canRead
Boolean

Instead of a unique prefix for Boolean values, I prefer this more readable notation.

That way you can distinguish a boolean from another variable by just looking at it.

arrSysId Array Unfortunately, even this notation cannot give any information about the data type of the values contained in the array.
objCar Object Collection of String-based key and values of any type (inclusive functions). Often also called Associative Array.
jsonResponse Object Indicating the special nature of an object, which only contains values (and not functions) as JSON is intended to be a language-independent exchange format.

 

 

Class Instances

 

ServiceNow provides an incredible amount of pre-built classes, from which object instances are usually created at runtime using the new operator. To distinguish such instances from ordinary data objects, I use as prefix an abbreviation from the first letters of the individual partial words:

Examples Class Remarks
grRequest GlideRecord See Why using 'gr' as a GlideRecord variable name in custom scripts is always a bad idea
gdtNow GlideDateTime  
notifyUtil NotifyUtil For helper classes it typically makes no sense to find any artificial name, and therefore I prefer using the class name as variable name.

 

 

Global / Public vs. Local / Private

 

To distinguish internally used or private variables (especially in functions) from global / public variables or even function parameters, I like to use a preceding underscore for them:

 

function getSum(intFigureA, intFigureB) {
  var _intFigureA = intFigureA;
  var _intFigureB = intFigureB;

  return _intFigureA + _intFigureB;
}

 

 

Some sources and authors prefer an underscore at the end of the name. However, I am not a friend of it, because in ServiceNow private functions (see chapter Functions) must necessarily start with an underscore (a prefixed hash sign for private variables/functions sign is not allowed in ServiceNow!). 

 

 

Semantic

 

Loop Indexes

 

Since the dawn of programming languages, there seems to be an unwritten convention that variables for loop indexes are defined in lowercase single letters. The letter "i" has achieved a particularly inglorious prominence in this context. I would argue that this is pure convenience, and yes, I find myself succumbing to this convenience from time to time. Especially with larger and nested loop blocks, however, it is a pain for the reader to have to scroll up again and again to look up what the letter stands for:

bad
for (var i = 0; i < intRows; i++) {
  for (var j = 0; j < intColumns; j++) {

  }
}
good
for (var intRowIndex = 0; intRowIndex < intRows; intRowIndex++) {
  for (var intColoumnIndex = 0; intColoumnIndex < intColumns; intColoumnIndex++) {

  }
}

 

 

Collections

 

Collections include objects such as Arrays and HashTables. In both cases, they are used to store multiple items. As such their names should be pluralized to reflect their multiplicity. But it is also acceptible to append the word "list" to the variable name:

bad good
var arrAccount = [a1, a2, a3]; var arrAccounts = [a1, a2, a3];
var arrAccountList = [a1, a2, a3];

 

 

 

Constants

 

Unfortunately, the JavaScript engine used by ServiceNow does not provide true constants. That means at the end, a constant is nothing else than a variable. 

 

Notation

 

However, to indicate the aspect of a constant anyway, the usual notation of capital letters can be used. Unfortunately, Camel Case no longer works with this notation, which is why it is helpful to separate word components with an underscore for better readability by exception (so-called Screaming Snake Case)

bad good
URLPARAMETERPAGENUMBER URL_PARAMETER_PAGE_NUMBER

 

 

 

Functions

 

Notation

 

Function names have to follow the Lower Camel Case notation. This is really important, since otherwise you have no way to distinguish functions from Script Includes: 

bad good
function FormatValue() function formatValue()

 

 

Public vs. Private 

 

In ServiceNow, it is mandatory that private functions within a class start with an underscore. The otherwise known notation with a leading hash character is not allowed.

 

var UserUtils = Class.create();

UserUtils.prototype = {
  initialize: function() {
  },

  testName: function(strUserName) {
    return _isValidName(strUserName);
  },
  
  _isValidName: function(strUserName) {

  },

  type: 'UserUtils'
};

 

 

Semantic 

 

Functions perform some action and therefore have an acting character. This aspect should also be reflected in the function name by prefixing it with a suitable verb like get, fetch, push, apply, perform, calculate, compute, post. The next component of the name is typically a noun that represents the recipient or the goal of the action:

bad good
function name(strFirstName, strLastName) function getName(strFirstName, strLastName)
function recipient(objReciopient) function storeRecipient(objReciopient)

 

 

The third and optional name component expands the action with additional information representing the answer to questions such as "Why", "With what", "Where to". This way, overloading of a generic function can be avoided and comprehensibility can be improved:

bad good
function sendEmail() function sendEmailImmediately()
function sendEmailLater()
function informUser() function informUserByEmail()

 

 

 

Classes

 

In ServiceNow JavaScript classes can only be defined in special containers like Script Includes or UI Scripts. 

By using the new operator, you can create instances of classes during the runtime:

 

var stringHelper = new StringHelper();

 

 

Notation

 

Class names have to follow the Upper Camel Case notation.

 

 

Semantic

 

Class names should only consist of nouns ideally, whereas the last part often indicates the type of the class:

Example Type
StringHelper
CustomerUtils
Collection of helper functions
ListCollectorAjax Client callable Script Include
IncidentConstants Container Class just for storing constants

 

 

 

More DevBasics articles

 

If you liked that article you maybe also want to read the other ones from my "DevBasics" series:

Comments
Anish Reghu
Tera Guru
Tera Guru

First of all, neat presentation of concepts, which makes this a great read. Looking forward to more on the dev topics.

 

Cheers,

Anish

Version history
Last update:
‎02-03-2024 09:16 PM
Updated by:
Contributors