2

I am building a common interface for several different backends that are shared libs loaded at runtime dependend on the used platform. It looks basically like the code below. My problem is, that while 90% of the functions of all backends are the same (just different implementations but same purpose) some of them have features that are not available to other platforms at all.

If I had a wrapper function for all features than they would run into the void for backends that do not support them which I want to avoid. I also don't like the idea of having implementations of backend functions that just return errors.

What would be a good way to have a generic common interface while still being able to call functions specific to a backend if the user wants to limit his application to that platform?

class CommonInterface
{
    void DoA(); // Calls InternalDoA() of loaded backend

    void DoB(); // Calls InternalDoB() of loaded backend

    void DoC(); // Calls InternalDoC() of loaded backend ???
};

class BackendOne
{
    void InternalDoA();

    void InternalDoB();

    // DoC does not exist!
};

class BackendTwo
{
    void InternalDoA();

    void InternalDoB();

    void InternalDoC();
};

Thanks a lot in advance!

  • 2
    The problem with these examples is that void Foo() is a black hole of "do something" with no real context. If that's the case, what's the problem with void BackendOne::InternalDoC(){}? Otherwise, what are the preconditions and postconditions of CommonInterfaces methods? – Caleth Aug 7 at 10:45
  • Hi @Caleth , thanks for the comment! Sorry, I wanted to keep the explanations simple and thought the actual purpose of the functions wasn't relevant. The different backends are basically for different hardware platforms. While all machines support A and B only machine Two supports C. Hence I cannot implement BackendOne::InternalDoC because it simply cannot do C due to hardware limitations. I am not sure what you mean by pre- and postconditions? – Stargazer Aug 7 at 12:53
  • You have to think about what doing C means for the user of CommonInterface. It might be that you can just ignore the absence of C, or that you can fallback to something involving A and B, or you split the interface into Common and CPossible. Preconditions are anything that must be true before you call a function. Postconditions are anything the function promises are true after you call it. – Caleth Aug 7 at 13:09
  • Okay, I see what you mean. C must not be abscent. While users of BackendOne cannot (and wouldn't want to) use it, BackendTwo very likely will have to use C. Also it is not directly related to A and B, using them to achieve C is not possible. A split of the interface into a common and a specific part might be possible. Like some kind of extension interface which only users of a certain backend would use in the firs tplace. I'll think more about that, thanks! – Stargazer Aug 7 at 13:33
  • In class BackendOne, throw an exception for DoC. Or use two different interfaces. – Robert Harvey Aug 7 at 14:32
4

I also don't like the idea of having implementations of backend functions that just return errors.

There is usually no one-size-fits-all solution for this. One has to decide on a by-case basis about the most appropriate solution.

Here are some options:

1) Make an empty or "dummy" implementation of DoC, if you know for sure not reacting to a call of this feature C which is not available won't cause any harm from the user's point of view.

2) Return an error / throw an exception if you think the caller must not ignore the fact C is not available. Don't feel unhealthy about it, this is often the correct approach, if you like it or not. If you throw an exception, state this clearly in the documentation, so the API user is demanded to handle it. And if callers think they can ignore the error within their context, they still have the choice to do so.

3) In case you think the user needs to query the availability of a feature C before actually calling / not calling the function "DoC", you could also provide something like bool IsFeatureCAvailable() in the interface (and return an error from DoC if the user calls it though it is not available).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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