bcquality/microsoft/knowledge/breaking-changes/choose-access-modifiers-deliberately.md
Jesper Schulz-Wedde 4ca6452ccf Add breaking-changes knowledge domain and review leaf skill
Seed a new breaking-changes (AL API stability) knowledge domain with six
articles plus good/bad AL samples, a new al-breaking-changes-review leaf
skill, and minimal wiring into al-code-review and the README.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-25 12:29:44 +02:00

2 KiB

bc-version domain keywords technologies countries application-area
all
breaking-changes
access-modifier
internal
local
public
protected
scope
encapsulation
al
w1
all

Choose access modifiers deliberately

Description

Access is a decision about what you are willing to support forever. The moment a procedure or object is reachable from another extension — no local, or a removed [Scope('OnPrem')] — it becomes a contract: callers bind to it, and changing or removing it later is a breaking change. The safe default is the narrowest access that works. Use local for implementation detail confined to one object, internal for code shared within the app but not exposed to consumers, and protected var for state intended as an inheritance point for extension objects. Reserve public for the deliberate, supported entry points you intend to maintain as a stable API. LLMs tend to make everything public "to be safe," which inverts the rule and turns every helper into an accidental contract.

Best Practice

Start everything local or internal and promote a member to public only when you have decided to support it as a stable contract. Expose a small, intentional surface — the supported entry point — and keep validation, posting, and helper routines internal for in-app reuse or local when single-object. Do not drop [Scope('OnPrem')] without intent, since that too widens the contract. Every public member is a maintenance commitment; spend them deliberately.

See sample: choose-access-modifiers-deliberately.good.al.

Anti Pattern

Declaring every procedure public by default, so internal helpers like ValidateOrder and PostOrder become a de-facto API that consumers bind to and that can no longer be changed freely. Detection: an object where implementation-detail procedures carry no access modifier or are public without a reason to support them externally. Default them to internal/local and make only the intended entry point public.

See sample: choose-access-modifiers-deliberately.bad.al.