[Journal - Indexing and Slicing]

Indexing and Slicing

Wednesday, October 13, 2004

Should a rectangle be defined as a point and a size, or as two points? Should a List.Slice method take an initial index and a length, or two indices called begin and end? Should a period of time be represented by a start timestamp and a timespan, or by the interval between two timestamps?

What these questions have in common is the choice between relative and absolute data measurements. In some systems, the latter is preferred, but I'd say use relative quantities whenever possible. For examle, it's much simpler to move a rectangle by just changing the coordinates of its upper left corner instead of messing with two points' coordinates.

Note that the term "absolute" in this respect is somewhat relative: the absolute data points talked about here are called absolute because they are not relative to the other absolute data point in question.

Even if you disagree with that judgment, it's still good to be aware that you even have such a choice. What's wrong with this method:

class Rectangle {

    void Move(int x, int y){}

}

The problem is that it's not immediately obvious whether x and y are absolute coordinates or relative offsets. And when, later, someone defines a MoveTo (or a MoveBy) method, the names are rather inconsistent.

Now, it's easy to say that you should "name your methods precisely" or "think before coding" and in general stress the importance of the design phase, but I'm trying to be a little more helpful while dispensing with unsolicited advice. One approach is to compile a list a antonyms, and think them trough when making design desicions: absolute-relative, local-remote, minimum-maximum, including-excluding, and so on.

Speaking of including vs. excluding, if you decide to use "begin" and "end" indices in a List.Slice method, the "end" index should by end-point exclusive. This is because it's the convention used in the C++ STL, in the Java API, and other systems that prefer absolute measurements. It's also simpler to work with than end-point inclusive ranges, because length = end - begin. Because of that rule, it's easier to switch between the two systems (such as in the case of java.lang.String.substring vs. System.String.Substring). And if your slice start at index 0, the second parameter is the same in both systems.