Class Invariants are logical conditions to ensure the correct working of a class

Yüklə 116 Kb.
ölçüsü116 Kb.

Class Invariants

  • Class invariants are logical conditions to ensure the correct working of a class.

    • Class invariants must hold true when an object is created, and they must be preserved under all operations of the class
  • Interface invariants are of interest to the class user, because they give a behavioral guarantee for any object of the class

Class Invariants

  • They express the fundamental integrity constrains on a class

  • They are independent from the individual routines of the class

  • Characterize the class long-term semantics

  • Class Invariants help in

    • Maintenance
    • Quality assurance
    • Configuration Management
    • Regression testing

Invariance Example

  • class Stack

  • {

  • public:

  • void push(double);

  • double pop();

  • bool is_empty();

  • bool is_full();

  • private:

  • // …

  • };

Invariance Example

  • We can formulate several interface invariants

  • After an element is pushed onto a stack, the stack is no longer empty:

Invariance Example

Invariance Example

  • One can give a complete algebraic description of a stack in this fashion. Other data types such as queue can be characterized in a similar fashion.

  • Implementation invariant makes an assertion about one particular implementation. Example stack with the following private section:

    • Private:
      • Int _sptr;
      • Array _data;

Implementation Invariant Example

  • We may wish to assert that the stack pointer is always within a certain range:


  • A precondition is a statement placed before the segment that must be true prior to entering the segment in order for it to work correctly

  • Example: preconditions for calling the

  • draw(Rectangle * r)

    • r != null
    • R bounds to Rectangle
  • Example: preconditions for calling the

    • setDate(int day, int month, int year)
    • Operation in the Date class
    • 1 <= day <=31
    • 1<=month<12

Pre-Conditions and Post-Conditions

  • We say that

  • is a precondition of the push operation.

  • Conversely, after pushing an element on the stack, we know that

  • must necessarily hold.

  • An operation is not responsible for doing anything sensible if its precondition fails to hold. Conversely, an operation will guarantee its post-condition whenever it is invoked when the precondition is true.

Testing for invariants and conditions

  • Someone has to verify that pre-condition or invariant is valid before actually invoking method or procedure.

    • Can we trust unknowledgeable class users who do not know anything about class implementation ? No, class users could be malicious.
  • We should perform checks against null pointers or range errors.

    • How much checking is enough?
    • Answer: Depends …

Testing for invariants and conditions

  • What do we do when test for invariant fails?

    • Don’t do anything
    • Don’t do anything, and display warning
    • Throw an exception and handle it
    • Abort the program
    • Crash OS ???
    • Depending on the nature of invariant, different actions should be taken
  • Sometimes we can put debugging code to help us identify the places where invariance does not hold true. Then we can investigate the reason.

Using the assert facility in C++

  • The assert macro is defined in the assert.h header. If the condition:

  • assert(condition should be true)

  • fails, the program will exit with an error message containing the text of the condition, the name of the source file and the line number in the file

  • Example:

  • assert(den != 0);

  • int x = num / den;

Using assert facility in C++

  • There are already defined macros to facilitate post/pre conditions test


    • Void Stack :: push(double x) {
    • ASSERT_PRECOND(!isFull());
    • // …
    • }

    • Void getName(int pos) {
    • String name;
    • //..
    • ASSERT_POSTCOND(isValidName(name));
    • }

Preconditions vs. Defensive Programming

  • Preconditions are strong contractual statements. The caller of the operation must fulfill it or lose the program.

    • There is no way to guaranty that the caller will fulfill all of the preconditions of the given operation. We simply “trust” the caller
  • Defensive programming allows the invocation of the operation on objects of any state, with any arguments. Operations are going to spend time checking the validity of the object and all arguments.

    • Tradeoff between performance and reliability
    • Different projects have different preferences towards performance and reliability

Yüklə 116 Kb.

Dostları ilə paylaş:

Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur © 2022
rəhbərliyinə müraciət

    Ana səhifə