c++design-patternsstatecompositeexception-safety

Exception safety in the composite pattern


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?


Solution

  • 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.