2

Imagine a LineSegment class that represents a line segment using two arbitrary endpoints.

Should the constructor throw if it is passed two approximately equal endpoints? Obviously this would require some arbitrary floating point comparison. For example, test the Euclidean distance between the endpoints is less than ε.

An advantage is users aren't going to get nonsense answers to certain questions if they construct a LineSegment with floating point noise, or two points that "should" be equal but diverged due to error in floating point calculations. For example, it would otherwise be dangerous if the user asked the direction a line segment was pointed.

A disadvantage is that the class now needs to try to encapsulate and maintain this requirement on the state of the two endpoints. Moving an endpoint of the LineSegment would have the potential to throw.

Imagine a PolyLine class that uses these LineSegment under the hood. If the user wants to insert a new point in the PolyLine it could throw if that point is within ε of another point. Would a SafeInsert need to delete all nearby points? Could users tolerate a SafeInsert that potentially reduced the size of their PolyLine? Even deleting a point could throw, because it could bring together two approximately equal points.

The alternative to throwing in the constructors is to skip validation, and rely on users to call a Douglas-Peucker or related algorithm if there is risk their LineSegment or PolyLine data would provide unreasonable answers. Users would provide their own ε when they used this function.

Is anyone familiar with existing implementations of LineSegment or PolyLine classes that prefer one approach to the other?

  • 3
    Any good answer depends too heavily on what you want your class for. If it's a general use class without a particular use case, I'd allow the construction and let users take care of validation. – Turksarama Dec 14 '17 at 3:46
4

Depends on context, but just generally speaking, if you don't know the answers to these questions, I would suggest to seek to make your LineSegment allow this case without throwing, and if possible, even find a way to allow your PolyLine cases to also work without throwing.

  • 2
    +1. A LineSegment of length zero is useful as a geometric element for the same reasons why the number zero is useful as a numeric element: it will allow to handle a wider range of use cases without requiring artifical case-by-case decisions. – Doc Brown Dec 14 '17 at 7:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.