Developer Guide

Introduction
The purpose of this is to provide development standards to be used when configuring, customizing, and developing on the ServiceNow platform.

Core Tables
The ServiceNow platform consists of two core tables Task (task) and Configuration Item (cmdb_ci).
A table can "extend" another table. A table that extends another table is called a child class, and the table it extends is the parent class. If a table is extended, but itself is not an extended table, it is then called a base class. Therefore, the Task table and the Configuration Item table are examples of base classes.
Modifications made to a base table will be applied to all child tables. Be sure that the changes being made should apply to all of the child tables. Adding fields is a low-impact change, because the field can be hidden on tables that do not need it; however, deleting fields may cause unwanted data loss if the field is being used across tables.
Task Fields
The task table has many important fields that are used across extended tables, see the ServiceNow Wiki for specifics on each. A few key fields are:
Active (active): Boolean – Determines whether the task has work to be done. Useful for filtering out tasks which are complete. The business rule task reopener sets the active flag to True if the state (see state below) is changed from Closed Skipped, Closed Incomplete, or Closed Complete to any other state.
State (state): Choice integer – A list of selections for the status of the task: Pending, Open, Work in Progress, Closed Complete, Closed Incomplete, and Closed Skipped. It is critical to NEVER modify the number value for these choices. The system makes use of them in many places, and this could cause many issues. To add values specific to process or table, use the TaskStateUtil overrides, see ServiceNow Wiki.
Number (number): String – A unique identifying number for the task, used as the display value of the task. This number is human friendly and different than the sys_id. Numbers are generated automatically when the task is created. To modify the behavior of numbers modify the Number Maintenance for the table in question.

Core Data
Core data refers to a set of data required by the system in order for it to function properly. Core data could be fed into ServiceNow via an external system integration, or ServiceNow may serve as the system of record for the data. Some examples of core data are as follows (User demographic data, User authentication, Groups, Group membership, Departments, Locations, Location hierarchy, Companies, Symptoms, Schedules, Configuration Items, Assets, and Cost Centers).
Groups and Roles
Group: A group is a collection of users who share a common purpose such as approving change requests, resolving certain incidents, etc. Users can belong to one or more groups.
Roles: A role is a persona or ability that is assigned to a group such as report_writer which gives the user an ability to write reports. Each role grants certain permission to a certain parts of the system. A single group can have many roles. Additionally, a role can consist of many other roles. When the parent role is given, all the child roles are inherited along with a parent.
ServiceNow Roles must always and only be granted to groups. Users are then added to groups and inherit roles.
Integrations
Integrations that feed Core Data into the system must set a "Source" field. Out of box the Task Table (task) contains two fields, correlation_id and correlation_display. The Configuration Item (cmdb_ci) table contains a similar field discovery_source.

Applications & Modules

  • Each process in ServiceNow will have a corresponding application in the left-hand navigation menu as well as a number of modules each locked down to the proper security role.
  • Each integration will have an application with the display name starting with "Integration – Name" where Name is the name of the system (i.e. Integration – SCCM). This application must have modules pointing to all configurations for the integration.
  • Any module that links to a large data set must be filtered by default to prevent poor performance.

Custom Tables & Fields

  • When creating a custom table always name it in a singular fashion (u_application_role instead of u_application_roles). ServiceNow will always append a 'u_' before any custom created fields or tables, except when creating a custom application.

List Layout

  • Use the record number or other unique information as the first column.
  • When designing a list, avoid using reference fields in the first column. If possible, use the string field that defines the list, for example, the item number, name, or ID. If the record does not have a string field, consider using a date field, such as the date the record was created or updated.
  • Avoid displaying fields with long values in list views, including HTML, large text, and journal fields. Some fields, such as work notes, take up more vertical and horizontal space in the list without providing the most essential information.
  • Avoid displaying too many field in list views. To save space, limit the number of columns to avoid horizontal scrolling. To enhance the user experience, include only the columns that most users really need to see. Users can personalize their own view of the list without affecting others if they want to add other columns.
  • Review the list controls and list UI actions to understand user access: If your list includes list controls or UI actions, review these elements to understand what they do, and who has access to them and under what conditions. By clicking this menu icon or right-clicking the list header, you can personalize the list controls to specify which roles are able to perform these actions.
  • Limit the number of records that a list can show per page: Users can specify the number of records listed per page from the menu icon in the title bar. It is best to stick with the base system maximum of 100 rows per page and not make larger numbers available. The more items displayed per page, the longer it takes the system to query the database and render the list. This is especially true if some fields must be calculated, or there are related lists on a form with many records. This results in better performance, and users can still view all items by paging through the list.

Form Layout

  • Every field is labeled case proper with the first word beginning with a capital letter and the following words lower case (i.e. Risk assessment, Assignment group and Resolution notes). This is an out-of-box convention within ServiceNow.
  • The selection values within a field will be case proper with all keywords being capitalized (i.e. Client Action Required, Request for Authorization, and Scheduled for Approval).
  • The Number field on any task based table must have an ACL in place to prevent it from being edited.
  • Fields will be arranged with the left column arranged in logical/sequential data entry order; right-column fields will be reserved for system-generated, read-only and reference fields.
  • Mandatory fields will be handled through the use of UI Policies. In the case that the UI Policy cannot handle the logic for the field to become mandatory a client script or access control rule can be used.
  • Field write access (read-only) will be managed through a Security ACL. If the field needs to become editable based on changes to the form a UI policy can be used.

Scripting in ServiceNow

Use scripts to extend the instances beyond standard configuration. ServiceNow provides many APIs (Application Programming Interfaces) within the Glide Stack; it is important to differentiate between client and Server APIs.
Client vs. Server
The web browser is the client, and is often the only software installed on a client's computer.
The Server refers to the Application Server and database located at the ServiceNow Data Center.

  • Client scripts run on the client (which is the web browser)
  • Server scripts run on the server (which includes the application server and the database)

The web browser is where you control and communicate with an instance, including communicating with the server and database.
For a complete list of the types of scripts and APIs see the ServiceNow Wiki and for specifics on when they run see their order of execution.
General Scripting Best Practices

  • Be consistent with naming conventions - Script Includes and other classes use upper camel case (i.e. InboundActionInclude) where methods and variables use lower camel case (i.e. fixDuplicateImages).
  • Name your variables/functions wisely - you should be able to read back your code and by looking at the variable names know what is going on (name your GlideRecord variables something like userRec instead of gr to denote that you are working with a user record, etc). Never use gr, gr1, gr2, etc
  • When possible use uniquely named Functions or Self executing Anonymous functions - Business rules are evaluated in the global scope, if two rules contain the same function call, they could interfere.
  • Wrap your scripts - In workflow run scripts and other areas, wrap your script in a function and call the function. This will prevent variables that exist in the system at the time of your function call from interacting with variables defined inside your function.
  • Be consistent with formatting - There is nothing worse than code that is difficult to read because it is poorly formatted.
  • Try to not use literals - Always try to store literal values in a custom system property or in another table instead of defining them in your code (i.e. hard coding an email address, category value, sys_id, etc). When you MUST use literals, define them as a variable (all caps) at the top of your code (i.e. var EMAIL_ADDRESS = user@mycompany.com). This makes it much easier to find all occurrences of literals when it comes time to update or debug.
  • Comment - Describe what the code is doing and why it is being done one way instead of another so if someone has to debug or fix your code down the road they understand what is going on.
  • Use toString() when pushing into arrays - When pushing items from a GlideRecord into an array remember to use toString() or + '' to force the value rather than a pointer. (i.e. array.push(userRec.name.toString()); or userRec.name +''(wink).


Server Scripting Best Practices

  • Avoid global business rules. Business Rules marked as running on Global are loaded and initialized at the beginning of EVERY interaction between a user and the platform since it ignores the condition field. Utilize script includes to define code that will be used repeatedly when possible, but if a global business rule is needed ALWAYS wrap the script in a function.
  • Know when to run business rules.
    • Display business rules run just before the form is loaded. These are typically used for passing g_scratchpad information to client scripts. Display business rules are useful for sending information from the server to the client.
    • Before business rules run after the changes are submitted but before they are committed to the database. These are generally used to manipulate the current record, for example, when calculating a Risk field based on the Importance and Priority fields.
    • After and async business rules run in parallel. Both are used mainly to perform operations on other related records that are affected by the changes to the current record. The difference is that after business rules run immediately while async rules run in the background, allowing the user to carry on without having to wait for the business rule to complete.
  • Timing of business rules is critical. To prevent upgrade issues, avoid modifying the base system business rules, and make sure the business rules run at the appropriate time.
  • Whenever possible leverage the power of the database instead of using JavaScript. GlideRecords are other APIs are optimized to perform heavy lifting.(i.e. userRec.setLimit(1), rather than only using userRec.hasNext())
  • Don't create single use script includes. Whenever possible try to bundle similar script include functionality into bundles. Try to make methods reusable and flexible so it can be used in many places. For example a script include named serviceCatalogAJAX could include all AJAX types of methods for the service catalog. This allows for easier maintenance.
  • Don't use current.update() in Business Rules. When the value of a certain field on a table needs to be set when a record is inserted or updated, set that in a before business rule since this runs before any database activity. Using current.update() can cause recursion and a potential loop in the system.
  • Use the JavaScript eval Function with CAUTION. Improper use of eval can cause vulnerabilities and injection of malicious code. Consider using a sandboxed or protected alternative. (i.e. GlideEvaluator.evaluateString("gs.log('Hello CPP, 'CPP');");
  • Always use the 'source' argument when using gs.log(). The log function accepts two parameters (message, and source), whenever logging to the system use the source parameter. This prevents the standard Script Log from being overloaded with scripts. In addition this helps tracing in case of debugging and disabling log statements.
  • Remember to remove your debugging statements prior to migrating business rules to production. Logging produces un-needed lines in the system log and volume could impact system performance.
  • Use an Async business rule in lieu of an After rule whenever possible so that control is returned to the end-user as quickly as possible.( gs.log('Hello CPP, 'CPP')(wink) The user's transaction will "clock" while Before and After business rules process and can influence the end-user's perception of performance.
  • Remove, comment out, or wrap calls to gs.log in a debug property so they can be disabled in production environments as it creates extra load on the database when inserting those log records.
  • Keep business rules small and specific so that they are easy to use and debug.


Client Scripting Best Practices

  • Avoid global client scripts. Global client scripts load on every page in the system causing delays and poor user experience. Leverage UI scripts and base table ([task], [cmdb_ci]) client scripts that can be inherited on child tables instead.
  • Reduce the number of server lookups. Use client data as much as possible or build an object with a before display business rule, but when you MUST make a roundtrip call to the server utilize the g_form getReference method, GlideRecord, or GlideAjax when needed. ServiceNow recommends against using GlideRecord client side.
  • Use g_scratchpad when leveraging data that is not on a form.
  • Use UI polcies for date/time type conditions, instead of client scripts.
  • Add conditions to client scripts. ServiceNow client script forms don't have a condition line, so all onLoad and onSubmit client scripts run every time. Add if statements in client scripts to verify code is only being run when needed.
  • When using getReference(), always use a callback. The getReference() method requires a server round trip and will halt processing, causing the end-user's browser to "hang" while they wait for the transaction to complete. Using a callback causes it to process asynchronously, so other activity/scripts will continue to execute until the reference is completed and the callback is invoked.  If you don't use a callback your script won't work on mobile or Service Portal.
  • Avoid DOM manipulation in Client Scripts when possible. In general, when using DOM manipulation methods, you reference an element in the DOM by id or using a CSS selector. When referencing out-of-box DOM elements, there is a risk that the element ID or placement within the DOM could change thus causing the code to stop working and/or generate errors.
  • When debugging use jslog() rather than console.log(), the platform locks this access to only administrators when the debugger is chosen from the UI. This eliminates the need to comment out debug lines for production instances.  jslog() doesn't work on Service Portal!

Workflow

  • Check workflows back in periodically, never keep workflows checked out for extended periods of time.
  • Always trigger Email notification events rather than hardcoding emails within the workflow.  This is mostly because notifications triggered in workflow can't be managed in notification preferences.
  • Handle errors in automation first with retries and then with manual task creation.
  • Make sure to handle the flow when catalog tasks are not closed complete.  Out of box a catalog task activity only has one condition 'always' which is almost 'always' not sufficient.

Catalog Items

  • Catalog Items must have a name and short description specified, and they should never contain duplicate values. These values are used when searching the system.

System Properties

  • Use Reverse domain name notation (for example, com.examplecompany.default.groupname)
  • Begin debug property names with string debug (for example, com.examplecompany.debug.idle.time)
  • Group properties into categories, this allows for easier updating and locating of custom properties.
  • Create a property page. An easy way to access system properties is to create a properties page.

Choice Lists

  • Consider using only letter, numbers, and underscores in Choice list options.
  • When adding an item to a choice list, show the choice list and make sure the Value field contains only letters, numbers, and underscores.
  • Reference choice lists for repetitive options.
    • Referencing choice lists is a shortcut for implementing multiple, identical choice lists throughout an instance. For example, there may be 50 places where the same choice list is used. Rather than creating choice lists individually, create a choice list once, and then add it to other forms by referencing the original. Not only does this save time when creating choice lists, but it also simplifies choice list maintenance.

Import Sets and Transform Maps

  • Use caution when using "Run business rules" on a transform map, depending on the data set size, this could cause the instance to perform poorly.
    • Consider using an onComplete transform script instead of business rules.
    • If you must use business rules, consider adding gs.isInteractive() to the condition field of specific business rules to prevent them from running during an import.
  • Transform maps must always coalesce on indexed fields.
  • When importing large sets of data ensure the "Import Set Deleter" job is running. The frequency may need to be adjusted.

Notifications

  • Leverage Notification scripts for redundant data entry. This allows for a single place to update/change data.
  • Be careful with the ServiceNow WYSIWYG as it inserts breaks and extra markup.
  • URLs in notifications must NEVER be hardcoded but utilize URI + URI_REF.
  • Reports can be attached to Notifications via mail script syntax.

Service Accounts

  • Service Accounts should have "web service" access only set on the User record.
  • Follow naming convention: s_application where application is the name of the system using this account to connect via web services, etc.
  • Follow naming convention: s_midserver where midserver is the name of the MID server.

Update Sets

  • Do not delete update sets. If an update set is deleted, any updated records may be overwritten in the next update.
  • Do not include the system_id field from the ldap_server_config record in an update set. An update set from a working configuration points to the wrong system_id node for the target instance and does not work.
  • Do not back out or close the Default update set. This action causes damage to the system.
  • Never change the update set field value (update_set) in a Customer Update record (sys_update_xml). If a customization is made in the wrong update set, take the following action:
    1. Switch to the desired update set.
    2. Modify the object (record) that was originally changed. You can make a trivial change, such as adding a field.
    3. Save the record.
    4. Back out the modification just performed, and then save the record again. This action ensures that the latest version of the object is included in the desired update set and prevents duplicate updates for the same object in a single update set.
      * Do not mark an update set as Complete until it is ready to migrate. Once an update set is complete, do not change it back to In progress. Instead, create another update set for the rest of the changes, and make sure to commit them together in the order that they were created. Naming conventions may help in this case (for example, Performance Enhancements and Performance Enhancements 2).

      * Do not manually merge updates into an update set. Always use the Merge Update Sets module. This tool compares duplicate files between update sets and selects the newest version.

  • If a committed update set has a problem in the test instance, build the fix in another update set in the development instance. Commit this set to the test instance, and then make sure both sets are migrated to the production instance and committed in the order they were made.
  • If Sets are merged, set completed update sets on the production instance to ignore. This state ensures the update set is not reapplied when cloning the instance.
  • Keep a to-do list of manual changes and data loads that need to be completed after an update set is applied.
  • Update sets cannot remove tables or change a column's data type if the change results in data loss. The target instance skips the update set and adds a log message if an incoming change would result in data loss. Perform these tasks manually on the target instance if they are crucial to the customization.

System Security

  • Avoid GlideRecord queries in ACL Rules.
  • Leverage Data Policy to enforce consistency. Data policies increase the security of UI policies by ensuring that data meets certain requirements regardless of whether the data comes from the UI form or another source, such as a web service, import set, or incoming mail. For example, use a data policy to ensure that incident records always have a short description and category even when the data comes from an integration. Data policies also prevent users from bypassing client-side policies.
  • Limit the number of users with the Admin role. Limiting the number of users with the admin role is consistent with the principle of least privilege and helps ensure separation of duties.
  • Create Multiple accounts for Administrators. Administrators should have both elevated privileges, and normal ITIL access. This maintains security and minimizes risk of accidental changes (particularly in production instances).
  • Frequently Audit the role 'admin' to ensure only the proper people maintain this role. 
  • *https://hi.service-now.com/kb_view.do?sysparm_article=KB0536146*