C++ tip 12: Make interfaces "Easy to use correctly" and "Hard to use incorrectly"

Hello there, today I want to share a very important tip in API design from the Effective C++ book. It is as follows:

Make interfaces easy to use correctly and hard to use incorrectly.

If you are developing a library, engine, etc, think of the kinds of mistakes that your clients might make. For example, let's say that you are developing a class that provides access to dates:

class Date{
public:
Date(int uMonth, int uDay, int uYear);
}

Your users may use this interface incorrectly by doing the following:

Date date(5,12,2015);  //Oops!!! They meant to say Dec 5, 2015

According to Scott Meyers, many clients errors can be prevented by the introduction of new types. In this case, you can provide simple wrapper types to distinguish between days, months and years:

struct Day{
explicit Day(int d):val(d){}
int val;
};

struct Month{
explicit Month(int m):val(m){}
int val;
};

struct Year{
explicit Year(int y):val(y){}
int val;
};

The class will now look like this:

class Date{
public:
Date(const Month& uMonth, const Day& uDay, const Year& uYear);
}

So now the users of your library will be able to use the interface as follows:

Date d(Month(12),Day(5),Year(2015));

This will prevent them from using the interface incorrectly. For example, if they try to do the following the code will not compile:

Date d(Day(5),Month(12),Year(2015)); //Wrong types, won't compile

Scott Meyers says to keep the following in mind:

Ideally, if an attempted use of an interface won't do what the client expects, the code won't compile; and if the code does compile, it will do what the client wants.

In summary, there are several ways to make an interface easy to use correctly and hard to use incorrectly. One of those ways is to use New Types as wrappers in your interface.

Hope this helps.

Sign up to my newsletter below and get Game Engine Development and C++ tips.

Harold Serrano

Computer Graphics Enthusiast. Currently developing a 3D Game Engine.