samedi 28 mars 2020

C++: implementing multiple instances of an interface or an optional interface in a class

I'm having trouble finding best practice information about what I believe should be a fairly common problem pattern.

I will start with a specific (software update related) example, because it makes the discussion more concrete, but the issue should be fairly generic.

Say that I have a software updater interface:

class Software_updater {
    virtual ~Software_updater() = default;
    virtual void action1(const Input1& input1) = 0;
    virtual void action2() = 0;
    virtual bool action3(const Input2& input2) = 0;
    virtual Data1 info1() = 0;
    virtual Data2 info2() = 0;
    // etc.
};

For my first implementation A, I am lucky, everything is straightforward.

class A_software_updater : public Software_updater {
    // ...
};

A B_software_updater, however, is more complicated. Like in the A-case, it is connected to the target to update in a non-trivial manner and maintains a target connection state. But more importantly, it can update two images: the application image, and the boot loader image.

Liking what I have so far, I see no real reason to go for a refactoring, so I assume I can just build upon it. I come up with the following solution:

class B_software_updater {
public:
    Software_updater& application_updater() { return application_updater_; }
    Software_updater& boot_loader_updater() { return boot_loader_updater_; }
private:
    class Application_updater : public Software_updater {
        // ...
    } application_updater_;
    class Boot_loader_updater : public Software_updater {
        // ...
    } boot_loader_updater_;
};

I.e. I am returning non-const references to "interfaces to" member variables. Note that they cannot be const, since they mute state.

I think it is a clean solution, but I would be happy to get some confirmation.

In fact, I have recently faced the issue of having to optionally provide an interface in a class, based on compile-time selection of a feature, and I believe the pattern above is a solution for that problem too:

class Optional_interface {
    virtual ~Optional_interface() = default;
    virtual void action1(const Input1& input1) = 0;
    virtual void action2() = 0;
    virtual bool action3(const Input2& input2) = 0;
    virtual Data1 info1() = 0;
    virtual Data2 info2() = 0;
    // etc.
};

class A_implementation {
public:
#ifdef OPTIONAL_FEATURE
    Optional_interface& optional_interface() { return optional_implementation_; }
#endif
// ...
private:
#ifdef OPTIONAL_FEATURE
    class Optional_implementation : public Optional_interface {
        // ...
    } optional_implementation_;
#endif
// ...
};

I could not find a simple (as in: not unnecessarily complicated template-based) and clean way to express a compile-time optional inheritance at the A_implementation-level. Can you?

Aucun commentaire:

Enregistrer un commentaire