Magic numbers are literal numeric values that are used in code without any explanation of their meaning. Magic strings are strings literals without any explanation either.
Why is it a problem ?
First of all, it is not easy to read when there is only a number that is written in code. Let's look at an example:
$myModel = new Model();
$myModel->status_id = 3; // A magic number
$myModel->save();
Here there is no explanation of the meaning behind the value "3". I can probably find the answer by looking at the code surrounding this snippet or look for a corresponding value elsewhere (like in a database table).
Also the number "3" is not important in itself for my comprehension of the code. The status should correspond to a more realistic status of my business like "Created", "Sent", "Archived".
The same applies to Magic Strings:
switch ($request->code_response) {
case "code_1": // Magic String
doAnAction();
break;
case "code_2": // Also a Magic String
doAnotherAction();
break;
...
I can probably guess the utility of these code values by looking at the code of the doAnAction() and doAnotherAction() functions but it would greatly help to have a code more readable at this stage.
How to solve this problem ?
Different solutions can be used. The simplest one is to use a named variable:
$statusCreated = 3;
$myModel = new Model();
$myModel->status_id = $statusCreated;
$myModel->save();
A better solution is to use constant values in a separate class or even an enum.
enum MyModelStatuses {
...
case CREATED = 3;
case ARCHIVED = 4;
...
}
$myModel = new Model();
$myModel->status_id = MyModelStatuses::CREATED->value; // don't forget to import the new class
$myModel->save();
A separate class allow you to have a global logic behind these values that can be reused elsewhere.
Another solution when the Magic Number is only used in one class is to use a const variable in the class:
From:
class MyClass {
public function myFunction() {
for ($i = 0; $i < 10; $i++) { // Here 10 is a Magic Number
// Do something
}
}
}
To:
class MyClass {
private const NUMBER_OF_ITERATIONS = 10;
public function myFunction() {
for ($i = 0; $i < self::NUMBER_OF_ITERATIONS; $i++) {
// Do something
}
}
}
Such constants are used as parameters inside your class and can be easily replaced by new values.
Let's see a last use case of avoiding Magic Numbers.
$myModel = new MyModel();
$myModel->duration = 60; // Magic Number
$myModel->save();
Here the value 60 can be confusing. What is its unit ? It could me seconds, it could be minutes or even hours !
$secondsInAMinute = 60;
$myModel = new MyModel();
$myModel->duration = $secondsInAMinute;
$myModel->save();
The name of the new variable itself helps to make the code readable. Also the same number could refer to different meanings (in this case we could have 60 as $minutesInAnHour somewhere else in the code).
That's it ! I hope that this article helped you understand what are Magic Numbers (and Magic Strings) and how to remove them from your code !
Top comments (0)