---
schema_version: "1"
id: 848f0954aa01bd659f2b4688b19298afa124718c117ea7db2df17a5701de5ee4
title: Write Graph Engine Friendly Code
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/code-analyzer/salesforce-code-analyzer/guides/engine-sfge-write-friendly-code.md
canonical_url: https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/engine-sfge-write-friendly-code.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: 1d0583e7f44d7d4a8f3f75d608ff540146b104b3648a11da8c7693c4a6b866b2
products:
  - Salesforce Code Analyzer
---
# Write Graph Engine Friendly Code

Graph Engine is a powerful tool for code analysis, but it has its own set of limitations. Learn about Graph Engine’s nuanced architecture and how to make small refactors to your code to significantly improve Graph Engine's performance.

**note:** Some suggested refactors in this guide can conflict with accepted best practices for Apex. Read through the options, and update your code as appropriate.

## Who Should Read This Guide?

If your codecase is highly complex, this guide is for you. Use the suggestions in this guide to refactor your code, be more compatible with Graph Engine's architecture, and find performance gains.

## Graph Engine Concepts

At a high level, Graph Engine identifies entry points into your codebase. Next, Graph Engine analyzes these entry points by using them to build paths through the code and then traverses those paths to apply rules.

### Performance Factors for Graph Engine

Two factors directly affect Graph Engine’s performance.

- The number of entry points analyzed. Entry points are evaluated in parallel, and the timeout is applied to each entry point separately.
- The number of paths each entry point constructs. Building paths is the most expensive part of analyzing an entry point. Typically, an entry point causes timeouts or memory issues because it constructs an inordinate number of paths.

Based on these factors, the most consequential refactoring that you can do is to decrease the number of paths a single entry point constructs or to more evenly distribute paths between entry points.

### How Paths Are Built

To understand how to decrease the number of paths in a given entry point, let’s review this example to see how paths are built.

```apex
public void foo(boolean b1, boolean b2) {
    if (b1) {
        System.debug('b1 is true');
    } else {
        System.debug('b1 is false');
    }
    if (b2) {
        System.debug('b2 is true');
    } else {
        System.debug('b2 is false');
    }
}
```

Assume that the value of parameter `b1` and `b2` are unknown. Graph Engine identifies four unique paths through the method. Why? When the values of these two parameters are unknown, both `if` expressions have an indeterminate outcome. One path must fork into two and then into four.

In other words, where possible, Graph Engine avoids building impossible paths.

## Refactoring Entry Points

If an entry point’s complexity causes it to encounter timeouts or memory problems, the easiest way to resolve these errors is to refactor that entry point into two separate entry points with fewer paths. These entry points are analyzed in parallel and have separate timeouts, complete faster, and are less likely to exceed time or memory limits.

Refactoring entry points to redistribute paths is low effort and low risk, but it's also powerful in its ability to make your code more compatible with Graph Engine.

### Code Example: One Inefficient Entry Point

Let’s look at an example with an Aura-Enabled method. Graph Engine considers this method an entry point.

```apex
@AuraEnabled
public void foo(boolean b1, boolean b2, boolean b3) {
    if (b1) {
        helperMethod1a();
    } else {
        helperMethod1b();
    }
    if (b2) {
        helperMethod2a();
    } else {
        helperMethod2b();
    }
    if (b3) {
        helperMethod3a();
    } else {
        helperMethod3b();
    }
}
```

The values of all three parameters, `b1`, `b2`, and `b3`, are unknown, so each conditional `if` expression causes paths to fork. If we assume that each helper method contains exactly one unique path, then the total number of possible paths is 8, or 1 x 2 x 2 x 2. That number of paths is unlikely to exceed time or memory limits.

### Code Example: One Inefficient Entry Point and an Explosion of Paths

Now let’s use the same example but assume that each helper method contains 10 unique paths. Then each conditional `if` expression actually creates 20 unique paths instead of just two. The total number of paths is then 8,000, or 1 x 20 x 20 x 20, which is an excessive number of paths.

### Code Example: Two Efficient Entry Points Reduces Paths

Let’s refactor the code from our previous example. We turn the single entry point into two entry points that include fewer paths. Our code now looks something like this.

```apex
@AuraEnabled
public void foo1(boolean b1, boolean b2) {
    innerFoo(b1, b2, true);
}

@AuraEnabled
public void foo2(boolean b1, boolean b2) {
    innerFoo(b1, b2, false);
}

public void innerFoo(boolean b1, boolean b2, boolean b3) {
    if (b1) {
        helperMethod1a();
    } else {
        helperMethod1b();
    }
    if (b2) {
        helperMethod2a();
    } else {
        helperMethod2b();
    }
    if (b3) {
        helperMethod3a();
    } else {
        helperMethod3b();
    }
}
```

Our refactored code with redistributed paths has two Aura-enabled entry points, `foo1` and `foo2`. Each of these entry points invokes `innerFoo` by passing in their own parameters and a literal boolean to `innerFoo`, which is identical to the old `foo`.

Each entry point uses a definitive value for `b3` in its invocation of `innerFoo`, so each entry point avoids forking at the final `if`. That means half as many paths are evaluated. If we assume that each helper method has 10 unique paths, each entry point builds only 4,000 paths, or 1 x 20 x 20 x 10.

| Entry Points               | Unknown Parameters | Indeterminate if Clauses | Paths Per Helper Method | Paths Per Entry Point Calculation | Total Paths Per Entry Point |
| -------------------------- | ------------------ | ------------------------ | ----------------------- | --------------------------------- | --------------------------- |
| One Inefficient, One Path  | 3                  | 3                        | 1                       | 1 x 2 x 2 x 2                     | 8                           |
| One Inefficient, Ten Paths | 3                  | 3                        | 10                      | 1 x 20 x 20 x 20                  | 8,000                       |
| Two Sufficient             | 2                  | 2                        | 10                      | 1 x 20 x 20 x 10                  | 4,000                       |

By refactoring the code from the inefficient example into two efficient entry points, we cut the total paths per entry point from 8,000 to 4,000. The new entry points are far less likely to time out than the original. Because they can be analyzed in parallel, they finish sooner.
