A useful reference for API design: the Qt Wiki’s API Design Principles. It distills practical guidelines—minimalism, clarity, const‑correctness, and common traps—that are worth keeping in mind whenever you design a library or internal interface. Short, clear, and to the point.
This is the original link:
API Design Principles - Qt Wiki
Good APIs have six characteristics.
1、Be mininal
Has few public members per class and as few classes as possible.This makes it easier to understand, remember, debug amd change the API.
2、Be complete
Expected functionality should be there.
3、Have clear and simple semantics
Make common tasks easy. Rare tasks should be possible but not the focus. Solve the specific problem; don't make the solution overly general when this is not needed.
4、Be intuitive
An API is intuitive if a semi-experienced user gets away without reading the documentation, and if a programmer who doesn't know the API can understand code written using it.
5、Be easy to memorize
To make the API easy to remember, choose a consistent and precise naming convention. Use recognizable patterns and concepts, and avoid abbreviations.
6、Lead to readable code
Code is written once, but read many times. Readable code may sometimes take longer to write, but saves time throughout the product's life cycle.
Static Polymorphism
Similar classes should have a similar API. This can be done using inheritance where it make sense - that is, when run-time polymorphism is used. But polymorphism also happens at design time. For example, if you exchange a QProgressBar with a QSlider, or a QString with a QByteArray, you'll find that the similarity of APIS makes this replacement very easy. This is what we call "static polymorphism".
Static polymorphism also makes it easier to memorize APIs and programming patterns. As a consequence, a similar API for a set of related classes is sometimes better than perfect individual APIs for each class.
When two subclasses inherit a parent class, but these two subclasses have different characters and functions, the parent class can't realize general characters and functions.
Property-Based APIs
Orthogonality
when practicable, users should be allowed to set the properties in any order. The properties should be orthogonal. They will not influence each other, and there is no specific order when setting them.
Delayed construction
when setting properties, we should not compile it until all properties are setting.Because when we set first property, we don't know the second property, this will waste performance.
Set != Get
In some cases, class method return something different than what was set. Because the final property depend on the parent class state.
C++ Specifics
Pointers vs. References
Prefer pointers because they make the user code more readable.
xxx(&h, &s, &v);
xxx(h, s, v);
Passing by const-ref vs. Passing by value
If the type is bigger than 16 bytes, pass by const-ref;
If the type has a non-trivial copy-constructor or a non-trival destructor, pass by const-ref to avoid executing these methods.(If pass value, will call the copy constructor).
All other types should usually be passed by value.
Constness
Input arguments: const pointers
Const functions that take input pointer arguments almost always take const pointer arguments.
If the function is really declared const, it means it will neighter have side effects. So why should it require a non-const input argument?Remember that const functions are often called from within other const functions, and from there, non-const pointers are hard to come by.
Return values: const values
Even if it is syntactically possible to add a "const" on Non-class-values it does not make much sense as it won't change anything.
When adding a "const" to a class type values access to non-const member functions is prohibited as well as direct manipulation of its members.
Return values: pointers vs. const pointers
Const functions should return const pointers. But in some cases, it would prevent developer to use.(Read the original text).
Avoid Common Traps
The Convenience Trap
It is a common misconception that the less code you need to achieve something, the better the API. Keep in mind that code is written more than once but has to be understood over and over again.
For example,
QSlider *slider = new QSlider(12, 18, 3, 13, Qt::Vertical, 0, "volume");
is much harder to read than
QSlider *slider = new QSlider(Qt::Vertical);
slider->setRange(12, 18);
slider->setPageStep(3);
slider->setValue(13);
slider->setObjectName("volume");
The Boolean Parameter Trap
Boolean paramters often lead to unreadable code. In particular, it's almost invariably a mistake to add a bool parameter to an existing function.
For example,
widget->repaint(false);
which beginners might read as meaning, "Don't repaint!"
The thinking is apparently that the bool parameter saves one function, thus helping reducing the bloat. In truth, it adds bloat.
A somewhat better API might have been
widget->repaint();
widget->repaintWithoutErasing();
posted on
浙公网安备 33010602011771号