Quite simply, when designing a new class, how do I figure out what the invariant should be? What defines the invariant? I’ve heard that it’s tied into validity, but that’s still ambiguous. What makes a given instance valid or invalid is debatable.
Should I just go with my “gut” feeling? Are there guidelines for figuring out what the invariant is?
Invariant can be always represented as predicate with arguments being some or all state variables (fields) of the class. One class can have more then one invariant. For example, suppose you have an
Accountclass that hasinitialBalance,listOfTransactions,currentBalance. Also, we keep the transactions in a sorted (by date) list . for This class there are at least two invariants that should be maintained:1) initialBalance + sum(transaction amounts) = currentBalance
2) for every element in the listOfTransactions, the
timestampof the transactions at positionishould be always less then thetimestampof the transaction at positionjifi < j.Invariants depend on what the
classis doing and also how the class is implemented.Let say, we can add one more state variable:
closedDate, and one more invariant will appear: no transaction can have date after the closeDate.Or if the list is not sorted by date, but by transaction amount, then the invatians would change.
Another example:
Let’s suppose that you have mutable
Ellipseclass defined with two fields,r1andr2which has setters forr1andr2. This class doesn’t have any invariant, as any values for r1 and r2 can represent well defined ellipse.Now let’s suppose that you create new
Circleclass that extends the mutableEllipse. The circle has only one radius add the invariant would be (r1==r2). In order to maintain the invariant, you have to disallow somebody setting r1 or r2, such that r1!=r2 happens.On the other hand if the
EllipseandCircleare immutable you don’t have to care for the invariants during the life of the objects, as the condition would be checked only during construction.With the previous examples, i wanted to explain that
1) the way the invariants are established and maintained depends very much on the choice of design of the relations between the classes.
2) What the class is doing
3) How the class is implemented.
Immutable classes tend to be less complex to maintain their invariant, as they are established at construction, and never change. (Immutability has many other benefits too – not in scope of the answer)