Avoiding magic numbers without creating dependencies
Asked Answered
E

2

9

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?

Estragon answered 12/2, 2013 at 13:46 Comment(1)
I wouldn't really call this "coupling", as ErrorCodes does not have any behavior. It's good practice, and definitely does not deserve the negative connotations of the term. You might want to think of it as "one logical entity implemented as two physical classes" rather than as "two logical entities coupled together".Orman
A
4

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|
+-----------------------+     +-------------+
Antisthenes answered 12/2, 2013 at 13:56 Comment(0)
S
1

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.

Sunbeam answered 12/2, 2013 at 15:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.