Which 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() {};
};
I’m lazy, and most of our codebase uses the first choice, so that’s the one I’d go with. I’d switch to the second choice immediately when things start getting more complex. But like I said, I’m lazy. 🙂
The second choice is definitely more future-proof and more flexible. Good programmers make classes easy to use. Making them easy to write is secondary.