The Zurich release has arrived! Interested in new features and functionalities? Click here for more

SaschaWildgrube
ServiceNow Employee
ServiceNow Employee

In the past (well, for many customers still at the current day), individual changes (or “customizations”) were done and captured in update sets. These update sets were then deployed selectively. And that was ok, if there are only a few dependencies and their sequence either did not change or did not matter.

Some clients have built their own methods, processes, and tools for handling the “update set hell” in more complex scenarios. Kudos for that.

This whitepaper "A mature development and deployment process" (see below) proposes a fundamentally different approach: Everything is shipped as an application. That can be

  • a scoped application (preferred)
  • a global application (should be the exception)
  • a customization application (if there is no other alternative to change a plugin’s or store app’s behavior)

Scoped applications are always the first choice. From an architectural point of view, these applications are the modules that constitute the architecture.

Architects have several decisions to make, and to make this process work, the most crucial decision is how to split the business capabilities into technical capabilities and how to slice and dice these technical capabilities into one or more applications.

That is the primary task for architects. The business describes a demand, the development team and the architects draft a solution, and decide:

  • which applications should be changed
  • what new applications should be created

The superset of these decisions is what I call the “Application Architecture”. Ideally there is an up-to-date visual representation and documentation of that architecture for reference and for new developers to understand what is going on.

When we talk about applications as modules, some of these modules might relate to each other. More precisely, they depend on each other.

This is where “Dependency Management” comes into play.

As important as the decision on which technical capability should be implemented into which application, so is to keep track about the dependencies between these applications.

First things first: What are dependencies?

In general terms application “A” is dependent on application “B” if

  • “A” calls a function in “B”
  • “A” extends something in “B”
  • “A” just only works if “B” is also installed

In ServiceNow terms, “A” is dependent on “B” if (for example)

  • “A” uses a Script Include contained in “B”
  • “A” extends a table defined in “B”
  • “A” adds a field to a table defined in “B”
  • “A” reads or writes records from or to a table that is defined in “B”
  • “A” requires a business rule, flow or other logic contained in “B” to work properly

After establishing the existence of a dependency between two applications, we also need to consider their versions. The dependency of one application on another may change over time and not all versions depend on each other in the same way.

The statement: Application “A” depends on application “B” is not sufficient – in fact it is a specific version of application “A” that depends on one or more versions of application “B”.

Imagine a case where application “A” version 1 depends on a function that has been introduced in application “B” version 2.

Application “A” version 1 depends on application “B” version 2 (or later) – you may refer to chapter “Sematic Versioning” for more details on versions, their compatibility and meaning.

To know the dependencies between all applications serves multiple purposes:

  • We can derive the exact order in which these applications must be installed during deployment
  • We can determine which other applications must be installed (or even baselined) before an application can be deployed
  • We can assess the impact of potential backward incompatible changes of an application on its consumers (the applications that depend on the to be changed application)

One can think of the superset of all applications in an instance as a forest of one or more dependency trees. Some applications are roots as no other applications depend on them. But these root applications may depend on other applications and these applications may then depend on even other applications – forming branches and leaves of the dependency trees.

To simplify this, one can transform the forest into a single tree.

Enter the “Platform” scoped application. Each instance should have its own platform scoped application that serves as the one and only tree root for all other applications. The version of the platform application could be interpreted as the version of an overarching release. The dependencies of the platform application define which versions of all other applications must be deployed as a release package.

The Platform application really is a scoped application with its own repository in the Source Control System – which needs to be maintained by the development team and baselined whenever a new release is prepared.

Once Deployment Automation has reached the highest grade, a deployment can be as simple as “just” installing the platform app (which will then lead to the installation of all its dependencies in the required versions).

The metaphor of the tree points to another detail which is important: Dependencies must ALWAYS be unidirectional.

If application A depends on application B, application B MUST NOT depend on application A.

This is also true for indirect dependencies: If application A depends on application B and application B depends on application C, application C MUST NOT depend on application A.

Such a scenario would form a circular dependency which is forbidden.

An application and its dependencies can be represented as a dependency tree where the root is the application on top and its dependencies are the branches, and their dependencies are the smaller branches, and their dependencies are the leaves and so on. Some applications may appear multiple times in the tree.

An example:

  • App Alpha
    • App Beta
      • App Epsilon
      • App Gamma
        • App Zeta
      • App Gamma
        • App Zeta
      • App Delta
        • App Eta
          • App Theta

The example should be read as “App Alpha” depends on “App Beta”. “App Beta” depends on “App Epsilon” etc.

Also note that in the real world each of the dependencies must also include a version requirement.

This dependency tree can also be represented as a dependency list which indicates the order in which application must be installed:

  1. App Theta
  2. App Eta
  3. App Delta
  4. App Zeta
  5. App Gamma
  6. App Epsilon
  7. App Beta
  8. App Alpha

Each dependency tree may be transformed into multiple valid dependency lists. In this example, the following list is also valid:

  1. App Zeta
  2. App Gamma
  3. App Epsilon
  4. App Beta
  5. App Theta
  6. App Eta
  7. App Delta
  8. App Alpha

Note that “App Gamma” appears at different positions in the two variants of the dependency list, but “App Zeta” is always installed BEFORE “App Gamma” because “App Gamma” depends on “App Zeta”.

In any case an application can only be installed after all its direct and indirect dependencies are installed in the required versions.

This rule must be strictly followed. The most important reason is this: Given an application Alpha adds a field to a table that is defined in application Beta, application Alpha depends on application Beta. If application Alpha were installed before application Beta is installed, a new table would be created in Alpha’s scope containing only the added field. A subsequent installation of application Beta would fail and only database administrators can fix the issue.

If a circular dependency is identified at any time during development, both involved applications must be refactored to resolve the issue. The team must apply zero tolerance to circular dependencies.

To perform Dependency Management on a day-to-day basis, the platform must be extended with the following capabilities:

  • Document dependencies from one application to another allowing multiple (major) version requirements
  • Such dependencies must be part of an application so that they are also stored in the application’s source code repository
  • The dependencies must be stored in a way that they can be retrieved and processed from a source code repository
  • The dependency tree must be visible to developers
  • The dependency list shows all required dependencies in the exact order in which they must be installed
  • Any issues (like circular dependencies) must be detected automatically

These requirements are not met by the OOTB dependency table provided in ServiceNow – hence this additional capability must be implemented.

The open-source application “DevTools” supports these capabilities.

As in most cases, by far the most relevant factor is people. Without a team of architects – or developers who perform that role and take the responsibility – any technical tool is pointless.

Setting up a team of people who really care for the application architecture, drive its development, create a vision, and pursue a long-term strategy is the key success factor.

 

The whitepaper "A mature development and deployment process" has the full story:

https://www.wildgrube.com/download/A%20mature%20Development%20and%20Deployment%20Process.pdf

The DevTools app can be found here:

https://www.wildgrube.com/servicenow-devtools 

Version history
Last update:
‎01-31-2025 09:02 AM
Updated by:
Contributors