I understand that a precondition, in context of Desing by contract/Liskov principle, is something that should be true before the code is called, e.g. the caller is responsible for that. Also, the author of the Eiffel language stated that most people do put another verification check into the called cade, simply as means of defensive programming.
Some time ago I read a question with a code similar to this:
void X(int value)
{
if (value > 100)
{do something...}
}
Some commenters argued that the if statement is not a precondition but I do not think that is right - if the contract states V must be 100, then this is verifying the precondition additionally and if a class is derived from this type and changes to v > 200, it would be strenghtening the precondition and thus violating the Liskov principle. Or isn't that the case?
As you said, a precondition is defined as a condition that must always be true before the proceeding code executes.
This means that anything that checks for a condition at the beginning of a function before other code is executed, then it is considered a precondition.
Example:
//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;
}
In the example, the function, input
is checked before anything else is executed. So long as the conditions are met, then the rest of the code will execute.
Bad Example:
//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;
}
In the example, the precondition is to check that input
is not null
and larger than 100. This is a bad precondition because it could introduce unnecessary nesting of if
s and loops.
Preconditions should do checks and only return when the checks fail. There should be no work done in a precondition.
In keeping with the Liskov Substitution Principle, if type S
is a subtype of type T
, then type T
can be replaced with type S
. If type S
overrides doSomethingCool
and changes the precondition, then it is in violation, because type T
is the base definition and defines the intended conditions that must be met.
Now for your answer
Yes, simple conditions still count as preconditions. As long as they are at the front of all other code that uses the variable, the condition is as what is needed by the program. Also, if the function is in a subtype and is overriding the parent class, then it should not change the precondition.
However, do not surround the code that you need to run within the precondition. That is bad practice. If value
needs to be larger than 100, check value < 100
and set a return in the if
check.