Our knowledge domain involves people walking over a pressure-recording plate with their bare feet. We do image recognition which results in objects of the 'Foot' class, if a human foot is recognized in the sensor data.
There are several calculations that must be performed on the foot's data.
Now, which API would be better:
class Foot : public RecognizedObject {
MaxPressureFrame getMaxPressureFrame();
FootAxis getFootAxis();
AnatomicalZones getAnatomicalZones();
// + similar getters for other calculations
// ...
}
Or:
class Foot : public RecognizedObject {
virtual CalculationBase getCalculation(QString aName);
// ...
}
Now, there are a lot of pro's and con's I can come up with, but I can't really decide which are the most important. Note, this is an end-user application, not a software library we sell.
Any advice?
Some pro's for the first approach could be:
- KISS - everything is very concrete. The API, but the implementation as well.
- strongly typed return values.
- inheriting from this class is fool-proof. Nothing can be overridden, only added.
- API is very closed, nothing goes in, nothing can be overridden, so less can go wrong.
Some con's:
- The number of getters will grow, as every new calculation we invent gets added to the list
- API is more likely to change, and if breaking changes are introduced, we need a new API version, a Foot2.
- in case of re-use of the class in other projects, we might not need every calculation
Some pro's for the second approach:
- more flexible
- the api is less likely to change, (assuming we got the abstraction correct, if not, changing will cost more)
Some con's:
- loosely typed. Needs casts on every call.
- the string parameter - I have bad feelings about that (branching on string values...)
- There is no current use case/requirement that mandates the extra flexibility, but there might be in the future.
- the API imposes restrictions: every calculation needs to derive from a base class. Getting a calculation will be forced through this 1 method, and passing extra parameters will be impossible, unless we devise an even more dynamic, super-flexible way of passing parameters which increases complexity even more.
enum
and switch on it's values. Still, I think the second option is evil, because it deviates from KISS.getCalculation()
.