mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-10-05 14:46:55 +01:00
Forslag: fixed-choice-set-must-use-enum-not-integer
This commit is contained in:
parent
02f0d49654
commit
e7f9d9f87a
1 changed files with 74 additions and 0 deletions
|
|
@ -0,0 +1,74 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: style
|
||||
keywords: [enum, option, integer, magic-number, variable-typing, field-typing]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
# A fixed set of named choices must use Enum, not a raw Integer
|
||||
|
||||
## Description
|
||||
|
||||
When a variable or field can only take on a fixed set of more than two
|
||||
named, mutually exclusive states — a difficulty level, a document type, a
|
||||
processing status — it must be typed as `Enum` (or `Option` when extending
|
||||
an object that still uses the legacy type). Representing that same state
|
||||
as a plain `Integer` and tracking the meaning of each value in a comment or
|
||||
in the developer's head (`1 = Beginner, 2 = Intermediate, 3 = Advanced`) is a
|
||||
magic-number anti-pattern: the compiler cannot catch an out-of-range value,
|
||||
`CASE`/`IF` branches read as opaque numbers instead of names, and every call
|
||||
site must either duplicate the numbering or trust a comment that can go
|
||||
stale.
|
||||
|
||||
This is distinct from a true two-state choice — see
|
||||
[[binary-choice-must-be-boolean]] — which should be `Boolean`, not an
|
||||
`Enum`/`Option` with two members. The line is the state count: more than
|
||||
two named states is an enumeration question, not a Boolean one.
|
||||
|
||||
## Best Practice
|
||||
|
||||
```al
|
||||
enum 50100 "Course Difficulty"
|
||||
{
|
||||
Extensible = true;
|
||||
value(0; Beginner) { }
|
||||
value(1; Intermediate) { }
|
||||
value(2; Advanced) { }
|
||||
}
|
||||
|
||||
field(50; Difficulty; Enum "Course Difficulty")
|
||||
{
|
||||
}
|
||||
...
|
||||
case Difficulty of
|
||||
"Course Difficulty"::Beginner:
|
||||
Level := 'Beginner';
|
||||
"Course Difficulty"::Intermediate:
|
||||
Level := 'Intermediate';
|
||||
"Course Difficulty"::Advanced:
|
||||
Level := 'Advanced';
|
||||
end;
|
||||
```
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
```al
|
||||
field(50; Difficulty; Integer)
|
||||
{
|
||||
}
|
||||
...
|
||||
// 1 = Beginner, 2..5 = Intermediate boundary is fuzzy, 6+ = Advanced?
|
||||
case Difficulty of
|
||||
1:
|
||||
Level := 'Beginner';
|
||||
2, 3:
|
||||
Level := 'Intermediate';
|
||||
end;
|
||||
```
|
||||
|
||||
A raw `Integer` standing in for a named set of states pushes the
|
||||
documentation of what each value means into a comment, a wiki page, or a
|
||||
developer's memory — none of which the compiler or a future maintainer can
|
||||
rely on.
|
||||
Loading…
Add table
Add a link
Reference in a new issue