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.
"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.
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?
sumber
Jawaban:
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:
sumber
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.
grep
dapat 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:
sumber
Saya juga cenderung
grep
untuk 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.sumber
$object->$variableMethod($arg1, $arg2);
grep
misalnya. fungsi yang mencakup bagian kode dapat memberikan petunjuk tentang bagaimana fungsi tersebut digunakan dan oleh karena itu isinya?sumber
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.
sumber
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.
sumber
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
sumber
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
DoSomething
menjadiDoSomethingX
) 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
if
pernyataan 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.
sumber
sumber
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:
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.
sumber
[[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.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.
sumber
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!)
sumber
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:
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!
sumber
Gunakan
grep
atau 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:
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.
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.
sumber
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.
sumber
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.
sumber
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.
sumber
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.
sumber
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).
sumber
Dua kemungkinan:
sumber