I commenti XML sono documenti necessari?

9

Ero un fan di richiedere commenti XML per la documentazione. Da allora ho cambiato idea per due motivi principali:

  1. Like good code, methods should be self-explanatory.
  2. In practice, most XML comments are useless noise that provide no additional value.

Molte volte usiamo GhostDoc per generare commenti generici, e questo è ciò che intendo per rumore inutile:

    /// <summary>
    /// Gets or sets the unit of measure.
    /// </summary>
    /// <value>
    /// The unit of measure.
    /// </value>
    public string UnitOfMeasure { get; set; }

Per me, è ovvio. Detto questo, se ci fossero istruzioni speciali da includere, allora dovremmo assolutamente usare i commenti XML.

Mi piace questo estratto da questo articolo :

Sometimes, you will need to write comments. But, it should be the exception not the rule. Comments should only be used when they are expressing something that cannot be expressed in code. If you want to write elegant code, strive to eliminate comments and instead write self-documenting code.

Ho sbagliato a pensare che dovremmo usare solo commenti XML quando il codice non è sufficiente per spiegarsi da solo?

Credo che questo sia un buon esempio in cui i commenti XML rendono il codice piuttosto brutto. Ci vuole una classe come questa ...

public class RawMaterialLabel : EntityBase
{
    public long     Id                      { get; set; }
    public string   ManufacturerId          { get; set; }
    public string   PartNumber              { get; set; }
    public string   Quantity                { get; set; }
    public string   UnitOfMeasure           { get; set; }
    public string   LotNumber               { get; set; }
    public string   SublotNumber            { get; set; }
    public int      LabelSerialNumber       { get; set; }
    public string   PurchaseOrderNumber     { get; set; }
    public string   PurchaseOrderLineNumber { get; set; }
    public DateTime ManufacturingDate       { get; set; }
    public string   LastModifiedUser        { get; set; }
    public DateTime LastModifiedTime        { get; set; }
    public Binary   VersionNumber           { get; set; }

    public ICollection<LotEquipmentScan> LotEquipmentScans { get; private set; }
}

... E lo trasforma in questo:

/// <summary>
/// Container for properties of a raw material label
/// </summary>
public class RawMaterialLabel : EntityBase
{
    /// <summary>
    /// Gets or sets the id.
    /// </summary>
    /// <value>
    /// The id.
    /// </value>
    public long Id { get; set; }

    /// <summary>
    /// Gets or sets the manufacturer id.
    /// </summary>
    /// <value>
    /// The manufacturer id.
    /// </value>
    public string ManufacturerId { get; set; }

    /// <summary>
    /// Gets or sets the part number.
    /// </summary>
    /// <value>
    /// The part number.
    /// </value>
    public string PartNumber { get; set; }

    /// <summary>
    /// Gets or sets the quantity.
    /// </summary>
    /// <value>
    /// The quantity.
    /// </value>
    public string Quantity { get; set; }

    /// <summary>
    /// Gets or sets the unit of measure.
    /// </summary>
    /// <value>
    /// The unit of measure.
    /// </value>
    public string UnitOfMeasure { get; set; }

    /// <summary>
    /// Gets or sets the lot number.
    /// </summary>
    /// <value>
    /// The lot number.
    /// </value>
    public string LotNumber { get; set; }

    /// <summary>
    /// Gets or sets the sublot number.
    /// </summary>
    /// <value>
    /// The sublot number.
    /// </value>
    public string SublotNumber { get; set; }

    /// <summary>
    /// Gets or sets the label serial number.
    /// </summary>
    /// <value>
    /// The label serial number.
    /// </value>
    public int LabelSerialNumber { get; set; }

    /// <summary>
    /// Gets or sets the purchase order number.
    /// </summary>
    /// <value>
    /// The purchase order number.
    /// </value>
    public string PurchaseOrderNumber { get; set; }

    /// <summary>
    /// Gets or sets the purchase order line number.
    /// </summary>
    /// <value>
    /// The purchase order line number.
    /// </value>
    public string PurchaseOrderLineNumber { get; set; }

    /// <summary>
    /// Gets or sets the manufacturing date.
    /// </summary>
    /// <value>
    /// The manufacturing date.
    /// </value>
    public DateTime ManufacturingDate { get; set; }

    /// <summary>
    /// Gets or sets the last modified user.
    /// </summary>
    /// <value>
    /// The last modified user.
    /// </value>
    public string LastModifiedUser { get; set; }

    /// <summary>
    /// Gets or sets the last modified time.
    /// </summary>
    /// <value>
    /// The last modified time.
    /// </value>
    public DateTime LastModifiedTime { get; set; }

    /// <summary>
    /// Gets or sets the version number.
    /// </summary>
    /// <value>
    /// The version number.
    /// </value>
    public Binary VersionNumber { get; set; }

    /// <summary>
    /// Gets the lot equipment scans.
    /// </summary>
    /// <value>
    /// The lot equipment scans.
    /// </value>
    public ICollection<LotEquipmentScan> LotEquipmentScans { get; private set; }
}
    
posta Bob Horn 22.10.2012 - 16:16
fonte

3 risposte

21

Se i tuoi commenti appaiono solo in questo modo:

/// <summary>
/// Gets or sets the sublot number.
/// </summary>
/// <value>
/// The sublot number.
/// </value>

Allora sì, non sono così utili. Se leggono qualcosa del genere:

/// <summary>
/// Gets or sets the sublot number.
/// Note that the sublot number is only used by the legacy inventory system.
/// Latest version of the online inventory system does not use this, so you can leave it null. 
/// Some vendors require it but if you don't set it they'll send a request for it specifically.
/// </summary>
/// <value>
/// The sublot number.
/// </value>

Quindi direi che hanno un valore. Quindi, per rispondere alla tua domanda: i commenti sono necessari quando dicono qualcosa che il codice non dice.

Un'eccezione: è bello avere commenti su qualsiasi cosa pubblicamente accessibile se stai scrivendo una libreria / API che sarà disponibile al pubblico. Io odio usando una libreria e vedendo una funzione chiamata getAPCDGFSocket() senza spiegazione di cosa sia un APCDGFSocket (sarei felice con qualcosa di semplice come This gets the Async Process Coordinator Data Generator File Socket ). Quindi, in questo caso, direi di usare qualche strumento per generare tutti i commenti e poi modificare manualmente quelli che ne hanno bisogno (e assicurati che gli acronimi criptici siano spiegati).

Inoltre, i getter / setter sono in genere esempi errati di "sono necessari commenti?" perché di solito sono abbastanza ovvi e non sono necessari commenti. I commenti sono più importanti sulle funzioni che eseguono alcuni algoritmi in cui alcune spiegazioni su perché vengono fatte nel modo in cui sono in grado di rendere il codice molto più comprensibile e renderlo più facile per i futuri programmatori con cui lavorare.

... e infine, sono abbastanza sicuro che questa domanda è rilevante per gli stili di commenti tutti , non solo quelli che sono formattati usando XML (che stai usando perché stai lavorando in un ambiente .NET).

    
risposta data 22.10.2012 - 16:24
fonte
5

I commenti che sembrano inutili agli utenti che possono leggere il codice diventano piuttosto utili agli utenti che non hanno accesso alla fonte. Ciò accade quando la classe viene utilizzata come API esterna da persone esterne alla tua organizzazione: gli HTML generati dai tuoi documenti XML sono l'unico modo per conoscere le tue classi.

Detto questo, un commento che reitera il nome del metodo con spazi aggiunti tra le parole rimane inutile. Se la tua classe verrà utilizzata al di fuori della tua organizzazione, devi documentare per evitare che i valori validi siano validi. Ad esempio, dovresti dire che impostare UnitOfMeasure su null è illegale, che il valore fornito al setter non deve contenere spazi all'inizio o alla fine della stringa, e così via. Dovresti anche documentare l'intervallo di LabelSerialNumber se differisce da quello di un Int32 semplice: forse non consente numeri negativi * , o non consente più di sette cifre. I tuoi utenti interni possono darlo per scontato, perché guardano i numeri seriali giorno dopo giorno, ma gli utenti esterni potrebbero essere sinceramente sorpresi di vedere un'eccezione da quello che sembra un setter innocente.

* ... nel qual caso uint potrebbe essere una scelta migliore     
risposta data 22.10.2012 - 16:44
fonte
1

Hai assolutamente ragione nell'evitare commenti così inutili. Rendono la lettura del codice più difficile invece di renderla più semplice e stanno prendendo troppo spazio.

Nella mia pratica le persone che scrivono commenti con getter / setter tendono ad omettere commenti quando sono veramente necessari (come la creazione di una query sql a 20 righe per un componente senza documentazione).

Scrivo commenti quando ci sono altre soluzioni ovvie _ Indico perché esattamente questo approccio è stato usato. O quando è difficile ottenere l'idea senza conoscere tutti i dettagli _ Elenco brevemente i dettagli necessari per comprendere il codice.

L'esempio che porti è più di scrivere commenti per dire che si scrivono commenti piuttosto che rendere la vita degli altri (e anche loro) più facile.

A proposito, puoi migliorare la tua capacità di scrivere commenti tornando al tuo vecchio codice e cercando di comprenderlo (potresti persino non riconoscere il tuo codice in 2-3 mesi _ è assolutamente come leggere il codice di qualcun altro). Se lo fai senza dolore, tutto va bene.

    
risposta data 22.10.2012 - 16:34
fonte