Skip to content

upper_snake_constant_identifiers #58508

Open
@mleonhard

Description

@mleonhard

Describe the rule you'd like to see implemented
Require const identifiers to be UPPER_SNAKE_CASE.

Allow a single _ underscore prefix for private file-level and class-level identifiers. Do not allow trailing underscores.

Example regular expression: _?\p{Lu}(\p{Lu}|[0-9])*(_(\p{Lu}|[0-9])+)*

Examples

Examples from a production Flutter app:

class MatchesModel implements WrappedModel {
  static const _ARC_ID = 'arc_id';
  // ...
}
class Bio {
  static const MAX_CHARS = 2048;
  // ...
}
// theme.dart
const String FONT_FAMILY = 'Muli';

Additional context

Upper-snake-case is industry-standard practice for naming constant identifiers.

Let's add a new upper_snake_constant_identifiers lint rule so folks can use it. Currently the only option is to disable the constant_identifier_names lint rule, leaving us with no checks of constant names.

The constant_identifier_names rule docs say "You may use SCREAMING_CAPS for consistency with existing code." Unfortunately, this allowance is not implemented. The rule adds lint warnings to the examples above.

A Dartlang Team member proposed and implemented the rule in one day, with no community discussion: #57190 . They gave several reasons for switching to lowerCamelCase:

Note: We initially used Java’s SCREAMING_CAPS style for constants. We changed for a few reasons:

  • SCREAMING_CAPS looks bad for many cases, particularly enum values for things like CSS colors.
  • Constants are often changed to final non-const variables, which would necessitate a name change.
  • The values property automatically defined on an enum type is const and lowercase.

I worked for 5 years as a SWE at Google reading and writing C++, Golang, Java, and Python (codesearch for my CLs under LDAP leonhard). Before that, I was at Amazon. In my professional opinion, the given reasons are weak. They don't apply to my current Dart codebase or any codebase I've worked on.

Code readability is paramount. When constants use a different case from variables, the reader can instantly understand that the value does not change during execution.

Constants are often imported from other modules. When an imported module-level value uses a special case, the reader is saved the effort of looking up the value to see if it is a constant or an evil global variable. This saves time and effort.

I reject "it looks bad" as a reason for deviating from industry standard practice and harming readability. I don't care how the code looks. I care about how quickly I can read and understand it. I expect that most professional developers share this opinion.

When a developer changes a constant to a variable, they and their reviewer should carefully examine every place where the value was used. Changing the name of the value makes this easy and hard to skip. Therefore having to rename the value is a feature, not problem.

Finally, the note author says that we should switch to lowerCamelCase because that's what Dartlang uses for one auto-generated value. This is unnecessary and drastic action. If Dartlang uses an inconsistent case for something, then fix that. Add the new one and deprecate the old one. Then remove the old one in Dart 3.0. Please don't demand massive codebase changes and habit retraining for consistency with a tiny thing.

Related: #57162, #57394

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3A lower priority bug or feature requestarea-devexpFor issues related to the analysis server, IDE support, linter, `dart fix`, and diagnostic messages.devexp-linterIssues with the analyzer's support for the linter packagelinter-lint-requesttype-enhancementA request for a change that isn't a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions