0

I used the composite pattern to represent devices, which I would like to shut down before killing their power (calling their dtor). I ran into a problem trying to group the devices, especially regarding their state.

How would I proceed in the following scenario:

class IDevice
{
public:
    virtual void shutdown() = 0;
    virtual void turn_on() = 0;
    virtual bool is_on() const = 0;
}

class Router: public IDevice {...};
class Computer: public IDevice {...};
class Monitor: public IDevice {...};
// etc...

class WorkStation: public IDevice {...};

The work station might contain several devices, and you'd want to shut all of them down safely before killing the station electricity. (In this metaphor, I'm very cheap). It is also worth noting that I would never want any one of the devices turned on on its own - Everything will always act as one unit.

The problem comes when one of the inner devices doesn't want to shut down safely - It will throw an exception (e.g. A computer's program prevents it from shutting down).

What should is_on() return in that state? what should consecutive method calls do? Alternatively, what is another design pattern can I use to represent my problem better?

Guy
  • 23
  • 4
  • 1
    Is a `Room` really substiutable for an `IDevice`? – Stephen Newell Sep 17 '20 at 19:38
  • 1
    Room is not a device, room has devices. Is-a relationship can be modeled via inheritance, has-a should not. – Quimby Sep 17 '20 at 19:42
  • This metaphor doesn't hold up that well in this case, but I can't share the actual problem I have here. The core of the problem is freeing resources before calling the dtor. – Guy Sep 17 '20 at 19:47
  • Well you could make `is_on` a 3-value enum: AllOn, SomeOn, AllOff. It really depends on what exactly you're trying to model and what aspects are important. In the absence of that, isn't it perfectly reasonable a Room could contain a TV that's on and also a Computer that's off, regardless of any destructor/exception issues? – TheUndeadFish Sep 17 '20 at 19:53
  • I edited the question to better match my problem @TheUndeadFish – Guy Sep 17 '20 at 20:04

1 Answers1

1

The main big problem is that you want to throw from the dtor. https://www.kolpackov.net/projects/c++/eh/dtor-1.xhtml has a nice explanation of why this does not play nicely with the language and its idioms.

In general, if you expect that a device can fail at shutting down, then you should probably handle this part explicity, because it not something that happens "exceptionally".

For example, you could have the destructor try to gracefully shut off the device, and in case of errors (or exceptions), apply a force shut off. then, if the user of your system wants to handle the case of a device that can't shut off, he can still call shutoff directly.

Finally, modeling from real world objects is just a first draft of your class design. don't worry to notstick to what the real world object do, if it helps to get a more practical design and a better UX.

andijcr
  • 427
  • 3
  • 13
  • That's true - and exactly why I have the shutdown method - To not throw in the dtor. – Guy Sep 26 '20 at 17:50