Komentar Kode Bersih vs dokumentasi kelas

83

Saya sedang berdiskusi dengan kolega baru saya mengenai komentar. Kami berdua menyukai Kode Bersih , dan saya baik-baik saja dengan fakta bahwa komentar kode sebaris harus dihindari dan bahwa nama kelas dan metode harus digunakan untuk mengekspresikan apa yang mereka lakukan.

Namun, saya penggemar menambahkan ringkasan kelas kecil yang mencoba menjelaskan tujuan kelas dan apa yang sebenarnya diwakili, terutama sehingga mudah untuk mempertahankan pola prinsip tanggung jawab tunggal . Saya juga terbiasa menambahkan ringkasan satu baris ke metode yang menjelaskan apa yang seharusnya dilakukan oleh metode tersebut. Contoh khas adalah metode sederhana

public Product GetById(int productId) {...}

Saya menambahkan ringkasan metode berikut

/// <summary>
/// Retrieves a product by its id, returns null if no product was found.
/// </summary

Saya percaya bahwa fakta bahwa metode mengembalikan null harus didokumentasikan. Pengembang yang ingin memanggil metode tidak harus membuka kode saya untuk melihat apakah metode mengembalikan nol atau melempar pengecualian. Terkadang ini merupakan bagian dari antarmuka, sehingga pengembang bahkan tidak tahu kode mana yang sedang berjalan?

Namun, kolega saya berpikir bahwa komentar semacam ini adalah " bau kode " dan bahwa "komentar selalu gagal" ( Robert C. Martin ).

Apakah ada cara untuk mengekspresikan dan mengkomunikasikan jenis pengetahuan ini tanpa menambahkan komentar? Karena saya penggemar berat Robert C. Martin, saya jadi agak bingung. Apakah ringkasan sama dengan komentar dan karenanya selalu gagal?

Ini bukan pertanyaan tentang komentar sebaris.

Bjorn
sumber
38
Robert Martin berkata "Komentar selalu gagal"? Nah, kalau begitu dia ekstremis pinggiran, dan harus diambil dengan sedikit garam. (Ya, saya sadar bahwa ia menulis seperti ini untuk tujuan retoris, untuk menyampaikan pesannya. Maksud saya adalah, Anda juga harus demikian .)
Kilian Foth
18
Buku-buku Paman Bob harus datang dengan 1 kg karung garam ...
AK_
6
Jika Anda mengikuti Robert Martin, dokumentasi untuk kasus nol harus menjadi ujian. Artinya, Anda harus memiliki tes yang menunjukkan dalam hal mana metode ini dapat mengembalikan nol. Atau, karena ini adalah Java, anotasi @Nullable juga akan lebih baik daripada komentar.
Martin Epsz
15
@Bjorn Saya memiliki salinan Kode Bersih dan telah membacanya dari depan hingga belakang lebih dari sekali. Ya, Paman Bob lebih suka kode untuk mendokumentasikan diri, tetapi ada beberapa contoh komentar dalam kode sendiri dalam buku . Intinya adalah jika Anda merasa terdorong untuk menulis komentar, cobalah benar-benar sulit untuk mengubah kode daripada menambahkan komentar, tetapi jangan melarang komentar sepenuhnya (bahkan komentar in-line).
6
Metode ini harus disebut TryGetById dan komentar harus dihapus.
usr

Jawaban:

116

Seperti yang dikatakan orang lain, ada perbedaan antara komentar yang mendokumentasikan API dan komentar in-line. Dari sudut pandang saya, perbedaan utama adalah bahwa komentar in-line dibaca di samping kode , sedangkan komentar dokumentasi dibaca di samping tanda tangan apa pun yang Anda komentari.

Dengan ini, kita dapat menerapkan prinsip KERING yang sama . Apakah komentar mengatakan hal yang sama dengan tanda tangan? Mari kita lihat contoh Anda:

Mengambil produk berdasarkan id-nya

Bagian ini hanya mengulangi apa yang sudah kita lihat dari nama GetByIdplus jenis kembali Product. Ini juga menimbulkan pertanyaan apa perbedaan antara "mendapatkan" dan "mengambil", dan apa yang membawa kode vs komentar tentang perbedaan itu. Jadi itu tidak perlu dan sedikit membingungkan. Jika ada, itu menghalangi bagian kedua dari komentar yang benar-benar bermanfaat:

mengembalikan nol jika tidak ada produk yang ditemukan.

Ah! Itu adalah sesuatu yang kita pasti tidak tahu pasti hanya dari tanda tangan, dan memberikan informasi yang bermanfaat.


Sekarang, selangkah lebih maju. Ketika orang berbicara tentang komentar ketika kode berbau, pertanyaannya bukanlah apakah kode seperti itu membutuhkan komentar, tetapi apakah komentar menunjukkan bahwa kode dapat ditulis lebih baik, untuk mengekspresikan informasi dalam komentar. Itulah yang dimaksud dengan "bau kode" - itu tidak berarti "jangan lakukan ini!", Itu berarti "jika Anda melakukan ini, itu bisa menjadi pertanda ada masalah".

Jadi, jika kolega Anda memberi tahu Anda komentar ini tentang null adalah bau kode, Anda cukup bertanya kepada mereka: "Oke, bagaimana saya harus mengungkapkan ini?" Jika mereka memiliki jawaban yang layak, Anda telah mempelajari sesuatu. Jika tidak, itu mungkin akan mematikan keluhan mereka.


Mengenai kasus khusus ini, umumnya masalah nol dikenal sebagai masalah yang sulit. Ada alasan mengapa basis kode dipenuhi dengan klausa penjaga, mengapa cek nol adalah prasyarat populer untuk kontrak kode, mengapa keberadaan null disebut sebagai "kesalahan miliaran dolar". Tidak ada banyak opsi yang layak. Namun, yang populer di C # adalah Try...konvensi:

public bool TryGetById(int productId, out Product product);

Dalam bahasa lain, mungkin idiom untuk menggunakan tipe (sering disebut sesuatu seperti Optionalatau Maybe) untuk menunjukkan hasil yang mungkin ada atau tidak ada di sana:

public Optional<Product> GetById(int productId);

Jadi, sikap anti-komentar ini telah membawa kita ke suatu tempat: setidaknya kita telah memikirkan apakah komentar ini mewakili bau, dan alternatif apa yang mungkin ada bagi kita.

Apakah kita benar - benar harus memilih ini daripada tanda tangan asli adalah debat lain, tetapi kita setidaknya memiliki opsi untuk mengekspresikan melalui kode daripada komentar apa yang terjadi ketika tidak ada produk yang ditemukan. Anda harus mendiskusikan dengan kolega Anda opsi mana yang menurut mereka lebih baik dan mengapa, dan semoga membantu melangkah lebih jauh dari pernyataan dogmatis tentang komentar.

Ben Aaronson
sumber
9
Atau Linq-setara dari Try...,, ...OrDefaultyang kembali default(T)jika klausa akan mengarah pada hasil kosong.
Bart van Nierop
4
Saya sangat menghargai perbedaan Anda antara inline-code-comment dan komentar dokumentasi, dan contoh-contoh yang diberikan :)
Rachel
2
Nilai pengembalian yang mungkin dari suatu fungsi harus jelas dengan tanda tangannya. The TryGetValuePola adalah cara yang masuk akal untuk melakukan hal ini di C #, tapi bahasa yang paling fungsional memiliki cara yang lebih baik untuk mewakili nilai yang hilang. Baca lebih lanjut di sini
AlexFoxGill
2
@ BenAaronson: Jika seseorang ingin memiliki antarmuka generik yang dapat mendukung kovarians, seseorang dapat menggunakan salah satu T TryGetValue(params, ref bool success)untuk semua jenis T, atau T TryGetValue(params), dengan nol menunjukkan kegagalan, untuk tipe T yang dibatasi kelas, tetapi TryGetXXpola yang mengembalikan booltidak sesuai dengan kovarians.
supercat
6
Di Java 8, Anda bisa mengembalikan sebuah Optional<Product>untuk menunjukkan bahwa mungkin tidak ada Produk yang dikembalikan dari metode.
Wim Deblauwe
102

Kutipan Robert C. Martin diambil di luar konteks. Berikut ini kutipan dengan konteks yang sedikit lebih banyak:

Tidak ada yang bisa sangat membantu sebagai komentar yang ditempatkan dengan baik. Tidak ada yang dapat mengacaukan modul lebih dari komentar dogmatis sembrono. Tidak ada yang bisa begitu merusak seperti komentar crufty tua yang menyebarkan kebohongan dan informasi yang salah.

Komentar tidak seperti Daftar Schindler. Mereka bukan "murni baik." Memang, komentar, paling tidak, adalah kejahatan yang perlu. Jika bahasa pemrograman kami cukup ekspresif, atau jika kami memiliki bakat untuk menggunakan bahasa tersebut secara halus untuk mengekspresikan niat kami, kami tidak akan terlalu membutuhkan komentar - mungkin tidak sama sekali.

Penggunaan komentar yang tepat adalah untuk mengkompensasi kegagalan kami untuk mengekspresikan diri dalam kode. Perhatikan bahwa saya menggunakan kata gagal. Aku serius. Komentar selalu gagal. Kita harus memilikinya karena kita tidak bisa selalu mencari cara untuk mengekspresikan diri tanpa mereka, tetapi penggunaannya bukan merupakan alasan untuk perayaan.

Jadi ketika Anda menemukan diri Anda dalam posisi di mana Anda perlu menulis komentar, pikirkan itu dan lihat apakah tidak ada cara untuk membalik tabel dan mengekspresikan diri Anda dalam kode. Setiap kali Anda mengekspresikan diri dalam kode, Anda harus menepuk punggung Anda. Setiap kali Anda menulis komentar, Anda harus meringis dan merasakan kegagalan kemampuan berekspresi Anda.

(Disalin dari sini , tetapi kutipan asli dari Clean Code: A Handbook of Agile Software Craftsmanship )

Bagaimana kutipan ini direduksi menjadi "Komentar selalu gagal" adalah contoh yang baik tentang bagaimana beberapa orang akan mengambil kutipan yang masuk akal dari konteks dan mengubahnya menjadi dogma bodoh.


Dokumentasi API (seperti javadoc) seharusnya mendokumentasikan API sehingga pengguna dapat menggunakannya tanpa harus membaca kode sumber . Jadi dalam hal ini dokumentasi harus menjelaskan apa metode ini. Sekarang Anda dapat berargumen bahwa "Mengambil produk dengan id-nya" berlebihan karena sudah ditunjukkan oleh nama metode, tetapi informasi yang nulldapat dikembalikan pasti penting untuk didokumentasikan, karena ini tidak dengan cara apa pun yang jelas.

Jika Anda ingin menghindari perlunya komentar, Anda harus menghapus masalah mendasar (yang merupakan penggunaan nullsebagai nilai pengembalian yang valid), dengan membuat API lebih eksplisit. Misalnya Anda dapat mengembalikan beberapa jenis Option<Product>, jadi tanda tangan jenis itu sendiri mengkomunikasikan dengan jelas apa yang akan dikembalikan jika produk tidak ditemukan.

Tetapi bagaimanapun juga tidak realistis untuk mendokumentasikan API sepenuhnya hanya melalui nama metode dan tipe tanda tangan. Gunakan komentar dokumen untuk informasi tambahan yang tidak jelas yang harus diketahui pengguna. Ambil katakan dokumentasi API dari DateTime.AddMonths()dalam BCL:

Metode AddMonths menghitung bulan dan tahun yang dihasilkan, dengan mempertimbangkan tahun kabisat dan jumlah hari dalam sebulan, kemudian menyesuaikan bagian hari dari objek DateTime yang dihasilkan. Jika hari yang dihasilkan bukan hari yang valid di bulan yang dihasilkan, hari valid terakhir dari bulan yang dihasilkan digunakan. Misalnya, 31 Maret + 1 bulan = 30 April. Bagian waktu-hari dari objek DateTime yang dihasilkan tetap sama dengan instance ini.

Tidak mungkin Anda bisa mengungkapkan ini hanya dengan menggunakan nama metode dan tanda tangan! Tentu saja dokumentasi kelas Anda mungkin tidak memerlukan tingkat detail ini, itu hanya sebuah contoh.


Komentar sebaris juga tidak buruk.

Bad komentar buruk. Misalnya komentar yang hanya menjelaskan apa yang bisa dilihat sepele dari kode, contoh klasiknya adalah:

// increment x by one
x++;

Komentar yang menjelaskan sesuatu yang dapat dibuat jelas dengan mengganti nama variabel atau metode atau merestrukturisasi kode, adalah bau kode:

// data1 is the collection of tasks which failed during execution
var data1 = getData1();

Ini adalah jenis komentar yang menentang Martin. Komentar adalah gejala kegagalan menulis kode yang jelas - dalam hal ini menggunakan nama yang jelas untuk variabel dan metode. Komentar itu sendiri tentu saja bukan masalahnya, masalahnya adalah kita perlu komentar untuk memahami kode.

Tetapi komentar harus digunakan untuk menjelaskan segala sesuatu yang tidak jelas dari kode, misalnya mengapa kode ditulis dengan cara yang tidak jelas:

// need to reset foo before calling bar due to a bug in the foo component.
foo.reset()
foo.bar();

Komentar yang menjelaskan apa yang dilakukan sepotong kode yang terlalu berbelit-belit juga merupakan bau, tetapi perbaikannya bukan untuk melarang komentar, perbaikannya adalah memperbaiki kodenya! Dengan kata lain, kode berbelit-belit memang terjadi (semoga hanya sementara sampai refactor) tetapi tidak ada pengembang biasa yang menulis kode bersih sempurna pertama kali. Ketika kode berbelit-belit terjadi, jauh lebih baik menulis komentar yang menjelaskan apa yang dilakukannya daripada tidak menulis komentar. Komentar ini juga akan memudahkan refactor nanti.

Terkadang kode tidak dapat dihindari kompleks. Ini mungkin algoritma yang rumit, atau mungkin kode yang mengorbankan kejelasan untuk alasan kinerja. Sekali lagi komentar diperlukan.

JacquesB
sumber
13
Ada juga kasus di mana kode Anda menangani situasi yang hanya yang rumit, dan tidak ada kode sederhana bisa mengatasinya.
gnasher729
6
Poin bagus, gnasher. Ini sepertinya sering terjadi ketika Anda harus mengoptimalkan beberapa kode untuk kinerja.
JacquesB
9
Bahkan komentar dalam x++mungkin baik jika itu seperti "kenaikan x satu, membungkus jika itu UINT32_MAX"; siapa pun yang tahu spesifikasi bahasa akan tahu bahwa penambahan uint32_tbungkus surat wasiat, tetapi tanpa komentar orang mungkin tidak tahu apakah pembungkus tersebut merupakan bagian yang diharapkan dari algoritma yang sedang dilaksanakan.
supercat
5
@ l0b0: Saya harap Anda bercanda!
JacquesB
9
@ l0b0 Tidak ada yang namanya kode sementara. Kode tidak akan pernah dire-refoured karena bisnis senang dengan hasilnya dan tidak akan menyetujui dana untuk memperbaikinya. Lima tahun dari sekarang, beberapa pengembang junior akan melihat kode ini, Anda bahkan tidak menggunakan WizBug 4.0 lagi karena Anda telah menggantinya dengan Bugtrocity v9, jadi "Bug123" tidak ada artinya baginya. Dia sekarang berpikir ini adalah bagaimana seharusnya kode permanen, dan menjadi pengembang yang mengerikan sepanjang karirnya. Pikirkan anak-anak. Jangan menulis kode sementara.
corsiKa
36

Ada perbedaan antara mengomentari kode Anda dan mendokumentasikan kode Anda .

  • Diperlukan komentar untuk mempertahankan kode nanti, yaitu mengubah kode itu sendiri.

    Komentar memang mungkin dianggap bermasalah. Poin ekstremnya adalah mengatakan bahwa mereka selalu menunjukkan masalah, baik di dalam kode Anda (kode terlalu sulit untuk dipahami) atau dalam bahasa (bahasa tidak dapat cukup ekspresif; misalnya, fakta bahwa metode tidak pernah kembali nulldapat diekspresikan melalui kontrak Kode dalam C #, tetapi tidak ada cara untuk mengekspresikannya melalui kode dalam, katakanlah, PHP).

  • Dokumentasi diperlukan untuk dapat menggunakan objek (kelas, antarmuka) yang Anda kembangkan. Target audiens berbeda: bukan orang yang akan menjaga kode Anda dan mengubahnya yang kita bicarakan di sini, tetapi orang yang hampir tidak perlu menggunakannya .

    Menghapus dokumentasi karena kodenya cukup jelas adalah gila, karena dokumentasi ada di sini khusus untuk memungkinkan penggunaan kelas dan antarmuka tanpa harus membaca ribuan baris kode .

Arseni Mourzenko
sumber
Ya, tetapi setidaknya bagian dari poin Martin adalah bahwa dengan praktik pembangunan modern, tes adalah dokumentasi, bukan kode itu sendiri. Dengan asumsi kode sedang diuji dengan sistem uji gaya BDD, misalnya specflow, tes itu sendiri merupakan deskripsi langsung dari perilaku metode ("diberi database produk ketika GetById dipanggil dengan id dari produk yang valid kemudian objek Produk yang sesuai dikembalikan [...] ketika GetById dipanggil dengan id produk yang tidak valid maka null dikembalikan "atau sesuatu seperti ini).
Jules
13

Nah, sepertinya rekan Anda membaca buku, menerima apa yang mereka katakan, dan menerapkan apa yang dia pelajari tanpa berpikir dan tanpa mempertimbangkan konteks.

Komentar Anda tentang apa fungsi yang harus dilakukan sehingga Anda dapat membuang kode implementasi, saya membaca komentar fungsi, dan saya dapat menulis pengganti untuk implementasi, tanpa ada yang salah.

Jika komentar tidak memberi tahu saya apakah pengecualian dilemparkan atau apakah nihil dikembalikan, saya tidak bisa melakukan itu. Selain itu, jika komentar tidak memberi tahu Anda apakah pengecualian dilemparkan atau apakah nil dikembalikan, maka di mana pun Anda memanggil fungsi, Anda harus memastikan kode Anda berfungsi dengan benar apakah pengecualian dilemparkan atau nihil dikembalikan.

Jadi kolega Anda benar-benar salah. Silakan baca semua buku, tetapi pikirkan sendiri.

PS. Saya melihat baris Anda "kadang-kadang bagian dari antarmuka, jadi Anda bahkan tidak tahu kode apa yang sedang berjalan." Bahkan hanya dengan fungsi virtual, Anda tidak tahu kode apa yang sedang berjalan. Lebih buruk lagi, jika Anda menulis kelas abstrak, bahkan tidak ada kode! Jadi jika Anda memiliki kelas abstrak dengan fungsi abstrak, komentar yang Anda tambahkan ke fungsi abstrak adalah satu - satunya hal yang harus dipandu oleh implementor kelas beton. Komentar-komentar itu mungkin juga satu-satunya hal yang dapat memandu pengguna kelas, misalnya jika semua yang Anda miliki adalah kelas abstrak dan pabrik yang mengembalikan implementasi konkret, tetapi Anda tidak pernah melihat kode sumber implementasi. (Dan tentu saja saya seharusnya tidak melihat kode sumber dari satu implementasi).

gnasher729
sumber
Saya belum berkomentar kode dalam 10 tahun. Komentar membengkak, sampah. Tidak ada kode komentar hari ini. Kami fokus pada kode yang dibentuk dengan baik dan bernama, modul kecil, decoupling, dll. YANG membuat kode Anda dapat dibaca bukan komentar. Pengujian memastikan bahwa jika Anda membuang kode, tidak ada yang salah, bukan komentar. Tes memberi tahu Anda bagaimana Anda menggunakan kode yang Anda tulis, bagaimana Anda memanggilnya, dan mengapa mereka ada di tempat pertama. Kamu sekolah yang terlalu tua, kamu harus belajar tentang pengujian dan membersihkan kode temanku.
PositiveGuy
12

Ada dua jenis komentar untuk dipertimbangkan - yang terlihat oleh orang-orang dengan kode dan yang digunakan untuk menghasilkan dokumentasi.

Jenis komentar yang dimaksud Paman Bob adalah jenis yang hanya dapat dilihat oleh orang-orang yang memiliki kode. Apa yang dia anjurkan adalah bentuk KERING . Untuk orang yang melihat kode sumber, kode sumber harus berupa dokumentasi yang mereka butuhkan. Bahkan dalam kasus di mana orang memiliki akses ke kode sumber, komentar tidak selalu buruk. Terkadang, algoritme rumit atau Anda perlu menangkap mengapa Anda mengambil pendekatan yang tidak jelas sehingga orang lain tidak akhirnya memecahkan kode Anda jika mereka mencoba untuk memperbaiki bug atau menambahkan fitur baru.

Komentar yang Anda gambarkan adalah dokumentasi API. Ini adalah hal-hal yang terlihat oleh orang-orang yang menggunakan implementasi Anda, tetapi itu mungkin tidak memiliki akses ke kode sumber Anda. Bahkan jika mereka memiliki akses ke kode sumber Anda, mereka mungkin bekerja pada modul lain dan tidak melihat kode sumber Anda. Orang-orang ini akan merasa berguna untuk memiliki dokumentasi ini tersedia di IDE mereka ketika mereka sedang menulis kode mereka.

Thomas Owens
sumber
Jujur saya tidak pernah berpikir KERING berlaku untuk kode + komentar, tetapi itu masuk akal. Semacam contoh "increment X" pada jawaban @ JacquesB.
7

Nilai komentar diukur dalam nilai informasi yang diberikan dikurangi upaya yang diperlukan untuk membacanya dan / atau mengabaikannya. Jadi jika kita menganalisis komentar

/// <summary>
/// Retrieves a product by its id, returns null if no product was found.
/// </summary>

untuk nilai dan biaya, kita melihat tiga hal:

  1. Retrieves a product by its idmengulangi apa yang dikatakan nama fungsi, jadi biayanya tanpa nilai. Itu harus dihapus.

  2. returns null if no product was foundadalah informasi yang sangat berharga. Kemungkinan mengurangi waktu coders lain harus melihat implementasi dari fungsi. Saya cukup yakin bahwa menghemat lebih banyak membaca daripada biaya pembacaan yang diperkenalkannya sendiri. Itu harus tetap.

  3. Garis

    /// <summary>
    /// </summary>
    

    tidak membawa informasi apa pun. Mereka adalah biaya murni untuk pembaca komentar. Mereka dapat dibenarkan jika generator dokumentasi Anda membutuhkannya tetapi dalam hal ini Anda mungkin harus memikirkan generator dokumentasi yang berbeda.

    Ini adalah alasan mengapa penggunaan generator dokumentasi adalah ide yang dapat diperdebatkan: Mereka umumnya memerlukan banyak komentar tambahan yang tidak membawa informasi atau mengulangi hal-hal yang jelas, hanya demi dokumen yang dipoles.


Pengamatan yang belum saya temukan di jawaban lain:

Bahkan komentar yang tidak diperlukan untuk memahami / menggunakan kode bisa sangat berharga. Inilah salah satu contohnya:

//XXX: The obvious way to do this would have been ...
//     However, since we need this functionality primarily for ...
//     doing this the non-obvious way of ...
//     gives us the advantage of ...

Mungkin banyak teks, benar-benar tidak perlu mengerti / menggunakan kode. Namun, ini menjelaskan alasan mengapa kode terlihat seperti itu. Ini akan menghentikan orang yang melihat kode, bertanya-tanya mengapa itu tidak dilakukan dengan cara yang jelas, dan akan mulai refactoring kode sampai mereka menyadari mengapa kode itu ditulis seperti ini di tempat pertama. Dan bahkan jika pembaca cukup pintar untuk tidak melompat ke refactoring secara langsung, mereka masih perlu mencari tahu mengapa kode terlihat seperti itu sebelum mereka menyadari bahwa sebaiknya tetap seperti itu. Komentar ini benar-benar dapat menghemat jam kerja. Dengan demikian nilainya lebih tinggi dari biaya.

Demikian juga, komentar dapat mengomunikasikan maksud kode, bukan hanya cara kerjanya. Dan mereka dapat melukis gambaran besar yang biasanya hilang dalam detail menit kode itu sendiri. Dengan demikian, Anda benar dalam mendukung komentar kelas. Saya paling menghargai komentar kelas jika mereka menjelaskan maksud kelas, bagaimana berinteraksi dengan kelas lain, bagaimana itu dimaksudkan untuk digunakan, dll. Sayangnya, saya bukan penulis besar dari komentar seperti itu ...

cmaster
sumber
2
Wow - ganti generator dokumen Anda karena memerlukan beberapa baris html tambahan untuk penguraian? Ayo jangan.
corsiKa
2
@corsiKa YMMV, tapi saya untuk satu lebih suka generator dokumentasi yang mengurangi biaya dalam komentar ke minimum. Tentu saja, saya juga lebih suka membaca file header yang ditulis dengan baik daripada dokumentasi doxygen yang tidak sinkron dengan kode yang sebenarnya. Tapi, seperti yang saya katakan, YMMV.
cmaster
4
Bahkan jika nama metode menggambarkan tujuannya dengan cemerlang, mengulangi tujuan itu menggunakan bahasa alami dapat memudahkan seseorang membacanya untuk mengaitkan tujuan itu dengan peringatan apa pun yang mengikuti. Penyajian kembali apa yang dijelaskan dalam nama akan cukup singkat sehingga meskipun nilainya rendah, biayanya juga rendah. Karena itu saya tidak setuju dengan bagian pertama dari posting Anda. Namun +1 untuk bagian kedua. Dokumentasi pendekatan alternatif yang dievaluasi dan ditolak bisa sangat berharga, tetapi informasi seperti itu jarang diberikan perhatian yang layak.
supercat
GetByIdmenimbulkan pertanyaan, apa itu id, dan juga, mendapatkan apa dari mana. Komentar dokumentasi harus memungkinkan lingkungan pengembangan untuk menampilkan jawaban atas pertanyaan-pertanyaan ini. Kecuali dijelaskan di tempat lain dalam komentar doc modul, itu juga akan menjadi satu tempat untuk mengatakan mengapa seseorang akan mendapatkan id.
hyde
Komentar pukulan, kode bersih (penjelasan sendiri), TDD (sering menerima umpan balik dan sering menerima umpan balik tentang desain Anda), dan aturan pengujian (memberi Anda kepercayaan diri dan perilaku dokumen)! UJI orang UJI. Tidak ada orang di sini yang membicarakan hal itu. bangun
PositiveGuy
4

Kode tidak komentar adalah kode buruk. Ini adalah mitos yang tersebar luas (jika tidak universal) bahwa kode dapat dibaca dengan cara yang sama seperti, katakanlah, bahasa Inggris. Itu harus ditafsirkan, dan untuk apa pun kecuali kode paling sepele yang membutuhkan waktu dan usaha. Plus, setiap orang memiliki tingkat kemampuan yang berbeda dalam membaca dan menulis bahasa apa pun. Perbedaan antara penulis dan gaya pengkodean dan kemampuan pembaca adalah hambatan kuat untuk interpretasi yang akurat. Ini juga merupakan mitos bahwa Anda dapat memperoleh niat penulis dari penerapan kode. Dalam pengalaman saya, jarang salah menambahkan komentar tambahan.

Robert Martin et al. menganggapnya sebagai "bau busuk" karena mungkin kode tersebut diubah dan komentar tidak. Saya mengatakan itu adalah hal yang baik (dengan cara yang persis sama bahwa "bau busuk" ditambahkan ke gas rumah tangga untuk mengingatkan pengguna akan kebocoran). Membaca komentar memberi Anda titik awal yang berguna untuk menafsirkan kode yang sebenarnya. Jika mereka cocok maka Anda akan memiliki peningkatan kepercayaan pada kode. Jika mereka berbeda maka Anda telah mendeteksi bau peringatan dan perlu menyelidiki lebih lanjut. Obat untuk "bau busuk" bukan untuk menghilangkan bau tetapi untuk menutup kebocoran.

Vince O'Sullivan
sumber
2
Mengingat bahwa Anda adalah seorang penulis yang cerdas dan teksnya adalah untuk kepentingan audiens yang cerdas; Anda menarik garis menggunakan akal sehat. Jelas, sebagaimana adanya, contohnya adalah bodoh tapi itu tidak berarti bahwa mungkin tidak ada alasan yang sangat baik untuk mengklarifikasi dengan komentar mengapa kode tersebut menyertakan i ++ pada saat itu.
Vince O'Sullivan
8
i++; // Adjust for leap years.
Vince O'Sullivan
5
"Robert Martin et al. Menganggapnya sebagai" bau busuk "karena mungkin kodenya diubah dan komentarnya tidak." Itu hanya sebagian dari baunya. Bau terburuk berasal dari gagasan bahwa programmer memutuskan untuk tidak mencoba menulis kode dengan cara yang lebih deskriptif, dan sebagai gantinya memilih untuk "menutup kebocoran" dengan komentar. Pernyataannya adalah bahwa alih-alih menampar komentar "// adjust for leap years", seseorang mungkin harus memiliki metode "adjustForLeapYears ()" dalam kode itu sendiri (atau yang serupa). Dokumentasi datang dalam bentuk tes yang menggunakan logika tahun kabisat.
Eric King
3
Saya akan mempertimbangkan menambahkan pemanggilan metode untuk mengganti satu baris kode dengan komentar berlebihan, terutama karena nama metode itu sendiri sebenarnya hanya komentar yang memberi label sepotong kode dan tidak ada jaminan akurasi dokumentasi yang lebih baik. (Jika garis itu terjadi di dua tempat atau lebih maka memperkenalkan pemanggilan metode, tentu saja, akan menjadi solusi yang tepat.)
Vince O'Sullivan
1
@ Jay Alasannya adalah membuat abstraksi Anda eksplisit (dengan, misalnya, memperkenalkan metode) adalah aturannya. Tidak melakukannya karena Anda mungkin berakhir dengan metode yang memiliki satu baris adalah pengecualian. Izinkan saya memparafrasekan aturan arbitrer yang nyata : "Gunakan struktur bahasa pemrograman Anda (biasanya metode dan kelas) untuk memperkenalkan abstraksi, kecuali implementasi abstraksi itu dapat dinyatakan sebagai satu baris kode, dalam hal ini tentukan abstraksi dalam bahasa alami dengan menambahkan komentar."
Eric
3

Dalam beberapa bahasa (F # misalnya) seluruh komentar / dokumentasi ini sebenarnya dapat diekspresikan dalam tanda tangan metode. Ini karena dalam F #, null umumnya bukan nilai yang diizinkan kecuali diizinkan secara khusus.

Apa yang umum dalam F # (dan juga beberapa bahasa fungsional lainnya) adalah bahwa alih-alih nol Anda menggunakan jenis opsi Option<T>yang bisa berupa Noneatau Some(T). Bahasa kemudian akan memahami ini dan memaksa Anda untuk (atau memperingatkan Anda jika Anda tidak) cocok dengan kedua kasus ketika Anda mencoba menggunakannya.

Jadi misalnya dalam F # Anda bisa memiliki tanda tangan yang terlihat seperti ini

val GetProductById: int -> Option<Product>

Dan kemudian ini akan menjadi fungsi yang mengambil satu parameter (int) dan kemudian mengembalikan produk, atau nilainya Tidak ada.

Dan kemudian Anda bisa menggunakannya seperti ini

let product = GetProduct 42
match product with
| None -> printfn "No product found!"
| Some p -> DoThingWithProduct p

Dan Anda akan mendapatkan peringatan kompiler jika Anda tidak cocok dengan kedua kemungkinan kasus. Jadi tidak ada cara yang mungkin untuk mendapatkan pengecualian referensi nol di sana (kecuali Anda mengabaikan peringatan kompiler tentu saja), dan Anda tahu semua yang Anda butuhkan hanya dengan melihat tanda tangan fungsi.

Tentu saja, ini mensyaratkan bahwa bahasa Anda dirancang dengan cara ini - yang banyak bahasa umum seperti C #, Java, C ++ dll tidak. Jadi ini mungkin tidak membantu Anda dalam situasi Anda saat ini. Tapi (mudah-mudahan) senang mengetahui bahwa ada bahasa di luar sana yang memungkinkan Anda mengekspresikan informasi semacam ini dengan cara yang diketik secara statis tanpa menggunakan komentar, dll. :)

wasatz
sumber
1

Ada beberapa jawaban yang sangat bagus di sini dan saya tidak ingin mengulangi apa yang mereka katakan. Tetapi izinkan saya menambahkan beberapa komentar. (Tidak ada pelesetan yang dimaksudkan.)

Ada banyak pernyataan yang dibuat oleh orang-orang pintar - tentang pengembangan perangkat lunak dan banyak mata pelajaran lain, saya kira - itu adalah saran yang sangat bagus ketika dipahami dalam konteks, tetapi orang-orang bodoh daripada mengambil di luar konteks atau menerapkan dalam situasi yang tidak pantas atau mengambil ke ekstrem konyol.

Gagasan bahwa kode harus mendokumentasikan diri sendiri adalah salah satu ide yang sangat bagus. Namun dalam kehidupan nyata, ada keterbatasan pada kepraktisan ide ini.

Satu tangkapan adalah bahwa bahasa tersebut mungkin tidak menyediakan fitur untuk mendokumentasikan apa yang perlu didokumentasikan dengan jelas dan ringkas. Sebagai bahasa komputer membaik, ini menjadi kurang dan kurang masalah. Tapi saya pikir itu tidak sepenuhnya hilang. Kembali pada hari-hari ketika saya menulis di assembler, masuk akal untuk memasukkan komentar seperti "harga total = harga barang tidak kena pajak ditambah harga barang kena pajak ditambah harga barang kena pajak * tarif pajak". Apa yang ada dalam register pada saat tertentu belum tentu jelas. Butuh banyak langkah untuk melakukan operasi sederhana. Dll. Tetapi jika Anda menulis dalam bahasa modern, komentar seperti itu hanya akan menjadi pernyataan ulang satu baris kode.

Saya selalu kesal ketika melihat komentar seperti, "x = x + 7; // tambahkan 7 ke x". Seperti, wow, terima kasih, jika saya lupa arti tanda plus yang mungkin sangat membantu. Di mana saya mungkin benar-benar bingung adalah mengetahui apa "x" itu atau mengapa itu diperlukan untuk menambahkan 7 pada waktu khusus ini. Kode ini dapat dibuat mendokumentasikan diri sendiri dengan memberikan nama yang lebih bermakna untuk "x" dan menggunakan konstanta simbolik daripada 7. Seperti jika Anda telah menulis "total_price = total_price + MEMBERSHIP_FEE;", maka komentar mungkin tidak diperlukan sama sekali .

Kedengarannya hebat mengatakan bahwa nama fungsi harus memberi tahu Anda dengan tepat fungsi apa yang dilakukan sehingga komentar tambahan akan berlebihan. Saya memiliki kenangan indah saat saya menulis sebuah fungsi yang memeriksa apakah nomor item ada di tabel Item database kami, mengembalikan benar atau salah, dan yang saya sebut, "ValidateItemNumber". Tampak seperti nama yang layak. Kemudian orang lain datang dan memodifikasi fungsi itu untuk juga membuat pesanan untuk item dan memperbarui database, tetapi tidak pernah mengubah namanya. Sekarang nama itu sangat menyesatkan. Kedengarannya seperti melakukan satu hal kecil, ketika benar-benar melakukan lebih banyak. Kemudian seseorang bahkan mengambil bagian tentang memvalidasi nomor item dan melakukannya di tempat lain, tetapi masih tidak mengubah nama. Jadi meskipun fungsi sekarang tidak ada hubungannya dengan memvalidasi nomor item,

Namun dalam praktiknya, sering kali tidak mungkin bagi nama fungsi untuk sepenuhnya menjelaskan apa fungsi yang dilakukan tanpa nama fungsi selama kode yang membentuk fungsi itu. Apakah nama akan memberi tahu kami apa yang dilakukan validasi pada semua parameter? Apa yang terjadi pada kondisi pengecualian? Sebutkan setiap ambiguitas yang mungkin? Pada titik tertentu namanya akan menjadi sangat panjang sehingga hanya membingungkan. Saya akan menerima String BuildFullName (String firstname, String lastname) sebagai tanda tangan fungsi yang layak. Meskipun itu tidak menjelaskan apakah nama tersebut dinyatakan "pertama terakhir" atau "terakhir, pertama" atau beberapa variasi lainnya, apa yang dilakukannya jika satu atau kedua bagian dari nama tersebut kosong, jika membebankan batas pada panjang gabungan dan apa fungsinya jika itu terlampaui,

Jay
sumber