Kode yang mengubah nilai menjadi representasi yang berbeda, lalu mengubahnya kembali ke tempat awalnya buruk, tetapi bagaimana caranya? [Tutup]

35

Saya sedang membaca artikel tentang praktik pemrograman yang buruk .

Itu disebutkan -

"Yo-Yo code" yang mengubah nilai menjadi representasi yang berbeda, lalu mengubahnya kembali ke tempat permulaannya (mis: mengubah desimal menjadi string dan kemudian kembali ke desimal, atau menambahkan string, lalu memangkasnya)

Saya tidak mengerti mengapa contoh khusus yang dia berikan adalah cara yang buruk untuk menulis program. Tampaknya baik-baik saja bagi saya untuk mengonversi kembali jika situasinya mengharuskannya sehingga nilainya dapat digunakan.

Adakah yang bisa menjelaskan lebih lanjut tentang ini?

pengguna13107
sumber
4
direkomendasikan membaca: Diskusikan $ {blog} ini
gnat
8
Sebagian besar waktu itu hanya mubazir dan itu terjadi hanya karena programmer tidak tahu cara yang lebih baik untuk mendapatkan apa yang mereka inginkan. Blog entry memberikan contoh yang khas beberapa paragraf kemudian: "Roundabout code" that accomplishes in many instructions what could be done with far fewer (eg: rounding a number by converting a decimal into a formatted string, then converting the string back into a decimal). if the situation is so that they have to be used?- situasi apa itu?
Konrad Morawski
3
@gnat Saya tidak mengerti bagaimana ini membuat pertanyaan ini buruk. Jika mau, saya dapat mengeditnya dengan mengatakan "apakah kode yang mengubah dan mengubah kembali nilai menjadi buruk?" dan itu tidak akan cocok dengan templat itu lagi.
djechlin
5
Saya baru-baru ini menemukan kode di Jawa yang beralih ke array, membuat serialisasi setiap objek menjadi objek JSON, menggunakan rangkaian string, bukan serializer JSON. Hasilnya kemudian diteruskan ke metode pribadi, yang mem-parsing array JSON untuk mengekstrak sekelompok ID, kemudian melewati ID di tempat lain. Ini adalah satu-satunya penggunaan array JSON dalam sistem. Itu adalah kode yo-yo. Tidak ada alasan untuk transformasi bolak-balik. Kita bisa dengan mudah melewati ID dari objek aslinya.
Brandon
3
decimal myValue = decimal.Parse(dataReader["myColumn"].ToString())adalah kesal hewan peliharaan saya.
Matius

Jawaban:

125

Bahkan jika Anda benar- benar membutuhkan representasi numerik dan string dari suatu angka, lebih baik mengonversi sekali saja dan juga berpegang pada nilai asli, alih-alih mengonversi lagi setiap kali Anda membutuhkan satu atau yang lainnya.

Prinsipnya adalah, seperti biasa, kode yang tidak ada tidak dapat memiliki cacat yang halus , sedangkan kode yang ada sering terjadi. Itu mungkin terdengar paranoid, tetapi pengalaman mengajarkan kita bahwa itu tepat. Jika Anda mendekati pemrograman dengan kecemasan ringan permanen tentang "Saya tidak cukup pintar untuk memahami sistem yang rumit ini", Anda berada di jalur yang benar.

Kilian Foth
sumber
5
Kata baik. Kita semua programmer harus sangat berhati-hati.
Neil
58
"kode yang tidak ada tidak dapat memiliki cacat halus, sementara kode yang ada sering" berharap saya dapat memberi Anda +2 untuk itu. Jangan pernah meremehkan nilai dari tidak harus menulis kode.
Benjamin Gruenbaum
2
Tetapi melakukan beberapa operasi sederhana (konversi ke string dan kembali) mungkin jauh lebih kompleks (lebih mudah dipahami dan kode) daripada cara "benar" memanipulasi bit. Dan menyimpan semua data dari suatu kategori dalam satu bentuk seringkali merupakan ide yang baik, bahkan jika datum tertentu akan secara tak terelakkan dikonversi ke bentuk lain.
Daniel R Hicks
36
@DanielRHicks jadi mari kita konversi tanggal sederhana itu (10 november 2014) menjadi sebuah string, -> 10-11-2014 dan kembali ke tanggal -> (11 oktober 2014) hei tunggu apa?
Pieter B
20
@PieterB Ada perangkat lunak akuntansi besar Jerman yang tidak berfungsi pada komputer dengan lokal bukan Jerman karena melakukan ini. Pertama-tama mengkonversi tanggal ke string menggunakan sistem lokal dan kemudian mencoba untuk menguraikannya dengan lokal tetap dan mengeluh tentang format ilegal. Itu melakukan hal yang sama dengan angka dan pemisah desimal yang berbeda-beda, kecuali bahwa itu tidak mengeluh di sana, itu merusak data dan menunjukkan perilaku aneh. Butuh waktu berhari-hari untuk memikirkannya.
CodesInChaos
23

Itu buruk karena tiga alasan utama:

  1. Ini menunjukkan Anda belum memikirkan jenis / format variabel yang seharusnya tetapi mengubahnya menjadi apa yang Anda butuhkan saat itu. Ini menunjukkan kurangnya pemikiran desain.
  2. Mungkin sia-sia. Anda hampir pasti membuang siklus, dan baris kode, melakukan konversi yang tidak perlu ada di sana. Ini akan membuat kode Anda lebih lambat dan lebih besar dari yang seharusnya.
  3. Jenis konversi cenderung mengalami kesalahan halus. Dengan mengubah konversi ini melalui kode Anda, Anda meningkatkan kemungkinan kesalahan.

Saya menduga alasan 1 adalah alasan yang dipikirkan sumber Anda berdasarkan konteks yang disebutkan.

Jack Aidley
sumber
6

Saya akan mengulangi deskripsi sebagai "kode yang mengubah tipe ke representasi yang berbeda untuk tujuan melakukan sesuatu yang bisa dilakukan dengan baik atau lebih baik dalam aslinya dan kemudian mengubahnya kembali. Ada banyak situasi di mana mengubah sesuatu menjadi sebuah tipe yang berbeda, menindaklanjutinya, dan mengubahnya kembali sepenuhnya tepat dan kegagalan untuk melakukannya akan menghasilkan perilaku yang salah.

Sebagai contoh di mana konversi baik:
Seseorang memiliki empat floatnilai tanda arbitrer yang besarnya mungkin berbeda dengan faktor hingga 1.000, dan seseorang perlu menghitung jumlah dalam 0,625 unit di tempat terakhir. Mengubah keempat nilai menjadi double, menghitung penjumlahan, dan mengubah hasilnya kembali floatmenjadi jauh lebih efisien daripada pendekatan apa pun yang menggunakanfloat sendiri.
Nilai titik-mengambang paling akurat hingga 0,5 unit di tempat terakhir (ULP). Contoh ini akan mengharuskan bahwa kesalahan pembulatan kasus terburuk tidak lebih dari 25% di atas kesalahan kasus terburuk optimal. Menggunakan ganda akan menghasilkan nilai yang akan akurat dalam 0,5001 ULP. Sementara persyaratan 0,625 ULP mungkin tampak dibuat-buat, persyaratan seperti itu sering penting dalam algoritme pendekatan-berturut-turut. Semakin ketat batas kesalahan ditentukan, semakin rendah persyaratan iterasi kasus terburuk.

Sebagai contoh di mana konversi buruk:
Seseorang memiliki angka floating-point, dan ingin menghasilkan string yang akan mewakili nilainya secara unik. Salah satu pendekatan adalah mengonversi angka menjadi string dengan jumlah digit tertentu, mencoba mengubahnya kembali, dan melihat apakah hasilnya cocok.

Tapi ini sebenarnya pendekatan yang buruk. Jika string desimal mewakili nilai yang berada hampir tepat di titik tengah antara dua nilai floating-point, itu cukup mahal untuk metode string-to-float untuk menjamin bahwa itu akan selalu menghasilkan semakin dekatfloat , dan banyak metode konversi seperti itu tidak dapat menegakkan jaminan seperti itu (antara lain, melakukan hal itu dalam beberapa kasus akan mengharuskan membaca semua digit angka, bahkan jika itu panjangnya miliaran digit).

Jauh lebih murah untuk suatu metode untuk menjamin bahwa ia akan selalu mengembalikan nilai yang berada dalam 0,5625 unit di tempat terakhir (ULP) dari nilai yang diwakili. Rutin format desimal-ke-string yang kuat "reversibel" harus menghitung seberapa jauh nilai output dari nilai yang benar, dan terus mengeluarkan digit hingga hasilnya berada dalam 0,375 (ULP) jika tidak 0,25 (ULP). Jika tidak, ini dapat menghasilkan string yang beberapa metode konversi akan proses dengan benar, tetapi metode konversi lainnya tidak.

Lebih baik terkadang mengeluarkan angka yang mungkin tidak "perlu" daripada menghasilkan nilai yang mungkin disalahtafsirkan. Bagian kuncinya adalah bahwa keputusan berapa digit harus menjadi output harus dibuat berdasarkan perhitungan numerik yang terkait dengan proses output, bukan pada hasil dari upaya satu metode tertentu untuk mengubah string kembali ke angka.

supercat
sumber
1
Contoh Anda tidak mengembalikan nilai asli yang diminta OP. Ini hanya mengembalikan nilai dengan tipe yang sama, dihitung dari beberapa input.
CJ Dennis
2

Berbagai alasan

  1. Tidak ada gunanya dan menambah kompleksitas - baik dalam jumlah kode untuk menulis dan memelihara, dan jumlah waktu CPU yang dibutuhkan

    1. Itu bisa kehilangan akurasi atau lebih buruk, merusak nilainya sama sekali

    2. Itu membuang-buang memori (berpotensi, tergantung pada bahasa) ketika Anda akhirnya menyimpan lebih banyak representasi dari nomor yang Anda butuhkan

Praktik yang baik hanya untuk menjaga representasi pertama, seakurat mungkin, untuk data apa pun yang Anda terima. Lakukan kalkulasi apa pun menggunakan data ini, dan hanya perlu mengonversinya jika Anda perlu menampilkan atau menampilkannya dalam format yang lebih mudah dibaca.

Jon Story
sumber
ini sepertinya tidak menambah sesuatu yang substansial pada poin yang dibuat dan dijelaskan dalam jawaban sebelumnya
agas
2
Apakah itu membenarkan pemungutan suara? Saya percaya posting saya berpotensi lebih ringkas
Jon Story
jawaban sebelumnya benar-benar terlihat lebih ringkas bagi saya, keduanya
agung
0

Mengapa? Karena bahkan yang terbaik dari kita dapat membuat kesalahan.

Lihat apa yang terjadi ketika Microsoft mencoba menerapkan format "pulang pergi" khusus untuk memastikan konversi string <-> float aman: https://stackoverflow.com/q/24299692/541686

Mehrdad
sumber
0

Ketika saya masih di sekolah (dan pasca sekolah di bidang teknik listrik) kami diajarkan untuk membelah setelah mengalikan. Pembagian sering banyak digit dan bulat. Mengalikan setelah pembagian mengalikan kesalahan pembagian.

Jenis konversi sama, Anda berisiko kehilangan data. CInt (1.3) = 1.

Dalam bahasa saya, Basic, kami hanya melakukan konversi jenis (program VB6 menghabiskan 90% waktunya untuk melakukan konversi ANSI / Unicode, untuk semua panggilan API yang menghasilkan runtime).

Konversi tipe tersirat dalam semua yang kami lakukan.

 Print 5

String "5" akan dicetak dari literal numerik.

form1.caption = "My Form"

String unicode literal akan dikonversi menjadi string ANSI dan dikirim ke SetWindowsTextA oleh paket formulir.

Bahkan ini berfungsi di dasar

a = "5"
b = 3

c = a + b (= 8)

Saya seorang programmer varian hari ini - saya bahkan tidak berpikir tentang tipe. Saya hanya mengandalkan konversi otomatis.

Pokoknya 3 kencing kesayangan saya adalah

Menetapkan string literal ke variabel untuk menggunakannya (menghabiskan memori dan lambat)

Fungsi tidak berguna ketika kode bisa inline (dan kompiler mungkin akan membatalkan fungsi Anda dan tetap inline)

Menyetel semua objek menjadi nol sebagai baris terakhir sebelum Fungsi Akhir atau akhir program.

dan yang ke-4 untuk program pendek

Peredupan 3 variabel Anda secara sia-sia dalam program 5 baris.

triggeradeadcat
sumber