mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-08-07 01:46:53 +01:00
- Introduced guidelines for "one codeunit one global function" architecture to enforce single responsibility in AL code. - Added best practices and anti-patterns for adding parameters via overloads to maintain backward compatibility. - Documented the importance of never deleting members in AL and always marking them as obsolete. - Established the requirement for OnBefore and OnAfter integration events for global procedures to enhance extensibility. - Defined naming conventions for CMFRT objects, including prefixes and object ID ranges to avoid conflicts. - Implemented patterns for case statements to ensure all cases are handled, including the necessity of an else clause. - Introduced the interface injection pattern to allow pluggable operations in table-level code. - Recommended using Confirm Management for user confirmations to improve testability. - Established a three-permission set pattern for security to ensure proper access control. - Created a review skill for CMFRT AL standards to automate compliance checks against established guidelines.
26 lines
1.8 KiB
Markdown
26 lines
1.8 KiB
Markdown
---
|
|
bc-version: [all]
|
|
domain: breaking-changes
|
|
keywords: [obsolete, delete, remove, breaking-change, backward-compatibility, obsolete-state, obsolete-reason]
|
|
technologies: [al]
|
|
countries: [w1]
|
|
application-area: [all]
|
|
---
|
|
|
|
# CMFRT never delete — always obsolete
|
|
|
|
## Description
|
|
|
|
In a CMFRT extension the following AL members must never be physically deleted: global procedures, table fields, page fields, enum values, and entire objects. Removing any of these breaks dependent extensions and upgrade paths without a compiler warning. The required approach is to retain the member, mark it with `ObsoleteState = Pending` when deprecation begins, and promote to `ObsoleteState = Removed` in a subsequent release after dependents have migrated. All obsoleted members are placed at the end of their containing object so that active code is never mixed with retired code.
|
|
|
|
## Best Practice
|
|
|
|
When a member is no longer needed, keep it in place, add `ObsoleteState = Pending`, `ObsoleteReason = '<explanation>'`, and `ObsoleteTag = '<task-id>'`. In a later release, promote to `ObsoleteState = Removed`. For fields, add the replacement field first, then obsolete the original. For procedures, add the replacement first, then obsolete the original. Provide an upgrade codeunit procedure whenever a field rename or type change requires data migration.
|
|
|
|
See sample: `cmfrt-never-delete-always-obsolete.good.al`.
|
|
|
|
## Anti Pattern
|
|
|
|
Deleting a global procedure, table field, page field, enum value, or entire AL object from the extension source. Physical deletion produces compiler errors in every dependent extension that referenced the removed member, and for table fields it causes data loss and upgrade failures in existing customer databases.
|
|
|
|
See sample: `cmfrt-never-delete-always-obsolete.bad.al`.
|