For less screaming in the code

4 months ago by David Grudl  

The Nette coding style is undergoing a minor modification: the PascalCase notation is now used for class constants instead of the original SCREAMING_SNAKE_CASE.

The tradition of using capital letters for constants comes from the C language, where so-called preprocessor macro constants were denoted as such. It was useful not to overlook the distinction between parser code and preprocessor code. PHP does not need this distinction since it does not have a preprocessor. On the other hand, overemphasizing the constants is counterproductive. Why should a constant shout and draw attention to itself, be a prominent element in the program flow? There is no reason for it.

Example of real code with SCREAMING_SNAKE_CASE constants that aggressively stand out in the code and are also harder to read:

foreach (self::SYMBOL_TO_NAME as $symbol => $name) {
	$idx = self::ACTION_BASE[$state] + $symbol;
	if (($idx >= 0 && $idx < count(self::ACTION) && self::ACTION_CHECK[$idx] === $symbol
			|| $state < self::YY_2_TBLSTATE
			&& ($idx = self::ACTION_BASE[$state + self::NUM_NON_LEAF_STATES] + $symbol) >= 0
			&& $idx < count(self::ACTION) && self::ACTION_CHECK[$idx] === $symbol)
		&& self::ACTION[$idx] !== self::UNEXPECTED_TOKEN_RULE
		&& self::ACTION[$idx] !== self::DEFAULT_ACTION
		&& $symbol === 0
	) {
		return true;
	}
}

An example of the same code with PascalCase constants, which looks much more compact:

foreach (self::SymbolToName as $symbol => $name) {
	$idx = self::ActionBase[$state] + $symbol;
	if (($idx >= 0 && $idx < count(self::Action) && self::ActionCheck[$idx] === $symbol
			|| $state < self::Yy2Tblstate
			&& ($idx = self::ActionBase[$state + self::NumNonLeafStates] + $symbol) >= 0
			&& $idx < count(self::Action) && self::ActionCheck[$idx] === $symbol)
		&& self::Action[$idx] !== self::UnexpectedTokenRule
		&& self::Action[$idx] !== self::DefaultAction
		&& $symbol === 0
	) {
		return true;
	}
}

Compatibility

Nette is of course careful about backwards compatibility. All public constants also remain in their original form and serve as aliases for the preferred PascalCase constants. They will continue to exist in the next major release and will have the @deprecated flag.

All newly added class constants are now only in the PascalCase variant. Global constants are not used by Nette.

Enumerations

PHP 8.1 comes with enumerations, which will be used in Nette as well. Enums will replace the previous solution using constants. There is no coding standard for how to write enumerations yet, the PHP-FIG organization has long failed in this regard and comes up with recommendations many years late. The PHP documentation itself is a guide. For “enum cases”, it exclusively uses PascalCase notation, and this also applies to the earlier experimental implementation SplEnum.

Combining PascalCase enumerations with SCREAMING_SNAKE_CASE constants would look inconsistent, so this is also a reason to change the style of writing constants.

Technical note: enumerations are syntactic sugar for constants, from PHP point of view there is no difference between “enum case” and class constant.

How to change the own code?

Any cosmetic change will always cause a lot of resentment. But if you try using PascalCase constants for a month, you will be thrilled with them and there will be no going back. And you'll want to introduce the new notation into your own code as well. How to do it? The ideal way is to rename the constants in PhpStorm using the Refactor > Rename function. Also, install the plugin String Manipulation and assign it a shortcut in the settings for Switch Case > To Pascal Case.

Then all you have to do is place the cursor on the constant, press Ctrl-F6 (rename) and then the shortcut for To Pascal Case and PhpStorm will change the constant throughout the project.

Happy coding!