jonnyseymour
ServiceNow Employee
ServiceNow Employee

In ServiceNow, we use scripts to extend your instance beyond standard configurations. When creating scripts like business rules or client scripts, we use Javascript. Javascript is a well-known and popular language that has benefited from significant investment over the years. JavaScript is a high-level, dynamic, untyped, interpreted programming language with a feel like java. As powerful as it is now, debugging is sometimes complex. To make it less complex, you can simplify your code using a code optimizer. Code optimization is any method of code modification to improve code quality and efficiency. A program may be optimized so that it becomes a smaller size, consumes less memory, executes more rapidly, or performs fewer input/output operations. Our business rules and client script editors do have a script syntax analyzer, but you can use Google closure compiler as an additional tool to simplify them.

chromespeedo.png

Here are 3 use case examples of how to utilize the Closure Compiler debugger tool:

  • Validating if the code syntax is correct, without having to run it
  • Simplifying logical operations (e.g complex conditions, etc)
  • Simplifying complex functions

Validating if the code syntax is correct, without having to run it

If you find a complex code that makes some sense, but you suspect it is incorrect, then run it thought the javascript optimizer. This is similar to our own syntax validation on the script editor. For example, let's check our password validation code for errors and inaccuracies using the debugger.

Here is an example of password validation:

gs.info("good password: " + CheckPassWd8CharSAnd3ofUpperLowerNumberNonAlpha("This4isAgoodPassw0rd!"));

gs.info("bad password: " + CheckPassWd8CharSAnd3ofUpperLowerNumberNonAlpha("thisisbadpassword"));

// The password must be 8 characters long (this I can do :-)).

// The password must then contain characters from at least 3 of the following 4 rules:

// * Upper case * Lower case * Numbers * Non-alpha numeric

function CheckPassWd8CharSAnd3ofUpperLowerNumberNonAlpha(passwordtext) {

      if (passwordtext.length < 😎 {

              return false;

      } else {

              var hasUpperCase = /[A-Z]/.test(passwordtext);

              var hasLowerCase = /[a-z]/.test(passwor dtext);

              var hasNumbers = /\d/.test(passwordtext);

              var hasNonalphas = /\W/.test(passwordtext);

              if (hasUpperCase + hasLowerCase + hasNumbers + hasNonalphas < 3) {

                      return false;

              } else {

                      return true;

              }

              // IT is missig a "}"

      };

We can run the code in Closure Complier to find the number of errors and where they may be. This allows us to ensure the Javascript we run is functioning and correct, and we do not need to do investigating once it is live. When we input the password validation code in the debugger, it returns with:

closure-compiler.jpg

Once you add the missing '}',   and remove the extra space on "passwor dtext", it get simplified as:

gs.info("good password: " + CheckPassWd8CharSAnd3ofUpperLowerNumberNonAlpha("This4isAgoodPassw0rd!"));

gs.info("bad password: " + CheckPassWd8CharSAnd3ofUpperLowerNumberNonAlpha("thisisbadpassword"));

function CheckPassWd8CharSAnd3ofUpperLowerNumberNonAlpha(a) {

      if (8 > a.length) {

              return !1;

      }

      var b = /[A-Z]/.test(a),

              c = /[a-z]/.test(a),

              d = /\d/.test(a);

      a = /\W/.test(a);

      return 3 > b + c + d + a ? !1 : !0;

};

---------------------

It reuses input variable 'a'. This is not very good when coding but thumbs up on recycling 'a'.

When executed, it returns:

*** Script: good password: true

*** Script: bad password: false

Simplifying logical operations (e.g complex conditions, etc)

There is a trick on Logical operations simplification. It is using logical optimisers. You suspect right. It is not one click. It is four(4) steps. You can simplify logical operation if you see redundancy or repetitions.

  1. The first step is to replace the expression components into the letters A,B,C,..., on the elements that could be redundant. For example:

    function ValidateInput(letter1, letter2, letter3, letter4, letter5, letter6) {

          if ((letter1 == 'a' && letter2 == 'b') ||

                  (letter1 == 'a' && letter2 == 'b' && letter3 == 'x') ||

                  (letter1 == 'a' && letter2 == 'b' && letter3 == 'x' && letter4 == 'y') ||

                  (letter1 == 'a' && letter2 == 'b' && letter3 == 'x' && letter4 == 'y' && letter5 == 'z') ||

                  (letter1 == 'a' && letter2 == 'b' && letter3 == 'x' && letter4 == 'y' && letter5 == 'z' && letter6 == 'm')) {

                  return true;

          } else {

                  return false;

          }

    }

    To simplify the logic, we replace <letter1=='a'> with A, <letter2=='b'> with B, and so on. Real life example may be a bit more complex but the target is the same. Replace it on units ready for the logical optimisers.

    The function would look like:

      if (A && B || A && B && C || A && B && C && D || A && B && C && D && E || A && B && C && D && E && F)

    Use a logic optimiser (e.g. wolframalpha) to remove redundancy.

  2. When I use wolframalpha to simplify the logical expression:

    "A && B || A && B && C || A && B && C && D || A && B && C && D && E || A && B && C && D && E && F" at www.wolframalpha.com

    logical expression.jpg

    It returns "ESOP | A AND B", which translate in javascript to "A && B"

    which translate to <(letter1=='a' && letter2=='b')>

    translate javascript.jpg

  3. Replace the expression components back. Reducing the original function, the example looks like:

    function ValidateInput(letter1, letter2) {

          if ((letter1 == 'a' && letter2 == 'b')) {

                  return true;

          } else {

                  return false;

          }

    };

  4. Run the Google optimize on the final code. When running it on google optimiser, the final function will be:

    function ValidateInput(a, b) {

          return "a" == a && "b" == b ? !0 : !1;

    };

    closure complier.jpg

The final code on step 4 looks much easier to debug than the original on step 1. The code looks much cleaner and the process of testing would be easier as you have less variables to worry about.

Simplifying complex functions

Another way to simplify your Javascript code is to remove the parts on the code that are just not used. Removing excess code will help make the code more readable.

For example:

This code produces a memory leak

var theThing = null;

var replaceThing = function() {

      var priorThing = theThing;

      var unused = function() {

              if (priorThing) { /* This part causes MEMORY LEAK because theThing can't be release */

                      gs.info("hi");

              }

      };

      theThing = {

              longStr: (new Array(1E6)).join("*")

              , someMethod: function() {

                      gs.info(someMessage);

              }

      };

};

for (var i = 0; i < 5; i++) {

      gs.info("testing " + i);

      replaceThing();

      gs.sleep(1E3);

};

When running it thought google Closure Compiler, it produces:

for (var theThing = null, replaceThing = function() {

              theThing = {

                      longStr: Array(1E6).join("*")

                      , someMethod: function() {

                              gs.info(someMessage);

                      }

              };

      }, i = 0; 5 > i; i++) {

      gs.info("testing " + i), replaceThing(), gs.sleep(1E3);

};

The results when debugged in the Closure Compiler will come out like this:

reduce code.jpg

This code is much easier to debug after being run through the optimizer. It will also make it clear when an unused part of the code has disappeared. For debugging purposes, you can investigate the redundant code that was causing the problem or review the remaining code for problems. The reason for the memory leak is found here.

"There is not one right way to ride a wave."

~ Jamie O'Brien

Debugging code is like surfing, there are several ways to ride a wave. One of them is to take a look from a different angle. Code sometimes tells the story but it sometimes it traps you on it. Use optimiser tools to simplify and help you focus on what it matters and sometimes get direct to the point.

More information here:

Closure Compiler   |   Google Developers

Wolfram|Alpha: Computational Knowledge Engine

The 10 Most Common Mistakes JavaScript Developers Make

Docs -Script syntax error checking

Performance considerations when using GlideRecord

Community Code Snippets: Articles List to Date

Mini-Lab: Using Ajax and JSON to Send Objects to the Server

ServiceNow Scripting 101: Two Methods for Code Development

Community Code Snippets - GlideRecord to Object Array Conversion

Community Code Snippets - Four Ways To Do An OR Condition

My other blogs

2 Comments