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 (1)
Nice initiative to have a post about this π