I have two camera devices that are able to find a specific hardware illuminated point in an image, as well as measuring the physical distance to the surface (and some more stuff I chose to leave out, as it doesn't affect this problem right now), and the application uses the point and distance information independently of each other. Aha - same functionality with different implementations? I should use an interface! I started to define some, but as you'll see I'm probably making some mistakes in my design.
interface IPointFinder {
// The point where the spot is
Point FindPoint(Image image);
}
interface IDistanceMeasurement {
// Distance in mm
int MeasureDistance();
}
interface IDevice {
string DeviceName { get; }
IPointFinder { get; }
IDistanceMeasurement { get; }
event CameraImage;
}
The reason for the device owning the interface ISpotFinder
is that the spot will be illuminated on the surface in different ways depending on the hardware (trying to keep things that will change for the same reason together).
There are two implementations of the IDevice
interface. One has an external hardware device for measuring the distance and calculates where the spot is from the distance value (hence ignoring the image parameter), and the other one calculates the distance value from the spot found by SpotFinder. I thought, "Well, I'll just make this dependency invisible for the application, and hide it in the implementation of IDevice
(for example by letting the distance measurement observe the point finder)", but that was not really optimal as:
- If the distance is dependent on that the point has been found, then it requires an image to have been taken, and processed. Calling this before that method would not return any valuable information.
- If the point is dependent on that the distance has been measured, then it requires that the client code already called
DistanceMeasurement.MeasureDistance()
, otherwise it would not be able to get the point.
The "sequence of execution"-dependency (lack of better term) (edit: I learned from the comments that this is called Temporal Coupling) is hence reversed depending on the implementation, which makes the interface rather useless, as implementation changes would change the way the interface is used.
I'm suspecting my view on the problem is too narrow, and think I could rework this. I would appreciate some feedback. What I thought of so far:
- Make the two interfaces into one
MeasureDistanceAndPoint
which would return both in one go. This feels appropriate as they are clearly related, but a bit weird since the values are used independently in the application, as mentioned. - Define arguments for
IDistanceMeasurement
so that it would require a point as input. Then theIPointFinder
could trigger the external distance measurement silently and calculate the point when external distance measurement is used. - Rethink this altogether, which is probably the way to go, but I spent two full days on it and am getting a bit crazy.