我了解,在按合同/利斯科夫原则进行设计的前提下,前提是在调用代码(例如,呼叫者对此负责。另外,埃菲尔语言的作者表示,大多数人确实将另一种验证检查放到了被称为cade中,只是作为防御性编程的手段。
Some time ago I read a question with a code similar to this:
void X(int value)
{
if (value > 100)
{do something...}
}
一些评论者认为if语句不是先决条件,但我认为这不是正确的-如果合同规定V必须为100,则这是在验证先决条件,并且是否从该类型派生了一个类并进行了更改如果v> 200,则将加强先决条件,从而违反Liskov原理。还是不是这种情况?
答案 0 :(得分:0)
正如您所说,先决条件定义为在继续执行代码之前必须始终为真的条件。
这意味着任何在执行其他代码之前在函数开始时检查条件的内容都被视为前提条件。
示例:
//We will do something cool here
//With an integer input
int doSomethingCool(final int input)
{
//Wait, what if input is null or less than 100?
if(null == input || input < 100)
{
//Return a -1 to signify an issue
return -1;
}
//The cool bit of multiplying by 50. So cool.
final int results = input * 50;
//Return the results;
return results;
}
在此示例中,在执行其他任何操作之前,先检查函数input
。只要条件满足,其余代码就会执行。
错误的示例:
//We will do something cool here
//With an integer input
int doSomethingCool(final int input)
{
//Want to make sure input is not null and larger than 100
if(null != input && input > 100)
{
//The cool bit of multiplying by 50. So cool.
final int results = input * 50;
//Return the results;
return results;
}
//Return a -1 to signify an issue because the
//preconditions were not met for some reason
return -1;
}
在该示例中,前提条件是检查input
是否不是null
且大于100。这是一个糟糕的前提条件,因为它可能会引入if
和循环的不必要的嵌套
前提条件应该进行检查,并且仅在检查失败时才返回。前提条件不应该做任何工作。
根据Liskov替换原理,如果类型S
是类型T
的子类型,则类型T
可以替换为类型S
。如果类型S
覆盖doSomethingCool
并更改了前提条件,那么它就违反了,因为类型T
是基本定义并定义了必须满足的预期条件。
现在回答您
是的,简单条件仍然算作前提条件。只要它们位于使用该变量的所有其他代码的最前面,条件就是程序所需的条件。同样,如果函数在子类型中并覆盖父类,则它不应更改前提条件。
但是,不要包围在前提条件下运行所需的代码。那是不好的做法。如果value
需要大于100,请检查value < 100
并在if
检查中设置一个返回值。