Bagaimana Anda menghapus sepotong kode dengan aman yang sepertinya tidak pernah dimasukkan?

125

Anda telah menemukan beberapa kode yang terlihat berlebihan, dan kompiler tidak memperhatikannya. Apa yang Anda lakukan untuk memastikan (atau sedekat mungkin) bahwa menghapus kode ini tidak akan menyebabkan regresi.

Dua ide muncul di benak.

  1. "Cukup" gunakan deduksi berdasarkan apakah kode tersebut terlihat atau tidak harus dijalankan. Namun, kadang-kadang ini bisa menjadi pekerjaan yang kompleks, memakan waktu, sedikit berisiko (penilaian Anda rentan terhadap kesalahan) tanpa pengembalian bisnis yang substansial.

  2. Tempatkan login di bagian kode itu dan lihat seberapa sering itu dimasukkan dalam praktek. Setelah eksekusi yang cukup, Anda harus memiliki keyakinan yang wajar menghapus kode aman.

Apakah ada ide yang lebih baik atau sesuatu seperti pendekatan kanonik?

Brad Thomas
sumber
55
Mungkin bermanfaat untuk melihat riwayat kontrol versi: Kapan "kode mati" dibuat? Apakah itu terlihat mati ketika diciptakan? Apakah kode lain (yang sejak itu telah dimodifikasi atau dihapus) diperiksa di mana menggunakannya, pada saat yang sama ketika itu dibuat?
ChrisW
9
Kompiler tidak dapat dipercaya jika segala bentuk pemrograman meta seperti refleksi sedang dimainkan. Grep yang tepat dari direktori dasar adalah praktik penting. Ini juga umum untuk memiliki beberapa kode aplikasi berbagi jadi pastikan untuk melihat pada lapisan direktori yang benar.
Adam Caviness
16
Saya akan bertanya - "Mengapa repot-repot menghapusnya?". Jika itu digunakan dalam beberapa kasus tepi yang disebut sekali di bulan biru, Anda telah merusak barang-barang. Jika tidak pernah digunakan dan Anda membiarkannya di sana, kerusakannya adalah file yang dapat dieksekusi sedikit lebih besar. Kecuali jika ini untuk beberapa perangkat tertanam, ini masalah besar? Tempel komentar di atasnya dan beralih menggunakan waktu Anda secara produktif.
mickeyf
40
@ mickeyf Kerusakannya adalah seseorang harus menjaga kode itu. Itu artinya pengembang harus memahami apa yang dilakukannya. Pengembang harus memodifikasinya jika ada perubahan dan kode di sekitarnya sekarang harus melakukan sesuatu yang berbeda. Percayalah, ketika Anda meninggalkan cruft tergeletak di sekitar, itu sakit kepala besar bagi siapa pun yang mencoba mencari tahu nanti.
jpmc26
9
@MichaelJ. Maksud saya adalah bahwa seharusnya tidak ada di tempat pertama. Dan jika saya meninggalkannya, situasinya lebih buruk: sekarang beberapa pengembang lain di telepon harus menyelidikinya juga. Semakin lama tinggal, semakin banyak waktu yang dihabiskan untuk memahaminya. Ini adalah biaya kode berlebihan.
jpmc26

Jawaban:

112

Dalam dunia fantasi sempurna saya di mana saya memiliki 100% cakupan tes unit saya hanya akan menghapusnya, menjalankan tes unit saya, dan ketika tidak ada tes yang berubah menjadi merah, saya melakukan itu.

Tapi sayangnya saya harus bangun setiap pagi dan menghadapi kenyataan pahit di mana banyak kode tidak memiliki tes unit atau ketika mereka ada tidak dapat dipercaya untuk benar-benar mencakup setiap kasus tepi yang mungkin. Jadi saya akan mempertimbangkan risiko / hadiah dan sampai pada kesimpulan bahwa itu sama sekali tidak layak:

  • Hadiah: Kode sedikit lebih mudah dipelihara di masa depan.
  • Risiko: Mematahkan kode dalam beberapa kasus tepi yang tidak jelas yang tidak saya pikirkan, menyebabkan insiden ketika saya tidak mengharapkannya, dan bersalah karena saya harus memenuhi OCD kualitas kode saya dan membuat perubahan tanpa nilai bisnis yang dapat dipahami. untuk setiap pemangku kepentingan yang bukan pembuat kode sendiri.
Philipp
sumber
249
Setelah mengamati keadaan proyek perangkat lunak besar di mana para insinyur, selama sepuluh hingga dua belas tahun, sebagian besar mengikuti pendekatan "tidak sepadan" untuk menghapus kode yang mungkin berlebihan, saya tidak bisa merekomendasikan pendekatan ini.
njuffa
125
Juga, unit test tidak memberi tahu Anda tentang apakah kode ini benar-benar digunakan dalam produksi. Kode dapat diuji dengan sempurna, tetapi masih tidak digunakan dalam produksi, oleh karena itu berlebihan.
Knub
8
Dalam pengalaman saya, keadaan proyek seperti itu tidak pernah disebabkan oleh pendekatan "tidak layak" untuk memperbaiki kode setelah fakta, itu selalu karena kode buruk yang ditulis di tempat pertama. Adalah kesalahan untuk menulis kode yang buruk, tetapi juga merupakan kesalahan (kesalahan yang lebih lanjut) untuk berpikir bahwa kode pembersihan selalu sepadan.
Weyland Yutani
42
@Yeyland Yutani Itu tidak cocok dengan pengalaman saya sama sekali. Sebagian besar kemungkinan kode berlebihan yang saya lihat cukup ditulis dengan baik dan masuk akal dengan spesifikasi perangkat lunak, platform perangkat keras, atau versi sistem operasi yang ada satu dekade sebelumnya, diperlukan untuk mengatasi bug atau keterbatasan dalam rantai alat atau perangkat keras yang tersedia sebelumnya, dll. .
njuffa
20
Jawaban kehilangan salah satu manfaat paling penting dan penting untuk terus maju dan melakukan perubahan: belajar sesuatu. Setelah mempelajarinya, Anda dapat menambahkan struktur (komentar, tes) untuk membantu pengembang pemeliharaan nantinya. Memilih untuk tidak mengubah sesuatu karena Anda tidak tahu konsekuensinya adalah pemrograman pemujaan kargo, bahkan jika pilihan itu bukan untuk menghapus sesuatu.
kojiro
84

Ada dua bagian dari proses ini. Yang pertama mengkonfirmasi bahwa kode tersebut memang sudah mati. Yang kedua adalah memahami biaya kesalahan dan memastikan mereka dapat dimitigasi dengan baik.

Banyak jawaban di sini memiliki solusi hebat untuk separuh sebelumnya. Alat-alat seperti analisa statis sangat bagus untuk mengidentifikasi kode mati. grepdapat menjadi teman Anda dalam beberapa kasus. Satu langkah tidak biasa yang sering saya ambil adalah mencoba mengidentifikasi apa tujuan asli kode itu. Jauh lebih mudah untuk berdebat "X tidak lagi menjadi fitur produk kami, dan segmen kode Y dirancang untuk mendukung fitur X" daripada mengatakan "Saya tidak melihat tujuan untuk segmen kode Y."

Babak kedua adalah langkah kunci untuk memecah kebuntuan apa pun mengenai apakah Anda harus menghapus kode. Anda perlu memahami apa implikasi dari mendapatkan jawaban yang salah. Jika orang-orang akan mati jika Anda mendapatkan jawaban yang salah, perhatikan! Mungkin ini saat yang tepat untuk menerima bahwa kode cruft berkembang seiring waktu dan alih-alih mencoba untuk tidak menulis lebih banyak sendiri. Jika orang-orang tidak akan mati, tanyakan pada diri Anda bagaimana memaafkan pengguna Anda. Bisakah Anda mengirimi mereka perbaikan terbaru jika Anda memecahkan sesuatu dan mempertahankan hubungan pelanggan Anda? Apakah Anda memiliki tim tanya jawab yang dibayar untuk menemukan masalah seperti ini? Pertanyaan-pertanyaan semacam ini sangat penting untuk memahami seberapa pasti Anda sebelum Anda menekan tombol hapus.

Dalam komentar, rmun menunjukkan ungkapan yang sangat baik dari konsep memahami tujuan asli kode sebelum menghapusnya. Kutipan itu sekarang dikenal sebagai Pagar Chesterton . Meskipun terlalu besar untuk dikutip secara langsung dalam komentar, saya pikir layak dikutip di sini:

Dalam hal mereformasi hal-hal, berbeda dari mendeformasi mereka, ada satu prinsip yang sederhana dan sederhana; sebuah prinsip yang mungkin akan disebut paradoks. Dalam kasus seperti itu ada lembaga atau hukum tertentu; katakanlah, demi kesederhanaan, pagar atau gerbang didirikan di seberang jalan. Tipe reformis yang lebih modern menyambutnya dengan gembira dan berkata, “Saya tidak melihat penggunaan ini; mari kita bersihkan. "Untuk itu jenis reformis yang lebih cerdas akan menjawab dengan baik:" Jika Anda tidak melihat penggunaannya, saya pasti tidak akan membiarkan Anda menghapusnya. Pergi dan pikirkan. Kemudian, ketika Anda dapat kembali dan memberi tahu saya bahwa Anda memang melihat penggunaannya, saya dapat mengizinkan Anda untuk menghancurkannya.

Cort Ammon
sumber
14
Pagar Chesterton menganggap penemuan datang murni dengan berpikir, dan tidak menawarkan jalan lain — filsafat Yunani-Kuno. Metode ilmiah lebih modern - merancang eksperimen terkontrol untuk menentukan konsekuensi dari penghapusan struktur. Yang pasti, saya tidak akan dengan santai mengusulkan percobaan ini dilakukan dalam produksi. Tetapi jika tidak ada alternatif, dan biaya percobaan dalam produksi sangat tinggi, well, saya lebih baik cepat meninggalkan tempat kerja yang tidak menawarkan saya cara yang aman untuk mengetahui mengapa ada kode - risiko pribadi pada pekerjaan seperti itu terlalu tinggi .
kojiro
15
@ Kojiro Itu sangat benar. Saya suka berpikir bahwa Chesterton akan baik-baik saja jika saya, sebagai "pembaru modern" datang dan berkata, "Saya tidak tahu mengapa pagar ini ada di sini, saya akui. Tapi saya ingin mengecatnya merah untuk melihat apakah yang memberi saya informasi baru, "Chesterton mungkin akan senang dengan itu.
Cort Ammon
41
Metode decoding jam mode kernel OS VMS SYS $ ASCTIM berisi baris kode yang membantu mengoreksi penyimpangan sidereal dari vernal equinox. Tidak ada uji unit DEC yang menggunakan kode ini. Itu berjalan sekali - dengan benar - pada 2000-02-28 di 23: 59: 59: 999. Itu tidak akan berjalan lagi sampai tahun 2400. Tolong jangan hapus itu.
AI Breveleri
13
@AIBreveleri Saya harus berharap bahwa ada komentar dalam kode itu sendiri yang menjelaskan hal ini, dan tidak hanya di sini di StackExchange: D
Kyle Strand
11
@KyleStrand Apa yang kamu bicarakan? Ini adalah dokumentasi. Bisakah Anda memikirkan tempat yang lebih baik untuk menaruh informasi penting sehingga orang lain menemukannya daripada StackExchange? ;-)
Cort Ammon
43

Saya juga cenderung grepuntuk fungsi / nama kelas dalam kode, yang dapat memberikan beberapa manfaat tambahan bahwa penganalisa kode mungkin tidak, seperti jika nama tersebut disebutkan dalam komentar atau dalam file dokumentasi, atau skrip, misalnya. Saya menjalankan grep pada file di pohon sumber dan menyimpan hasilnya dalam file; biasanya hasilnya memberikan informasi terkondensasi: nama file / jalur, nomor baris, dan baris di mana nama itu ditemui, yang dapat memberikan petunjuk di mana fungsi / kelas dipanggil atau disebutkan tanpa makna semantik (berbeda dengan penganalisa kode ), dan terlepas dari ekstensi file. Jelas bukan solusi akhir tetapi tambahan yang bagus untuk analisis.

piwi
sumber
11
Saya bukan downvoter, tetapi bagaimana jika bagian kode yang Anda curigai tidak pernah dijalankan bukanlah fungsi atau kelas yang lengkap tetapi bagian dari metode / fungsi?
Tulains Córdova
9
Tergantung pada bahasanya ini mungkin tidak selalu dapat diandalkan - beberapa bahasa memungkinkan pemanggilan metode dilakukan secara dinamis. Misalnya php:$object->$variableMethod($arg1, $arg2);
Dezza
9
@ TulainsCórdova Maka ini mungkin bukan solusi yang baik, jelas. Adapun setiap solusi potensial, gunakan jika masuk akal dalam konteks yang diberikan. Tapi mungkin grepmisalnya. fungsi yang mencakup bagian kode dapat memberikan petunjuk tentang bagaimana fungsi tersebut digunakan dan oleh karena itu isinya?
piwi
7
"seperti jika nama disebutkan dalam komentar atau file dokumentasi, atau skrip" - Atau jika seseorang menggunakan refleksi untuk memanggil metode (jika menggunakan bahasa OO tingkat tinggi). Meskipun masih belum tentu 100% akurat, karena beberapa bahasa mendukung beberapa cara yang sangat tumpul untuk menemukan dan menerapkan metode.
Agustus
Ini berguna jika Anda memiliki akses ke semua kode yang mungkin yang dapat menggunakan fungsi. Namun, jika kode tersebut merupakan bagian dari perpustakaan, bagaimana Anda akan tahu bahwa hal lain yang tidak dapat Anda telusuri tidak akan pecah?
Kevin Shea
30
  • Identifikasi kode yang terlihat mati (analisis statis, dll).
  • Tambahkan pesan log untuk setiap permintaan kode yang diduga mati. Sangat mudah dengan fungsi / metode; dengan anggota statis seperti konstanta itu lebih sulit. Terkadang Anda hanya dapat menandai kode sebagai usang, dan runtime akan mencatat pesan untuk Anda secara otomatis. Biarkan kodenya utuh.
    • Log pesan ketika modul mati dimuat: sebagian besar bahasa memiliki cara untuk menjalankan inisialisasi statis pada waktu buka, yang dapat didukung piggy.
    • Pastikan pesan log Anda menyertakan jejak tumpukan yang masuk akal, sehingga Anda memahami apa yang disebut kode mati.
  • Jalankan kode yang diubah melalui semua suite pengujian Anda. Suite tes Anda juga harus menguji untuk waktu-waktu khusus, seperti melintasi tengah malam, pergantian seperempat, pergantian tahun, dll. Lihat log, perbarui pemahaman Anda tentang apa yang mati. Perhatikan bahwa tes unit dapat secara khusus menguji kode mati, sementara tidak ada tes unit lain dan tidak ada tes integrasi yang menyentuhnya.
  • Jalankan kode yang diubah dalam produksi selama beberapa minggu. Pastikan setiap proses periodik, seperti pekerjaan cron ETL sebulan sekali, dijalankan selama periode ini.
  • Lihatlah log. Apa pun yang dicatat tidak benar-benar mati. Penutupan transitif dari grafik panggilan selama sisa kode mati juga berpotensi tidak mati, bahkan jika itu tidak dipanggil. Analisis itu. Mungkin beberapa cabang mati dengan aman (misalnya bekerja dengan API layanan yang sekarang sudah punah), sementara beberapa lainnya belum. Mungkin seluruh modul / kelas hanya dimuat untuk konstanta yang didefinisikan di dalamnya, dan Anda dapat dengan mudah tidak menggunakannya.
  • Apa pun yang tersisa mati dengan aman, dan dapat dihapus.
9000
sumber
Ada yang pertama kali untuk semuanya, jadi hanya karena kode tidak berjalan sebelumnya tidak berarti itu tidak akan pernah berjalan, terutama jika ada jalur eksekusi untuk itu. Yang mengatakan, memutuskan untuk menghapus sesuatu yang dapat dieksekusi adalah proses yang berbeda dari menentukan apakah itu bisa dijalankan.
7
@nocomprende persis apa yang terjadi jika kode ini hanya digunakan untuk fungsi akhir tahun dan Anda menjalankan tes Anda dijalankan Februari - November. Anda tidak akan menemukan penggunaannya meskipun Anda memprofilkannya selama hampir setahun penuh.
Erik
1
@ 9000 Saya setuju secara teori tetapi sistem lawas dipenuhi dengan dependensi tersembunyi yang dapat menggagalkan pengujian semacam ini. Agar contoh pengujian Anda berfungsi, Anda perlu tahu bahwa ada semacam kopling temporal. Jika pemasangan sementara adalah eksternal dari kode yang Anda uji maka Anda tidak akan melihatnya dalam kode dan tahu bahwa pemasangan sementara adalah sebuah faktor. Misalnya kode silo A dipasang di GAC . Bertahun-tahun yang lalu silo B meminta silo A untuk menambahkan jalur kode untuk laporan yang mereka perlukan terhadap data silo A. lanjutan
Erik
1
@ 9000 lanj. Sekarang kode silo B memiliki penggabungan temporal ke jalur kode "mati" dalam kode silo A yang tidak terlihat hanya dengan melihat kode silo A. Bagaimana Anda menguji unit untuk pemasangan sementara ini karena pemasangan sementara hanya dalam kode silo B tanpa mengetahui untuk berbicara dengan silo B? Meski begitu waktu bukanlah faktor dalam kode Anda (silo A) jadi seperti apa tes temporal itu?
Erik
2
Adakah yang ingat kepanikan Y2k ? Beberapa kode benar pada tahun 2000 karena salah untuk 2100! Kami memiliki masalah potensial yang dapat terjadi sekali dalam 100 tahun atau bahkan sekali dalam 400 tahun.
Steve Barnes
16

Selain jawaban yang ada disebutkan Anda juga bisa menghapus kode berulang beberapa versi.

Di versi awal Anda bisa melakukan peringatan penghentian dengan blok kode yang masih berfungsi. Dalam versi setelah itu Anda dapat menghapus blok kode tetapi meninggalkan pesan kesalahan yang membiarkan pengguna fitur tersebut tidak digunakan lagi dan tidak lagi tersedia. Dalam versi final Anda akan menghapus blok kode dan pesan apa pun.

Ini dapat membantu mengidentifikasi fungsionalitas yang tidak terduga tanpa peringatan kepada pengguna akhir. Dalam skenario terbaik, kode benar-benar tidak melakukan apa-apa dan semua yang terjadi adalah bahwa kode yang tidak dibutuhkan disimpan lebih dari beberapa versi sebelum dihapus.

pengguna3196468
sumber
7
+1. Saya telah melihat begitu banyak bug dan masalah yang dihadapi pelanggan yang bisa dihindari jika pengembang (atau manajemen mereka) bersedia untuk memecah proyek menjadi dua atau tiga fase aman daripada mencoba untuk membuang semuanya sekaligus untuk memenuhi suatu tenggat waktu sewenang-wenang sebelum pindah ke proyek berikutnya.
ruakh
Ini menjawab pertanyaan yang diajukan dalam judul, tetapi jika Anda bertanya kepada saya, pertanyaan itu memiliki judul yang salah. Judul bertanya bagaimana menghapus kode, tetapi tubuh adalah tentang bagaimana mengidentifikasi apakah kode itu aman untuk dihapus. Anda pasti menjawab yang pertama, tapi saya tidak yakin itu yang sebenarnya ditanyakan OP.
underscore_d
7

Banyak orang menyarankan bahwa hal "aman" yang harus dilakukan adalah meninggalkan kode jika Anda tidak dapat membuktikan bahwa kode itu tidak digunakan.

Tapi kode bukan aset, itu kewajiban.

Kecuali Anda dapat menjelaskan mengapa ini penting dan menunjukkan pengujiannya, alternatif yang "lebih aman" mungkin adalah menghapusnya.

Jika Anda masih tidak yakin, maka setidaknya pastikan untuk menambahkan tes untuk menjalankan kode zombie.

Adrian McCarthy
sumber
Langkah 1: Hapus semua kode. Langkah 2: kembalikan apa yang dibutuhkan. Langkah 3: ulangi.
1
@Adrian Bisakah saya menarik perhatian Anda ke Knight Capital? en.wikipedia.org/wiki/… - untuk berjaga-jaga jika Anda ingin meningkatkan poin Anda dengan referensi untuk itu. Mereka pada dasarnya meledak karena beberapa kode lama hidup kembali dan dengan ramah kehilangan hampir $ 500 juta untuk mereka. Penyelidikan selanjutnya berfokus pada prosedur rilis mereka, tetapi masalah utamanya adalah "fungsionalitas mati tidak dihapus".
SusanW
6

Anda dapat menggunakan fitur toggle untuk mengubah jalur eksekusi perangkat lunak Anda untuk sepenuhnya mengabaikan kode yang dimaksud.

Dengan cara ini Anda dapat menggunakan perubahan dengan aman menggunakan kode yang tidak digunakan, dan mematikannya. Jika Anda melihat beberapa kesalahan utama yang terkait dengan kode, nyalakan kembali dan selidiki jalur yang memungkinkan.

Pendekatan ini harus memberi Anda kepercayaan diri jika Anda tidak melihat masalah selama periode waktu yang lama serta kemampuan untuk mengubahnya kembali saat penyebaran langsung. Namun cara yang lebih baik adalah menerapkan penebangan ekstra dan menguji cakupan di sekitar area yang bersangkutan yang akan memberikan lebih banyak bukti apakah digunakan atau tidak.

Baca lebih lanjut tentang beralih di sini: https://martinfowler.com/articles/feature-toggles.html

Selempang
sumber
6

Analisis statis tentu saja ... dan yang menyenangkan adalah, Anda tidak memerlukan alat baru; kompiler Anda memiliki semua alat analisis statis yang Anda butuhkan.

Cukup ganti nama metode (mis. Ubah DoSomethingmenjadi DoSomethingX) lalu jalankan build.

Jika bangunan Anda berhasil, metode ini, jelas, tidak digunakan oleh apa pun. Aman untuk dihapus.

Jika bangunan Anda gagal, pisahkan baris kode yang memanggilnya dan periksa untuk melihat ifpernyataan apa yang mengelilingi panggilan untuk menentukan cara memicunya. Jika Anda tidak dapat menemukan case use data apa pun yang memicu, Anda dapat menghapusnya dengan aman.

Jika Anda benar-benar khawatir tentang menghapusnya, pertimbangkan untuk menyimpan kode tersebut tetapi menandainya dengan ObsoleteAttribute (atau yang setara dalam bahasa Anda). Lepaskan seperti itu untuk satu versi, lalu hapus kode setelah tidak ditemukan masalah di alam bebas.

John Wu
sumber
8
Ini adalah saran yang bagus untuk bahasa pemrograman yang tidak memiliki ikatan dinamis / terlambat penuh . Namun, bagi yang punya, itu lebih sulit. Dan, tentu saja - kode mungkin menggunakan metode bahkan jika itu tidak pernah digunakan dalam produksi.
eis
Pertanyaan mengandaikan resolusi simbol waktu kompilasi ( Jadi Anda telah menemukan beberapa kode yang terlihat berlebihan. Kompiler tidak memperhatikan hal itu. ). Dan bahkan fungsi atau objek yang terikat lebih lambat biasanya didefinisikan di dua tempat, misalnya antarmuka atau file peta, sehingga pembuatannya masih gagal.
John Wu
1
Hmm ... Saya tertarik, saya tidak berpikir yang terakhir yang Anda katakan itu benar. Ini bukan untuk javascript vanilla (tidak dikompilasi), ruby, python atau smalltalk misalnya, kan? Jika Anda merujuk pada hal-hal yang tidak ada, kesalahan itu hanya saat runtime.
eis
Mungkin kita tidak setuju pada apa yang dimaksud dengan "mengikat" yang bagi saya menunjukkan resolusi representasi logis untuk representasi fisik, misalnya simbol ke alamat. Fungsi-fungsi Javascript disimpan sebagai pasangan tag / nilai di dalam objek yang mengandung, jadi setiap gagasan tentang pengikatan tampaknya tidak berurutan.
John Wu
1
Ya, kami benar-benar tidak setuju. Istilah ini memiliki arti berbeda pada bahasa yang tidak memiliki ikatan akhir penuh (seperti yang saya jelaskan di komentar pertama). Saat Anda mengikat metode saat runtime - dalam bahasa yang dapat menambah dan menghapus metode runtime, saat itu juga - Anda menggunakan pengikatan yang terlambat seperti yang saya mengerti harus dilakukan. Ini benar dalam bahasa ruby ​​/ python / smalltalk-style, dan di sana Anda tidak memiliki file peta yang terpisah. Karena terutama ruby ​​dan python sangat banyak digunakan, saya tidak setuju dengan pengertian Anda tentang apa artinya "biasanya".
eis
4
  • Saya akan mulai menggunakan penganalisa kode untuk memeriksa apakah ini kode mati
  • Saya akan mulai memeriksa tes saya dan mencoba untuk mencapai kode. Jika saya tidak dapat mencapai kode dalam suatu test case mungkin itu kode mati
  • Saya akan menghapus kode dan sebagai gantinya melemparkan pengecualian. Untuk satu rilis pengecualian diaktifkan, dan dalam rilis kedua pengecualian dapat dihapus. Agar aman, letakkan bendera darurat (di Jawa, properti sistem) untuk dapat mengaktifkan kode asli, ketika pelanggan melihat pengecualian. Jadi pengecualian dapat dinonaktifkan dan kode asli dapat diaktifkan di lingkungan produksi.
Markus Lausberg
sumber
6
-1. Sama sekali tidak direkomendasikan untuk membuat perubahan ini dalam kode produktif, bendera keselamatan atau tidak. Hanya ketika seseorang yakin kode yang dimaksud tidak digunakan harus dihapus dalam kode produktif. Semacam itu main-main adalah mengapa harus selalu ada lingkungan produktif dan pengujian yang berbeda.
Johannes Hahn
3
Ini akan bekerja dalam fantasi ketika cakupan tes hampir 90%, tetapi bagaimana jika tidak dan Anda memiliki proyek dengan 100.000 baris kode. Itulah sebabnya saya jelaskan untuk mencoba menguji kode dan jika tidak ada tes yang dapat mencapai kode ... itu mungkin mati.
Markus Lausberg
IMHO Jika Anda tidak cukup yakin untuk menahan diri dari menghapus kode sepenuhnya - Anda tidak boleh melempar pengecualian dalam produksi - logging yang disarankan oleh OP adalah alternatif yang jauh lebih baik, mencapai hal yang sama, dan Anda bisa mendapatkan diagnostik alih-alih mengandalkan pelanggan yang mengeluh
Sebi
@JohannesHahn Saya pikir maksud Anda, "kode produksi," yang merupakan kode yang berjalan di lingkungan produksi.
jpmc26
@ jpmc26 Ya, tentu saja.
Johannes Hahn
3

Menghapus kode yang tidak dapat dijangkau

Dalam bahasa yang diketik secara statis berprinsip, Anda harus selalu tahu apakah kode tersebut benar-benar dapat dijangkau atau tidak: hapus, kompilasi, jika tidak ada kesalahan, maka kode itu tidak dapat dijangkau.

Sayangnya, tidak semua bahasa diketik secara statis, dan tidak semua bahasa yang diketik secara statis berprinsip. Hal-hal yang bisa salah termasuk (1) refleksi dan (2) kelebihan beban berprinsip.

Jika Anda menggunakan bahasa yang dinamis, atau bahasa dengan refleksi yang cukup kuat bahwa potongan kode di bawah pengawasan berpotensi dapat diakses saat run-time melalui refleksi, maka Anda tidak dapat bergantung pada kompiler. Bahasa tersebut termasuk Python, Ruby atau Java.

Jika Anda menggunakan bahasa dengan kelebihan beban yang tidak berprinsip, maka menghapus kelebihan beban bisa dengan mudah mengubah resolusi kelebihan beban ke kelebihan beban lainnya secara diam-diam. Beberapa bahasa seperti itu memungkinkan Anda memprogram peringatan / kesalahan waktu kompilasi yang terkait dengan penggunaan kode, jika tidak, Anda tidak dapat mengandalkan kompiler. Bahasa tersebut termasuk Java (gunakan @Deprecated) atau C ++ (gunakan [[deprecated]]atau = delete).

Jadi, kecuali Anda sangat beruntung bekerja dengan bahasa yang ketat (Rust datang ke pikiran), Anda mungkin benar-benar menembak diri sendiri dengan mempercayai kompiler. Dan sayangnya test suite umumnya tidak lengkap sehingga tidak banyak membantu.

Beri tanda pada bagian selanjutnya ...


Menghapus kode yang berpotensi tidak digunakan

Kemungkinan besar, kode tersebut sebenarnya direferensikan, namun Anda curiga bahwa dalam praktiknya cabang-cabang kode yang merujuknya tidak pernah diambil.

Dalam hal ini, apa pun bahasanya, kode ini dapat dijangkau dengan mudah, dan hanya instrumentasi run-time yang dapat digunakan.

Di masa lalu, saya telah berhasil menggunakan pendekatan 3-fase untuk menghapus kode tersebut:

  1. Pada setiap cabang yang diduga TIDAK diambil, catat peringatan.
  2. Setelah satu siklus, lempar pengecualian / kembalikan kesalahan saat memasukkan potongan kode tertentu.
  3. Setelah siklus lain, hapus kodenya.

Apa itu siklus? Ini adalah siklus penggunaan kode. Sebagai contoh, untuk aplikasi keuangan saya akan mengharapkan siklus bulanan pendek (dengan gaji dibayarkan pada akhir bulan) dan siklus tahunan yang panjang. Dalam hal ini, Anda harus menunggu setidaknya satu tahun untuk memverifikasi bahwa tidak ada peringatan yang pernah dikeluarkan untuk inventaris akhir tahun yang dapat menggunakan jalur kode yang tidak pernah digunakan.

Semoga sebagian besar aplikasi memiliki siklus yang lebih pendek.

Saya menyarankan untuk memberikan komentar TODO, dengan tanggal, memberi nasihat kapan harus melanjutkan ke langkah berikutnya. Dan pengingat di kalender Anda.

Matthieu M.
sumber
1
Sebenarnya, di C ++ Anda dapat menandai tersangka Anda kelebihan [[deprecated]]untuk mengidentifikasi situs yang memanggil versi itu; maka Anda dapat memeriksa mereka untuk melihat apakah perilaku mereka akan berubah. Atau, tentukan kelebihan Anda sebagai = delete- dalam hal ini, Anda harus secara eksplisit melemparkan argumen untuk menggunakan salah satu versi lain.
Toby Speight
@TobySpeight: Itu benar, dan alternatif yang bagus juga. Izinkan saya mengeditnya.
Matthieu M.
"Dokter, sakit ketika saya melakukan ini." "Yah, jangan lakukan itu! " Jangan menggunakan pendekatan yang membuat kode tidak bisa dikelola.
2

Menghapus kode dari produksi seperti membersihkan rumah. Pada saat Anda membuang benda dari loteng, istri Anda akan membunuh Anda pada hari berikutnya karena membuang hadiah keponakan keponakan ketiga kakek buyut neneknya dari tetangga mereka yang meninggal pada tahun 1923.

Serius, setelah analisis sepintas menggunakan berbagai alat yang semua orang telah sebutkan, dan setelah menggunakan pendekatan penghentian melangkah yang telah disebutkan, perlu diingat bahwa Anda mungkin pergi dari perusahaan ketika pemindahan yang sebenarnya terjadi. Membiarkan kode tetap dan eksekusi dieksekusi dan memastikan bahwa setiap peringatan dari eksekusi pasti dikomunikasikan kepada Anda (atau penerus dan penerima tugas Anda) sangat penting.

Jika Anda tidak mengikuti pendekatan ini, Anda kemungkinan besar akan dibunuh oleh istri Anda. Jika Anda menyimpan kode (seperti setiap kenang-kenangan) maka Anda dapat mengistirahatkan hati nurani Anda dalam kenyataan bahwa hukum Moore datang untuk menyelamatkan Anda dan biaya ruang junk disk yang digunakan oleh kode yang terasa seperti "batu di sepatu saya", mengurangi setiap tahun dan Anda tidak berisiko menjadi pusat beberapa gosip pendingin air dan penampilan aneh di lorong.

PS: Untuk mengklarifikasi dalam menanggapi komentar .. Pertanyaan aslinya adalah "Bagaimana Anda menghapus dengan aman .." tentu saja, Kontrol Versi diasumsikan dalam jawaban saya. Sama seperti menggali di tempat sampah untuk menemukan yang berharga diasumsikan. Tidak ada badan dengan akal membuang kode dan kontrol versi harus menjadi bagian dari kekakuan setiap pengembang.

Masalahnya adalah tentang kode yang mungkin berlebihan. Kita tidak akan pernah tahu sepotong kode itu berlebihan kecuali kita dapat menjamin 100% dari jalur eksekusi tidak mencapainya. Dan diasumsikan bahwa ini adalah perangkat lunak yang cukup besar sehingga jaminan ini hampir tidak mungkin. Dan kecuali saya membaca pertanyaan yang salah, satu-satunya waktu seluruh utas percakapan ini relevan adalah untuk kasus selama produksi di mana kode yang dihapus mungkin dipanggil dan karenanya kami memiliki masalah runtime / produksi. Kontrol versi tidak menyelamatkan siapa pun di belakang karena kegagalan produksi, sehingga komentar tentang "Kontrol Versi" tidak relevan dengan pertanyaan atau poin asli saya, yaitu dengan benar mencabut kerangka waktu yang sangat lama jika Anda benar-benar harus, jika tidak,

IMHO, komentar itu berlebihan dan merupakan kandidat untuk dihapus.

LMSingh
sumber
12
Jika saya memiliki kontrol versi yang setara , keberatan istri saya akan mudah dibalik. Begitu juga dengan menghapus kode: itu bukan pelanggaran pembunuhan. Repositori tidak pernah dibuang.
JDługosz
Saya pikir pemrograman Object Oriented seharusnya mempersempit ruang lingkup di mana metode dapat dipanggil. Jadi harus mengarah pada kode yang lebih mudah dipahami dan dikelola, bukan? Kalau tidak, mengapa kita melakukannya dengan cara itu?
@nocomprende Tidak ada di utas ini yang mengindikasikan bahwa diskusi terbatas pada desain / bahasa OOP saja. Saya tidak yakin mengapa Anda berpikir itu relevan.
underscore_d
1

Mungkin compiler tidak melihat bahwa, hal itu tidak membuat keributan.

Jalankan build dengan optimisasi kompiler penuh, yang disesuaikan dengan ukuran. Kemudian hapus kode yang dicurigai, dan jalankan kembali build.

Bandingkan binari. Jika mereka identik, maka kompiler telah memperhatikan dan diam-diam menghapus kode. Anda dapat menghapusnya dari sumber dengan aman.

Jika binari berbeda ... maka itu tidak meyakinkan. Mungkin ada beberapa perubahan lain. Beberapa kompiler bahkan menyertakan tanggal dan waktu kompilasi dalam biner (dan mungkin bisa dikonfigurasikan!)

Emilio M Bumachar
sumber
1
Tidak semua bahasa dikompilasi, tidak semua kompiler memiliki optimisasi dan tidak semua optimisasi sama, banyak yang tidak menghapus kode yang tidak dipanggil hanya jika kode ada karena suatu alasan. Jika kode tinggal di perpustakaan bersama / DLL itu tidak akan dihapus.
Steve Barnes
1
@ SveveBarnes Ya, jika Anda tidak melakukan KPP dan menghubungkan semuanya secara statis, Anda akan kesakitan. Itu diberikan.
Navin
1

Saya sebenarnya baru saja menemukan situasi yang tepat ini, dengan metode yang disebut "deleteFoo". Tidak ada tempat di seluruh basis kode adalah string yang ditemukan selain deklarasi metode, tapi saya dengan bijak menulis baris log di bagian atas metode.

PHP:

public function deleteFoo()
{
    error_log("In deleteFoo()", 3, "/path/to/log");
}

Ternyata kode itu digunakan! Beberapa metode AJAX memanggil "metode: delete, elem = Foo" yang kemudian digabungkan dan dipanggil dengan call_user_func_array () .

Jika ragu, masuk! Jika Anda memiliki waktu yang cukup tanpa melihat log diisi, maka pertimbangkan untuk menghapus kode. Tetapi bahkan jika Anda menghapus kode, biarkan log di tempat dan komentar dengan tanggal untuk membuat menemukan komit di Git lebih mudah bagi orang yang harus mempertahankannya!

dotancohen
sumber
Ada perpustakaan untuk PHP dan Perl disebut Tombstone (php: github.com/scheb/tombstone ) yang dapat berguna di sini.
Alister Bulman
0

Gunakan grepatau alat apa pun yang Anda miliki terlebih dahulu, Anda mungkin menemukan referensi ke kode. (Awalnya bukan instruksi / saran saya.)

Kemudian putuskan apakah Anda ingin mengambil risiko menghapus kode, atau jika saran saya dapat digunakan untuk:

Anda dapat memodifikasi fungsi / blok kode untuk menulis bahwa ia telah digunakan untuk file log. Jika tidak ada pesan seperti itu "pernah" direkam dalam file log, maka Anda mungkin dapat menghapus kode logging.

Dua masalah:

  1. Mendapatkan log dari pengguna lain. Mungkin Anda dapat menetapkan bendera global yang akan membuat crash program saat keluar dan dengan ramah meminta pengguna untuk mengirimi Anda log kesalahan.

  2. Menelusuri penelepon. Dalam beberapa bahasa tingkat tinggi (mis. Python) Anda dapat dengan mudah mendapatkan traceback. Tetapi dalam bahasa yang dikompilasi Anda harus menyimpan alamat kembali ke log dan memaksa dump inti saat keluar (titik 1).
    Dalam C, ini seharusnya cukup sederhana: gunakan blok kondisional (mis. #Ifdef ... #endif) hanya menggunakan ini ketika Anda tahu itu akan berhasil (dan telah diuji ternyata berhasil), dan cukup baca alamat pengirim dari tumpukan (mungkin atau mungkin tidak memerlukan bahasa rakitan inline).

Menyimpan argumen dalam file log mungkin bermanfaat atau tidak.

Oskar Skog
sumber
0

Jika Anda tahu kode apa yang mengelilinginya, ujilah untuk melihat apakah rusak. Ini adalah cara paling sederhana dan paling hemat biaya untuk refactor sepotong kode yang sedang Anda kerjakan, dan harus tetap dilakukan sebagai masalah mengembangkan perubahan pada kode yang Anda kerjakan di tempat pertama.

Jika, di sisi lain, Anda melakukan refactoring sepotong kode di mana Anda tidak tahu apa artinya, jangan hapus . Pahami terlebih dahulu, kemudian refactor jika Anda memutuskan untuk aman (dan hanya jika Anda dapat menentukan bahwa refactoring akan menjadi penggunaan waktu Anda secara tepat).

Sekarang, mungkin ada beberapa keadaan (saya tahu saya sudah mengalami sendiri) di mana kode yang 'mati' sebenarnya tidak terhubung dengan apa pun . Seperti pustaka kode yang dikembangkan oleh kontraktor yang tidak pernah benar-benar diimplementasikan di mana saja karena mereka menjadi usang segera setelah aplikasi dikirim (mengapa ya, saya punya contoh spesifik dalam pikiran, bagaimana Anda tahu?).

Saya pribadi akhirnya menghapus semua kode ini, tetapi ini adalah risiko besar yang tidak saya rekomendasikan untuk diambil ringan - tergantung pada seberapa banyak kode yang berpotensi berdampak pada perubahan ini (karena selalu ada potensi bahwa Anda telah mengabaikan sesuatu) Anda harus sangat berhati-hati dan menjalankan tes unit agresif untuk menentukan apakah menghapus kode lama ini akan merusak aplikasi Anda.

Sekarang semua itu dikatakan, mungkin tidak sepadan dengan waktu atau kewarasan Anda untuk mencoba dan menghapus kode seperti itu. Tidak, kecuali jika itu menjadi masalah serius dengan aplikasi Anda (misalnya, tidak dapat menyelesaikan pemindaian keamanan karena aplikasi mengasapi ... mengapa ya saya DO masih memiliki contoh dalam pikiran), jadi saya tidak akan merekomendasikannya kecuali Anda mencapai situasi di mana kode benar-benar mulai membusuk dengan cara yang berdampak.

Jadi singkatnya - jika Anda tahu kode apa yang dikerjakan, ujilah terlebih dahulu. Jika tidak, Anda mungkin bisa membiarkannya sendiri. Jika Anda tahu Anda tidak bisa membiarkannya sendirian, persembahkan waktu Anda untuk menguji perubahan secara agresif sebelum menerapkan perubahan.

Zibbobz
sumber
0

Pendekatan saya, yang saya selalu anggap standar industri dalam kasus ini, anehnya belum disebutkan sejauh ini:

Dapatkan sepasang mata kedua.

Ada berbagai jenis "kode yang tidak digunakan" dan dalam beberapa kasus menghapusnya sesuai, dalam kasus lain Anda harus refactor, dan dalam kasus lain Anda melarikan diri sejauh yang Anda bisa dan tidak pernah melihat ke belakang. Anda perlu mencari tahu yang mana itu, dan untuk melakukannya Anda berpasangan dengan yang terbaik - berpengalaman! - pengembang, orang yang sangat akrab dengan basis kode. Ini secara signifikan mengurangi risiko untuk kesalahan yang tidak perlu, dan memungkinkan Anda untuk melakukan perbaikan yang diperlukan untuk menjaga basis kode dalam keadaan terpelihara. Dan jika Anda tidak melakukan ini, pada titik tertentu Anda kehabisan pengembang yang sangat akrab dengan basis kode.

Saya telah melihat pendekatan logging juga - lebih tepatnya, saya telah melihat kode logging: bahkan lebih banyak kode mati yang tersisa di sana selama 10 tahun. Pendekatan logging cukup baik jika Anda berbicara tentang menghapus seluruh fitur, tetapi tidak jika Anda hanya menghapus sebagian kecil kode mati.

Peter
sumber
0

Jawaban sederhana untuk pertanyaan Anda adalah Anda tidak dapat dengan aman menghapus kode yang tidak Anda mengerti, yang mencakup tidak memahami bagaimana panggilan itu. Akan ada risiko.

Anda harus menilai cara terbaik untuk mengurangi risiko yang tidak dapat dihindari itu. Yang lain menyebutkan penebangan. Logging tentu saja dapat membuktikan bahwa itu digunakan, tetapi tidak dapat membuktikan bahwa itu tidak digunakan. Karena masalah utama dengan kode mati adalah kode itu dipelihara, Anda mungkin bisa lolos dengan menambahkan komentar yang mengatakan bahwa kode itu diduga merupakan kode mati, dan tidak melakukan pemeliharaan apa pun terhadapnya.

Jika kode berada di bawah kendali sumber, Anda selalu dapat mengetahui kapan kode itu ditambahkan dan menentukan bagaimana namanya saat itu.

Pada akhirnya, Anda bisa memahaminya, membiarkannya, atau mengambil risiko.

jmoreno
sumber
0

Jika pengembang kode yang dimaksud masih tersedia, tinjau penghapusan kode dengannya . Juga, membaca komentar dalam kode .

Anda akan mendapatkan penjelasan yang tepat, mengapa kode ini ditambahkan dan fungsi apa yang dilayaninya. Ini dapat dengan mudah menjadi dukungan untuk kasus penggunaan khusus, atau Anda bahkan mungkin tidak memiliki keahlian yang cukup untuk menilai jika itu benar-benar tidak diperlukan. Dalam kasus ekstrem, seseorang dapat menghapus semua pernyataan bebas dari program C dan gagal untuk melihat ada yang salah (mungkin butuh beberapa menit untuk kehabisan memori).

Ini benar-benar budaya yang buruk ketika penulis kode duduk di sebelah Anda, namun Anda tidak melihat alasan untuk berbicara karena Anda yakin dia hanya menulis kode yang buruk, dan Anda semua sangat sempurna. Dan, tentu saja, dia hanya menulis kata-kata acak dalam komentar, tidak perlu buang waktu membaca.

Salah satu alasan paling penting untuk menulis komentar dalam kode adalah untuk menjelaskan MENGAPA telah diterapkan dengan cara ini. Anda mungkin tidak setuju dengan solusinya, tetapi Anda harus mempertimbangkan masalahnya.

Diskusi dengan penulis juga dapat mengungkapkan bahwa kode adalah sisa sejarah dari sesuatu yang dihapus atau tidak pernah selesai, sehingga aman untuk dihapus.

h22
sumber
-1

Saya sangat setuju dengan poin pertama Markus Lausberg: Kode pasti harus dianalisis dengan bantuan alat. Otak kera tidak bisa dipercaya dengan tugas seperti ini !!

Kebanyakan bahasa pemrograman standar dapat digunakan dalam IDE dan setiap IDE yang layak disebut yang memiliki fitur "find for all use" - fitur yang merupakan alat yang tepat untuk situasi seperti ini. (Ctrl + Shift + G di Eclipse misalnya)

Tentu saja: Alat analisa statis tidak sempurna. Seseorang harus menyadari situasi yang lebih rumit di mana keputusan bahwa metode yang dimaksud dipanggil terjadi hanya pada saat runtime dan tidak lebih cepat (panggilan melalui Refleksi, panggilan ke "eval" -fungsi dalam bahasa scripting dll).

Johannes Hahn
sumber
5
Mungkin otak kera seharusnya tidak menulis kode? " Tersentuh oleh tangan manusia " digunakan untuk menjadi frase pemasaran. Saya selalu membayangkan tangan gorila melakukan pekerjaan itu.
3
(Otak kera juga menulis alatnya) (Ssst! Anda akan merusak ceritanya!)
1
Saya pikir Anda berdua kehilangan maksud saya. Saya jelas mengatakan bahwa tidak ada jaminan bahwa analisis kode statis akan menemukan setiap permohonan metode atau kelas. Ini, seperti yang tertulis di kaleng, adalah analisis statis. Tidak dapat dan seharusnya tidak diharapkan untuk menemukan doa dinamis melalui refleksi, eval () dll. Maksud saya adalah bahwa analisis kode statis harus dianggap sebagai prasyarat yang diperlukan untuk menghapus sepotong kode. Dan semakin besar proyeknya, semakin kecil kemungkinannya bahwa otak manusia bahkan mampu melakukan analisis itu sama sekali, apalagi melakukannya dengan benar ...
Johannes Hahn
1
... analisis kode statis adalah pekerjaan yang membosankan dan berulang yang paling baik dilakukan oleh komputer. Tepatnya jenis tugas yang dapat dieksekusi secara andal oleh komputer tetapi sangat tidak dapat diandalkan ketika dijalankan oleh otak kera. Yang terakhir hanya boleh digunakan untuk hal-hal yang tidak bisa dilakukan komputer seperti menemukan refleksi rumit dan panggilan jarak jauh.
Johannes Hahn
1
Sekali lagi, kehilangan intinya. Sekalipun alatnya tidak sempurna karena ditulis oleh otak kera (dan saya bahkan tidak yakin apakah saya harus mengabulkannya! Menghitung hierarki panggilan statis tidak sesulit itu), mereka masih jauh lebih unggul daripada eksekusi tugas manual. Ini bukan situasi yang semuanya atau tidak sama sekali. Alat yang andal 99% masih lebih disukai daripada otak yang mungkin dimulai dengan 99% persen tetapi dengan cepat turun ke tingkat yang jauh lebih rendah setelah ribuan baris kode pertama.
Johannes Hahn
-1

Dua kemungkinan:

  1. Anda memiliki 99% + cakupan tes : Hapus kode dan selesaikan.
  2. Anda tidak memiliki cakupan pengujian yang dapat dipercaya: Maka jawabannya adalah menambahkan peringatan penghentian . Yaitu, Anda menambahkan beberapa kode ke tempat itu yang melakukan sesuatu yang waras (catat peringatan ke tempat yang mudah terlihat yang tidak bertentangan dengan penggunaan aplikasi Anda sehari-hari, misalnya). Kemudian biarkan mendidih selama beberapa bulan / tahun. Jika Anda tidak pernah menemukan kejadian itu, gantilah penghinaan itu dengan sesuatu yang melempar pengecualian. Biarkan itu berdiri sebentar. Akhirnya, hapus semuanya sepenuhnya.
AnoE
sumber
2
ini tampaknya tidak menawarkan sesuatu yang substansial atas poin yang dibuat dan dijelaskan dalam 17 jawaban sebelumnya. Baik liputan dan peringatan penghentian sudah dibahas di sana
nyamuk
@gnat, kamu benar. Ketika saya pertama memindai jawaban, untuk beberapa alasan saya pikir saya telah melihat beberapa yang di atas yang tidak singkat dan ringkas sampai ke dua titik ini. Di tengah jawaban ada beberapa yang seperti itu.
AnoE