Should the NVI idiom be used for simple interface classes?

What should i use?

struct IFilterTreeNode
{
    virtual unsigned int GetEasiestProveRank() const = 0;
    virtual unsigned int GetEasiestDisproveRank() const = 0;
    virtual unsigned int GetEasiestProveNumber() const = 0;
    virtual unsigned int GetEasiestDisproveNumber() const = 0;
    virtual std::vector<IFilterTreeNode *> GetChildren() const = 0;
    virtual bool AttemptToProve() = 0;
    virtual bool AttemptToDisprove() = 0;
    virtual ~IFilterTreeNode() {};
};

or

class IFilterTreeNode
{
    virtual unsigned int GetEasiestProveRankImpl() const = 0;
    virtual unsigned int GetEasiestDisproveRankImpl() const = 0;
    virtual unsigned int GetEasiestProveNumberImpl() const = 0;
    virtual unsigned int GetEasiestDisproveNumberImpl() const = 0;
    virtual std::vector<IFilterTreeNode *> GetChildrenImpl() const = 0;
    virtual bool AttemptToProveImpl() = 0;
    virtual bool AttemptToDisproveImpl() = 0;
public:
    unsigned int GetEasiestProveRank() const
    {
        return GetEasiestProveRankImpl();
    }
    unsigned int GetEasiestDisproveRank() const
    {
        return GetEasiestDisproveRankImpl();
    }
    unsigned int GetEasiestProveNumber() const
    {
        return GetEasiestProveNumberImpl();
    }
    unsigned int GetEasiestDisproveNumber() const
    {
        return GetEasiestDisproveNumberImpl();
    }
    std::vector<IFilterTreeNode *> GetChildren() const
    {
        return GetChildrenImpl();
    }
    bool AttemptToProve()
    {
        return AttemptToProveImpl();
    }
    bool AttemptToDisprove()
    {
        return AttemptToDisproveImpl();
    }
    virtual ~IFilterTreeNode() {};
};
+2
source share
4 answers

I am lazy and most of our code base uses the first choice, so the one I would go with. I would immediately switch to the second option, when everything starts to get complicated. But, as I said, I'm lazy. :-)

The second option is definitely more reliable and more flexible. Good programmers make it easy to use classes. Making them easy to write is secondary.

+2
source

Michael Kristofik answer is correct as far as I know.

But I would add: your interface will be applied to all types inheriting from it.

, , , ( ), NVI.

, , .

+2

NVI . - , , .

, , . Herb Sutter .

: " ?" . , , , .

+1
source

Probably not worth the trouble in this simple case. Whether there were any parameters for the methods and / or the need to extend the extensible protocols / tools / parameters before / after processing, I would use NVI.

0
source

Source: https://habr.com/ru/post/1758545/


All Articles