Cara membuat basis kode besar lebih mudah dimengerti

104

Misalkan saya sedang mengembangkan proyek yang relatif besar. Saya sudah mendokumentasikan semua kelas dan fungsi saya dengan Doxygen, namun, saya punya ide untuk meletakkan "catatan programmer" pada setiap file kode sumber.

Gagasan di balik ini adalah untuk menjelaskan dalam istilah awam bagaimana kelas tertentu bekerja (dan tidak hanya mengapa seperti kebanyakan komentar lakukan). Dengan kata lain, untuk memberi sesama programmer pandangan lain tentang cara kerja kelas.

Sebagai contoh:

/*
 * PROGRAMMER'S NOTES:
 *
 * As stated in the documentation, the GamepadManager class 
 * reads joystick joystick input using SDL and 'parses' SDL events to
 * Qt signals.
 *
 * Most of the code here is about goofing around the joystick mappings.
 * We want to avoid having different joystick behaviours between
 * operating systems to have a more integrated user experience, since
 * we don't want team members to have a bad surprise while
 * driving their robots with different laptops.
 *
 * Unfortunately, we cannot use SDL's GamepadAPI because the robots
 * are interested in getting the button/axes numbers, not the "A" or
 * "X" button.
 *
 * To get around this issue, we created a INI file for the most common 
 * controllers that maps each joystick button/axis to the "standard" 
 * buttons and axes used by most teams. 
 *
 * We choose to use INI files because we can safely use QSettings
 * to read its values and we don't have to worry about having to use
 * third-party tools to read other formats.
 */

Apakah ini cara yang baik untuk membuat proyek besar lebih mudah bagi programmer / kontributor baru untuk memahami cara kerjanya? Selain mempertahankan gaya pengkodean yang konsisten dan organisasi direktori 'standar', apakah ada 'standar' atau rekomendasi untuk kasus ini?

Alex Spataru
sumber
32
Tidak. Jika kode Anda tidak dapat dibaca, dokumentasi tidak akan membantu.
Telastyn
35
@ jeffo - masalahnya adalah meluangkan waktu untuk melakukan ini bisa terjadi sekali. Waktu untuk menjaga kode dapat dibaca terjadi seiring waktu. Saya pernah berada di tempat-tempat dengan dokumentasi semacam ini, dilakukan ketika proyek masih muda, atau ketika Joe the Perfeksionis masih di tim. Itu kemudian ditinggalkan dan komentar bertahan, tidak lagi akurat.
Telastyn
25
Setidaknya pada tingkat yang lebih tinggi, deskripsi prosa out-of-code tentang apa yang dilakukan proyek, cara kerjanya, dan pengorbanan apa yang telah dibuat dalam arsitektur sangat berharga. Jenis dokumen ini harus dibaca oleh pendatang baru sebelum mereka melakukan tur kode. Ada banyak saya-metodologi-adalah-terlalu-radikal-untuk-docs-dude omong kosong sekitar bersih, dan sementara itu adalah benar bahwa lengkungan doc awal dan berkembang lengkungan doc tidak akan menyelaraskan, deskripsi prosa diperlukan bagi siapa saja untuk dengan cepat memahami basis kode besar, non-sepele. Berikut adalah contoh (buruk): zxq9.com/erlmud/html/001-002_architecture.html
zxq9
11
@ Telastyn: Ini tidak ada hubungannya dengan apakah kode dapat dibaca atau tidak (dan saya harap begitu). Mendokumentasikan alasan desain sangat penting.
Lightness Races dalam Orbit
7
@ Telastyn: Ya, mungkin. Secara pribadi saya akan menulisnya di dokumen mandiri. Tetapi blok komentar di bagian atas file sumber tidak terlalu buruk.
Lightness Races di Orbit

Jawaban:

139

Ini luar biasa. Saya berharap lebih banyak pengembang perangkat lunak meluangkan waktu dan upaya untuk melakukan ini. Saya t:

  • Menyatakan dengan bahasa Inggris sederhana apa yang dilakukan kelas (yaitu tanggung jawab),
  • Memberikan informasi tambahan yang berguna tentang kode tanpa mengulang kata demi kata apa yang sudah dikatakan kode,
  • Menjabarkan beberapa keputusan desain dan mengapa keputusan itu dibuat, dan
  • Sorot beberapa gotcha yang mungkin menimpa orang berikutnya yang membaca kode Anda.

Sayangnya, banyak programmer jatuh ke perkemahan "jika kode ditulis dengan benar, seharusnya tidak harus didokumentasikan." Tidak benar. Ada banyak hubungan tersirat antara kelas kode, metode, modul, dan artefak lainnya yang tidak jelas hanya dengan membaca kode itu sendiri.

Seorang programmer yang berpengalaman dapat dengan hati-hati merancang suatu desain yang memiliki arsitektur yang jelas dan mudah dipahami yang jelas tanpa dokumentasi. Tapi berapa banyak program seperti itu yang sudah Anda lihat?

Robert Harvey
sumber
15
Dan mengapa "Mythical Man Month" menjadi ramalan yang terpenuhi dengan sendirinya, tidak ada yang meluangkan waktu untuk menulis semua ini untuk dev baru ketika itu segar di pikiran mereka dan proyek tidak ketinggalan.
JeffO
3
Saya setuju dengan setiap poin yang Anda buat di sini. Saya tidak suka istilah OP yang digunakan dalam jabatannya how a class works. Ini berubah seiring waktu dan pemeliharaan. Padahal tim saya tidak memasukkan sumber di atas. Kami memelihara wiki dengan keputusan dan menyalin diskusi slack channel tentang keputusan desain mentah ke dalam dokumen (Kami menyediakan tautan dari ringkasan keputusan dan kesimpulan ke catatan mentah sehingga kami tidak perlu kembali mengambil keputusan lama). Semua dilakukan dengan rapi di github (jadi semuanya ada di satu tempat).
Martin York
1
Satu-satunya masalah saya adalah menerapkan ini secara global. Kelas ini cukup kompleks, dengan gotchas tertentu tersedia, jelas itu sangat berguna (walaupun Anda akhirnya berurusan dengan Comment Rot). Ketika sebuah kelas lebih jelas, komentarnya bisa sedikit berlebihan.
deworde
1
"Seorang pembuat kode yang berpengalaman dapat dengan hati-hati merancang sebuah desain yang memiliki arsitektur yang jelas dan mudah dipahami, yang jelas tanpa dokumentasi. Tetapi berapa banyak program seperti yang telah Anda lihat sebenarnya" Meskipun ini benar, kualitas dokumentasi tidak pernah lebih baik daripada kualitas Kode. Kode yang dirancang dengan baik cenderung memiliki dokumentasi yang bagus, jika tidak ada gunanya. Kode arsitek buruk memiliki komentar seperti "kenaikan x oleh 1"
deworde
3
Saya sangat setuju dengan jawaban ini, dan jika saya menemukan sesuatu seperti contoh OP dalam kode, saya akan sangat senang. Hanya satu tambahan: pertimbangkan untuk menambahkan tanggal pada komentar Anda, hanya untuk memberikan petunjuk kepada pembaca pada akhirnya tentang kesegaran deskripsi, dan memperbaruinya setiap kali Anda memperbarui teks.
Svalorzen
36

Kunci untuk bekerja dengan basis kode besar adalah tidak harus membaca seluruh basis kode untuk membuat perubahan. Agar seorang programmer dapat dengan cepat menemukan kode yang dia cari, kode itu harus diorganisir, dan organisasi itu jelas. Artinya, setiap unit logis dalam kode, dari yang dapat dieksekusi, perpustakaan, ruang nama, hingga kelas individu harus memiliki tanggung jawab yang jelas terlihat. Karena itu saya tidak hanya mendokumentasikan file sumber, tetapi juga direktori tempat mereka tinggal.

Catatan programmer Anda juga memberikan latar belakang pada keputusan desain. Meskipun ini bisa menjadi informasi yang berharga, saya akan memisahkannya dari pernyataan tanggung jawab (untuk memungkinkan pembaca memilih apakah dia ingin membaca tentang tanggung jawab kelas atau alasan rancangannya), dan memindahkannya sedekat mungkin dengan sumber yang dijelaskannya. sebisa mungkin, untuk memaksimalkan kesempatan dokumentasi diperbarui ketika kode tersebut (dokumentasi hanya berguna jika kita dapat mempercayai keakuratannya - dokumentasi yang sudah ketinggalan zaman bisa lebih buruk daripada tidak sama sekali!).

Yang mengatakan, dokumentasi harus tetap KERING, yaitu tidak mengulangi informasi yang bisa diungkapkan dalam kode atau sudah dijelaskan di tempat lain (frasa seperti "sebagai negara dokumentasi" adalah tanda peringatan). Khususnya, pengelola masa depan hanya akan mahir dalam bahasa pemrograman proyek seperti halnya mereka dalam bahasa Inggris; parafrase implementasi dalam komentar (yang saya lihat terlalu sering ketika orang bangga dengan dokumentasi mereka) tidak memiliki manfaat, dan kemungkinan akan menyimpang dari implementasi, khususnya jika dokumentasi tidak dekat dengan kode yang dijelaskannya.

Akhirnya, struktur dokumentasi harus distandarisasi di seluruh proyek sehingga semua orang dapat menemukannya (ini adalah kekacauan besar dokumen Peter di pelacak bug, Sue di wiki, Alan di readme, dan John dalam kode sumber ...) .

meriton - mogok
sumber
Kalimat pertama Anda persis seperti yang saya lihat ini. Basis kode besar harus dikomposisikan sebagai sejumlah komponen yang lebih kecil di mana programmer baru dapat dengan andal mengubah satu tanpa membahayakan yang lain.
Jon Chesterfield
1
memindahkannya sedekat mungkin dengan sumber yang dideskripsikannya, untuk memaksimalkan kesempatan dokumentasi diperbarui ketika kode tersebut . Ini pengalaman berharga.
laike9m
KERING sebagai pedoman untuk dokumentasi adalah poin yang sangat bagus! Itu secara otomatis mengatur fokus dengan benar dan melarang komentar "// increment x by 1" yang terkenal menjengkelkan.
Hans-Peter Störr
13

Saya tidak akan setuju ini adalah pendekatan yang sangat baik, terutama karena

  1. Ketika Anda memperbaiki proyek Anda, memindahkan metode, dokumentasi rusak.

  2. Jika dokumentasi tidak diperbarui dengan benar, itu akan menghasilkan lebih banyak kebingungan daripada membantu memahami kode.

Jika Anda memiliki tes unit untuk setiap metode / tes integrasi untuk setiap modul, itu akan menjadi dokumentasi mandiri yang lebih mudah dikelola dan dipahami dibandingkan dengan komentar kode.

Ya, memiliki struktur direktori yang tepat pasti akan membantu.

Pelican Terbang Rendah
sumber
+1 untuk Tes menjadi cara terbaik untuk memahami basis kode. Tes unit, tes integrasi, tes penerimaan semuanya menceritakan kisah tentang bagaimana aplikasi seharusnya bekerja, dan bagaimana seharusnya digunakan.
BZink
7

Saya pribadi penggemar dokumen desain tingkat tinggi - lebih disukai ditulis SEBELUM kode apa pun - yang memberikan gambaran umum desain dan daftar kelas dan sumber daya. Desain top-down sangat menyederhanakan hal - milik Anda mungkin "mesin permainan -> perangkat keras -> pengendali -> joystick"; dengan demikian, seorang programmer baru mengatakan "memperbaiki tombol 'a' pada 'xyz controller" setidaknya akan tahu di mana harus mulai mencari.

Terlalu banyak bahasa modern cenderung memecah kode menjadi ratusan file kecil, jadi hanya menemukan file yang benar dapat menjadi tantangan bahkan pada proyek moderat.

DWalker
sumber
16
20 tahun yang lalu semua kode saya dalam satu file besar. Sekarang ada dalam ribuan file kecil dan file uji. Ada alasan bagus untuk ini dan itu mencerminkan 20 tahun pengembangan perangkat lunak (ekosistem umum, bukan pengetahuan saya). Waaay terlalu lama untuk berkomentar.
Michael Durrant
4
ah, metode air terjun lama untuk menulis Kebenaran tunggal, yang semuanya mencakup, tidak berubah, bahkan sebelum pengkodean dimulai dan membuatnya tidak mungkin untuk menyimpang dalam implementasi dari kebenaran tersebut.
jwenting
2
@jwenting: Anda tidak harus sejauh itu. Tapi masih baik untuk memiliki beberapa ide apa yang Anda sedang membangun.
Robert Harvey
1
Tentu saja tanpa peringatan tentang cara memecah ini dengan benar dan di mana harus melanggar aturan, Anda akan dengan cepat memiliki dokumen yang ketinggalan zaman atau batu kilangan. "Aku perlu menambahkan kelas baru; ke Documanto, Behemoth yang makan waktu!"
deworde
2
@deworde: Saya membacanya sebagai "terlalu malas untuk memelihara dokumentasi."
Robert Harvey
6

Jika basis kode besar - saya mencoba memberikan dokumen desain yang memetakan elemen-elemen kunci dari desain dan implementasinya . Tujuannya di sini bukan untuk merinci kelas mana saja yang digunakan, tetapi memberikan kunci kode dan pemikiran yang masuk ke dalam desain. Ini memberikan konteks menyeluruh pada sistem, komponen-komponennya dan penerapannya.

Hal-hal untuk dimasukkan dalam dokumen desain adalah;

  • Arsitektur aplikasi
  • Struktur kode logis
  • Aliran data
  • Pola kunci yang digunakan dan motivasi di balik penggunaannya
  • Struktur sumber kode
  • Cara membangunnya (ini menawarkan wawasan tentang dependensi implisit dan struktur sumber kode fisik)

Sebagai kelanjutan dari ini, dokumentasi untuk kelas, dan fungsi / metode harus diselesaikan sebagaimana mestinya . Khususnya API publik; harus jelas apa yang semuanya berikut dalam setiap kasus;

  • Prasyarat
  • Efek
  • Invarian
  • Kondisi pengecualian (lemparan)
Niall
sumber
+1 Lebih baik daripada menggambarkan setiap kelas, karena itu akan keluar dari tanggal dengan cara yang lebih cepat daripada desain keseluruhan.
Lode
4

Aturan paling penting yang saya temukan untuk memudahkan pengembang baru untuk memahami basis kode adalah kesepakatan sempurna adalah mahal.

Jika pengembang baru harus benar-benar memahami sistem yang sedang mereka kerjakan, itu mencegah semua peluang untuk belajar di tempat kerja. Saya pikir catatan programmer adalah awal yang baik, tetapi saya akan melangkah lebih jauh. Cobalah untuk menulis kode yang, jika didekati lagi, akan memungkinkan pengembang untuk mencari tahu apa yang mereka lakukan dengan cepat, daripada mengharuskan mereka untuk belajar sebelum mereka melakukannya. Hal-hal kecil seperti penegasan untuk kasus-kasus yang Anda tahu tidak akan pernah terjadi, bersama dengan komentar yang menjelaskan mengapa pernyataan itu valid, sangat bermanfaat. Begitu juga penulisan kode yang gagal dengan anggun dan bukannya segfaulting jika Anda melakukan kesalahan.

Cort Ammon
sumber
Aturan saya adalah bahwa komentar harus tentang MENGAPA , bukan BAGAIMANA . Kode tersebut menjelaskan BAGAIMANA.
user11393
3

Saya telah melihat kelas besar dengan dokumentasi, dan setelah membaca dokumentasi saya tidak punya petunjuk apa yang seharusnya baik untuk kelas ini dan mengapa ada orang yang menggunakannya! Dan pada saat yang sama, saya memerlukan beberapa fungsi dan saya benar-benar yakin harus ada kelas untuk menanganinya, dan tidak dapat menemukannya di mana pun - karena tidak ada dokumentasi yang mengarahkan saya dari apa yang saya butuhkan ke kelas. lakukanlah.

Jadi hal pertama yang saya inginkan dalam dokumentasi hanyalah beberapa kalimat tentang apa yang dilakukan kelas, dan mengapa saya ingin menggunakannya. Komentar dalam pertanyaan awal berjalan cukup baik dalam hal itu. Setelah membaca komentar ini, jika saya memiliki joystick yang tidak berfungsi dengan baik karena saya tidak bisa menginterpretasikan nilai yang diberikannya, saya akan tahu kode apa yang harus diperiksa.

gnasher729
sumber
0

Mirip dengan apa yang dikatakan @meriton, pecah kodenya menjadi beberapa komponen yang terpisah. Lebih baik lagi, pilah basis kode menjadi paket terpisah (JAR, permata, telur, apa pun) untuk membuatnya lebih jelas bagaimana komponen-komponen dipisahkan. Jika ada bug, pengembang hanya perlu menemukan paket di mana bug itu berada, dan (semoga) hanya memperbaikinya di sana. Belum lagi, lebih mudah untuk melakukan pengujian unit, dan Anda bisa memanfaatkan manajemen ketergantungan.

Solusi lain: buat basis kode lebih kecil. Semakin sedikit kode yang ada, semakin mudah untuk dipahami. Refactor keluar kode yang tidak digunakan atau digandakan. Gunakan teknik pemrograman deklaratif . Ini membutuhkan usaha, tentu saja, dan seringkali tidak mungkin atau praktis. Tapi itu tujuan yang layak. Seperti yang ditulis Jeff Atwood: Kode Terbaik Tidak Ada Kode Sama Sekali

Sam Jones
sumber
-1

Untuk sistem yang kompleks, mungkin tidak hanya mendokumentasikan setiap file, tetapi juga interaksi dan hierarki mereka, dan bagaimana struktur program dan alasannya.

Misalnya mesin permainan biasanya cukup kompleks dan sulit untuk memutuskan apa yang disebut apa setelah ratusan lapisan abstraksi. Mungkin layak membuat file seperti "Architecture.txt" untuk menjelaskan bagaimana dan mengapa kode terstruktur seperti ini, dan mengapa ada lapisan abstraksi yang tampak tidak berguna di sana.

akaltar
sumber
-7

Ini bisa sebagian karena sulit bagi seorang programmer untuk menulisnya, karena masing-masing individu hanya memahami bagian dari proyek mereka.

Kadang-kadang Anda bisa mendapatkan info ini dari catatan manajer proyek, tetapi hanya itu yang akan Anda dapatkan, karena mereka jarang menulis ulang catatan mereka dalam format ini.

Ilqar Rasulov
sumber
7
Jika Anda melihat github, Anda akan menemukan banyak proyek yang memiliki catatan seperti ini di file README.md. Ini menjadi bagian dari budaya git pada umumnya dan proyek javascript khususnya bagi kebanyakan orang tidak akan menggunakan perpustakaan yang tidak memiliki dokumentasi tingkat tinggi semacam ini. Jadi tidak benar bahwa "tidak ada programmer yang akan menulisnya" karena Anda hanya perlu melihat sesuatu seperti jQuery atau socket.io dan mencari programmer yang menulis hal-hal seperti itu. Ini juga menjadi budaya bahwa file README yang tidak akurat menghasilkan laporan bug.
slebetman
1
Ini sepertinya tidak menjawab pertanyaan, yang mencari alasan mengapa gaya dokumentasi yang diusulkan akan berhasil atau tidak, dan juga untuk standar dokumentasi.
user52889
5
Jika Anda memiliki tim programmer yang mengerjakan suatu produk, dan setiap programmer hanya memahami kode spesifik yang mereka kerjakan, maka tim Anda tidak hanya sangat tidak berfungsi dengan faktor bus yang tidak masuk akal, tetapi juga mempertanyakan kualitas kode. Bagaimana cara mengintegrasikan kode ke dalam produk tanpa memahami sisa kode dalam sistem yang sama ??!?
Lightness Races dalam Orbit