qgis / QGIS-Enhancement-Proposals

QEP's (QGIS Enhancement Proposals) are used in the process of creating and discussing new enhancements for QGIS
118 stars 37 forks source link

QEP 67: API Documentation Guidelines #67

Open wonder-sk opened 8 years ago

wonder-sk commented 8 years ago

QGIS Enhancement 67: API Documentation Guidelines

Date 2016/07/18

Author Martin Dobias (@wonder-sk)

Contact wonder dot sk at gmail dot com

maintainer @wonder-sk

Version QGIS 3.0

Summary

This QEP presents guidelines for QGIS API documentation that should be followed for classes that are available within QGIS API. The overall target is to improve the quality of the provided documentation so that API users are likely to understand purpose of the class and how to use it just from reading the API documentation.

Current Status

The API documentation is generated using Doxygen from the comments in class header files.

The main problems of the QGIS API documentation:

The following sections set rules for doxygen comments in header files. In general the idea is to have API documented in a fashion similar to Qt API documentation.

Class Documentation

Class documentation should start with one sentence about the purpose of the class. This should be followed by brief description of the class, introducing the main methods of interest. If there are some pieces of functionality that are not obvious, they should be further explained in follow up sections. It is not necessary to explain common GIS concepts or design patterns (a link to other source may be provided if necessary).

It is useful to put the class into context of other related classes by mentioning those and how do they interact, with a link to API overview page (see below).

Classes that provide reusable widgets should normally include a screenshot of the widget. Classes involved in map rendering may include output generated by the class. It is encouraged to include diagrams or other illustrations in the class documentation if they may help in understanding the API.

Code examples are highly recommended, especially for classes that need non-trivial setup. As the main audience for the documentation are Python plugin developers, examples should be written in Python. Examples should be ideally self-contained so it is possible to just copy and paste them in Python console in QGIS without extra setup (for example without loading some layers). Example(s) should cover just the most common use cases to help people start using the API, it is not necessary to provide examples of advanced functionality. Example code may be written either inline or it may refer to snippets from external files. At some point the doxygen snippets should be automatically tested in the QGIS test suite to make sure they are still valid.

Classes should have a note in what QGIS version they have been introduced.

Method Documentation

Each method should have a description that explains its purpose in sufficient detail. Behavior in various special cases should be documented too, including reasons why the method may fail, what happens if an argument is a null pointer and so on.

It is preferred to write documentation about a method in third person, for example "Paints XYZ" or "Returns XYZ" (instead of "Paint XYZ", "Return XYZ"). Try to use full sentences in documentation as much as possible. I.e. "Sets the coordinates reference system for the layer" instead of "sets coordinate system" or "mutator for coordinate system". Use correct capitalization for sentences, and make sure there's a "." on the end!

Methods should have a not in what QGIS version they have been introduced if they were added later that the class:

@note added in QGIS 2.16

If there is any difference between Python API and C++ API, this must be clearly stated. Most commonly this is the case when a value is returned through an argument, in SIP file such argument is marked with /Out/ annotation. Other special cases may appear if SIP includes /Array/ annotation or %MethodCode directive. If Python method is not available for some reason, that should be noted as well:

@note not available in python bindings

In cases there is transfer of ownership of objects (e.g. a pointer passed to a method will get owned by its class or a method returns a new pointer), this fact should be documented. Similarly, if a returned piece of data is only temporary and may become invalid, this needs to be noted.

Try to link related methods, ie setWidth() should have a @see setWidthUnits() link. This makes the documentation much more useful as it gives a hint that there may be important notes in the related methods. Especially link getters and setters using "@see" tags ie setName should have a @see name(), and name() should have a @see setName().

Use correct capitalization for acronyms and terms (ie "DOM" not "dom", "XML" not "xml", "Python" not "python", "PostGIS" not "postgis" etc).

For documentation of arguments and return values, one should use @param and @returns doxygen tags to document them.

API Overview Pages

Each are of API documentation should have a dedicated page in the API documentation that gives a brief overview of the API in question, for example: symbology API, map rendering API, raster API, map canvas API.

Doxygen Style

Doxygen supports Markdown syntax, this is the preferred way for markup compared to using Doxygen tags (Markdown is easier to read or write).

Some recommendations for Doxygen comments:

We are not very picky about how exactly the multi-line comments should be written (e.g. First and last line only contain opening closing sequence, whether asterisks must be at the beginning). Sometimes people are get too opinionated about such details :-) (http://lkml.iu.edu/hypermail/linux/kernel/1607.1/00627.html)

Examples

Method documentation:

/** Returns text with occurences of "bar" replaced by "foo".
 * @param bar Input text to be processed
 * @returns Processed text after replacements
 * @note added in QGIS 2.16
 * @see foobar()
 */
QString foo(const QString& text);

Examples of well documented classes:

When still unsure, have a look at documentation of Qt classes.

New and Existing Classes

Classes and methods newly added to the API should follow the new rules for the documentation. (Incomplete API documentation should be a showstopper for merge of a pull request.)

It will take a lot of effort to bring existing classes up to the new standards. Significant improvements or reworks of existing classes should therefore also improve the documentation.

Votes

(required)

nyalldawson commented 8 years ago

Great stuff, and sorely needed! Some things which jump to mind

Use @copydoc for documentation of overridden functions

I'm not sure about this... is it really needed? Doxygen does this automatically anyway.

Examples should be ideally self-contained so it is possible to just copy and paste them in Python console in QGIS without extra setup (for example without loading some layers).

This sounds good in theory, but I'm not sure how practical it is. From working with the Python unit tests it's often the case that the setup can be 10's/100's of lines long, before getting to the relevant call. In this case I think the extra setup code would just complicate the example and obscure the point it's trying to demonstrate.

Some other additions I'd like to see:

wonder-sk commented 8 years ago

Use @copydoc for documentation of overridden functions

I'm not sure about this... is it really needed? Doxygen does this automatically anyway.

Not sure about that either - happy to leave it out

This sounds good in theory, but I'm not sure how practical it is. From working with the Python unit tests it's often the case that the setup can be 10's/100's of lines long, before getting to the relevant call. In this case I think the extra setup code would just complicate the example and obscure the point it's trying to demonstrate.

True... For cases where real setup would obscure the actual code examples I think it would be reasonable to display just the relevant part showcasing the API and refer to the source file with a complete example.

This makes me think also about the need to have actual runnable example projects, just like in Qt documentation, possibly a 'qgis demo' app that would integrate various examples together. That needs some more thoughts.... better to leave it out from this QEP :-)

How do you think we ensure that class documentation is up to date? The (few) classes with large slabs of documentation currently tend to be outdated or wrong content. Is this something we just need to be diligent about checking regularly?

I think it will just need to get into our PR review checklist as another item - to check whether the API documentation is updated when it should be. I assume the problem with the few classes with long documentation slabs is that everyone knows those docs have been outdated for 10 years already, so nobody is bothered to update those...

Some other additions I'd like to see: [...]

Sure - thanks for the suggestions - I'm adding them...

Can we revisit the discussion about including the API docs in the sip bindings? I find it horribly cumbersome to keep these updated and it seems like a lot of duplicate effort.

Yes! I also find it very annoying. I will look into that. I can imagine it could be also done using a simple python script that would cut out comments from .h file prior to running vimdiff...

m-kuhn commented 8 years ago

Yes! I also find it very annoying. I will look into that. I can imagine it could be also done using a simple python script that would cut out comments from .h file prior to running vimdiff...

Very good idea! At the same time a couple of other things could be addressed as well:

//! Inline code
bool isActive() const { return mActive; }
//! should be in .sip
bool isActive() const;

//! override
virtual bool requiresAttention() const override;
//! should be in .sip
virtual bool requiresAttention() const;

These would make life a lot easier.

I guess adding fully qualified name to nested classes would be out of scope

//! usage of nested class
void addArrow( Arrow arrow );
//! in .sip
void addArrow( QgsDrawing::Arrow arrow );