0

Background: My company is working with camera systems. In the beginning we built our application around different models/setups of them, which i.e. consisted of different cameras or procedures to acquire and combine the data they acquired. However, we were always limited to having a single active system in our application. Some day we had the idea to link multiple camera systems together to acquire more data simultaneously in shorter periods of time. Since then, we are having trouble to cleanly represent this in our software.

Conceptually we have this very simplified design:

class ICamSystem
{}

class SomeCamSystemImpl : public ICamSystem
{}

class MultiCamSystem
{
  std::vector<ICamSystem> cam_systems;
}

The big decision is whether or not we should have MultiCamSystem derive and implement ICamSystem. At first glance this seems very reasonable because in theory a MultiCamSystem should support pretty much the same set of operations any ICamSystem does. In fact, most of what MultiCamSystem's implementations do is just forwarding a method call to all of its composite camera systems. Deciding against this also means we would have to bloat every single call site with a distinction of cases between having a single camera system or a multi camera system. On the other hand, following Liskov's Substitution Principle a MultiCamSystem just isn't a ICamSystem and has led to all sorts of follow-up problems. Two very simple examples:

ICamSystem::set_parameter

has a very natural implementation for a camera system: It either succeeds and sets the parameter or fails with an exception. On a multi camera system I'd intuitively want to implement it like this:

MultiCamSystem::set_parameter( const Param& p )
{
  for(auto* cs : cam_systems)
    cs->set_parameter(p)
}

But this doesn't make sense in some cases because each camera system might have different ranges of valid/acceptable parameters. For example setting the exposure this way most likely doesn't make much sense because due to external lighting conditions I most often have to adjust them for each system individually which breaks my abstraction of having a single camera system accepting a single exposure time. I also need to worry about error handling, i.e. when an operation just fails on a subset of the camera systems.

Data ICamSystem::acquire_data() or
SystemID ICamSystem::getID()

Before, I just had a single return value from a method. With a multi camera system this rather has to be:

std::vector<Data> ICamSystem::acquire_data() or
std::vector<SystemID> ICamSystem::getID()

so again this breaks my abstraction. I could of course change the signature in the abstract interface and have single camera systems return a vector of size 1, too. But it seems ill-advised to taylor a generic and perfectly reasonable interface to specific implementations of it.

What is a better way to represent this then?

2
  • You don't need ICamSystem in your question; it makes it more complex than necessary to read. Your question is typical, but there is no better solution in OO languages than using a base class or interface. Erik's answer is the best; if you want to model a collection of objects as a single object, that is possible. Commented Aug 9, 2017 at 21:39
  • I suggest you have a look at scene graphs - those data structures used to represent 3D geometry, cameras, views, etc.
    – user44761
    Commented Aug 10, 2017 at 7:30

1 Answer 1

3

A collection of X is not necessarily itself an X. Sometimes a collection of X is just that; other times, it is probably more often a manager of X's (having some additional domain-oriented management responsibilities) rather than functioning as a single X itself (though it would certainly not unheard of to be both a manager of X's and itself an X).

However, in this case, the group of cameras simply isn't itself a camera.

Deciding against this also means we would have to bloat every single call site with a distinction of cases between having a single ... or a multi ...

This is a negligible cost, IMHO. (However, if it is practical for you, you can implement just the multi, and then wrap a single X in a collection as needed to use the multi routines.)

1
  • I agree with that last point. And might expand on it. It might be worth representing everything as a collection of cameras, in some places the collection just happens to be 1 camera only. Commented Aug 10, 2017 at 13:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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