Link to home
Start Free TrialLog in
Avatar of gudii9
gudii9Flag for United States of America

asked on

java assertion


I have not understood assertion clearly. Any good simple document, tutorial, material to start with step by step.

Any ideas, resources, links, sample code highly appreciated. thanks in advance.
Avatar of for_yan
for_yan
Flag of United States of America image

Avatar of gudii9

ASKER

i was going through the link.

>>>The second form of the assertion statement is:

    assert Expression1 : Expression2 ;
where:

Expression1 is a boolean expression.
Expression2 is an expression that has a value. (It cannot be an invocation of a method that is declared void.)



>>>Preconditions

By convention, preconditions on public methods are enforced by explicit checks that throw particular, specified exceptions. For example:

    /**
     * Sets the refresh rate.
     *
     * @param  rate refresh rate, in frames per second.
     * @throws IllegalArgumentException if rate <= 0 or
     *          rate > MAX_REFRESH_RATE.
     */
     public void setRefreshRate(int rate) {
         // Enforce specified precondition in public method
         if (rate <= 0 || rate > MAX_REFRESH_RATE)
             throw new IllegalArgumentException("Illegal rate: " + rate);

         setRefreshInterval(1000/rate);
     }
This convention is unaffected by the addition of the assert construct. Do not use assertions to check the parameters of a public method. An assert is inappropriate because the method guarantees that it will always enforce the argument checks. It must check its arguments whether or not assertions are enabled. Further, the assert construct does not throw an exception of the specified type. It can throw only an AssertionError.



I hae not understood above statements. please advise
Avatar of gudii9

ASKER

i was not clear on

>>Class Invariants

A class invariants is a type of internal invariant that applies to every instance of a class at all times, except when an instance is in transition from one consistent state to another. A class invariant can specify the relationships among multiple attributes, and should be true before and after any method completes. For example, suppose you implement a balanced tree data structure of some sort. A class invariant might be that the tree is balanced and properly ordered.
The assertion mechanism does not enforce any particular style for checking invariants

please advise
well, I clearly understand only the first section of it

>>>The second form of the assertion statement is:

    assert Expression1 : Expression2 ;
where:

Expression1 is a boolean expression.
Expression2 is an expression that has a value. (It cannot be an invocation of a method that is declared void.)

Expression2  provides the detailed message, perhaps includin some calculated parameter, so that
if Expression1 fails it will not just throw AssertionError but it would add this
message to AssertionError constructor and you'll be able
to print this message say using toString() or getMessage() error of the
AssertionError - so it will give you more information to daignose the error, if you'll be samrt enough
to create this Expression2 with meaningful information.

The usage of the other two points is not absolutely clear to me either.
I'm not using Assertion to that level of sophistication, I'll try to unerstand it later, and
if I get it, I'll post it here




Avatar of gudii9

ASKER

i was going through the links

>>pre-conditions (in private methods only)


why pre-conditions is only for  private methods. please advise
Avatar of gudii9

ASKER

>>>

I was going threough this example in the link. I have not understood use of asserion, class invariant in this program. please advise

>>


import java.util.Random;

public final class Flower {

  public static void main (String... arguments) {
    final Flower tulip = new Flower("Tulip", 1);
    tulip.grow();
    tulip.grow();
    System.out.println( tulip );

    tulip.randomGrowOrWither();
    System.out.println( tulip );

    tulip.wither();
    tulip.wither();
    System.out.println( tulip );
  }

  /**
  * @param aSpecies must have content.
  * @param aInitialLength must be greater than 0.
  */
  public Flower( final String aSpecies, final int aInitialLength ) {
    //assert is NOT used to validate params of public methods
    if ( !isValidSpecies(aSpecies) ) {
      throw new IllegalArgumentException("Species must have content.");
    }
    if ( !isValidLength(aInitialLength) ) {
      throw new IllegalArgumentException("Initial length must be positive.");
    }

    fSpecies = aSpecies;
    fLength = aInitialLength;

    //check the class invariant
    assert hasValidState(): "Construction failed - not valid state.";
  }

  public boolean isMature() {
    return fLength > 5 ;
    //not necessary to assert valid state here, since
    //the state has not changed.
  }

  /**
  * Increase the length by at least one unit.
  */
  public void grow(){
    //this style of checking post-conditions is NOT recommended,
    //since the copy of fLength is always made, even when
    //assertions are disabled.
    //See <code>wither</code> (below) for an example with an improved style.
    final int oldLength = fLength;
    fLength += getLengthIncrease( fLength );
    //post-condition: length has increased
    assert (fLength > oldLength);

    //check the class invariant
    assert hasValidState(): this;
  }

  /**
  * Decrease the length by one unit, but only if the resulting length
  * will still be greater than 0.
  */
  public void wither() {

    //this local class exists only to take a snapshot of the current state.
    //although bulky, this style allows post-conditions of arbitrary complexity.
    class OriginalState {
      OriginalState() {
        fOriginalLength = fLength;
      }
      int getLength() {
        return fOriginalLength;
      }
      private final int fOriginalLength;
    }
    OriginalState originalState = null;
    //construct object inside an assertion, in order to ensure that
    //no construction takes place when assertions are disabled.
    //this assert is rather unusual in that it will always succeed, and in that
    //it has side-effects - it creates an object and sets a reference
    assert( (originalState = new OriginalState()) != null);

    if (fLength > 1) {
      --fLength;
    }

    //post-condition: length has decreased by one or has remained the same
    assert( fLength <= originalState.getLength() );

    //check the class invariant
    assert hasValidState(): this;
  }

  /**
  * Randomly select one of three actions
  * <ul>
  * <li>do nothing
  * <li>grow
  * <li>wither
  * </ul>
  */
  public void randomGrowOrWither() {
    //(magic numbers are used here instead of symbolic constants
    //to slightly clarify the example)
    Random generator = new Random();
    int action =  generator.nextInt(3);
    //according to the documentation for the Random class, action
    //should take one of the values 0,1,2.
    if ( action == 0 ) {
      //do nothing
    }
    else if ( action == 1 ) {
      grow();
    }
    else if ( action == 2 ) {
      wither();
    }
    else {
      //this is still executed if assertions are disabled
      throw new AssertionError("Unexpected value for action: " + action);
    }
    //check the class invariant
    assert hasValidState(): this;
  }

  /**
  * Use for debugging only.
  */
  public String toString(){
    final StringBuilder result = new StringBuilder();
    result.append( this.getClass().getName() );
    result.append( ": Species="  );
    result.append( fSpecies );
    result.append( " Length=" );
    result.append( fLength );
    return result.toString();
  }

  // PRIVATE ////
  private final String fSpecies;
  private int fLength;

  /**
  * Implements the class invariant.
  *
  * Perform all checks on the state of the object.
  * One may assert that this method returns true at the end
  * of every public method.
  */
  private boolean hasValidState(){
    return isValidSpecies(fSpecies) && isValidLength(fLength);
  }

  /**
  * Species must have content.
  */
  private boolean isValidSpecies( final String aSpecies ) {
    return aSpecies != null && aSpecies.trim().length()>0;
  }

  /**
  * Length must be greater than 0.
  */
  private boolean isValidLength( final int aLength ) {
    return aLength > 0;
  }

  /**
  * Length increase depends on current length.
  */
  private int getLengthIncrease( int aOriginalLength ) {
    //since this is a private method, an assertion
    //may be used to validate the argument
    assert aOriginalLength > 0: this;
    int result = 0;
    if ( aOriginalLength > 10 ) {
      result = 2;
    }
    else {
      result = 1;
    }
    assert (result > 0):result;
    return result;
  }
}
 
Now I understood what is class invariant - this may be a method which
allows to validate certain state which is supposed to satisfy  some condition at any
moment of the life of the instance of the object.

let's say in some program you track the state of teeth in the mouth of
the patient, so you may have three fields:

int numTeethGood;
int numTeethBad;
int numTeethExtracted;

you may have different methods in your class
which move teeth from one category to another
thus changing the overall numbers but
at any moemnt of life of your instance sum of all three
numbers should be equal to 32.

Sol like in the example above you may have method

  private boolean hasValidState(){
if(numTeethGood + numTeethBad + numTeethExtracted == 32) return true;
    else return false;
  }

and then as some of your buisness methods
finish working you can check class invariant
 assert hasValidState(): this;

  public String toString(){
   System.out.println(patientName + " : wrong total number of teeth: " +  numTeethGood + numTeethBad + numTeethExtracted );

  }

here we aslo used the second from of assertion statement
 assert Expression1 : Expression2 ;

(see description above)

In this way we can take advantage of the class invariant - knowledge
that some parameter or compbionation of parameters whould be invariant
for any momemnt of the life of the instance











 
It uses a method to check the state of the object is valid (thats the class invariannt bit)

  private boolean hasValidState(){
    return isValidSpecies(fSpecies) && isValidLength(fLength);
  }

It then uses assertions to call that method at the end of each method

    assert hasValidState(): this;

What this does is ensure that after every method is called the object is still in a valid state.
This way it fails as soon as it goes into an invalid state instead of failing later in the execution because it was in an invalid state

As I discussed in your other question about invariants its important to catch errors as early as possible.
 
SOLUTION
Avatar of for_yan
for_yan
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
> why pre-conditions is only for  private methods. please advise

its not saying that they can only be used on private methods
You can have preconditions on public methods, it just doesn't make sense.

assertions are something you can turn on and off. For public methods you should *always* be checking that pre conditions are met, thus assertions here are redundant.
Avatar of gudii9

ASKER

>>or public methods you should *always* be checking that pre conditions are met, thus assertions here are redundant.

i was not lear on this point. What you mean you 'should *always* be checking that pre conditions are met'
please advise
the good practice when you code public methods - you anyway would check the
input parameters before you use them - say if you have public method square root -
you'll nomally first check if the argument is positive, and if it is not
you'll return error message to the user.
pre-conditions are more or less analogous process for private methods,
but private methods is something you call in your own code,
so you may want to check parameters using assertions only during the
development of the applicvaation and debugging stage - when your code
is ready, you amy be sure that it will not
feed invalid parameters and you can disable these kind of assertions.
For public methods - the third party provides the parameters - and checking
of the parameters before actual executing the method should always be part of
good public methiod

Avatar of gudii9

ASKER

>>>pre-conditions are more or less analogous process for private methods,
but private methods is something you call in your own code,
so you may want to check parameters using assertions only during the
development of the applicvaation and debugging stage - when your code
is ready, you amy be sure that it will not
feed invalid parameters and you can disable these kind of assertions.



do you mean pre-conditions are similar for both private and public methods. I was not clear. can you advise
you usually do not need to deal with pre-conditions in public methods when dealing
with assertions, because pre-conditions in public methods should be part of your regular code - should
be executed not as assertions but as regular checks which should be executed always when you use this public method.
Because if your public method parameters need to meet certain conditions, it is part
of your good coding to check for these conditions and return error message to the users - it becomes not part
of testing - it becomes already part of regular work of the program

If you have public arcsine method - it is your good java writing first to check that your argument is less than 1.0
and then report error to the calling user that argiument is inadequeate even before you start executing the code itself

if your arcsine method is priveate - then you want to use pre-coditinioons as part of your testing operations
and in regular execution you should be sure that you'll be calling with correct values - after your program is debugged and tested
Avatar of gudii9

ASKER

any simpe example sameple code to explain in detail this public and private method assertion concept. please advise
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial