Czy komentarze XML są niezbędną dokumentacją?

10

Kiedyś byłem fanem wymagania komentarzy XML do dokumentacji. Od tego czasu zmieniłem zdanie z dwóch głównych powodów:

  1. Podobnie jak dobry kod, metody powinny być zrozumiałe.
  2. W praktyce większość komentarzy XML to bezużyteczny szum, który nie zapewnia żadnej dodatkowej wartości.

Wiele razy po prostu używamy GhostDoc do generowania ogólnych komentarzy, a to rozumiem przez bezużyteczny hałas:

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

Dla mnie to oczywiste. Powiedziawszy to, jeśli byłyby specjalne instrukcje do włączenia, powinniśmy bezwzględnie używać komentarzy XML.

Podoba mi się ten fragment tego artykułu :

Czasami będziesz musiał pisać komentarze. Ale powinien to być wyjątek, a nie reguła. Komentarze powinny być używane tylko wtedy, gdy wyrażają coś, czego nie można wyrazić w kodzie. Jeśli chcesz napisać elegancki kod, postaraj się wyeliminować komentarze, a zamiast tego napisz kod samodokumentujący.

Czy mylę się, sądząc, że powinniśmy używać komentarzy XML tylko wtedy, gdy kod nie wystarcza do samodzielnego wyjaśnienia?

Uważam, że to dobry przykład, w którym komentarze XML sprawiają, że ładny kod wygląda brzydko. To wymaga takiej klasy ...

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; }
}

... I zamienia to w to:

/// <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; }
}
Bob Horn
źródło
2
Twierdziłbym, że XML jest strasznym wyborem do tego celu. Jest to zbyt szczegółowe i ogólne, aby można było z niego skorzystać. Sprawdź reStructuredText i sphinx, aby znaleźć język znaczników, który osadza się w komentarzach, nie czyniąc ich nieczytelnymi.
Latty
2
@Lattyware: VisualStudio domyślnie obsługuje ten styl, nie są wymagane żadne dodatkowe wtyczki ani narzędzia. Komentarze wygenerowane w ten sposób są natychmiast widoczne w wyskakujących podpowiedziach.
FrustratedWithFormsDesigner
@FrustratedWithFormsDesigner Powiedziałbym, że warto pobrać wtyczkę, aby kod był znacznie bardziej czytelny. Wbudowana obsługa reST z takimi podpowiedziami jest w PyCharm, więc jestem pewien, że istnieją wtyczki dla innych języków w innych IDE. Oczywiście, jeśli masz projekt, w którym wszystko jest udokumentowane w ten sposób, nie sugeruję, abyś zaczął dzielić sposób, w jaki to się robi, ale w przypadku nowych projektów, po prostu uważam, że jest to okropne do przeczytania i utrzymania.
Latty

Odpowiedzi:

21

Jeśli twoje komentarze wyglądają tylko tak:

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

Zatem tak, nie są one tak przydatne. Jeśli przeczytają coś takiego:

/// <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>

Powiedziałbym, że mają wartość. Aby odpowiedzieć na twoje pytanie: komentarze są konieczne, gdy mówią coś, czego nie mówi kod.

Wyjątek: dobrze jest mieć komentarze do wszystkiego, co jest publicznie dostępne, jeśli piszesz bibliotekę / interfejs API, który będzie dostępny publicznie. I hate użyciu biblioteki i widząc funkcję o nazwie getAPCDGFSocket()bez wyjaśnienia co za APCDGFSocket jest (byłbym zadowolony z czegoś tak prostego jak This gets the Async Process Coordinator Data Generator File Socket). W takim razie powiedziałbym, że użyj jakiegoś narzędzia do wygenerowania wszystkich komentarzy, a następnie ręcznie popraw te, które tego potrzebują (i upewnij się, że wyjaśniono twoje tajemnicze akronimy).

Ponadto pobierające / ustawiające są ogólnie złymi przykładami dla „czy komentarze są konieczne?” ponieważ są zwykle dość oczywiste, a komentarze nie są konieczne. Komentarze są ważniejsze dla funkcji wykonujących pewien algorytm, w których wyjaśnienie, dlaczego tak się dzieje, może uczynić kod znacznie bardziej zrozumiałym, a także ułatwić pracę przyszłym programistom.

... i wreszcie jestem całkiem pewien, że to pytanie dotyczy wszystkich stylów komentarzy, nie tylko tych sformatowanych przy użyciu XML (których używasz, ponieważ pracujesz w środowisku .NET).

FrustratedWithFormsDesigner
źródło
2
+1 - GhostDoc jest dla mnie punktem wyjścia do przekształcenia pierwszej wersji, która jest podstawką, w drugą wersję, która zawiera szczegółową wiedzę w dziedzinie.
Jesse C. Slicer
4
+1 za część dlaczego . Obowiązuje zasada DRY - nie powtarzaj się, a jeśli kod już dobrze radzi sobie z opisywaniem tego, jaka część, twoje komentarze powinny koncentrować się na wyjaśnieniu czegoś innego (zazwyczaj dlaczego ).
Daniel B
@DanielB, a może wcale nie potrzebujesz komentarzy;) W większości zgadzam się z tą odpowiedzią, z wyjątkiem słowa niezbędnego w „Komentarze są konieczne, gdy mówią coś, czego nie mówi kod”. Myślę, że jeśli kod mówi wszystko, co potrzebne, to nie potrzebujesz więcej informacji w komentarzach, nawet jeśli komentarze podają informacje spoza kodu.
Jimmy Hoffa
1
@DanielB - Komentarze XML w .NET są przeznaczone głównie do sytuacji, gdy programista końcowy biblioteki lub usługi nie ma dostępnego kodu źródłowego.
jfrankcarr
2
@Lattyware - Komentarze XML bezproblemowo integrują się z Intellisense programu Visual Studio, co znacznie oszczędza czas w porównaniu z wyszukiwaniem rzeczy w osobnym dokumencie.
jfrankcarr
5

Komentarze, które wydają się bezużyteczne dla użytkowników, którzy potrafią odczytać kod, stają się raczej przydatne dla użytkowników, którzy nie mają dostępu do źródła. Dzieje się tak, gdy klasa jest używana jako zewnętrzny interfejs API przez osoby spoza organizacji: HTML-y generowane z twoich dokumentów XML to ich jedyny sposób na poznanie twoich klas.

To powiedziawszy, komentarz powtarzający nazwę metody z dodanymi spacjami między słowami pozostaje bezużyteczny. Jeśli twoja klasa będzie wykorzystywana poza organizacją, musisz udokumentować co najmniej prawidłowe zakresy swoich wartości. Na przykład powinieneś powiedzieć, że ustawienie UnitOfMeasureto nulljest nielegalne, że wartość podana setterowi nie może zawierać spacji na początku lub na końcu łańcucha itd. Powinieneś także udokumentować zakres, LabelSerialNumberjeśli różni się on od zwykłego Int32: być może nie pozwala na liczby ujemne *lub nie dopuszcza więcej niż siedmiu cyfr. Twoi użytkownicy wewnętrzni mogą przyjąć to za pewnik, ponieważ codziennie patrzą na numery seryjne, ale użytkownicy zewnętrzni mogą być naprawdę zaskoczeni, widząc wyjątek od czegoś, co wygląda jak niewinny setter.


* ... w takim przypadku uintmoże być lepszym wyborem

dasblinkenlight
źródło
1
Nie dotyczy to tylko sytuacji, gdy nie masz źródła. Jeśli Twój edytor może je parsować (tak jak Visual Studio robi z komentarzami Xml), może podawać informacje w postaci kursora myszy / wyskakujących okienek bez konieczności przechodzenia do innego pliku. Walidator zakresu 1 linii, który ogranicza liczbę int do węższego zakresu, jest oczywisty, gdy przejdziesz do pliku, w którym zaimplementowany jest setter; ale gdy „FrobableID musi wynosić od 0 do 1000”, pojawia się, gdy zaczynasz pisać „myFrobable.Fro ...”, a autouzupełnianie uruchamia nam pomocne przypomnienie.
Dan Is Fiddling By Firelight
1

Masz całkowitą rację, unikając takich bezużytecznych komentarzy. Utrudniają czytanie kodu zamiast go ułatwiać i zajmują zbyt dużo miejsca.

W mojej praktyce ludzie, którzy piszą komentarze za pomocą metod pobierających / ustawiających, zwykle pomijają komentarze, gdy są one naprawdę konieczne (np. Budują 20-wierszowe zapytanie SQL dla komponentu bez dokumentacji).

Piszę komentarze, gdy istnieją inne oczywiste rozwiązania _ Wskazuję, dlaczego dokładnie zastosowano to podejście. Lub gdy trudno jest zrozumieć ten pomysł bez znajomości wszystkich szczegółów _ krótko wymieniam szczegóły niezbędne do zrozumienia kodu.

Przywołujesz przykład pisania komentarzy, aby powiedzieć, że ktoś pisze komentarze, zamiast ułatwiać życie innym (i ich także).

BTW, możesz poprawić swoją zdolność do pisania komentarzy, wracając do starego kodu i próbując go zrozumieć (możesz nawet nie rozpoznać własnego kodu w ciągu 2-3 miesięcy _ to absolutnie jak czytanie kodu innej osoby). Jeśli zrobisz to bezboleśnie, wszystko będzie w porządku.

superM
źródło
Nie znam nikogo, kto by się starał pisać komentarze na temat pobierających / ustawiających. Jeśli używasz prawie dowolnego nowoczesnego IDE (a nawet zaawansowane edytory tekstu mogą to obsługiwać za pomocą wtyczek), programy pobierające i ustawiające można zwykle bardzo łatwo dokumentować jednym lub dwoma kliknięciami myszy lub odpowiednim naciśnięciem klawisza (jeśli zostało skonfigurowane). Czasami są generowane automatycznie, gdy generujesz kod na podstawie schematu bazy danych lub WSDL ...
FrustratedWithFormsDesigner
@FrustratedWithFormsDesigner, osoba, o której mówiłem, opuściła firmę i uważam, że wszystkie te komentarze dotyczące osób pobierających / ustawiających zostały zrobione przez tę osobę, aby pokazać, że on / ona
postarał
Czy wszystkie uwagi bogo zostały wprowadzone po powiadomieniu osoby? Widziałem, jak ludzie tworzą puste / bezużyteczne komentarze XML w tym miejscu, co jest kościstym sposobem na powstrzymanie VS przed generowaniem ostrzeżeń „Brakujący komentarz xml do publicznie widocznych ostrzeżeń Foo”.
Dan Is Fiddling By Firelight
@ Dan Neely, myślę, że ta osoba tak naprawdę nie dbała i po prostu dodała komentarze, aby powiedzieć, że komentarze zostały dodane. Zazwyczaj nie zwracamy uwagi na komentarze, ale jeśli ktoś ma odejść i pracuje nad komponentem, trzeba napisać czytelny kod.
superM