Bones pràctiques
- XML Documentation Comments
- Etiqueta <see> & <seealso>
- Exemples: una classe (mètodes, atributs, propietats...)
- La documentació XML en C#
- Javadoc, JSdoc, PHPdoc...
- EXEMPLE: Esquema d'un README.md
XML Documentation Comments
Etiqueta <see> & <seealso>
La funció principal de l'etiqueta <see> dins dels Comentaris de Documentació XML de C# és crear una referència creuada o un enllaç en línia a un altre element de codi.
Aquesta etiqueta s'utilitza principalment per:
-
Crear Enllaços per a IntelliSense: Permet que eines com Visual Studio mostrin l'element referenciat (una classe, un mètode, una propietat, etc.) com un hiperenllaç que l'usuari pot seguir fàcilment dins la finestra d'informació ràpida (Quick Info) o la documentació generada.
-
Especificar Tipus: Com hem vist, s'utilitza sovint per indicar el tipus d'un paràmetre o el valor d'una propietat dins de les etiquetes
<param>,<returns>o<value>.
Sintaxi
L'etiqueta <see> és una etiqueta buida (sense contingut intern) i només requereix l'atribut cref (que significa "code reference").
<see cref="element"/>
-
cref: Aquest atribut conté el nom qualificat de l'element del codi al qual vols fer referència (p. ex.,System.String,LaMevaClasse,ElMeuMetode(int)).
Exemple
Imagina que tens una classe d'error i un mètode que la pot llançar.
/// <summary>
/// Representa un error quan no es troba l'article.
/// </summary>
public class ArticleNoTrobatException : Exception { }
public class GestorInventari
{
/// <summary>
/// Intenta obtenir un article del magatzem.
/// </summary>
/// <param name="id">L'identificador únic de l'article.</param>
/// <returns>L'objecte Article sol·licitat.</returns>
/// <exception cref="ArticleNoTrobatException">Es llança si l'article amb el <paramref name="id"/> donat no existeix. Veure <see cref="ArticleNoTrobatException"/> per a més detalls.</exception>
public Article ObtenirArticle(int id)
{
// ...
// codi que pot llançar ArticleNoTrobatException
// ...
throw new ArticleNoTrobatException();
}
}
En aquest exemple, l'etiqueta <see cref="ArticleNoTrobatException"/> permet al desenvolupador fer clic directament des de la descripció de l'excepció a la definició de la classe ArticleNoTrobatException.
Important: L'etiqueta <see> es fa servir per a referències en línia dins d'una descripció (com a part d'una frase), mentre que l'etiqueta <seealso> es fa servir per crear una secció separada de "Veure també" al final de la documentació d'un membre.
L'etiqueta <seealso> s'utilitza per indicar elements relacionats que l'usuari podria trobar útils. A diferència de <see>, que insereix un enllaç en línia, <seealso> típicament es renderitza en una secció separada anomenada "Veure També" o "Related Topics" en la documentació final.
<seealso>
Imaginem una classe que gestiona la configuració, i un mètode que llegeix les dades.
/// <summary>
/// Propietat que obté la clau de configuració de la base de dades.
/// </summary>
/// <value>
/// El valor de la clau com a cadena de caràcters (<see cref="string"/>).
/// </value>
/// <seealso cref="ObtenirValorConfiguracio(string)"/>
/// <seealso cref="GuardarValorConfiguracio(string, string)"/>
public string ClauBaseDeDades { get; }
// ---
/// <summary>
/// Llegeix un valor de configuració desat amb el nom especificat.
/// </summary>
/// <param name="clau">El nom de la clau de configuració a buscar.</param>
/// <returns>El valor de configuració associat a la clau.</returns>
/// <seealso cref="ClauBaseDeDades"/>
/// <seealso cref="GuardarValorConfiguracio(string, string)">Mètode per guardar la configuració</seealso>
public string ObtenirValorConfiguracio(string clau)
{
// Codi per obtenir la configuració...
return "Valor";
}
// ---
/// <summary>
/// Desa un nou valor de configuració.
/// </summary>
/// <param name="clau">El nom de la clau de configuració.</param>
/// <param name="valor">El valor a desar.</param>
public void GuardarValorConfiguracio(string clau, string valor)
{
// Codi per guardar la configuració...
}
Com es visualitza <seealso>
Quan es genera la documentació o s'utilitza l'IntelliSense en un entorn com Visual Studio:
-
Quan l'usuari mira la documentació de la propietat
ClauBaseDeDades, veurà una secció al final amb enllaços cap aObtenirValorConfiguracio(string)iGuardarValorConfiguracio(string, string). -
Quan l'usuari mira la documentació del mètode
ObtenirValorConfiguracio, veurà una secció amb enllaços cap a la propietatClauBaseDeDadesi una referència amb el text "Mètode per guardar la configuració" (gràcies al contingut que s'ha posat dins de l'etiqueta).
Utilitzeu <seealso> per a enllaços addicionals, relacionats, però no essencials per entendre la descripció principal.
Exemples: una classe (mètodes, atributs, propietats...)
Classe
/// <summary>
/// Representa un producte disponible a l'inventari.
/// </summary>
/// <remarks>
/// Aquesta classe s'utilitza per gestionar l'estoc, el preu i el nom de cada article.
/// </remarks>
public class Producte
{
// ... membres
}
Atribut (camp / field)
public class Producte
{
/// <summary>
/// El preu intern del producte abans d'aplicar impostos.
/// </summary>
private decimal preuBase;
// ...
}
Per especificar el tipus d'un paràmetre o d'un atribut (camp/camp privat amb propietat) en la Documentació XML de C#, utilitzem l'etiqueta <param> o <value>, i dins d'elles, fem servir l'etiqueta <see cref="Tipus"> o el format de text.
Propietat (property)
Per documentar una propietat (amb get i/o set). S'utilitza l'etiqueta <value> per descriure el valor que representa.
public class Producte
{
/// <summary>
/// Obté o estableix el nom únic del producte.
/// </summary>
/// <value>
/// Un <see cref="string"/> que conté el nom del producte. No pot ser buit.
/// </value>
public string Nom { get; set; }
// ...
}
Especificar el tipus
Per a les propietats, s'utilitza l'etiqueta <value> per descriure el valor que obté o estableix la propietat. Dins de <value>, de nou, s'aconsella usar <see cref="Tipus">.
Exemple
public class Usuari
{
/// <summary>
/// Obté o estableix el nom complet de l'usuari.
/// </summary>
/// <value>
/// Una cadena de caràcters (<see cref="string"/>) que no pot ser nul·la.
/// </value>
public string NomComplet { get; set; }
/// <summary>
/// Obté el nivell d'accés de l'usuari.
/// </summary>
/// <value>
/// Un valor de l'enumeració <see cref="NivellAcces"/>.
/// </value>
public NivellAcces Acces { get; }
}
Mètode (method)
Documentar una acció que pot realitzar la classe. Utilitza <param> per a les entrades i <returns> per a la sortida.
public class Producte
{
/// <summary>
/// Calcula el preu final del producte aplicant l'impost sobre el valor afegit (IVA).
/// </summary>
/// <param name="percentatgeIVA">El percentatge d'IVA a aplicar (ex: 0.21 per al 21%).</param>
/// <returns>
/// El preu total del producte, incloent-hi l'IVA.
/// </returns>
/// <exception cref="ArgumentOutOfRangeException">Llançada si el percentatge d'IVA és negatiu.</exception>
public decimal CalcularPreuTotal(decimal percentatgeIVA)
{
if (percentatgeIVA < 0)
{
throw new ArgumentOutOfRangeException(nameof(percentatgeIVA), "L'IVA no pot ser negatiu.");
}
return preuBase * (1 + percentatgeIVA);
}
}
Funció (mètode Estàtic / funció local)
La documentació de funcions estàtiques o locals segueix el mateix format que els mètodes.
public static class UtilitatsMatematiques
{
/// <summary>
/// Determina si un nombre enter és parell o no.
/// </summary>
/// <param name="nombre">El nombre enter a comprovar.</param>
/// <returns>
/// <c>true</c> si el nombre és parell; <c>false</c> en cas contrari.
/// </returns>
public static bool EsParell(int nombre)
{
// Utilitzem l'operador mòdul per comprovar si el residu de la divisió per 2 és 0.
return nombre % 2 == 0;
}
}
La documentació XML en C#
La Documentació XML és el mètode preferit en C# per incrustar la documentació directament al codi font. Aquests comentaris s'inicien amb tres barres inclinades (///) just abans de la declaració d'un tipus (classe, struct, enum, etc.) o un membre (mètode, propietat, camp, etc.).
Quan compiles el projecte, el compilador de C# pot extreure tots aquests comentaris i generar automàticament un fitxer XML de documentació. Aquest fitxer s'utilitza posteriorment per:
-
Proporcionar IntelliSense a l'IDE (com Visual Studio), mostrant descripcions útils quan es fa servir el codi.
-
Generar automàticament documentació de l'API (similar a Javadoc o Sandcastle).
Etiquetes XML habituals
Aquest format utilitza un conjunt d'etiquetes XML predefinides per estructurar la informació:
| Etiqueta | Funció | S'utilitza per |
<summary> |
Descripció concisa del tipus o membre. | Tots els elements. |
<param name="nom"> |
Descriu un paràmetre d'un mètode. | Mètodes. |
<returns> |
Descriu el valor retornat per un mètode. | Mètodes i funcions. |
<exception cref="Tipus"> |
Documenta una excepció que el codi pot llançar. | Mètodes i propietats. |
<value> |
Descriu el valor d'una propietat. | Propietats. |
<remarks> |
Descripció ampliada i informació addicional. | Tots els elements. |
<see cref="element"> |
Afegir una referencia a un altre element | Tots els elements |
Javadoc, JSdoc, PHPdoc...
Documentació XML vs Javadoc
La Documentació XML de C# (amb ///) s'inspira en el format Javadoc (utilitzat principalment en Java, i amb variants com JSDoc per a JavaScript i PHPDoc per a PHP). Tots aquests formats tenen l'objectiu comú d'incrustar la documentació directament al codi mitjançant etiquetes especials per a la generació automàtica de documentació.
Tot i que la sintaxi és diferent (XML amb /// vs. @etiqueta amb /**), les funcions de les etiquetes principals es corresponen directament:
| Funció de Documentació | C# (Documentació XML) | Java/JS/PHPDoc (Javadoc Style) |
| Descripció Principal | <summary> |
Text lliure abans de la primera @etiqueta |
| Paràmetre | <param name="nom"> |
@param {Tipus} nom |
| Valor Retornat | <returns> |
@return {Tipus} |
| Excepcions/Errors | <exception cref="Tipus"> |
@throws Tipus o @exception Tipus |
| Informació Addicional | <remarks> |
Text lliure addicional o @note |
| Referència Creuada | <see cref="Element"> |
@see Element |
| Descripció de Propietat/Valor | <value> |
Generalment inclòs a la descripció principal. |
Correspondències
Mètodes/Funcions
| C# (Documentació XML) | Javadoc / JSDoc / PHPDoc |
csharp
/// <summary>
/// Calcula el volum d'una esfera.
/// </summary>
/// <param name="radi">El radi de l'esfera.</param>
/// <returns>El volum calculat.</returns>
/// <seealso cref="System.Math.PI"/>
public double CalcularVolum(double radi) |
java
/**
* Calcula el volum d'una esfera.
*
* @param radi El radi de l'esfera.
* @return El volum calculat.
* @see Math#PI
*/
public double calcularVolum(double radi) |
Les etiquetes
| Etiqueta | Funció | C# | Javadoc/JSDoc/PHPDoc |
| Paràmetre | Identifica un argument d'entrada. | <param name="radi"> |
@param radi |
| Retorn | Descriu el valor que surt. | <returns> |
@return |
| Referència | Enllaç a un altre element. | <see cref="Tipus"> |
@see Tipus |
Aquesta similitud en el disseny fa que sigui relativament fàcil per a un desenvolupador canviar entre llenguatges, ja que el concepte de documentació de codi basada en etiquetes és consistent.
Exemple classe C# en Javadoc
Exemple d'una classe desenvolupada en C#, però documentada utilitzant la sintaxi de Javadoc/JSDoc (amb /** ... */ i etiquetes amb @).
RECORDA: Encara que el codi sigui C#, la sintaxis del comentari no és l'estàndard de C# (Documentació XML).
/**
* Classe que representa un Lector (o Usuari) en un sistema de gestió de biblioteca.
*
* @author George Write
* @version 1.1
* @see GestorBiblioteca
*/
public class Lector
{
/**
* Identificador únic del lector.
* <p>Aquest camp és privat i es llegeix a través de la propietat <c>ID</c>.</p>
*
* @type {int}
*/
private int lectorID;
/**
* El nombre màxim de llibres que un lector pot tenir prestats simultàniament.
* Aquest és un valor estàtic per a tots els lectors.
*
* @type {int}
*/
public static int LIMIT_PRESTEC_LLIBRES = 5;
/**
* Constructor per inicialitzar un nou Lector.
*
* @param nomEl nom complet del lector.
* @param identificador L'ID únic assignat.
* @throws IllegalArgumentException Si l'identificador és negatiu.
*/
public Lector(string nom, int identificador)
{
if (identificador < 0)
{
// Noteu que en C# normalment es llançaria ArgumentOutOfRangeException,
// però aquí documentem l'equivalent de Javadoc.
throw new ArgumentException("L'ID no pot ser negatiu.");
}
this.Nom = nom;
this.lectorID = identificador;
}
/**
* Propietat que obté el nom del lector.
*
* @return {string} El nom complet de l'usuari.
*/
public string Nom { get; }
/**
* Mètode per simular el préstec d'un llibre.
*
* @param llibre El títol del llibre que es vol prestar.
* @param dataLimit La data màxima de retorn del llibre.
* @param {bool} haNotificacio Si s'ha d'enviar una notificació per correu electrònic.
* @returns {bool} Retorna 'true' si el préstec ha estat satisfactori.
* @throws PrestecExcesLimitException Quan el lector ja ha superat el <c>LIMIT_PRESTEC_LLIBRES</c>.
* @see #LIMIT_PRESTEC_LLIBRES
*/
public bool PrestarLlibre(string llibre, DateTime dataLimit, bool haNotificacio)
{
// ... (lògica de C#)
return true;
}
}
/**
* Excepció personalitzada que es llança quan el lector intenta prestar
* més llibres dels que el seu límit permet.
*
* @extends Exception
*/
public class PrestecExcesLimitException : Exception
{
// ...
}
Documentació Javadoc en C#
A continuació, s'explica com s'han utilitzat les etiquetes Javadoc per als diferents elements de C#:
| Element C# | Etiqueta Javadoc Utilitzada | Explicació de la Correspondència |
Classe (Lector) |
@author, @version, @see |
Proporcionen metadades i referències creuades. |
Atribut (Camp) (lectorID) |
@type {int} |
S'utilitza la sintaxi de JSDoc/PHPDoc per especificar el tipus de dades d'un camp. |
Propietat (Nom) |
@return {string} |
Es documenta com si fos una funció que només retorna un valor. |
Mètode (PrestarLlibre) |
@param, @returns, @throws |
Les etiquetes principals són idèntiques en funció a les de C# XML (<param>, <returns>, <exception>). |
Excepció (PrestecExcesLimitException) |
@extends Exception |
Indica la classe de la qual hereta l'excepció (equivalent a l'etiqueta JSDoc). |
| Especificar Tipus (Paràmetre) | @param {bool} haNotificacio |
S'utilitza la sintaxi de JSDoc/PHPDoc per especificar el tipus entre claus ({}). |
| Referència Creuada | @see #LIMIT_PRESTEC_LLIBRES |
S'utilitza la sintaxi de Javadoc per referenciar membres dins de la mateixa classe. |
ATENCIÓ: Utilitzar aquest tipus de documentació està generalment desaconsellada en un projecte de C#, ja que el compilador i les eines no podran generar el fitxer XML de documentació ni oferir la funcionalitat d'IntelliSense completa de la mateixa manera que ho farien amb la Documentació XML.
Com seria amb Documentació XML de C#?
La mateixa classe Lector desenvolupada en C#, però aquesta vegada documentada correctament utilitzant l'estàndard de Documentació XML de C# (amb ///).
Aquesta és la manera en què s'ha de documentar el codi de C# per garantir la compatibilitat total amb l'IntelliSense de Visual Studio i les eines de generació de documentació.
/// <summary>
/// Representa un Lector (o Usuari) en un sistema de gestió de biblioteca.
/// </summary>
/// <remarks>
/// Aquesta classe encapsula la informació bàsica d'un usuari i les regles de préstec.
/// </remarks>
/// <seealso cref="GestorBiblioteca"/>
public class Lector
{
/// <summary>
/// Identificador únic del lector.
/// </summary>
/// <remarks>
/// Aquest camp és privat i es llegeix a través d'una propietat pública si és necessari.
/// </remarks>
private int lectorID;
/// <summary>
/// El nombre màxim de llibres que un lector pot tenir prestats simultàniament.
/// </summary>
/// <value>
/// Un <see cref="int"/> que representa el límit per a tots els lectors.
/// </value>
public static int LIMIT_PRESTEC_LLIBRES = 5;
/// <summary>
/// Constructor per inicialitzar un nou <see cref="Lector"/>.
/// </summary>
/// <param name="nom">El nom complet del lector.</param>
/// <param name="identificador">L'ID únic assignat.</param>
/// <exception cref="ArgumentOutOfRangeException">Es llança si l'identificador és negatiu.</exception>
public Lector(string nom, int identificador)
{
if (identificador < 0)
{
throw new ArgumentOutOfRangeException(nameof(identificador), "L'ID no pot ser negatiu.");
}
this.Nom = nom;
this.lectorID = identificador;
}
/// <summary>
/// Obté el nom complet del lector.
/// </summary>
/// <value>
/// El nom complet de l'usuari com a <see cref="string"/>.
/// </value>
public string Nom { get; }
/// <summary>
/// Mètode per simular el préstec d'un llibre al lector.
/// </summary>
/// <param name="llibre">El títol del llibre que es vol prestar.</param>
/// <param name="dataLimit">La data màxima de retorn del llibre, de tipus <see cref="DateTime"/>.</param>
/// <param name="haNotificacio">Indica si s'ha d'enviar una notificació per correu electrònic.</param>
/// <returns>
/// <c>true</c> si el préstec ha estat satisfactori; <c>false</c> en cas d'error o límit.
/// </returns>
/// <exception cref="PrestecExcesLimitException">Quan el lector ja ha superat el <see cref="LIMIT_PRESTEC_LLIBRES"/>.</exception>
public bool PrestarLlibre(string llibre, DateTime dataLimit, bool haNotificacio)
{
// ... (lògica de C#)
return true;
}
}
/// <summary>
/// Excepció personalitzada que es llança quan el lector intenta prestar
/// més llibres dels que el seu límit permet.
/// </summary>
/// <seealso cref="Lector.LIMIT_PRESTEC_LLIBRES"/>
public class PrestecExcesLimitException : Exception
{
// ...
}
Que canvia?
| Element | Format Javadoc | Format XML Documentation (C#) |
| Delimitador | /** ... */ |
/// |
| Descripció general | Text lliure | Etiqueta <summary> |
| Paràmetre | @param nom |
Etiqueta <param name="nom"> |
| Valor retornat | @return |
Etiqueta <returns> |
| Tipus (Referència) | {bool} (sintaxi JSDoc) |
Etiqueta <see cref="bool"/> o <see cref="DateTime"/> |
| Excepció | @throws Tipus |
Etiqueta <exception cref="Tipus"> |
| Valor de propietat | S'implica a @return |
Etiqueta <value> |
Totes les etiquetes de C# són elements XML ben formats, cosa que permet que el compilador pugui processar-los amb èxit.
EXEMPLE: Esquema d'un README.md
Un fitxer README.md ben estructurat és essencial per a qualsevol projecte. Els apartats més interessants a incloure són els que s'indiquen a continuació tot i que aquests aniran en funció del projecte i les seves caracteristiques.
1. Títol i descripció breu
-
Títol Principal: Utilitza un nom clar i concís.
-
Exemple:
# Gestor Universal de Dades [NOM DEL PROJECTE]
-
-
Insígnies (Badges): Estat de la construcció, versió, llicència, etc.
-
Descripció: Una frase o dos que expliqui la funció principal del projecte i la raó de les dues interfícies.
-
Exemple: Aquest projecte proporciona una solució de gestió de dades amb dues interfícies d'usuari: una aplicació Windows Forms (GUI) per a ús interactiu i una aplicació de Consola (CLI) per a automatització i execució amb scripts.
-
2. Estructura i requisits
2.1 Requisits del sistema
-
Plataforma: (Exemple: Windows 10 o superior)
-
Framework: El framework de .NET necessari (Exemple: .NET 8.0, .NET Framework 4.8).
-
Dependències: (Exemple: Base de dades local SQL Server, fitxers de configuració específics).
2.2 Contingut
Descriure breument què conté el directori, especialment la sortida de la compilació.
-
\bin\Release\: Conté els executables.-
NomProjecte.exe: Aplicació Windows Forms (GUI). -
NomProjecte.Consola.exe: Aplicació de Consola (CLI).
-
-
\Docs\: Fitxers de documentació addicional.
3. Aplicació GUI: Windows Forms
Aquesta secció ha de guiar l'usuari sobre com utilitzar la interfície gràfica.
3.1 Instal·lació i execució
-
Com executar: Indica si només cal executar l'
.exedirectament o si requereix una instal·lació (MSI). -
Configuració Inicial: Passos necessaris abans del primer ús (Exemple: "Configureu la connexió a la base de dades a la pestanya 'Configuració'").
3.2 Funcionalitats
Utilitza punts clau per descriure les funcions principals (Exemple: Gestió d'usuaris, Exportació de dades a CSV, Visualització de registres).
4. Aplicació CLI: Consola
Aquesta secció és crucial per a usuaris avançats o automatització. Ha de detallar tots els paràmetres i sortides.
4.1 Utilització bàsica
Explica com es crida l'executable des de la línia d'ordres.
.\NomProjecte.Consola.exe [COMANDA] [OPCIONS]
4.2 Llista de comandes i paràmetres
Utilitza una taula per a una referència ràpida.
| Comanda | Descripció | Paràmetres Obligatoris | Paràmetres Opcionals |
--export |
Exporta dades d'una taula. | --taula <Nom> |
`--format <csv> |
--import |
Importa dades des d'un fitxer. | --fitxer <Ruta> |
--sobreescriu |
--ajuda |
Mostra la documentació. | Cap | Cap |
4.3 Exemples d'ús
Proporciona exemples d'ús que l'usuari pugui copiar i enganxar directament.
📝 Exemple 1: Exportar dades a JSON
# Exporta la taula 'Usuaris' al format JSON
.\NomProjecte.Consola.exe --export --taula Usuaris --format json
📝 Exemple 2: Importar dades sobrescrivint
# Importa dades des d'entrada.csv i sobreescriu els registres existents
.\NomProjecte.Consola.exe --import --fitxer C:\dades\entrada.csv --sobreescriu
5. Instal·lació i desenvolupament
En cas que l'aplicació permeti descarregar el codi font per a afegir funcionalitats, cal donar instruccions als futurs desenvolupadors com podrien continuar la tasca de desenvolupament de noves funcionalitats.
5.1 Obtenció del Codi
git clone https://github.com/el-teu-usuari/nom-projecte.git
5.2 Compilació
-
Requisit: Instal·lar el SDK de .NET.
-
Ordre:
Bashdotnet build NomProjecte.sln --configuration Release
6. Contribució i Llicència
-
Contribució: Instruccions sobre com reportar errors o enviar pull requests.
-
Llicència: Indica la llicència sota la qual es distribueix el projecte (Exemple: MIT).
-
[Enllaç a LICENSE.md]
-
7. Contacte
-
Nom: El teu nom o el de l'equip.
-
Correu Electrònic: (Exemple:
suport@exemple.com)