Doxygen: Difference between revisions

From Bohemia Interactive Community
Jump to navigation Jump to search
(Page creation)
 
(Add Class documentation info + Examples)
Line 1: Line 1:
{{TOC|side}}{{Wiki|WIP}}
{{TOC|side}}
 
'''Doxygen''' is a tool that generates documentation from code comment respecting a certain format. This code documentation is used across [[Enfusion]] projects, starting with {{armaR}}.
 
'''Doxygen''' is a tool that generates documentation from code comment respecting a certain format.


{{Feature|informative|
{{Feature|informative|
Line 14: Line 12:
== Project Documentation ==
== Project Documentation ==


{{Feature|armaR|{{armaR}}'s Doxygen documentation can be found {{Link|{{SERVER}}/Doxygen/arma-reforger/|here}}.}}
{{Wiki|WIP|{{armaR}}'s Doxygen documentation is to be released and linked.}}
<!--{{Feature|arma4|{{arma4}}'s Doxygen documentation can be found {{Link|{{SERVER}}/Doxygen/arma-reforger/|here}}.}}-->
<!--{{Feature|armaR|{{armaR}}'s Doxygen documentation can be found {{Link|{{SERVER}}/Doxygen/arma-reforger/|here}}.}}
{{Feature|arma4|{{arma4}}'s Doxygen documentation can be found {{Link|{{SERVER}}/Doxygen/arma-reforger/|here}}.}}-->




Line 25: Line 24:
* Document what is '''important''' (features, concepts, specifics like variables or constants, etc)
* Document what is '''important''' (features, concepts, specifics like variables or constants, etc)
* Document what is '''dangerous''' (performance-wise, crash-wise)
* Document what is '''dangerous''' (performance-wise, crash-wise)
{{Name|bi}} recommendations:
* use {{hl|/*! */}} and {{hl|//!}}; format {{hl|/** */}} is avoided.
* do not go too much into details (e.g <enforce inline>//! This method does xxx if provided Y but will not do it if Z is set to true at line 246 and ...</enforce>)
* do not over-document code (<enforce inline>m_iVar++; // increments m_iVar by 1</enforce> is of absolutely no value) again, code should be self-explanatory and a comment should explain a design decision (if needed)
{{Feature|important|
Reminder: an eventual '''code''' comment tells '''''why''''' code is done this way,
'''method''' comment plainly explains '''''what''''' the method does / when it should be used,
and '''class''' comment explains the whole system / feature of this class.<br>
For a system / feature that spans across multiple classes, Doxygen grouping is required. See {{Link|https://www.doxygen.nl/manual/grouping.html|Doxygen Grouping}} documentation.
}}


=== Class ===
=== Class ===
A class documentation explains what the class does. It can add said class to groups (see Doxygen's {{Link|https://www.doxygen.nl/manual/grouping.html|grouping}} documentation).
Grouping is usually done in a different comment block than class comment.
<enforce>
/*!
This class is a databag used by the TAG_WholeSystemClass's WholeSystem feature.
Member variables are public for that purpose. It holds info X and Y related to Z.
*/
class TAG_MyDataClass
{
bool m_bIsValid;
int m_iNumber;
ref TAG_OtherDataClass m_OtherData;
}
</enforce>


=== Method ===
=== Method ===
Line 39: Line 67:
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
/*!
/*!
doc goes here
Documentation goes here with the same indent
*/
*/
int GetIntMethod1(bool returnPositive)
int GetIntMethod1(bool returnPositive)
Line 58: Line 86:
<enforce>
<enforce>
//! \param myParam parameter description
//! \param myParam parameter description
//! \param myParam[out] parameter description
//! \param[out] myParam parameter description
//! \param myParam[inout] parameter description
//! \param[inout] myParam parameter description
</enforce>
</enforce>


Line 66: Line 94:
//! \return return value description
//! \return return value description
</enforce>
</enforce>
To be used when a <enforce inline>void</enforce> signature is not used.


=== Variable ===
=== Variable ===
Line 73: Line 102:
protected float m_fVar1;
protected float m_fVar1;


protected float m_fVar2; //!< or like this - the '<' symbol states "document what just precedes"
protected float m_fVar2; //!< or like this - the '<' symbol means "document what just precedes"
</enforce>
 
 
== Examples ==
 
=== Do ===
 
This example is taken from {{Link/Enfusion|armaR|SCR_ObstacleDetector}}:
<enforce>
//------------------------------------------------------------------------------------------------
//! Detects obstacles based on current settings - a SCR_ObstacleDetector.RefreshObstaclesBy*() method must have been called earlier
//! \param worldPos the location to check - only the 2D position will be checked
//! \param exclusionList list of entities that should not be considered as obstacles
//! \return true if an obstacle has been detected or on error, false otherwise
bool HasObstacle(vector worldPos, array<IEntity> exclusionList = null)
</enforce>
 
This comment is fine for multiple reasons:
* the main description states the method's goal and usage condition
* parameters are documented and specifics (when present) are explained
* the return value is described accurately
* error cases are covered
 
=== Don't ===
 
{| class="wikitable" style="width: 100%"
! Example
! Explanation
|-
| <enforce>
//------------------------------------------------------------------------------------------------
//! Returns true if has obstacle
bool HasObstacle(vector worldPos, array<IEntity> exclusionList = null)
</enforce>
|
* the description is straightforward but does not provide context
* parameters are not described
* return value is included in the description and only covers one case (when everything works)
|-
| <enforce>
//------------------------------------------------------------------------------------------------
//! Returns true if has obstacle
//! \param worldPos the world position
//! \param exclusionList the exclusion list
//! \return true or false
bool HasObstacle(vector worldPos, array<IEntity> exclusionList = null)
</enforce>
|
* the description is still straightforward without context
* parameter descriptions are based on their name and do not help understanding further
* the return value's description describes the value itself and not the added value
|-
| <enforce>
//------------------------------------------------------------------------------------------------
//! Returns false when an obstacle is detected
bool HasObstacle(vector worldPos, array<IEntity> exclusionList = null)
</enforce>
</enforce>
|
This one is one of the worst possible cases: '''no comment is better than a wrong comment'''.<br>
Prefer leaving it undocumented (ideally with a TODO) if you do not have the time to document your code at the moment.
|}





Revision as of 00:28, 25 May 2023

Doxygen is a tool that generates documentation from code comment respecting a certain format. This code documentation is used across Enfusion projects, starting with Arma Reforger.

What is not documented does not exist!


Project Documentation

🏗
This article is a work in progress! Reason: Arma Reforger's Doxygen documentation is to be released and linked.


Bohemia Interactive Guidelines

Documentation is important:

  • Document what is public (protected methods go second - people should use public methods anyway)
  • Document what is important (features, concepts, specifics like variables or constants, etc)
  • Document what is dangerous (performance-wise, crash-wise)


Bohemia Interactive recommendations:

  • use /*! */ and //!; format /** */ is avoided.
  • do not go too much into details (e.g //! This method does xxx if provided Y but will not do it if Z is set to true at line 246 and ...)
  • do not over-document code (m_iVar++; // increments m_iVar by 1 is of absolutely no value) again, code should be self-explanatory and a comment should explain a design decision (if needed)
Reminder: an eventual code comment tells why code is done this way,

method comment plainly explains what the method does / when it should be used, and class comment explains the whole system / feature of this class.

For a system / feature that spans across multiple classes, Doxygen grouping is required. See Doxygen Grouping documentation.

Class

A class documentation explains what the class does. It can add said class to groups (see Doxygen's grouping documentation). Grouping is usually done in a different comment block than class comment.

/*! This class is a databag used by the TAG_WholeSystemClass's WholeSystem feature. Member variables are public for that purpose. It holds info X and Y related to Z. */ class TAG_MyDataClass { bool m_bIsValid; int m_iNumber; ref TAG_OtherDataClass m_OtherData; }

Method

A method documentation goes below the //--- separator and must ideally document the method's purpose, its parameters, and its return value.

Always amend the documentation when changing a method's signature!

class Example { //------------------------------------------------------------------------------------------------ /*! Documentation goes here with the same indent */ int GetIntMethod1(bool returnPositive) { // method content } //------------------------------------------------------------------------------------------------ //! Alternative syntax int GetIntMethod2(bool returnPositive) { // method content } }

Various parameter formats:

//! \param myParam parameter description //! \param[out] myParam parameter description //! \param[inout] myParam parameter description

Only one return format:

//! \return return value description

To be used when a void signature is not used.

Variable

//! a member variable can be documented like this protected float m_fVar1; protected float m_fVar2; //!< or like this - the '<' symbol means "document what just precedes"


Examples

Do

This example is taken from SCR_ObstacleDetector:

//------------------------------------------------------------------------------------------------ //! Detects obstacles based on current settings - a SCR_ObstacleDetector.RefreshObstaclesBy*() method must have been called earlier //! \param worldPos the location to check - only the 2D position will be checked //! \param exclusionList list of entities that should not be considered as obstacles //! \return true if an obstacle has been detected or on error, false otherwise bool HasObstacle(vector worldPos, array<IEntity> exclusionList = null)

This comment is fine for multiple reasons:

  • the main description states the method's goal and usage condition
  • parameters are documented and specifics (when present) are explained
  • the return value is described accurately
  • error cases are covered

Don't

Example Explanation
//------------------------------------------------------------------------------------------------ //! Returns true if has obstacle bool HasObstacle(vector worldPos, array<IEntity> exclusionList = null)
  • the description is straightforward but does not provide context
  • parameters are not described
  • return value is included in the description and only covers one case (when everything works)
//------------------------------------------------------------------------------------------------ //! Returns true if has obstacle //! \param worldPos the world position //! \param exclusionList the exclusion list //! \return true or false bool HasObstacle(vector worldPos, array<IEntity> exclusionList = null)
  • the description is still straightforward without context
  • parameter descriptions are based on their name and do not help understanding further
  • the return value's description describes the value itself and not the added value
//------------------------------------------------------------------------------------------------ //! Returns false when an obstacle is detected bool HasObstacle(vector worldPos, array<IEntity> exclusionList = null)

This one is one of the worst possible cases: no comment is better than a wrong comment.
Prefer leaving it undocumented (ideally with a TODO) if you do not have the time to document your code at the moment.


See Also