Consider:
Language,
Framework,
Context.
1. Language
Using ∞ can be a solution for a maximum.
JavaScript, for example, has an infinity. C# doesn't¹.
Ada, for example, has ranges. C# doesn't.
In C#, there is int.MaxValue
, but you cannot use it in your case. int.MaxValue
is the maximum integer, 2,147,483,647. If in your code, you have a maximum value of something, like a maximum accepted pressure before something explodes, using 2,147,483,647 has no sense.
2. Framework
.NET Framework is rather inconsistent on this point, and its usage of magic values can be criticized.
For example, "Hello".IndexOf("Z")
returns a magic value -1
. It maybe makes it easier (does it?) to manipulate the result:
int position = "Hello".IndexOf("Z");
if (position > 0)
{
DoSomething(position);
}
rather than using a custom structure:
SearchOccurrence occurrence = "Hello".IndexOf("Z");
if (occurrence.IsFound)
{
DoSomething(occurrence.StartOffset);
}
but is not intuitive at all. Why -1
and not -123
? A beginner may also mistakenly think that 0
means "Not found" too or just mistype (position >= 0)
.
3. Context
If your code is related to timeouts in network sockets, using something which was used by everyone for decades for the sake of being consistent is not a bad idea. Especially, 0
for a timeout is very clear: it's a value which cannot be zero. Using a custom class in this case may make things more difficult to understand:
class Timeout
{
// A value indicating whether there is a timeout.
public bool IsTimeoutEnabled { get; set; }
// The duration of the timeout, in milliseconds.
public int Duration { get; set; }
}
- Can I set
Duration
to 0 if IsTimeoutEnabled
is true?
- If
IsTimeoutEnabled
is false, what happens if I set Duration
to 100?
This can lead to multiple mistakes. Imagine the following piece of code:
this.currentOperation.Timeout = new Timeout
{
// Set the timeout to 200 ms.; we don't want this operation to be longer than that.
Duration = 200,
};
this.currentOperation.Run();
The operation runs for ten seconds. Can you see what's wrong with this code, without reading the documentation of Timeout
class?
Conclusion
null
expresses well the idea that the value is not here. It's not provided. Not available. It's neither a number, nor a zero/empty string or whatsoever. Don't use it for maximum or minimum values.
int.MaxValue
is strongly related to the language itself. Don't use int.MaxValue
for a maximum speed limit of Vehicle
class or a maximum acceptable speed for an aircraft, etc.
Avoid magic values like -1
in your code. They are misleading and lead to mistakes in code.
Create your own class which would be more straightforward, with the minimum/maximum values specified. For example VehicleSpeed
can have VehicleSpeed.MaxValue
.
Don't follow any previous guideline and use magic values if it's a general convention for decades in a very specific field, used by most people writing code in this field.
Don't forget to mix approaches. For example:
class DnsQuery
{
public const int NoTimeout = 0;
public int Timeout { get; set; }
}
this.query.Timeout = 0; // For people who are familiar with timeouts set to zero.
// or
this.query.Timeout = DnsQuery.NoTimeout; // For other people.
¹ You can create your own type which includes infinity. Here, I'm talking about native int
type only.
CSS isn't trying to make things more difficult on purpose, it was designed with a far simpler goal in mind, variables and hierarchies are hardly its only shortcomings. LESS and Sass exist specifically to address these shortcomings, and until either capability is natively supported, you should stick with them.
That said, W3C's CSS Working Group is working on drafts for both CSS variables and CSS hierarchies:
There's absolutely no way to tell when either draft will be ready for implementation, or how soon major browsers will adopt them. All I can say is that the CSS Variables draft is closer to being adopted, you can already test drive CSS variables in Chrome, Safari and Firefox, but keep in mind that support in all three browsers is considered experimental and subject to change. Read Using CSS variables on MDN for more details.
Best Answer
Firstly, magic values are avoided in programming by using variables or constants. CSS does not support variables, so even if magic values were frowned on, you don't have much of a choice (except using a preprocessor as SASS, but you wouldn't do that for a single snippet).
Secondly, values might not be as magic in a domain specific language like CSS. In programming, a magic number is a number where the meaning or intent is not obvious. If a line says:
You will ask "why 23"? What is the reasoning? A variable could clarify the intent:
This is because a lone number could mean absolutely anything in general purpose code. But consider CSS:
The height and color are not magic, because the meaning is perfectly clear from the context. And the reason for choosing the spefic value is simple because the designers thought it would look good. Introducing a variable would not help anything, since you would just name it something like "
defaultBackgroundColor
" and "defaultFontSize
" anyway.