How to represent self-composed implementations in inheritance hierarchies

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

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

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật