Unfortunately, there is no systematic way to look at a piece of code and work out its invariants. One technique is to think of ways that an instance's state might be invalid and then check that those can't happen; in that case, each rule for what makes a state "valid" is an invariant. But you need to use intuition and experience to do this.
For your example, this class has two invariants:
- The stack only contains integers in the range 1 to 10 inclusive.
- The element on the bottom of the stack is the integer 5.
It is straightforward to verify that the constructor establishes both invariants, and the addCard
method preserves them:
- The constructor only adds the number 5 which is in range, and
addCard
only adds numbers to the stack if they are within the range.
- Numbers are never removed from the stack, and numbers are only added at the top of the stack, so the 5 at the bottom of the stack (which is put there by the constructor) will stay at the bottom of the stack.
It's important to note that the constructor and the addCard
method are the only two ways to change the state of the instance or its stack, so we don't have to check whether any other code preserves the invariants. If the stack wasn't private
then it would be different; other code would be able to put numbers onto the stack which are out of range (or null
), or other code could remove the 5 from the bottom of the stack.