/[http://wiki.kde.org/tiki-index.php?page=KDE+Community+World+Summit|aKademy] / [http://wiki.kde.org/tiki-index.php?page=Talks+@+aKademy|Talks] / Qt Style APIs -=How to write Qt-style APIs=- Designing APIs is very complex and can not be captured in a 45 minute talk. API is an Application Programmer Interface, not Program, the Programmers are human. API is to the programmer what a GUI is to the end user: you can't just add things all over the place (or you end up with KControl). APIs should be both minimal and complete (which can conflict), have clear and simple semantics, be intuitive and easy to remember, guide the user to readable code in the same way as a good user interface guides you to what to do. Minimal means minimising the number of public members per class and the number of classes. This makes it easier to remember, debug and understand. Overloads are preferred over new items. A complete API means the expected functionality should be there. This can conflict with keeping it minimal. If a member function is in the wrong class this can lead to extra functions in the same wrong place. As with other design work apply the principle of least surprise. Make common tasks easy, rare tasks should be possible but not the focus. Solve the specific problem so don't make it overly general when this is not needed, e.g. QMimeSourceFactory should have been a QImageLoader. Async I/O framework is the same because it was really only written to load images. If you are not sure about something, remove it (QCom). Add it later when you understand how to do it properly. As with anything else on a computer an API should be intuitive. This is based on experience (e.g. click on a floppy disk to save even if you have never used a floppy disk). A Qt API is intuitive if someone familiar with Qt does not have to read the documentation or if a non-Qt programmer can understand code written with it. To make it easy to remember choose a consistent and precise naming. Use words that non-native English speakers will understand and do not use abbreviations. Use recognisable patterns and concepts. An API should result in readable code, this is because code is read many times after it has been written. Readable code takes longer to write but saves time, which is why you should not save keystrokes by using abbreviations. Remember your user, they will use it for different things such as subclassing. Normal classes should not require subclassing so any classes which do require this are marked as abstract. E.g. in Qt 1 or 2 size policy was not a QT Property so to change the size policy you had to subclass, this should not be required. It is a misconception that the less code needed to achieve something means a better API. Mind that code is written more than once but has to be understood over again. Example QSlider* slider = new QSlider(12, 18, 3, 13, Vertical, 0, "Convenience level") requires reading the documentation to understand, it is much more readable as slider = new QSlider slider->setRange(12,18) slider->setPageStep(3) slider->setValue(13); Also consider bindings to dynamically typed language. Boolean trap, when you add functionality to a function by adding a new boolean argument. This appears a lot in KDE. Example widget->repaint(false); someone may read this as don't repaint Mind the inheritance structure. e.g. QToolButton has Qobject::name, QWidget::caption, QButton::text, QToolButton::textlabel. This is improved in Qt4. APIs need quality assurance. The first revision is never right, you must test it. Make use cases by looking at code which uses this API, the API is good if the code is readable. Have somebody else use it without documentation. Document your classes but don't just write functional documentation but also a class overview which covers all the methods in the API. Always get your names right. Names can be found by documenting it and the words are probably in the first sentence. If you cannot find a precise name it probably means the API is wrong. You can invent a name but be very careful about this (e.g. widget, buddy). Bad example QSizePolicy::setHorStretch(uint sf), should not have been abbreviated. Boolean properties are the most important, use "is" for singar adjectives otherwise nothing. A case study of QProgressBar was given. For example totalSteps() and progress() are related but not named alike, should use similar names to QSpinBox but does not. Indicator and Percentage are two words used for the same thing. Can this be automated, no because it is human judgement same as GUIs. Why no 'gets'? This was decided against because it doesn't look nice "if (widget->getVisible())" isn't as nice as "if (widget->visible())". 'Get' is used for functions which have several out pointers because it has to be obvious that this is an outputting function. One problem if using 'is' in a name is when you have plural properties because it would have to be 'are'. Are there guidelines for Qt (related) bindings to C libraries? All of Qt is just bindings to C libraries but the shape of the C library should not effect the shape of the API. Could we have written guidelines to use for cleaning up KDE 4? Oh yes. Will users of the old QProgressBar be given a refund? Talk to Eirik. Richard Dale talked about stuff.