mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-10-05 06:36:55 +01:00
knowledge(breaking-changes): exclude appended event parameters from the signature-change rule
The article's detection guidance flags 'a parameter added' on any shipped procedure. Applied to an event publisher that is bound to rather than called, this produced a false positive on BCApps PR 10278, where a trailing var parameter was appended to the existing IntegrationEvent OnAfterOpenForRecRef and the developer twice replied that adding a parameter to an existing integration event is not a breaking change. It also contradicted events/add-new-event-parameters-at-the-end, which already states that existing subscribers still bind to the leading parameters. Scope the rule to called procedures, carve out appended event parameters as additive, and keep every other event signature edit - removal, reorder, retype, var flip - in scope. Point the IsHandled case at events/do-not-add-ishandled-to-an-existing-event, which owns that semantic concern.
This commit is contained in:
parent
293f9b13e7
commit
36430b305c
1 changed files with 4 additions and 2 deletions
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: breaking-changes
|
||||
keywords: [signature, public-procedure, parameter, return-value, overload, contract]
|
||||
keywords: [signature, public-procedure, parameter, return-value, overload, contract, integration-event]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
|
|
@ -13,6 +13,8 @@ application-area: [all]
|
|||
|
||||
A procedure that is reachable from outside its object — any procedure not marked `local` (and, for on-prem-scoped code, anything a dependent app can still bind to) — is a contract. Once another extension compiles against it, changing its shape breaks that extension at build time. Signature changes include adding, removing, or reordering parameters, changing a parameter or return type, and toggling a parameter between by-value and `var` (by-reference). The platform treats the procedure's identity as its full signature, so even a "compatible-looking" tweak is a new method to dependents. There is exactly one safe edit: naming a previously unnamed return value, which adds no caller obligation. LLMs routinely "improve" a public procedure in place by adding a parameter, not realizing every consumer must be recompiled.
|
||||
|
||||
This rule governs procedures that dependents *call*. An event publisher — a procedure carrying `[IntegrationEvent]` or `[BusinessEvent]`, conventionally declared `local` — is bound to, not called, and binds on a leading prefix of its parameter list. Appending a new parameter at the end of a shipped event therefore leaves every existing subscriber binding successfully, so it is additive rather than breaking and must not be flagged under this rule. See `events/add-new-event-parameters-at-the-end`. Every other edit to a published event signature — removing, reordering, or retyping a parameter, or flipping one to or from `var` — still breaks binding and is in scope here. Appending `var IsHandled: Boolean` is a separate concern: it binds fine but changes the event's contract, and is covered by `events/do-not-add-ishandled-to-an-existing-event`.
|
||||
|
||||
## Best Practice
|
||||
|
||||
Treat a published signature as frozen. When new behavior needs more inputs, add a new procedure or overload alongside the original — for example a `CalculateDiscountWithRate(Amount; Rate)` next to the unchanged `CalculateDiscount(Amount)` — and let the old one delegate to the new one. Existing callers keep compiling; new callers opt into the richer entry point. Naming an unnamed return value is the one in-place change that is always safe.
|
||||
|
|
@ -21,6 +23,6 @@ See sample: `do-not-change-published-procedure-signatures.good.al`.
|
|||
|
||||
## Anti Pattern
|
||||
|
||||
Editing the existing public procedure's parameter list — here, adding a `Rate` parameter to `CalculateDiscount` — so every dependent extension that called the old form fails to compile. Detection: a parameter added, removed, reordered, retyped, or flipped to/from `var`, or a changed return type, on any non-`local` procedure that already shipped. Add a new overload instead.
|
||||
Editing the existing public procedure's parameter list — here, adding a `Rate` parameter to `CalculateDiscount` — so every dependent extension that called the old form fails to compile. Detection: a parameter added, removed, reordered, retyped, or flipped to/from `var`, or a changed return type, on any non-`local` procedure that already shipped. Add a new overload instead. Exclude event publishers whose only change is a parameter appended at the end of the list: subscribers bind on the leading prefix, so that edit is additive and reporting it here is a false positive.
|
||||
|
||||
See sample: `do-not-change-published-procedure-signatures.bad.al`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue