Bir değeri farklı bir gösterime dönüştüren, sonra tekrar başladığı yere dönüştüren kod kötüdür, ama nasıl? [kapalı]


35

Kötü programlama uygulamaları hakkında bir makale okuyordum .

Bahsetti -

Bir değeri farklı bir gösterime dönüştüren "Yo-Yo code", sonra tekrar başladığı yere dönüştürür (örneğin, bir ondalık basamağı dizgeye dönüştürmek ve sonra ondalık basamağa dönüştürmek veya dizgiyi doldurmak ve sonra kırpmak)

Neden verdiği belirli örneğin program yazmak için kötü bir yol olduğunu anlamıyorum. Durumun gerektirmesi durumunda, değeri kullanabilmem için bana geri dönmem uygun gözüküyor.

Bunun hakkında daha fazla şey açıklayabilir misiniz?


4
Önerilen okumalar: Tartışın $ {blog}
gnat

8
Çoğu zaman sadece gereksizdir ve yalnızca programcının istediklerini elde etmek için daha iyi bir yol bilmediği için gerçekleşir. Blog girişi birkaç paragraf sonra tipik bir örnek verir: "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?- bu ne olurdu?
Konrad Morawski

3
@gnat Bunu nasıl kötü bir soru yaptığımı anlamıyorum. İsterseniz, "Kötü bir değeri dönüştüren ve geri dönüştüren kod mu?" ve artık bu şablona uymuyor.
djechlin

5
Yakın zamanda Java'da bir dizinin üzerinde yinelenen, her nesneyi bir JSON nesnesine serileştiren, bir JSON serileştiricisini değil dize bitiştirme kullanarak kod buldum. Sonuçta, bir grup ID'yi çıkarmak için JSON dizisini ayrıştıran özel bir yönteme geçildi, ardından kimlik numarası başka bir yere geçti. Bu sistemdeki JSON dizisinin tek kullanımıydı. Bu yo-yo kodudur. İleri ve geri dönüş için hiçbir sebep yoktu. Kimliği basitçe orijinal nesnelerden geçirebilirdik.
Brandon

3
decimal myValue = decimal.Parse(dataReader["myColumn"].ToString())benim evcil hayvan peeve.
Matthew

Yanıtlar:


125

Eğer bile yapmak gerek sayısal hem de bir sayının dize gösterimini, bunun yerine yine bir veya diğer ihtiyaç her zaman dönüştürme, sadece bir kez dönüştürmek ve aynı zamanda orijinal değerine asmak daha iyidir.

İlke, her zaman olduğu gibi, varolmayan kodun, genellikle varolan kodun yaptığı gibi, ince kusurlara sahip olmamasıdır . Bu paranoyak gelebilir, ancak deneyim bize bunun uygun olduğunu gösteriyor. Eğer "Bu karmaşık sistemi anlayacak kadar akıllı değilim" olarak sürekli bir ışık kaygısı ile programlamaya yaklaşıyorsanız, doğru yoldasınız.


5
İyi dedi. Programcıların hepimiz çok dikkatli olması gerekir.
Neil

58
"var olmayan kodlar ince kusurlara sahip olamazlar, buna rağmen var olan kodlar sık ​​sık ortaya çıkar" keşke bunun için seni +2 yapabilseydim. Kod yazmak zorunda olmamanın değerini asla küçümsemeyin.
Benjamin Gruenbaum

2
Ancak birkaç basit işlem yapmak (dizgiye ve geriye dönüştürmek) bitleri işlemenin "doğru" yönteminden çok daha az karmaşık (anlaşılması ve kodlanması daha kolay) olabilir. Ve bir kategorinin tüm verilerini tek bir formda tutmak, belirli veriler kaçınılmaz olarak diğer formlara dönüştürülse bile, genellikle iyi bir fikirdir.
Daniel R Hicks

36
@DanielRHicks bu basit tarihi (10 kasım 2014) bir dizgeye, -> 10-11-2014 ve bir tarihe geri dönelim -> (11 ekim 2014) hey bekle?
Pieter B

20
@PieterB Alman olmayan bir yerel ayarı olan bilgisayarlarda çalışmayan büyük bir Alman muhasebe yazılımı var çünkü bunu yapıyor. İlk önce sistem yerel ayarını kullanarak dizgiyi dönüştürür ve daha sonra sabit bir yerel ayar ile ayrıştırmaya çalışır ve geçersiz formattan şikayet eder. Sayılarla ve değişken ondalık ayırıcılarla aynı şeyi yapar, burada şikayet etmemesi dışında verileri bozar ve tuhaf davranışlar sergiler. Bunu çözmem günler sürdü.
KodlarInChaos

23

Üç ana nedenden dolayı kötü:

  1. Değişkenin gerçekte ne tür / formatta olması gerektiğini düşünmediniz ama bunun yerine o anda ihtiyacınız olana onu dönüştürüyorsunuz. Bu tasarım düşüncesi eksikliğini göstermektedir.
  2. Muhtemelen savurgandır. Neredeyse kesinlikle döngüleri ve kod satırlarını boşa harcıyorsunuz, orada olması gerekmeyen dönüşümleri yapıyorsunuz. Bu, kodunuzu olması gerekenden daha yavaş ve daha şişkin hale getirecektir.
  3. Tür dönüşümleri, ince hatalara açıktır. Bu dönüşümleri kodunuzla işaretleyerek hata olasılığını artırıyorsunuz.

1. nedenin, kaynağınızın söz konusu içeriğe dayanmayı düşündüğünün sebebi olduğunu düşünüyorum.


6

Açıklamayı "bir türün orjinalinde iyi ya da daha iyi şekilde yapılabilecek bir şeyi yapmak amacıyla farklı bir gösterime dönüştüren ve daha sonra geri dönüştüren kod" olarak değiştirirdim . farklı türde, üzerine etkiyen ve geri dönüştürülmesi tamamen uygun olan ve hata yanlış davranışa neden olur bunun için.

Dönüşümün iyi olduğu bir örnek olarak:
Biri, floatbüyüklükleri 1.000'e kadar bir faktöre göre değişebilen dört rastgele işaret değerine sahiptir ve birisinin toplamı en son 0.625 birim içinde hesaplaması gerekir. Dört değeri de birleştirmek double, toplamı hesaplamak ve sonucu tekrar geri dönüştürmek, floatkullanan herhangi bir yaklaşımdan çok daha verimli olacaktır.float tek başına .
Kayan nokta değerleri, en son yerde (ULP) 0,5 birime kadar doğrudur. Bu örnek, en kötü durum yuvarlama hatasının en iyi en kötü durum hatasının% 25'inden daha fazla olmamasını gerektirir. Bir çift kullanılması, 0.5001 ULP içerisinde doğru olacak bir değer verecektir. 0.625 ULP gereksinimi kabul edilmiş gibi görünse de, bu gereksinimler art arda yaklaştırma algoritmalarında sıklıkla önemlidir. Hata sınırı ne kadar sıkı belirtilirse, en kötü durum yineleme gereksinimi o kadar düşük olur.

Dönüşümün kötü olduğu bir örnek olarak:
Birinde kayan nokta sayısı vardır ve değerini benzersiz şekilde temsil edecek bir dize yazdırmak ister. Bir yaklaşım, sayıyı belirli sayıda hane sahip bir dizgeye dönüştürmek, geri dönüştürmeyi denemek ve sonucun eşleşip eşleşmediğine bakmaktır.

Fakat bu aslında zayıf bir yaklaşım. Ondalık bir dize, iki kayan nokta değeri arasındaki yarı nokta noktasında neredeyse tam olarak oturan bir değeri temsil ediyorsa, kayan noktaya yönteminin her zaman daha yakın olacağını garanti etmek oldukça pahalıdır.float değeri Böyle bir garantiyi yerine getirmeyin (diğer şeylerin yanı sıra, bazı durumlarda milyarlarca rakam uzunluğunda olsa bile, bir rakamın tüm rakamlarını okumayı gerektirir).

Bir yöntemin, temsil edilen değerin en son yerinde (ULP) her zaman 0.5625 birim içindeki bir değeri geri döndüreceğini garanti etmek için çok daha ucuzdur. Sağlam bir "ters çevrilebilir" ondalık-dizge formatlama yordamı, çıktı değerinin doğru değerden ne kadar uzakta olduğunu hesaplamalı ve sonuç 0,25 (ULP) değilse, sonuç 0,375 (ULP) içinde olana kadar rakamları yazdırmaya devam etmelidir. Aksi takdirde, bazı dönüştürme yöntemlerinin doğru işleyeceği bir dize verebilir, ancak diğer dönüştürme yöntemleri de vermez.

Bazen "gerekli" olmayan bir basamağı, yanlış yorumlanabilecek bir değerin çıktısından daha iyidir. Kilit nokta, belirli bir yöntemin dizgiyi tekrar sayıya dönüştürme girişiminin sonucundan ziyade, çıktı işlemiyle ilgili sayısal hesaplamalara dayanarak kaç basamak çıkması gerektiğine karar verilmesi gerektiğidir.


1
Örneğiniz, OP'nin sorduğu orijinal değeri vermez. Birden çok girişten hesaplanan yalnızca aynı türden bir değer döndürür.
CJ Dennis,

2

Çeşitli sebepler

  1. Bu anlamsız ve karmaşıklık yaratıyor - hem yazılacak hem de korunacak kod miktarına ve gereken CPU zamanına

    1. Doğruluğunu veya daha kötüsünü kaybedebilir, değeri tamamen bozabilir

    2. İhtiyacınız olan bir sayının daha fazla gösterimini kaydettiğinizde hafızayı boşa harcar (potansiyel olarak dile bağlı)

İyi bir uygulama, aldığınız tüm veriler için yalnızca ilk ve en doğru gösterimi mümkün kılmaktır. Bu verileri kullanarak herhangi bir hesaplama yapın ve yalnızca çıktısını almanız veya okunması kolay bir formatta göstermeniz gerektiğinde dönüştürün.


bu, önceki cevaplarda verilen ve açıklanan hususlara önemli bir şey ekliyor gibi görünmüyor
gnat

2
Bu bir oyu haklı kılıyor mu?
Jon Story 16

önceki cevaplar aslında her ikisi de benim için daha özlü görünüyor
gnat

0

Niye ya? Çünkü en iyilerimiz bile hata yapabilir.

Microsoft, <-> kayan dönüşümlerin güvenli olduğundan emin olmak için özel olarak bir "gidiş-dönüş" biçimi uygulamaya çalıştığında neler olduğuna bakın: https://stackoverflow.com/q/24299692/541686


0

Okuldayken (ve elektrik mühendisliğinde okul sonrası) çoğaldıktan sonra bölmemiz öğretildi. Bölme çoğu zaman birçok rakam ve yuvarlanır. Bölme işleminden sonra çarpma bölme hatasını çoğaltır.

Tür dönüşümleri aynıdır, veri kaybı riski vardır. CInt (1.3) = 1.

Dilimde, Temel olarak yalnızca dönüşümler yazıyoruz (bir VB6 programı, çalışma zamanının yaptığı tüm API çağrıları için ANSI / Unicode dönüşümü yaparken zamanının% 90'ını harcıyor).

Tür dönüşümü, yaptığımız her şeyde ima edilir.

 Print 5

"5" dizgisi sayısal değişmezden yazdırılıyor.

form1.caption = "My Form"

Unicode string değişmezi bir ANSI dizgisine dönüştürülür ve form paketi tarafından SetWindowsTextA'ya gönderilir.

Bu bile temel çalışır

a = "5"
b = 3

c = a + b (= 8)

Bugünlerde değişken bir programcıyım - türünü bile düşünmüyorum. Ben sadece otomatik dönüşümlere güveniyorum.

Neyse benim 3 evcil hayvan peeves

Dize değişmezlerini kullanmak için değişkenlere atama (belleği boşa harcar ve yavaş)

Kod satır içi olduğunda anlamsız işlevler (ve derleyici muhtemelen işlevinizi geri alır ve yine de satır içi yapar)

Tüm nesneleri bir Son İşlev veya programın sonundan önce son satır olarak hiçbir şey olarak ayarlamak.

ve kısa programlar için dördüncü

5 değişkenli bir programda 3 değişkeninizi çok karartma.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.