Her yerde veri kontrolleri yapmak için iyi kod stili?


10

Kafamdaki her yönü artık tutamayacağım kadar büyük boyutlu bir projem var. İçinde birkaç sınıf ve işlevle uğraşıyorum ve veriyi veriyi aktarıyorum.

Zamanla hatalar almaya devam ettiğimi fark ettim, çünkü veriyi farklı işlevlere geçirdiğimde ne kadar kesin bir form olması gerektiğini unuttum ( örneğin, bir işlev daha sonra yazdığım bir dizi diziyi, başka bir işlevi kabul eder ve çıktılar, bir sözlük vb tutulur dizeleri kabul, bu yüzden ben bir dizide onları bir sözlük sahip olmak için birlikte çalıştığım dizeleri dönüştürmek zorunda ).

Her zaman neyin nerede kırıldığını bulmak zorunda kalmamak için, her bir fonksiyona ve sınıfı, doğru girdiyi veren dış koda güvenemeyeceği ve giriş kontrollerini kendisi yapmak zorunda olduğu anlamında bir "izole varlık" olarak ele almaya başladım (veya, bazı durumlarda, veriler yanlış biçimde verilirse verileri yeniden düzenleyin).

Bu, geçirdiğim verilerin her işleve "uyduğundan" emin olmak için harcadığım zamanı büyük ölçüde azalttı, çünkü sınıflar ve işlevler artık bazı girdiler kötü olduğunda (ve hatta bazen düzeltir) beni uyarıyor ve yapmıyorum bir şey haywire nereye gittiğini anlamak için artık tüm kod boyunca bir hata ayıklayıcı ile gitmek zorunda.

Diğer taraftan bu da genel kodu artırdı.
Benim sorum, bu kod stili bu sorunu çözmek için uygunsa?
Tabii ki, en iyi çözüm, projeyi tamamen yeniden düzenlemek ve verilerin tüm işlevler için tek tip bir yapıya sahip olduğundan emin olmak olacaktır - ancak bu proje sürekli büyüdüğü için, aslında yeni şeyler eklemekten çok daha fazla harcama ve temiz kod hakkında endişelenmek istiyorum. .

(Bilginize: Hala yeni başlayan biriyim, bu yüzden bu sorunun naif olması durumunda lütfen özür dilerim; projem Python'da.)



3
@gnat Benzer, ancak sorumu cevaplamak yerine, OP'nin daha genel sorgumdan farklı olduğu belirtilen belirli bir örnek için ("olabildiğiniz kadar savunmacı olun") tavsiyelerde bulunur .
user7088941

2
"ama bu proje sürekli büyüdüğü için, aslında yeni şeyler eklemekten çok daha fazla harcama ve temiz kod için endişelenmeye başladım" - bu, temiz kod hakkında endişelenmeye başlamanız gerektiği gibi geliyor. Aksi takdirde, mevcut kod nedeniyle her yeni işlevsellik parçasının eklenmesi zor olduğundan üretkenliğinizi yavaşlatır ve yavaşlatırsınız. Tüm yeniden düzenleme işlemlerinin "tamamlanması" gerekmez, dokunduğu mevcut kod nedeniyle yeni bir şey eklemek zorlaşırsa, yalnızca bu dokunma kodunu yeniden
düzenleyin ve

3
Bu, insanların genellikle zayıf yazılan dilleri kullanırken karşılaştığı bir sorundur. Daha katı bir şekilde yazılmış bir dil istemiyorsanız veya bu dile geçebiliyorsanız, yanıt "evet, bu kod stili bu sorunu çözmek için uygundur" dır . Sonraki soru?
Doc Brown

1
Kesin olarak yazılan bir dilde, uygun veri türlerinin tanımlandığı şekilde, derleyici bunu sizin için yapardı.
SD

Yanıtlar:


4

Daha iyi bir çözüm, Python dil özelliklerinden ve araçlarından daha fazla yararlanmaktır.

Örneğin, işlev 1'de beklenen girdi, ilk dizenin bir şeyin başlığını ve ikinci dizinin bibliyografik bir referansı gösterdiği bir dizeler dizisidir. İşlev 2'de beklenen girdi hala bir dizi dizidir, ancak şimdi dizelerin rolleri ters çevrilmiştir.

Bu sorun a namedtuple. Hafiftir ve dizinizin üyelerine kolay anlamsal anlam kazandırır.

Dilleri değiştirmeden bazı otomatik yazım denetiminin avantajlarından yararlanmak için yazım ipucundan faydalanabilirsiniz . İyi bir IDE bunu aptalca bir şey yaptığınızda size bildirmek için kullanabilir.

Ayrıca, gereksinimler değiştiğinde işlevlerin eski haline gelmesinden endişe duyuyorsunuz. Bu, otomatik testle yakalanabilir .

Manuel kontrolün hiçbir zaman uygun olmadığını söylememe rağmen, mevcut dil özelliklerinin daha iyi kullanılması bu sorunu daha sürdürülebilir bir şekilde çözmenize yardımcı olabilir.


Beni namedtupleve diğer güzel şeyleri işaret ettiğin için +1 . Etrafta değildim namedtuple- ve otomatik test hakkında bilgi sahibi olsam da, gerçekten çok fazla kullanmadım ve bu durumda bana ne kadar yardımcı olacağını fark etmedim. Bunların hepsi gerçekten statik bir analiz kadar iyi görünüyor. (Statik bir analizde yakalanmayacak tüm ince şeyleri yakalayabildiğim için otomatik test daha da iyi olabilir!) Başka birini biliyorsanız, lütfen bana bildirin. Soruyu bir süre daha açık tutacağım, ancak başka cevap gelmezse, seninkini kabul edeceğim.
user7088941

9

Tamam, asıl sorun bu cevabın altındaki bir yorumda açıklanmaktadır:

Örneğin, işlev 1'de beklenen girdi, ilk dizenin bir şeyin başlığını ve ikinci dizinin bibliyografik bir referansı gösterdiği bir dizeler dizisidir. İşlev 2'de beklenen girdi hala bir dize dizisidir, ancak şimdi dizelerin rolleri ters çevrilmiştir

Buradaki sorun, siparişin anlambilimi ifade ettiği dizelerin bir listesinin kullanılmasıdır. Bu gerçekten hataya meyilli bir yaklaşımdır. Bunun yerine titleve adında iki alan içeren özel bir sınıf oluşturmanız gerekir bibliographical_reference. Bu şekilde onları karıştırmayacaksınız ve gelecekte bu problemden kaçınacaksınız. Tabii ki, birçok yerde dizgi listeleri kullanıyorsanız, ancak bana inanın, uzun vadede daha ucuz olacaksa, bu yeniden düzenleme gerektirir.

Dinamik olarak yazılan dillerdeki ortak yaklaşım, "ördek yazma" dır; bu, iletilen nesnenin "türünü" gerçekten umursamadığınız anlamına gelir, yalnızca üzerinde çağırdığınız yöntemleri destekliyorsa umursarsınız. Sizin durumunuzda, bibliographical_referenceihtiyaç duyduğunuzda çağrılan alanı okuyacaksınız . Aktarılan nesnede bu alan yoksa, bir hata alırsınız ve bu, işleve yanlış türün aktarıldığını gösterir. Bu, herhangi bir tip kontrolü kadar iyidir.


Bazen inci sorunu daha da incedir: Doğru türü geçiyorum, ancak girişimin "iç yapısı" işlevi bozuyor: Örneğin, işlev 1'de, beklenen girdi ilk dizenin dizildiği bir dizidir bir şeyin başlığını, ikincisinin ise bibliyografik bir referansı belirtir. İşlev 2'de beklenen girdi hala bir dizgidir, ancak şimdi dizelerin rolleri ters çevrilmiştir: İlk dize bibliyografik referans ve ikincisi bibliyografik referans olmalıdır. Bu kontroller için uygun sanırım?
user7088941

1
@ user7088941: Açıkladığınız sorun iki başlıklı bir sınıfa sahip olmakla kolayca çözülebilir: "başlık" ve "bibliographical_reference". Bunu karıştırmayacaksın. Dizeler listesindeki sıraya güvenmek çok hata eğilimli görünüyor. Belki de bu altta yatan problemdir?
JacquesB

3
Cevap bu. Python nesneye yönelik bir dildir, dize-tamsayı-yönelimli (ya da her neyse) bir sözlükler listesi değildir. Yani, nesneleri kullanın. Nesneler kendi devletini yönetme ve kendi değişmezleri uygulanmasından sorumlu olan diğer nesneleri olamaz (doğru tasarlanmış ise) herhangi bir zamanda, onları bozuk. Yapılandırılmamış veya yarı yapılandırılmış veriler sisteminize dışarıdan girerse , sistem sınırında bir kez doğrular ve ayrıştırır ve mümkün olan en kısa sürede zengin nesnelere dönüştürürsünüz.
Jörg W Mittag

3
"Sürekli yeniden düzenleme yapmaktan gerçekten kaçınırım" - bu zihinsel blok sizin probleminizdir. İyi kod sadece yeniden düzenleme işleminden kaynaklanır. Yeniden düzenleme. Birim testleri ile desteklenir. Özellikle bileşenlerin uzatılması veya geliştirilmesi gerektiğinde.
Doc Brown

2
Şimdi anladım. Tüm güzel bilgiler ve yorumlar için +1. Ve inanılmaz faydalı yorumları için herkese teşekkürler! Bazı sınıfları kullanarak iken (/ ı şimdi gördüğünüz gibi, iyi bir fikir değildi, sözü listeleri, onları serpiştirilmiş nesneleri. Soru kalmıştır nasıl ben JETMs cevabını somut öneriler kullanılan nerede en iyi şekilde, bu uygulamaya , bu gerçekten hatasız bir duruma ulaşma hızı açısından radikal bir fark
yarattı

3

Her şeyden önce, şu anda yaşadığınız şey kod kokusudur - kokunun farkında olmanıza neden olan şeyi hatırlamaya çalışın ve bir kodun ne kadar erken ve daha kolay koktuğunu fark ettiğinizde "zihinsel" burnunuzu bilemeye çalışın. altta yatan sorunu çözebilirsiniz.

Her zaman neyin kırıldığını bulmak zorunda kalmamak için, her bir fonksiyona ve sınıfı, doğru girdiyi veren dış koda güvenemeyeceği ve giriş kontrollerini kendisi yapmak zorunda olduğu anlamında bir "izole varlık" olarak ele almaya başladım.

Defansif programlama - bu teknik denildiği gibi - geçerli ve sık kullanılan bir araçtır. Bununla birlikte, her şeyde olduğu gibi, doğru miktarı kullanmak çok önemlidir, çok az çek ve sorunları yakalayamazsınız, çok fazla ve kodunuz aşırı şişirilir.

(veya bazı durumlarda veriler yanlış biçimde verilirse verileri yeniden düzenleyin).

Bu daha az iyi bir fikir olabilir. Programınızın bir bölümünün hatalı biçimlendirilmiş veriye sahip bir işlevi çağırdığını fark ederseniz, BU PARÇA DÜZELTİN , kötü verileri sindirebilmek için zaten çağrılan işlevi değiştirmeyin.

Bu, geçirdiğim verilerin her işleve "uyduğundan" emin olmak için harcadığım zamanı büyük ölçüde azalttı, çünkü sınıflar ve işlevler artık bazı girdiler kötü olduğunda (ve hatta bazen düzeltir) beni uyarıyor ve yapmıyorum bir şey haywire nereye gittiğini anlamak için artık tüm kod boyunca bir hata ayıklayıcı ile gitmek zorunda.

Kodunuzun kalitesini ve sürdürülebilirliğini artırmak, uzun vadede zaman tasarrufu sağlar (bu anlamda, bazı işlevlerinize yerleştirdiğiniz kendi kendini düzeltme işlevine karşı tekrar uyarmalıyım - hatalar için sinsi bir kaynak olabilir. program çökmez ve yanma doğru çalıştığı anlamına gelmez ...)

Sonunda sorunuzu cevaplamak için: Evet, savunmacı programlama (yani sağlanan parametrelerin geçerliliğini doğrulama) - sağlıklı bir düzeyde - iyi bir stratejidir. Bununla birlikte , kendiniz söylediğin gibi, kodunuz tutarsız ve kokan parçaları yeniden düzenlemek için biraz zaman harcamanızı şiddetle tavsiye ediyorum - her zaman temiz kod hakkında endişelenmek istemediğinizi söylediniz. - Eğer temiz kodunuzu tutmak yoksa yeni özellikler uygulamak Ezici böcek temiz bir kod tutmak VE zor bir zaman olacak değil itibaren "save" iki kez vakit gidebilir ... yeni özellikler hakkında daha "temizlik" teknik borç can seni ezmek.


1

Sorun yok. Nerede bir TRY..CATCH blokları neredeyse her büyük işlevi vardı FoxPro kodlamak için kullanılır. Şimdi, JavaScript / LiveScript'te kod yazıyorum ve "dahili" veya "özel" işlevlerdeki parametreleri nadiren kontrol ediyorum.

"Ne kadar kontrol edileceği", seçilen projeye / dile, kod becerinize bağlı olduğundan daha fazla bağlıdır.


1
Sanırım, TL ... CATCH ... IGNORE. OP'nin ne istediğinin tersini yaptın. IMHO'nun amacı, programınız bir tanesine çarparken patlamamasını sağlarken tutarsızlıktan kaçınmaktır.
maaartinus

1
@maaartinus doğru. Programlama dilleri tipik olarak bize patlamayı önlemek için kullanımı kolay yapılar verir - ancak programlama dilleri tutarsızlıkları önlemek için bize daha zor görünüyor: bildiklerime göre, her şeyi sürekli olarak yeniden düzenleyin ve en iyi kapsayıcı sınıfları kullanın uygulamanızdaki bilgi akışı. Bu tam olarak sorduğum şey - bunu düzeltmenin daha kolay bir yolu var.
user7088941

@ user7088941 Bu yüzden zayıf yazılmış dillerden kaçınırım. Python harika, ama daha büyük bir şey için, başka bir yerde ne yaptığımı takip edemiyorum. Bu nedenle, oldukça ayrıntılı olan (Lombok ve Java 8 özellikleri ile çok fazla değil), statik analiz için sıkı yazım ve araçlara sahip Java'yı tercih ederim. Başka türlü nasıl çözüleceğini bilmediğim için bazı kesin dilleri denemenizi öneririm.
maaartinus

Katı / gevşek tip parametresi ile ilgili değildir. Bu parametrenin doğru olduğunu bilmekle ilgilidir. (Tamsayı 4 bayt) kullansanız bile, örneğin 0..10 aralığında olup olmadığını kontrol etmeniz gerekebilir. Parametrenin her zaman 0..10 olduğunu biliyorsanız, kontrol etmeniz gerekmez. FoxPro örneğin ilişkilendirilebilir diziler yoktur, bu çek çek çek için neden .. olduğunu .. onun değişkenleri kendi kapsamı ile ve benzeri işletmek çok zor
Michael Quad

1
@ user7088941 OO değil, ama "hızlı başarısız" kuralı var. Özel olmayan her yöntemin argümanlarını kontrol etmesi ve bir sorun olduğunda atması gerekir. Deneme-yakalama yok, düzeltmeye çalışma yok, sadece gökyüzüne uçurun. Elbette, daha yüksek bir düzeyde, istisna günlüğe kaydedilir ve işlenir. Testleriniz çoğu sorunu önceden bulduğunda ve hiçbir sorun gizlenmediğinden, kod hatasız çözümden çok daha hızlı hatasız bir çözüme dönüşür.
maaartinus
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.