Is an exception a valid postcondition? - design-by-contract

Consider the following interface:
public interface AISPI
{
public Path getPath(Entity entity, Entity target, World world) throws NoPathException;
}
Granted that entity, target, and world are all valid input. But the algorithm used to find a path (it is Astar in this case) fails to find a path, due to eg. the position of target being surrounded by concrete walls.
Is it valid to state that the postcondition is either a Path from entity to target (start to goal) or a NoPathException (given that a path was not found)?
- Or should the precondition state that there must be a valid path from start to goal?
This is not homework, but a question for improving our semester project report. I am not looking to learn about any frameworks, this is purely a question of standards and formalities in regards to design by contract. Thanks for any clarification on the matter.

It depends on the definition of the term postcondition. In general, a precondition is a relation on input state and input values at routine entry, and a postcondition is a relation on input state, input values and output state and output values at routine exit.
Because a routine can exit either normally or exceptionally, it is possible to define a postcondition for normal termination and a postcondition for abnormal termination. Clearly both involve input values, input state and output state. The key difference is in output values. In the first case this is a value specified in the routine signature, in the second - it depends on the language. In your example it might be NoPathException, but what if there is a memory allocation error, stack overflow or other exception or signal that is not specified in the signature? It may indeed seem to be possible to have a precondition that guarantees that there is always a valid result that does not involve exceptions. But this is not the case, e.g. when there is communication to external world, concurrency, etc. Also if a precondition is too costly to compute, it does not look nice to do the same work twice - on the client side to make sure a call is applicable and on the supplier's side to do essentially the same computation to get the result.
According to the Design by Contract philosophy a postcondition is what the client can safely rely on after calling a routine. Coming back to the exceptional case, from the practical point of view it makes sense to make the abnormal postcondition strong enough so that a program can continue execution, but weak enough so that the cases that are not or cannot be specified in the signature, but are possible in practice, are allowed.
So, unless the language does really guarantee all possible exceptional cases and nothing else, the most important part is output state that should not make the associated objects unusable. And this could either be expressed in an explicit or implicit postcondition or as a class invariant.
As to the specific example with getPath, the situation when a path does not exist is normal, i.e. it may happen, is expected. Some guidelines recommend to use normal values to indicate normal termination cases. Here it would be value null. Using null may lead to other issues on the caller's side, such as NullPointerException if result is not checked for null-ness, but in some languages that guarantee absence of such exceptions (e.g., void-safety in Eiffel) this would be the preferred way to indicate absence of a path (the return type would be detachable PATH in that case).

Related

Why is my %h is List = 1,2; a valid assignment?

While finalizing my upcoming Raku Advent Calendar post on sigils, I decided to double-check my understanding of the type constraints that sigils create. The docs describe sigil type constraints with the table
below:
Based on this table (and my general understanding of how sigils and containers work), I strongly expected this code
my %percent-sigil is List = 1,2;
my #at-sigil is Map = :k<v>;
to throw an error.
Specifically, I expected that is List would attempt to bind the %-sigiled variable to a List, and that this would throw an X::TypeCheck::Binding error – the same error that my %h := 1,2 throws.
But it didn't error. The first line created a List that seemed perfectly ordinary in every way, other than the sigil on its variable. And the second created a seemingly normal Map. Neither of them secretly had Scalar intermediaries, at least as far as I could tell with VAR and similar introspection.
I took a very quick look at the World.nqp source code, and it seems at least plausible that discarding the % type constraint with is List is intended behavior.
So, is this behavior correct/intended? If so, why? And how does that fit in with the type constraints and other guarantees that sigils typically provide?
(I have to admit, seeing an %-sigiled variable that doesn't support Associative indexing kind of shocked me…)
I think this is a grey area, somewhere between DIHWIDT (Docter, It Hurts When I Do This) and an oversight in implementation.
Thing is, you can create your own class and use that in the is trait. Basically, that overrides the type with which the object will be created from the default Hash (for %) and Array (for # sigils). As long as you provide the interface methods, it (currently) works. For example:
class Foo {
method AT-KEY($) { 42 }
}
my %h is Foo;
say %h<a>; # 42
However, if you want to pass such an object as an argument to a sub with a % sigil in the signature, it will fail because the class did not consume the Associatve role:
sub bar(%) { 666 }
say bar(%h);
===SORRY!=== Error while compiling -e
Calling bar(A) will never work with declared signature (%)
I'm not sure why the test for Associative (for the % sigil) and Positional (for #) is not enforced at compile time with the is trait. I would assume it was an oversight, maybe something to be fixed in 6.e.
Quoting the Parameters and arguments section of the S06 specification/speculation document about the related issue of binding arguments to routine parameters:
Array and hash parameters are simply bound "as is". (Conjectural: future versions ... may do static analysis and forbid assignments to array and hash parameters that can be caught by it. This will, however, only happen with the appropriate use declaration to opt in to that language version.)
Sure enough the Rakudo compiler implemented some rudimentary static analysis (in its AOT compilation optimization pass) that normally (but see footnote 3 in this SO answer) insists on binding # routine parameters to values that do the Positional role and % ones to Associatives.
I think this was the case from the first official Raku supporting release of Rakudo, in 2016, but regardless, I'm pretty sure the "appropriate use declaration" is any language version declaration, including none. If your/our druthers are static typing for the win for # and % sigils, and I think they are, then that's presumably very appropriate!
Another source is the IRC logs. A quick search quickly got me nothing.
Hmm. Let's check the blame for the above verbiage so I can find when it was last updated and maybe spot contemporaneous IRC discussion. Oooh.
That is an extraordinary read.
"oversight" isn't the right word.
I don't have time tonight to search the IRC logs to see what led up to that commit, but I daresay it's interesting. The previous text was talking about a PL design I really liked the sound of in terms of immutability, such that code could become increasingly immutable by simply swapping out one kind of scalar container for another. Very nice! But reality is important, and Jonathan switched the verbiage to the implementation reality. The switch toward static typing certainty is welcome, but has it seriously harmed the performance and immutability options? I don't know. Time for me to go to sleep and head off for seasonal family visits. Happy holidays...

Questions about the Boundary Value Check

I'm doing my JUnit homework and need some explanations here.
Here's the quotation from my homework description:
One of the issues with boundary conditions is that the system needs to behave well even if the boundary is approached multiple times. This should be obvious, but it doesn't always happen in practice.
Remember that we can characterize an object as state and behavior. Typically, the state is not directly accessible, but instead, is accessed indirectly by means of the behavior. That is, the behavior reflects the state of the object.
Now, if we think about boundaries in math, it might not be too surprising to imagine the the value at some boundary will be different if we approach that boundary in different ways. So, if the value can be likened to the state, the state at the boundary may vary depending on how we got there. This would mean that the behavior could be different.
To make objects that behave consistently, we would have to insure that the internal state at those boundaries is consistent. So, test cases should check this assumption. To receive challenge points for this homework assignment enhance your test cases so that potential problems around the boundaries may be discovered.
Clearly mark the Challenge test cases with the string "### challenge ###" in the comments. Include in those comments what boundary is being tested, and how you're guessing that the state of the object may be different depending on how the boundary is being approached.
I don't understand this especially the highlighted part. What does he mean by "object behave consistently" and the "potential probelms"?
Also, how is this different than general boundary check that will just throws the exception and i expected in the JUnit?
Thank you!
Without knowing the details of the homework, an answer could only be somewhat generic, but I'll try.
Boundary checking is not just exception checking, its about seeing which paths in your code are execution on what condition. If you have control statements, loops, if-else, switch, etc you have to verify, on what conditions (of your internal state) those statements are processed in what way.
To me, boundary testing is that you change certain values of an instance field in a way that would cause the behavior to run through different branches of your code.
for example, you have this behavior:
if(someInstanceValue > 5) {
return "great";
} else {
return "poor";
}
Now you could test with data for someInstanceValue that define the boundary
4 : "poor"
5 : "great"
If you have multiple fields in your class, all of them define the state but only some of them may affect a certain path in your code. As the test is a specification of your class under test, written in code, you should specify which fields are relevant to a function, and which are not (by leaving them out).
So you should set up your instance-under-test accordingly (calling all setters) or if you require more complex objects, you could use frameworks like Mockito to specify the state (in a when().thenReturn() syntax).
If you want to verify if you covered all your boundaries, you could run a mutation test against your suite using a mutation testing tool like PIT. It will flip the switches in your code (i.e. replacing a < with a >=) to check whether your test will fail. Often, it's a good source of inspiration for improving the way you test.
Neverthelss, some parts of the homework assignment sound a bit confusing to me. You may approach a boundary from two sides, ok, but there is no such thing as a state that represents THE boundary, you're either on one or the other side of the boundary. If the way, how you approached one side of a boundary matters, and the object behaves differently depending on that "history" of how you reached that state, the history becomes part of the state. In other words: different history = different state.
Keep in mind: every instance field is part of the state. Every possible combination of values of your instance fields defines a single state. Every transition from one combination to another is a state transition triggered by calling a behavior. No think of your test describing this statemachine, be listing the triple of {currentState,input} -> nextState (with input being method invocation). Wich is basically the Given-When-Then structure good tests should have.

Why use an exception instead of if...else

For example, in the case of "The array index out of bound" exception, why don't we check the array length in advance:
if(array.length < countNum)
{
//logic
}
else
{
//replace using exception
}
My question is, why choose to use an exception? and when to use an exception, instead of if-else
Thanks.
It depends on acceptable practices for a given language.
In Java, the convention is to always check conditions whenever possible and not to use exceptions for flow control. But, for example, in Python not only using exception in this manner is acceptable, but it is also a preferred practice.
They are used to inform the code that calls your code an exceptional condition occurred. Exceptions are more expensive than well formed if/else logic so you use them in exceptional circumstances such as reaching a condition in your code you cannot handle locally, or to support giving the caller of your code the choice of how to handle the error condition.
Usually if you find yourself throwing and catching exceptions in your own function or method, you can probably find a more efficient way of doing it.
There are many answers to that question. As a single example, from Java, when you are using multiple threads, sometimes you need to interrupt a thread, and the thread will see this when an InterruptedException is thrown.
Other times, you will be using an API that throws certain exceptions. You won't be able to avoid it. If the API throws, for example, an IOException, then you can catch it, or let it bubble up.
Here's an example where it would actually be better to use an exception instead of a conditional.
Say you had a list of 10,000 strings. Now, you only want those items which are integers. Now, you know that a very small number of them won't be integers (in string form). So should you check to see if every string is an integer before trying to convert them? Or should you just try to convert them and throw and catch an exception if you get one that isn't an integer? The second way is more efficient, but if they were mostly non-integers then it would be more efficient to use an if-statement.
Most of the time, however, you should not use exceptions if you can replace them with a conditional.
As someone has already said, 'Exceptions' in programming languages are for exceptional cases and not to set logical flow of your program. For example, in the case of given code snippet of your question, you have to see what the enclosing method's or function's intention is. Is checking array.length < countNum part of the business logic or not. If yes, then putting a pair of if/else there is the way to go. If that condition is not part of the business logic and the enclosing method's intention is something else, then write code for that something else and throw exception instead of going the if/else way. For example you develop an application for a school and in your application you have a method GetClassTopperGrades which is responsible for the business logic part which requires to return the highest marks of the student in a certain class. the method/function definition would be something like this:
int GetClassTopperGrades(string classID)
In this case the method's intention is to return the grades, for a valid class, which will always be a positive integer, according to the business logic of the application. Now if someone calls your method and passes a garbage string or null, what should it do? If should throw an exception e.g. ArgumentException or 'ArgumentNullException' because this was an exceptional case in this particular context. The method assumed that always a valid class ID will be passed and NULL or empty string is NOT a valid class ID (a deviation from the business logic).
Apart from that, in some conditions there is no prior knowledge about the outcome of a given code and no defined way to prevent an exceptional situation. For example, querying some remote database, if the network goes down, you don't have any other option there apart from throwing an exception. Would you check network connectivity before issuing every SQL query to the remote database?
There is strong and indisputable reason why to use exceptions - no matter of language. I strongly believe that decision about if to use exceptions or not have nothing to do with particular language used.
Using exceptions is universal method to notify other part of code that something wrong happened in kind of loosely coupled way. Let imagine that if you would like to handle some exceptional condition by using if.. nad else.. you need to insert into different part of your code some arbitrary variables and other stuff which probably would easily led to have spaghetti code soon after.
Let next imagine that you are using any external library/package and it's author decided to put in his/her code other arbitrary way to handle wrong states - it would force you to adjust to its way of dealing with it - for example you would need to check if particular methods returns true or false or whatever. Using exceptions makes handling errors much more easy - you just assume that if something goes wrong - the other code will throw exception, so you just wrap the code in try block and handle possible exception on your own way.

assert() vs enforce(): Which to choose?

I'm having a hard time choosing whether I should "enforce" a condition or "assert" a condition in D. (This is language-neutral, though.)
Theoretically, I know that you use assertions to find bugs, and you enforce other conditions in order to check for atypical conditions. E.g. you might say assert(count >= 0) for an argument to your method, because that indicates that there's a bug with the caller, and that you would say enforce(isNetworkConnected), because that's not a bug, it's just something that you're assuming that could very well not be true in a legitimate situation beyond your control.
Furthermore, assertions can be removed from code as an optimization, with no side effects, but enforcements cannot be removed because they must always execute their condition code. Hence if I'm implementing a lazy-filled container that fills itself on the first access to any of its methods, I say enforce(!empty()) instead of assert(!empty()), because the check for empty() must always occur, since it lazily executes code inside.
So I think I know that they're supposed to mean. But theory is easier than practice, and I'm having a hard time actually applying the concepts.
Consider the following:
I'm making a range (similar to an iterator) that iterates over two other ranges, and adds the results. (For functional programmers: I'm aware that I can use map!("a + b") instead, but I'm ignoring that for now, since it doesn't illustrate the question.) So I have code that looks like this in pseudocode:
void add(Range range1, Range range2)
{
Range result;
while (!range1.empty)
{
assert(!range2.empty); //Should this be an assertion or enforcement?
result += range1.front + range2.front;
range1.popFront();
range2.popFront();
}
}
Should that be an assertion or an enforcement? (Is it the caller's fault that the ranges don't empty at the same time? It might not have control of where the range came from -- it could've come from a user -- but then again, it still looks like a bug, doesn't it?)
Or here's another pseudocode example:
uint getFileSize(string path)
{
HANDLE hFile = CreateFile(path, ...);
assert(hFile != INVALID_HANDLE_VALUE); //Assertion or enforcement?
return GetFileSize(hFile); //and close the handle, obviously
}
...
Should this be an assertion or an enforcement? The path might come from a user -- so it might not be a bug -- but it's still a precondition of this method that the path should be valid. Do I assert or enforce?
Thanks!
I'm not sure it is entirely language-neutral. No language that I use has enforce(), and if I encountered one that did then I would want to use assert and enforce in the ways they were intended, which might be idiomatic to that language.
For instance assert in C or C++ stops the program when it fails, it doesn't throw an exception, so its usage may not be the same as what you're talking about. You don't use assert in C++ unless you think that either the caller has already made an error so grave that they can't be relied on to clean up (e.g. passing in a negative count), or else some other code elsewhere has made an error so grave that the program should be considered to be in an undefined state (e.g. your data structure appears corrupt). C++ does distinguish between runtime errors and logic errors, though, which may roughly correspond but I think are mostly about avoidable vs. unavoidable errors.
In the case of add you'd use a logic error if the author's intent is that a program which provides mismatched lists has bugs and needs fixing, or a runtime exception if it's just one of those things that might happen. For instance if your function were to handle arbitrary generators, that don't necessarily have a means of reporting their length short of destructively evaluating the whole sequence, you'd be more likely consider it an unavoidable error condition.
Calling it a logic error implies that it's the caller's responsibility to check the length before calling add, if they can't ensure it by the exercise of pure reason. So they would not be passing in a list from a user without explicitly checking the length first, and in all honesty should count themselves lucky they even got an exception rather than undefined behavior.
Calling it a runtime error expresses that it's "reasonable" (if abnormal) to pass in lists of different lengths, with the exception indicating that it happened on this occasion. Hence I think an enforcement rather than an assertion.
In the case of filesize: for the existence of a file, you should if possible treat that as a potentially recoverable failure (enforcement), not a bug (assertion). The reason is simply that there is no way for the caller to be certain that a file exists - there's always someone with more privileges who can come along and remove it, or unmount the entire fielsystem, in between a check for existence and a call to filesize. It's therefore not necessarily a logical flaw in the calling code when it doesn't exist (although the end-user might have shot themselves in the foot). Because of that fact it's likely there will be callers who can treat it as just one of those things that happens, an unavoidable error condition. Creating a file handle could also fail for out-of-memory, which is another unavoidable error on most systems, although not necessarily a recoverable one if for example over-committing is enabled.
Another example to consider is operator[] vs. at() for C++'s vector. at() throws out_of_range, a logic error, not because it's inconceivable that a caller might want to recover, or because you have to be some kind of numbskull to make the mistake of accessing an array out of range using at(), but because the error is entirely avoidable if the caller wants it to be - you can always check the size() before access if you have no other way of knowing whether your index is good or not. And so operator[] doesn't guarantee any checks at all, and in the name of efficiency an out of range access has undefined behavior.
assert should be considered a "run-time checked comment" indicating an assumption that the programmer makes at that moment. The assert is part of the function implementation. A failed assert should always be considered a bug at the point where the wrong assumption is made, so at the code location of the assert. To fix the bug, use a proper means to avoid the situation.
The proper means to avoid bad function inputs are contracts, so the example function should have a input contract that checks that range2 is at least as long as range1. The assertion inside the implementation could then still remain in place. Especially in longer more complex implementations, such an assert may inprove understandability.
An enforce is a lazy approach to throwing runtime exceptions. It is nice for quick-and-dirty code because it is better to have a check in there rather then silently ignoring the possibility of a bad condition. For production code, it should be replaced by a proper mechanism that throws a more meaningful exception.
I believe you have partly answered your question yourself. Assertions are bound to break the flow. If your assertion is wrong, you will not agree to continue with anything. If you enforce something you are making a decision to allow something to happen based on the situation. If you find that the conditions are not met, you can enforce that the entry to a particular section is denied.

Do you use tense when naming methods of boolean return type?

So, when you are writing a boolean method, do you use tense, like "has" or "was", in your return method naming, or do you solely use "is"?
The following is a Java method I recently wrote, very simply ..
boolean recovered = false;
public boolean wasRecovered()
{
return recovered;
}
In this case, recovered is a state that may or may not have already occurred at this point in the code, so grammatically "was" makes sense. But does it make the same sense in code, where the "is" naming convention is usually standard?
I prefer to use IsFoo(), regardless of tense, simply because it's a well-understood convention that non-native speakers will still generally understand. Non-native speakers of English are a regular consideration in today's global dev't industry.
I use the tense which is appropriate the meaning of the value. To do otherwise essentially creates code which reads one way and behaves another. Lets look at a real world example in the .Net Framework: Thread.IsAlive
This property is presented with the present tense. This has the implication the value refers to the present and makes code like the following read very well
if (thread.IsAlive ) {
// Code that depends on the thread being alive
...
The problem here is that the property does not represent the present state of the object it represents a past state. Once the value is calculated to be true, the thread in question can immediately exit and invalidate the value. Hence the value can only safely be used to identify the past state of the thread and a past tense property is more appropriate. Lets now revisit the sample which reads a bit differently
if ( thread.WasAlive ) {
// Code that depends on the thread being alive
...
They behave the same but one reads very poorly because it in fact represents poor code.
Here's a list of some other offenders
File.Exists
Directory.Exists
DriveInfo.IsReady
WeakReference.IsAlive
The isXxx prefix is a widespread naming convention, so it's generally the best choice.
For order-sensitive operations, wasXxx is appropriate. For example, in JDBC, retrieving the value of a database column might return zero when the field is actually NULL (unset); in this case, a follow-up call to wasNull determines which it is after the actual retrieval was performed.
For retrieving attribute settings, hasXxx may be more appropriate. It's a grammar preference, as in "the object's flag is set" versus "the object has an attribute".
Then there are capability tests canXxx. For example, calling canWrite to see if a file is writable. But names like these can probably be renamed to the isXxx form, such as isWritable.
I tend to, yes. For example in error checking:
$errors = false;
public function hasErrors()
{
return $this->errors;
}
I am not sure that you are thinking about this correctly. The reason one would use the Recovered property is because that is the state the object is in now, not because that was the state the object used to be in. There may have been some process in the past (The Recovery) that has now completed, but the fact that we are accessing this property now means that there is something about that completed process that altered current state, and that current state is important. To me "Recovered" captures the nature of that state. For this example (and most similar situations) I would use IsRecovered to name the predicate that indicates this condition. (This also matches normal English: "This is a recovered document.")
It is extremely rare that I would use anything other than present tense to name a predicate (IsDirty, HasCoupon) or boolean function (IsPrime(x)) in a program.
An exception would be to indicate state that has since been changed that might need to be reinstated (DocumentWindow.WasMaximizedAtLastExit).
I would usually use an infinitive for future tense (ToBeCopied rather than WillBeCopied), since the best laid plans of software are sometimes altered (or cancelled).
It depends on whether or not you care about the past or future state of the property in question.
To try to simplify the semantics, realize that there are a few scenarios that make the IsXXX form debatable and some very common scenarios where the IsXXX form is the only useful one.
Below is the 'truth table' for Thread.IsAlive() based on possible states of the thread over time. Forget about why a thread might flip flop states, we need to focus on the language used.
Scenarios of possible thread states over time:
Past Present Future
===== ======= =======
1. alive alive alive
2. alive alive dead
3. alive dead dead
4. dead dead dead
5. dead dead alive
6. dead alive alive
7. dead alive dead
8. alive dead alive
Note: I talk about the Future state below for consistency. Knowing whether a thread will die is very likely unknowable as a subset of The Halting Problem)
When we interrogate an object by calling a method, there is a common assumption "Is this thread alive, at the time I asked? For these cases, the answer in the "Present" column is all we care about and using the IsXXX form works fine.
Scenarios #1(always alive) and #4(always dead) are the simplest and most common. The answer to IsAlive() will not change between calls. The battle over language that comes up is due to the other 6 cases where the result of calling IsAlive() depends on when it is called.
Scenarios #2(will die) and #3(has died) transitions from alive to dead.
Scenarios #5(will start) and #6(has started) transitions from dead to alive.
For these four (2, 3, 5, 6) the answer to IsAlive() is not constant. The question becomes, do I care about the Present state, IsAlive(), or am I interested in the Past/Future state, WasAlive() and WillBeAlive()? Unless you can predict the future, the WillBeAlive() call becomes meaningless for all but the most specific designs.
When dealing with a thread pool, we might need to restart threads that are in the 'dead' state to service connect requests and it doesn't matter whether they were ever alive, just that they are currently dead. In this case we might actually want to use WasDead(). Of course we should try to guarantee we don't restart a thread that was just restarted but that is a design problem, not a semantic one. Assuming that no one else can restart the thread, it doesn't matter much whether we use IsAlive() == false or WasDead() == true.
Now for the last two scenarios. Scenario #7(was dead, is alive, will be dead) is practically the same as #6. Do you know when in the future it will die? In 10 seconds, 10 minutes, 10 hours? Are you going to wait before deciding what to do. No, you only care about the current (Present) state. We're talking about naming here, not multi-threaded design.
Scenario #8(was alive, is dead, will be alive), is practically the same as #3. If you are reusing threads, then they can cycle through the alive/dead states several times. Worrying about the difference between #3 and #8 goes back to the Halting Problem and so can be disregarded.
IsAlive() should work for all cases. IsAlive() == false works (for #5 and #6) instead of adding WasAlive().
I don't mind wasRecovered that much. Recovery is a past event that may or may not have happened - this tells you whether it did or not. But if you're using it because of some consequence of recovery, I'd prefer isCached, isValid, or some other description of what those consequences actually are. Just because you've recovered something doesn't inherently mean you haven't lost it again since.
Always beware that in English, the use of a past participle as an adjective is ambiguous between transitive and intransitive verbs (and perhaps between active and passive voice). isRecovered might mean that the object has been recovered by something else, or it might mean that the object has recovered. If your object represents a patient at a hospital, does "isRecovered" mean that the patient is fit and well, or that someone has fetched the patient back from the X-ray department? wasRecovered might therefore be better for the latter.
The conceit for method naming is that you are retrieving information about the object in question. For it to be named in the past tense, it would have to be information about a previous state of the object, rather than its current state.
The only reason I could ever think of for using past tense is if I was checking a cached result of something that previously occurred but is no longer the case. For a contrived example, perhaps retriveing the previous value after something like a swap() call. It could be useful in operations that are atomic by design. Not real likely in the wild though.
Since your question is specific to Java, the method name should start with "is" if your class is a JavaBean and the method is an accessor method for a property.
http://download.oracle.com/javase/tutorial/javabeans/properties/properties.html