Typically where are preconditions checked for methods?

  • Thread starter in the rye
  • Start date
In summary: I generally call methods in try catch blocks of event handlers where the data is at risk of being indeterminate. I code in C# using the Entity Framework. The Entity Framework has specialized exception objects that are thrown when a error occurs. Sometimes I write my own exception objects. I have found it is always a good idea to plan HOW data and errors are going to be handled at application design time, otherwise the code ends up quickly becoming difficult to maintain.
  • #1
in the rye
83
6
Hey all,

I'm currently taking data structures and algorithms.

We are running member functions that have preconditions (requirements for the function to work), and post-conditions (what the function guarantees will happen provided the preconditions are met). We are doing a "quick and dirty" way in that if the precondition fails, we quit the program entirely with an error message.

My question is are preconditions normally checked AFTER the method is called? The book doesn't specify.

Thanks.
 
Technology news on Phys.org
  • #2
Variables that are passed into a method are typically checked at the beginning of the method.
 
  • #3
in the rye said:
My question is are preconditions normally checked AFTER the method is called? The book doesn't specify.
It wouldn't be good to call a method, and then check the parameter values after the method returns to the caller. For example, if the method needs to perform a division of two parameters, you would need to check that the divisor isn't zero before the division occurs, not after the method returns.
 
  • #4
Usually, checking the parameters is the very first thing that a method does. If a method is documented to only accept a particular input, then it needs to check. How you handle that error is up to you, here are several common ways to do it.

Always check: Check the parameters every single time the method is called. This is useful for functions that talk to dynamic entities: servers, users... Because it's not only possible, but probable that you'll get a bad input at some point, you need to document exactly what the valid parameters are and what will happen otherwise.

Code:
float divide(float one, float two){
    if (one != one) throw std::out_of_range;
    if (two != two) throw std::out_of_range;
    if (two == 0.0f) throw std::out_of_range;
    return one / two;
}

You can also do a debugging only check. This is more likely to be used for internal functions that don't have any user input. The case here is that if any incorrect input is ever detected, it's a programming error rather than a user input error. For this, you use checks that disappear when you put it into production mode.

Code:
static std::string deepCopy(const std::string & str){
    assert(str.data() != null);
    return std::string(str.data(), str.length());
}
 
  • #6
jim mcnamara said:
You cannot generally compare floats like this, right?:


https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html is the old version. There are newer takes on this, like Fujitsu Sparc 10, and boost has an fp library, I think, that uses constructs like nextafter to handle this gracefully.
http://www.boost.org/doc/libs/1_64_0/libs/math/doc/html/utils.html
Right, you can only compare floats like that when you are interesting in a very precise number that you know is representable. In this case, only exactly zero will cause a problem, so that’s what we compare against.
 
  • #7
There are many approaches to handling requirements with methods. In general a method performs a business rule or requirement. Some people like to test the variables before passing them into the method others will do the validation in method. These decisions are (should) be decided during the high level design of the program. My coding style is to minimize the use of if then else statements and take advantage of polymorphism and other OOP mechanisms. I generally call methods in try catch blocks of event handlers where the data is at risk of being indeterminate. I code in C# using the Entity Framework. The Entity Framework has specialized exception objects that are thrown when a error occurs. Sometimes I write my own exception objects. I have found it is always a good idea to plan HOW data and errors are going to be handled at application design time, otherwise the code ends up quickly becoming difficult to maintain. Anyone can go to a computer and start coding but it is important to plan and design the system before writing code that way it can be maintained and will be readable by someone else instead of being rewritten
 
  • #8
There are often input conditions that are hard to check at the beginning of the method, but become more apparent as the method runs. It is wise to check as soon as it can be done without introducing significantly more code that has to be verified and debugged. Regardless of where the problem is detected, the method should be able to return an error code without aborting. The calling program should be able to detect an error condition and take appropriate action regardless of where the method detects a problem. That usually requires a returned error flag or an illegal returned value.
 
Last edited:
  • #9
There is a differentiation between a business rule and the stability of data presented to the business rule. Please clarify your situation that is causing difficulty in checking input variables in the method. I have not run into that.

My variables are either database defined or ones that I create by creating classes. These variables are objects, and there is not much to test for if they are in a valid state or not.

Sure less code is better, but if a bunch of if then statements are being created to try to test for every possible error, there is a requirements definition problem or the design of how errors are to handed through the program. I’m personally not a big fan of returning a status code from a business rule in C# because it forces me to do an If then else on that method or assign the return status to variable and test it with a if then else construct. Everyone is forced to do this in database stored procedures because stored procedures are not object oriented. I have seen many database programmers bring the coding skills to C# and start writing C# programs the way they were forced to write database procedures and their code is horrible to maintain because they don’t understand OOP.

Using properly implemented try catch blocks allows the program to consume my own user defined errors as well as .net runtime errors more compactly, this type of structure is much easier to debug because I am not constantly branching through if then statements

You did not say what environment you are working in but I have written code for hardware I have designed and business applications like I was referring to earlier

Sure it is important to know up front how the inputs of the software may vary. In my projects, which are business application software, it is mostly null references to look out for and that’s it. The .net framework/entity framework and the database enforce variables to conform to their allowable types. If I was writing software for an engineering project where inputs from a hardware device could be completely unknown. A new embedded system for example, that might be a problem. But again those decisions about the state of inputs are usually handled at the hardware design stage so that a predictable range input can be achieved for the software. In summary, i have not had those kinds of problems you are referring to, but goo upfront design is very important before writing a line of code.
 
  • #10
newjerseyrunner said:
Code:
static std::string deepCopy(const std::string & str){
    assert(str.data() != null);
    return std::string(str.data(), str.length());
}
Code:
std::string deepCopy(const std::string & str){
    return str;
}
Is a deep copy already.
 
Last edited:
  • #11
Jarvis323 said:
Code:
std::string deepCopy(const std::string & str){
    return str;
}
Is a deep copy already.
Not true.

It is entirely possible (and within the bounds of the C++ standard) to make a std::string copy constructor that simply does a reference count. Not sure if any of them do it this way, but there is no reason that they can't. (I think the single threaded version of the template library of VC++ uses copy-on-write std::string objects.) In which case, your code would produce a shallow copy where the data() would point to the exact same char pointer.
 
  • #12
newjerseyrunner said:
Not true.

It is entirely possible (and within the bounds of the C++ standard) to make a std::string copy constructor that simply does a reference count. Not sure if any of them do it this way, but there is no reason that they can't. (I think the single threaded version of the template library of VC++ uses copy-on-write std::string objects.) In which case, your code would produce a shallow copy where the data() would point to the exact same char pointer.

Interesting, I would not have expected that. It appears that copy-on-write strings are now illegal since c++11, but compilers don’t always conform anyways I guess.
 
  • Like
Likes newjerseyrunner
  • #13
Mark44 said:
It wouldn't be good to call a method, and then check the parameter values after the method returns to the caller. For example, if the method needs to perform a division of two parameters, you would need to check that the divisor isn't zero before the division occurs, not after the method returns.
I guess some people didn't care and that's why std::isinf was created. http://en.cppreference.com/w/cpp/numeric/math/isinf
 
  • #14
ChrisVer said:
I guess some people didn't care and that's why std::isinf was created. http://en.cppreference.com/w/cpp/numeric/math/isinf
It can be hard to anticipate what will happen inside a method. Most methods are not so simple as a simple division. Overflows happen.
 

1. Where are preconditions typically checked for methods?

Preconditions are typically checked at the beginning of a method, before any other code is executed. This ensures that all necessary conditions are met before the method proceeds.

2. Why is it important to check for preconditions in methods?

Checking for preconditions helps to ensure that the method will run correctly and safely. It can also help prevent errors or unexpected behavior by ensuring that all necessary conditions are met before the method is executed.

3. What happens if preconditions are not checked in a method?

If preconditions are not checked in a method, it can lead to errors or unexpected behavior. The method may try to execute without all necessary conditions being met, which can result in incorrect output or even cause the program to crash.

4. Are preconditions only checked for public methods?

No, preconditions can and should be checked for all methods, not just public ones. Private methods may also have preconditions that need to be met in order for the method to run correctly.

5. Can preconditions be checked in the middle of a method?

Technically, preconditions can be checked at any point in a method. However, it is best practice to check them at the beginning of the method to ensure that all necessary conditions are met before any other code is executed.

Similar threads

  • Linear and Abstract Algebra
Replies
1
Views
1K
  • Programming and Computer Science
Replies
29
Views
3K
  • Programming and Computer Science
Replies
6
Views
2K
  • Set Theory, Logic, Probability, Statistics
Replies
7
Views
464
  • Programming and Computer Science
Replies
4
Views
5K
  • Engineering and Comp Sci Homework Help
Replies
2
Views
5K
  • Programming and Computer Science
Replies
2
Views
1K
Replies
2
Views
2K
  • Programming and Computer Science
Replies
16
Views
3K
Back
Top