从虚构的游戏引擎API中考虑这个示例函数:
function Entity.SetHealth( Number health )
让这样的函数接受-1
作为参数是不是很糟糕,在这种情况下,导致实体变得无敌?
我是否应该使用两个额外的功能:Entity.SetInvincible
和Entity.GetInvincible
?
请注意,这个具有无敌和健康的例子实际上只是由我组成。
答案 0 :(得分:1)
你可以做很多糟糕的事情,我在很多游戏引擎和UI框架中经常看到这种确切的方法用于各种任务(例如,在命令中重复一个动作,将重复设置为-1表示“永远重复”)。如果你把其他一切都做得恰到好处,那么批评这种设计选择只会是一种挑剔。
那就说,语义是不直观的(-1是无敌的?嗯?)所以最好有额外的功能。
答案 1 :(得分:1)
魔术数字通常是一个不好的迹象,但我不会说你应该禁止它们。换句话说,如果-1
是非法值,那么可以使用它,但我至少会为它创建一个常量,以便对该方法的调用看起来像这样:
someEntity.SetHealth(Health.Infinite)
或类似的,常数的命名取决于你。
但是,更好的方法(在我看来)是封装值,为其提供额外的数据,例如你可以在C#中创建这样的类型:
public struct Health
{
private readonly int _Value;
public int Value { get { return _Value; } }
public Health(int value)
{
if (value < 0 || value > SOME_ARBITRARY_MAX_NUMBER)
throw new ArgumentOutOfRangeException("value");
_Value = value;
}
public static Health Infinite
{
get
{
Health result = new Health(0);
result._Value = -1;
return result;
}
}
public bool IsInfinite
{
get
{
return _Value == -1;
}
}
}
然后,您还将添加必要的比较方法,运算符等,以便您可以执行此操作:
Health a = Health.Infinite;
Health b = 100; // automatic type coercion
if (b < a) // custom operator, knows that Infinite > *
...