Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoiding magic numbers without creating dependencies

I'm creating an error manager for an API I'm work on. The idea is that it provides a single store of error codes that can be returned from the API, ensuring that the same error in different calls is handled in the same way (e.g. required value missing from the request).

My initial approach was along the lines of:

$this->_errorManager->setError(ErrorCodes::REQUIRED_FIELD);

However this creates a dependency on the error codes class anywhere I want to set an error.

The alternative is:

$this->_errorManager->setError(100);

But now I've got a number sitting in the middle of my code that means nothing.

While I can think of solutions to this specific problem there will be other situations where I will want to use an 'enum' and I can't think of a solution that doesn't tightly couple the classes.

Is there a better way of doing this or a different approach I can take to remove magic numbers? Or is the tight coupling something I just have to accept and consider on a case by case basis?

like image 672
Dan Avatar asked Feb 12 '13 13:02

Dan


People also ask

Why should you avoid magic numbers in programming?

The use of unnamed magic numbers in code obscures the developers' intent in choosing that number, increases opportunities for subtle errors (e.g. is every digit correct in 3.14159265358979323846 and is this equal to 3.14159?) and makes it more difficult for the program to be adapted and extended in the future.

How do you avoid magic numbers in CSS?

At least in CSS, using relative units is the way to be preferred to disenchant magic numbers. Additionally, using reusable patterns and keeping your codebase DRY reduces the risk of introducing magic numbers into your codebase. . my-class { font-size: 1em; line-height: 1.

How do you avoid magic numbers in C++?

Programming isn't magic, so don't incant it: Avoid spelling literal constants like 42 or 3.14159 in code. They are not self-explanatory and complicate maintenance by adding a hard-to-detect form of duplication. Use symbolic names and expressions instead, such as width * aspectRatio .


2 Answers

This is desired coupling. While it is a good idea, to have the application and its error manager loosely coupled, there is no reason to separate the application and its error codes, they belong together.

Dependencies:

+-----------------------+
|Application error codes|<------------+
+-----------------------+             |
           ^                          |
           |                          |
+----------+----------+               |
|Application component|               |
+----------+----------+               |
           |                          |
           v                          |
+-----------------------+     +-------+-----+
|Error handler interface|<|---+Error handler|
+-----------------------+     +-------------+
like image 158
Fabian Schmengler Avatar answered Nov 11 '22 16:11

Fabian Schmengler


You can clear some of these hurdles with "preprocessor" macros and a makefile. The preprocessor macros come courtesy of m4.

Assume you maintain a file of error codes like this.

   define(`ERR_REQUIRED_FIELD',`100')dnl

Then you can write your PHP code with the English error "constant".

$this->_errorManager->setError(ERR_REQUIRED_FIELD);

And include a line in your makefile that runs these two files through m4. There's more than one way to manage that. (For brevity, I'm omitting the makefile, and just running my test file through m4.)

$ m4 test.php.m4 > test.php
$ cat test.php
$this->_errorManager->setError(100);

This does introduce a dependency; the php files will all depend on the file of error codes. But it's a trivial dependency that's easily managed through the makefile. In practice, I'd probably build a file of error codes that looks like this . . .

ERR_DISK_FULL
ERR_REQUIRED_FIELD
ERR_MISSING_ARG

and use text utilities and make to either

  • build the m4 macro definitions, or
  • build the definitions for your ErrorCodes module.

The numeric values equal the line numbers; this guarantees you never have a duplicate error code.

like image 26
Mike Sherrill 'Cat Recall' Avatar answered Nov 11 '22 16:11

Mike Sherrill 'Cat Recall'