前提条件是否可以表达(用于验证)为简单条件?
Can preconditions be expressed (for verification) as simple conditions?
我理解,在根据 contract/Liskov 原则进行设计的上下文中,前提条件是在调用代码之前应该为真,例如来电者对此负责。此外,Eiffel 语言的作者表示,大多数人确实会在调用的 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,那么这将额外验证先决条件,如果 class 是派生自这种类型并更改为 v > 200,这将加强前提条件,从而违反 Liskov 原则。或者不是这样?
如您所说,先决条件定义为在后续代码执行之前必须始终为真的条件。
这意味着在执行其他代码之前在函数开头检查条件的任何内容都被视为先决条件。
示例:
//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
嵌套和循环。
先决条件应该进行检查,并且只有在检查失败时才 return。前提条件下不应该做任何工作。
根据 Liskov 替换原则,如果类型 S
是类型 T
的子类型,则类型 T
可以替换为类型 S
。如果类型 S
覆盖 doSomethingCool
并更改前提条件,则它是违反的,因为类型 T
是基本定义并定义了必须满足的预期条件。
现在为您解答
是的,简单的条件仍然算作前提条件。只要它们位于使用该变量的所有其他代码的前面,条件就是程序所需要的。此外,如果函数在子类型中并且正在覆盖父类型 class,则它不应更改前提条件。
但是,不要将您需要 运行 的代码括在前提条件中。那是不好的做法。如果 value
需要大于 100,请检查 value < 100
并在 if
检查中设置一个 return。
我理解,在根据 contract/Liskov 原则进行设计的上下文中,前提条件是在调用代码之前应该为真,例如来电者对此负责。此外,Eiffel 语言的作者表示,大多数人确实会在调用的 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,那么这将额外验证先决条件,如果 class 是派生自这种类型并更改为 v > 200,这将加强前提条件,从而违反 Liskov 原则。或者不是这样?
如您所说,先决条件定义为在后续代码执行之前必须始终为真的条件。
这意味着在执行其他代码之前在函数开头检查条件的任何内容都被视为先决条件。
示例:
//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
嵌套和循环。
先决条件应该进行检查,并且只有在检查失败时才 return。前提条件下不应该做任何工作。
根据 Liskov 替换原则,如果类型 S
是类型 T
的子类型,则类型 T
可以替换为类型 S
。如果类型 S
覆盖 doSomethingCool
并更改前提条件,则它是违反的,因为类型 T
是基本定义并定义了必须满足的预期条件。
现在为您解答
是的,简单的条件仍然算作前提条件。只要它们位于使用该变量的所有其他代码的前面,条件就是程序所需要的。此外,如果函数在子类型中并且正在覆盖父类型 class,则它不应更改前提条件。
但是,不要将您需要 运行 的代码括在前提条件中。那是不好的做法。如果 value
需要大于 100,请检查 value < 100
并在 if
检查中设置一个 return。