Documentation for Object-oriented classes often involves tradeoff between giving the maintainers of the class flexibility to change its design, versus allowing consumers of the class to make full use of its potential. If an immutable class will have a number of properties which will have a certain exact relationship with each other (e.g. the Left
, Right
, and Width
properties of an integer-coordinate grid-aligned rectangle), one might design the class to store any combination of two properties and calculate the third, or one might design it to store all three. If nothing about the interface makes clear which properties are stored, the programmer of the class may be able to change the design in the event that doing so would prove helpful for some reason. By contrast, if e.g. two of the properties are exposed as final
fields and the third isn't, then future versions of the class will always have to use the same two properties as being the "basis".
If properties do not have an exact relationship (e.g. because they're float
or double
rather than int
), then it may be necessary to document which properties "define" the value of a class. For example, even though Left
plus Width
is supposed to equal Right
, floating-point math is often inexact. For example, suppose a Rectangle
which uses type Float
accepts Left
and Width
as constructor parameters is constructed with Left
given as 1234567f
and Width
as 1.1f
. The best float
representation of the sum is 1234568.125 [which may display as 1234568.13]; the next smaller float
would be 1234568.0. If the class actually stores Left
and Width
, it may report the width value as it was specified. If, however, the constructor computed Right
based upon the passed-in Left
and Width
, and later computed Width
based upon Left
and Right
, it would report the width as 1.25f
rather than as the passed-in 1.1f
.
With mutable classes, things can be even more interesting, since a change to one of the inter-related values will imply a change to at least one other, but it may not always be clear which one. In some cases, it may be best to avoid having methods which "set" a single property as such, but instead either have methods to e.g. SetLeftAndWidth
or SetLeftAndRight
, or else make clear what properties are being specified and which are changing (e.g. MoveRightEdgeToSetWidth
, ChangeWidthToSetLeftEdge
, or MoveShapeToSetRightEdge
).
Sometimes it may be useful to have a class which keeps track of which properties' values have been specified and which have been computed from others. For example, a "moment in time" class might include an absolute time, a local time, and a time zone offset. As with many such types, given any two pieces of information, one may compute the third. Knowing which piece of information was computed, however, may sometimes be important. For example, suppose that an event is recorded as having occurred at "17:00 UTC, time zone -5, local time 12:00pm", and one later discovers that the time zone should have been -6. If one knows that the UTC was recorded off a server, the record should be corrected to "18:00 UTC, time zone -6, local time 12:00pm"; if someone keyed in the local time off a clock it should be "17:00 UTC, time zone -6, local time 11:00am". Without knowing whether the global or local time should be considered "more believable", however, it's not possible to know which correction should apply. If, however, the record kept track of which time was specified, changes to the time zone could leave that one alone while changing the other.