Sanitizing my alrules.json files

In this video, I try to figure out what code analyzer rules I should use and I create a global master. My current alrules.json file is attached below.

https://youtu.be/_GnEUHcOzt0
{
    "name": "RULES",
    "description": "Erik's Rules",
    "rules": [
        {
            "id": "AA0215",
            "action": "Hidden",
            "justification": "This is OK -> Don't need MS to dictate filenames."
        },
        {
            "id": "AA0072",
            "action": "Hidden",
            "justification": "This is OK -> Don't need MS to dictate variable names."
        },
        {
            "id": "AA0074",
            "action": "Hidden",
            "justification": "This is OK -> Don't need MS to dictate label names."
        },
        {
            "id": "AA0021",
            "action": "Hidden",
            "justification": "This is OK -> Don't need sorted variables."
        },
        {
            "id": "AA0214",
            "action": "Hidden",
            "justification": "Not working right now..."
        },
        {
            "id": "AA0217",
            "action": "Hidden",
            "justification": "No Microsoft, bad Microsoft, you don't get it!!!"
        },
        {
            "id": "AA0210",
            "action": "Hidden",
            "justification": "Yes, I know I'm setting a filter on a key-value!"
        },
        {
            "id": "AA0470",
            "action": "Hidden",
            "justification": "No needed right now (only for translators)"
        },
        {
            "id": "AW0009",
            "action": "Hidden",
            "justification": "We're using a blob - try to stop us!"
        }
    ]
}

In this video, Erik walks through the process of cleaning up and consolidating his alrules.json files across multiple Business Central AL projects. He turns on code analysis for one of his projects, reviews each warning, and decides which rules to keep and which to suppress — ultimately building a single master ruleset file he can reuse across all projects.

Why Sanitize Your AL Rules?

Erik noticed that across his various Business Central projects, he had accumulated roughly 10 different versions of rule sets scattered around. Some projects had extensive rule lists, others had only two entries. The goal of this exercise was to consolidate everything into a single, well-reasoned master alrules.json file that could be applied consistently.

Enabling Code Analysis

To turn on code analysis in a Business Central AL project, you configure the settings.json file located in the .vscode folder. You specify which code analyzers to use, enable them, and point to a rule set file that controls which rules are active and which are suppressed.

Erik noted an interesting quirk: if you have an empty alrules.json file, it seems to confuse the compiler into thinking there are no issues at all. Something to watch out for.

The Starting Point: 283 Warnings

The project in question — a compiler Erik has been building in AL — contains roughly 4,571 lines of AL code. After enabling code analysis, 283 problems were reported (243 warnings plus 43 additional). The project still compiled without errors, so all of these were warnings to be triaged.

Walking Through the Rules

Rules Erik Chose to Suppress

Here are the rules Erik decided to exclude, along with his reasoning:

  • AA0215 — File naming conventions: This rule flags files whose names don’t match a prescribed pattern (e.g., “source editor.al” should be “source editor.controladdininterlay.al”). Erik prefers to name files in whatever way makes sense for the project. “I don’t need Microsoft to dictate filename rules.”
  • AA0021 — Variable declaration should be ordered by type: The rule wants variables sorted in a specific order (Record, Report, Codeunit, XMLport, Page, Query, etc.), but Erik points out that the rule is incomplete — it doesn’t handle KeyRefs, for instance.
  • AA0072 — Variable and parameter naming suffixes: This rule requires variables and parameters to be suffixed with their type or object name. Erik disagrees: “We’re in a strongly typed language with IntelliSense. We really don’t need variables prefixed with the type.”
  • AA0074 — Label naming suffixes: Similar to AA0072, this requires labels to be suffixed indicating what kind of label they are (Message, Token, Error, Question, or Text). Erik finds this overly prescriptive.
  • AA0214 — Local record should be modified before saving: Erik notes this rule has never worked correctly for him.
  • AA0210 — Avoid non-indexed fields in filtering: While well-intentioned, sometimes you simply have to filter on a non-indexed field. Erik considers these warnings to be noise.
  • AA0417 — Placeholders should have a comment explaining their content: This rule is important if you work with translators, since they need to understand what %1, %2, etc. represent. But if you’re not dealing with translations, Erik suggests suppressing it.
  • PTE0004 — Table definition must have a matching permission set: Flagged as not working at the time of recording.

Rules Erik Chose to Keep

Several warnings turned out to be genuinely valuable:

  • Unnecessary begin…end blocks: Erik found he had wrapped many single statements (especially inside case statements) with begin…end unnecessarily. He agreed these should be cleaned up.
  • Unused variables: Multiple variables were declared but never used — typically leftovers from copy-pasting code. Definitely worth cleaning up.
  • Format string placeholder mismatch: The number of parameters passed to a format string didn’t match the placeholders. “That was a real bug. Score one for the code analyzers.”
  • Local variable name identical to a global variable: A local variable named _start shadowed a global variable of the same name. This could easily lead to subtle bugs.
  • Parameter passed by reference but never modified: A parameter was declared as var but never changed within the method — a valid catch.
  • Missing parentheses on function calls: Calling Current without parentheses when it’s a function — a reasonable style rule.
  • Declared but never used local methods: A local method called Next was declared but never called.
  • AA0218 — Missing tooltips: Erik acknowledges this is annoying but necessary for building quality apps. Even if you just repeat the field name as the tooltip, it’s better than nothing.
  • AL0603 — Conversion between Option and Enum: This will become an error in future versions of AL, so it’s best to address it now.
  • Implicit with usage: Erik keeps this rule active to stay ahead of deprecation warnings.

The Signal-to-Noise Problem

Erik’s core message is about the signal-to-noise ratio. Out of 283 warnings, only a handful were genuine bugs — a format string mismatch and a variable shadowing issue. The rest were either style preferences or rules that didn’t apply to the project. Without a curated rule set, those real bugs would be buried under hundreds of irrelevant warnings.

“If you don’t apply this, your signal-to-noise ratio will be terrible, and you won’t actually see the important ones — like the bug where a percentage placeholder was missing in an error message.”

A Note on Build Automation

Erik mentions his ALBuild tool for automating the build and deployment process. Here’s an example of a build configuration file that handles everything from pulling the latest code from Git, updating versions, downloading symbols, compiling, translating, and pushing the result back to the repository:

{
  "Project": "Point of Sale",
  "Report" : "Email",
  "ReportDestination" : "erik@hougaard.com",
  "Tasks": [
    {
      "Type": "DeployBasicDocker",
      "Settings": {
        "AppFile": "c:\\projects\\albuild\\testrunner\\Hougaard_ALBuild TestRunner_1.0.0.0.app",
        "BaseURL": "http://bc20:7049/BC/",
        "User": "demo",
        "Password": "demo",
        "SchemaUpdateMode": "forcesync"
      }
    },
    {
      "Type": "Git",
      "Settings": {
        "Path": "c:\\projects\\youtube\\point of sale",
        "Command": "pull"
      }
    },
    {
      "Type": "UpdateVersion",
      "Settings": {
        "AppPath": "c:\\projects\\youtube\\point of sale",
        "VersionPartToIncrement": 4,
        "Increment": 1,
        "DateInVersionPartNo": 3
      }
    },
    {
      "Type": "Compile",
      "Settings": {
        "AppPath": "%APPPATH%"
      }
    },
    {
      "Type": "Translate",
      "Settings": {
        "XLFPath": "%APPPATH%\\Translations\\%NAME%.g.xlf",
        "ProductName": "%NAME%"
      }
    },
    {
      "Type": "Compile",
      "Settings": {
        "AppPath": "%APPPATH%"
      }
    },
    {
      "Type": "Git",
      "Settings": {
        "Path": "%APPPATH%",
        "Command": "commit -a -m \"ALBuild Version %VERSION%\""
      }
    },
    {
      "Type": "Git",
      "Settings": {
        "Path": "%APPPATH%",
        "Command": "push"
      }
    }
  ]
}

Integrating code analysis into a pipeline like this ensures that warnings are caught consistently across builds, not just when a developer happens to check the Problems panel in VS Code.

Summary

The key takeaways from Erik’s rule sanitization exercise:

  1. Turn on code analysis. It will find real bugs — format string mismatches, variable shadowing, unused code — that are easy to miss during manual review.
  2. Curate your rule set. Don’t just accept every rule. Many are stylistic preferences that may not match your team’s conventions. Suppressing irrelevant rules dramatically improves the signal-to-noise ratio.
  3. Create a master rule file. Instead of maintaining different rule sets across projects, build one well-reasoned alrules.json and use it everywhere.
  4. Review periodically. As the AL language evolves and new analyzers are added, revisit your rule set to make sure it still makes sense.
  5. Share and discuss. Different teams will have different opinions on which rules matter. The important thing is to make a deliberate, documented choice rather than leaving it to chance.