Neden çoğu modern programlama dilinde Sözleşme ile Tasarım için bu kadar sınırlı destek var?


40

Kısa süre önce Design by Contract'ı (DbC) keşfettim ve kod yazmanın son derece ilginç bir yolunu buldum. Diğer şeylerin yanı sıra, teklif gibi görünüyor:

  • Daha iyi belgeler. Sözleşme dokümantasyon olduğundan, birinin eski olması imkansızdır. Ek olarak, sözleşme tam olarak bir rutinin ne yaptığını belirttiğinden, yeniden kullanımın desteklenmesine yardımcı olur.
  • Basit hata ayıklama. Programın yürütülmesi bir sözleşmenin başarısız olduğu anı durdurduğu için, hatalar yayılamaz ve ihlal edilen belirli iddialar muhtemelen vurgulanacaktır. Bu, geliştirme ve bakım sırasında destek sunar.
  • Daha iyi statik analiz. DbC temel olarak sadece Hoare mantığının bir uygulamasıdır ve aynı prensipler geçerli olmalıdır.

Karşılaştırmada maliyetler oldukça küçük görünüyor:

  • Ekstra parmakla yazma. Çünkü sözleşmelerin hecelenmesi gerekiyor.
  • Yazma sözleşmelerinde rahatlamak için bir miktar eğitim alıyor.

Şimdi, öncelikle Python'a aşina olduğumda, ön koşulları yazmanın (sadece uygunsuz girdi için istisnalar atma) aslında mümkün olduğunu ve bazı post-koşulları tekrar test etmek için iddiaları kullanmanın mümkün olduğunu fark ediyorum. Ancak, "eski" veya "sonuç" gibi bazı özellikleri, nihayetinde Pythonic’in dışında olduğu düşünülen fazladan bir sihir olmadan simüle etmek mümkün değildir. (Buna ek olarak, destek sunan birkaç kütüphane var, ama nihayetinde çoğu geliştiricinin yapmadığı gibi bunları kullanmanın yanlış olacağını vibe aldım.) Bunun diğer diller için de benzer bir problem olduğunu kabul ediyorum (elbette hariç) Eyfel

Sezgim bana destek eksikliğinin, uygulamanın bir tür reddedilmesinin bir sonucu olması gerektiğini, ancak çevrimiçi aramaların verimli olmadığını söyledi. Birisi neden çoğu modern dilin bu kadar az destek sunduğunu açıklayabilir mi acaba? DbC hatalı veya aşırı pahalı mı? Yoksa Ekstrem Programlama ve diğer metodolojilerden dolayı eski mi?


Programınızı test etmenin faydası olmadan, test odaklı programlama yapmanın aşırı karmaşık bir yolu gibi görünüyor.
Dan

3
@Dan, gerçekten değil, daha çok tip sisteminin bir uzantısı olarak düşünüyorum. örneğin, bir fonksiyon sadece bir tamsayı argümanı almaz, sözleşmeye bağlı olarak sıfırdan büyük olması gereken bir tamsayı alır
Carson63000 0

4
@Dan kod sözleşmeleri yapmanız gereken test sayısını önemli ölçüde azaltır.
Rei Miyasaka

24
@Dan, TDD'nin zavallı adamın sözleşmesi olduğunu söyleyeceğim, bunun tersi değil.
SK-mantık

Dinamik dilde, nesnelerinizi isteğe bağlı bir bayrağa dayanan sözleşmelerle "süsleyebilirsiniz". İsteğe bağlı olarak sözleşmelerle mevcut nesneleri yamalamak için çevre bayraklarını kullanan örnek bir uygulamaya sahibim . Evet, destek yerel değil, ancak eklemesi kolay. Aynısı test kayışları için de geçerlidir, bunlar doğal değildir, ancak eklemesi / yazması kolaydır.
Raynos,

Yanıtlar:


9

Muhtemelen hemen hemen her programlama dilinde desteklenirler.

İhtiyacınız olan şey "iddialar".

Bunlar kolayca "if" ifadeleri olarak kodlanır:

if (!assertion) then AssertionFailure();

Bununla, giriş kısıtlamaları için bu tür iddiaları kodunuzun en üstüne yerleştirerek sözleşmeler yazabilirsiniz; dönüş noktalarında olanlar çıkış kısıtlamalarıdır. Kodunuz boyunca değişmezler bile ekleyebilirsiniz (gerçekte "sözleşmeyle tasarım" ın bir parçası olmasa da).

Bu yüzden yaygın olmadığını, çünkü programcıların kodlamak için fazla tembel olduklarını, çünkü bunu yapamayacağınızı çünkü.

Bunları çoğu dilde, derleme zamanı bir Boole sabiti "kontrol etme" tanımlayarak ve ifadeleri biraz gözden geçirerek biraz daha verimli hale getirebilirsiniz:

if (checking & !Assertion) then AssertionFailure();

Sözdizimini beğenmiyorsanız, makrolar gibi çeşitli dil soyutlama tekniklerine başvurabilirsiniz.

Bazı modern diller size bunun için güzel bir sözdizimi veriyor ve "modern dil desteği" ile ne demek istediğinizi düşünüyorum. Bu destek, ama oldukça zayıf.

Modern dillerin çoğunun bile size veremediği şey "geçici" iddialar (keyfi önceki veya sonraki durumlar üzerine [sonunda geçici işleç "" sonunda "], gerçekten ilginç sözleşmeler yazmak istiyorsanız ihtiyacınız olan Buradasınız.


Yalnızca varsayımlara erişimde bulduğum problem, postkoşulları sık sık önkoşul durumuyla karşılaştırmanız gerektiğinden, komutları sonlandırmak için etkili bir yol bulunmamasıdır. .) Python'da, bu işlevsellik dekoratörler kullanılarak önemsiz bir şekilde yeniden yaratılabilir, ancak iddiaları kapatma zamanı geldiğinde kısa sürede ortaya çıkıyor.
Sezar Bautista,

Eiffel önceki durumun ne kadarını kurtarıyor? Durma problemini çözmeden hangi bölüme erişebileceğinizi / değiştirebileceğinizi makul bir şekilde bilmediğinden (fonksiyonunuzu analiz ederek), ya makinenin tamamını ya da hueristik olarak, sadece çok sığ bir kısmını korumalıdır. İkincisinden şüpheleniyorum; ve bunlar önkoşuldan önce basit skaler atamalarla "simüle edilebilir". Eiffel'in aksini öğrendiğini öğrenmekten memnuniyet duyarım.
Ira Baxter,

7
... Eyfel'in nasıl çalıştığını kontrol ettim. "old <exp>", işleve girişte <exp> değeridir, bu nedenle beklediğim gibi işlev girişinde sığ kopyalar yapıyor. Onları da yapabilirsiniz. Derleyicinin pre / post / old'un sözdizimini uygulamasının tüm bunları elle yapmaktan daha uygun olduğu konusunda hemfikir olacağım, ancak mesele elle elde etmek için bir zorunluluktur ve gerçekten zor değildir. Tembel programcılara geri döndük.
Ira Baxter,

@IraBaxter No. Kod, sözleşmeyi gerçek mantıktan ayırabilirseniz daha kolay hale gelir. Ayrıca, derleyici sözleşmeyi ve kodları birbirinden ayırabilirse, çoğaltmayı çok azaltabilir . Örneğin, D'de bir arayüz veya üst sınıfta bir sözleşme ilan edebilirsiniz ve iddialar, fonksiyonlarındaki koddan bağımsız olarak tüm uygulama / genişletme sınıflarına uygulanacaktır. Örneğin, python veya Java ile, tüm supermetodu çağırmanız ve sadece çoğaltmadan kontrol edilen sözleşmeleri istiyorsanız, sonuçları atmanız gerekir. Bu gerçekten temiz LSP uyumlu kodun uygulanmasına yardımcı olur.
marstato

@ marstato: Dilde desteğin iyi bir şey olduğu konusunda hemfikirdim.
Ira Baxter,

15

Dediğiniz gibi, Sözleşme tarafından Tasarımı olduğunu uzun toplum içinde saygı duyulur ama hangi hiç çekici gelmeyen bu programlama dilleri biri olmuştur Eiffel, bir özellik.

DbC, en popüler dillerden hiçbirinde değildir, çünkü ana akım program topluluğunun, kodlarına sınırlamalar / beklentiler eklemenin, programcılardan beklenecek “makul” bir şey olduğunu kabul etmesi son zamanlardadır. Programcıların ünite testinin ne kadar değerli olduğunu anlamaları ve programcıların argümanlarını doğrulamak ve faydalarını görmek için kod koymayı daha fazla kabul etmeleriyle ilgisi çok yaygındır. Fakat on yıl önce, muhtemelen çoğu programcı “bu, bildiğiniz şeyler için her zaman düzeleceğiniz şeyler için ekstra bir iş” derdi.

Sanırım bugün ortalama bir geliştiriciye gidip post-koşullardan bahsedecekseniz, coşkuyla başını salladılar ve "Tamam, bu ünite testi gibi." Ve eğer ön koşullar hakkında konuşursanız, "Tamam, bu her zaman yapmadığımız parametre doğrulama gibi, ama bilirsin, sanırım sorun değil ..." derler ve sonra değişmezler hakkında konuşursanız "Gee, bu ne kadar ek yük? Bu daha kaç böcek yakalayacağız?" demeye başlarlardı. vb.

Bu yüzden DbC'nin geniş çapta kabul edilmesinden önce daha gidilecek uzun bir yol olduğunu düşünüyorum.


Ana programcılar olan OTOH, iddiaları bir süredir yazmakta kullanılıyordu. En modern ana dillerde kullanılabilir bir önişlemcinin olmaması bu güzel uygulamayı verimsiz hale getirmiştir, ancak C ve C ++ için hala yaygındır. Şimdi Microsoft Kod Sözleşmelerinde bir geri dönüş yapıyor (sürüm oluşturma için bir byte kodu olan AFAIK'a dayanarak).
SK-mantık

8

Sezgim bana destek eksikliğinin uygulamanın bir tür reddedilmesinin sonucu olması gerektiğini söylüyor.

Yanlış.

Bu bir tasarım pratiği. Açıkça kod (Eyfel stili) veya örtük olarak kod (çoğu dil) veya birim testlerinde somutlaştırılabilir. Tasarım pratiği var ve iyi çalışıyor. Dil desteği tüm harita üzerindedir. Bununla birlikte, birim test çerçevesinde birçok dilde mevcuttur.

Birisi neden çoğu modern dilin bu kadar az destek sunduğunu açıklayabilir mi acaba? DbC hatalı veya aşırı pahalı mı?

Pahalı. Ve. Daha da önemlisi, kanıtlanamaz bazı şeyler vardır içinde verili bir dil. Döngü sonlandırma, örneğin, bir programlama dilinde kanıtlanamaz, "yüksek dereceli" bir kanıtlama yeteneği gerektirir. Bu yüzden bazı tür sözleşmeler teknik olarak açıklanamaz.

Yoksa Ekstrem Programlama ve diğer metodolojilerden dolayı eski mi?

Hayır.

DbC'nin yerine getirildiğini göstermek için çoğunlukla birim testleri kullanıyoruz.

Python için, belirttiğiniz gibi, DbC çeşitli yerlere gider.

  1. Dokümantasyon ve dokümantasyon testi sonuçları.

  2. Giriş ve çıkışları doğrulamak için iddialar.

  3. Birim testleri.

Daha ileri.

Okuryazar programlama stili araçları kullanarak DbC bilgilerinizi içeren ve temiz Python plus birim test komut dosyaları üreten bir belge yazabilirsiniz. Okuryazar programlama yaklaşımı, sözleşmeleri ve tüm kaynağı içeren güzel bir literatür yazmanıza izin verir.


Sabit bir sonlu dizi üzerinde yineleme gibi önemsiz döngü sonlandırma durumlarını kanıtlayabilirsiniz. Önemsiz bir şekilde sonlandığı gösterilemeyen genelleştirilmiş döngü (“ilginç” matematiksel varsayımlara yönelik çözümler arayabildiğinden beri); Halting Probleminin özü budur.
Donal Fellows

+1. Bence en kritik noktayı ele alan tek kişi sizsiniz there are some things which cannot be proven. Resmi doğrulama harika olabilir, ancak her şey doğrulanabilir değil! Bu özellik aslında programlama dilinin yapabileceklerini sınırlar!
Dipan Mehta

@DonalFellows: Genel durum kanıtlanamadığından, (a) pahalı ve (b) eksik olduğu bilinen bir dizi özelliği kullanmak zor. Bu cevaptaki amacım, bu özelliklerin hepsinden kaçınmanın ve genel olarak resmi doğruluk kanıtlarının yanlış beklentilerini belirlemenin önüne geçilmesinin daha kolay olmasıdır. Bir tasarım alıştırması olarak (dilin dışında) birçok ispat tekniği kullanılabilir (ve gerekir).
S.Lott,

Kontrat kontrolünün bülten oluşturma aşamasında derlendiği C ++ gibi bir dilde hiç pahalı değil. DBC kullanmak daha hafif olan derleme kodunu yayınlamaya meyillidir, çünkü programın yasal bir durumda olup olmadığına dair daha az çalışma zamanı kontrolü yaparsınız. Çok sayıda fonksiyonun yasadışı bir durumu kontrol ettiği ve yanlış olarak döndüğü, uygun şekilde test edilmiş bir sürümde ASLA böyle bir durumda olmamasını gördüğümde gördüğüm çok sayıdaki kod tabanı sayısını kaybettim.
Kaitain

6

Sadece tahmin ediyorum. Belki de bu kadar popüler olmama sebebinin bir kısmı “Sözleşme ile Tasarım” Eyfel tarafından tescillidir.


3

Bir hipotez, yeterince hareketli ve karmaşık bir program için, özellikle hareketli hedefi olanlar için, sözleşmelerin kendilerinin, yalnızca program kodundan daha fazla hata ayıklaması ve hata ayıklaması veya daha fazlası olabileceğidir. Herhangi bir düzende olduğu gibi, azalan getirilerden geçmiş bir kullanımın yanı sıra daha hedefli bir şekilde kullanıldığında net avantajlar olabilir.

Bir diğer olası sonuç, “yönetilen dillerin” popülaritesinin, seçilen yönetilen özellikler için sözleşmeye göre tasarım desteğinin mevcut kanıtı olduğudur (sözleşmeyle sınırlanan dizi, vb.).


> sözleşmelerin kendileri, daha önce hiç görmediğim program kodundan daha fazla hataya neden olabilir, hata ayıklamak zor olabilir.
Kaitain

2

Ana dillerin çoğunun dilde DbC özelliklerinin bulunmamasının nedeni, dili uygulayanlar için onu uygulamanın maliyet fayda oranıdır.

Bunun bir tarafı zaten diğer cevaplara bakılmış, birim testleri ve diğer çalışma zamanı mekanizmaları (ya da şablon meta programlama ile derleme zamanı mekanizmaları bile) size DbC iyiliğinin çoğunu verebilir. Bu nedenle, bir fayda olsa da, oldukça mütevazı olarak görülüyor.

Diğer taraftan maliyet, DbC'yi mevcut bir dile uyarlamak, büyük olasılıkla çok büyük bir değişim ve önyükleme yapmak için çok karmaşık. Eski kodu bozmadan bir dilde yeni sözdizimi sunmak zor. Mevcut standart kütüphanenizi bu kadar geniş kapsamlı bir değişiklik kullanacak şekilde güncellemek pahalıya mal olur. Bu nedenle, DbC özelliklerini mevcut bir dilde uygulamanın yüksek bir maliyeti olduğu sonucuna varabiliriz.

Ben de dikkat ediyorum kavramları oldukça şablonları için çok sözleşmelerdir ve bu nedenle biraz DBC ile ilgili, hatta işin hala ihtiyaç duyulan yıl tahmin edildi üzerlerinde çalışma yıllar sonra gibi en son C ++ standardından düştü. Bu tür büyük, geniş, geniş kapsamlı dil değişikliklerini uygulamak çok zor.


2

Sözleşmelerin derleme zamanında kontrol edilmesi halinde herhangi bir sözleşmeyi ihlal eden bir programın yürütülememesi mümkün olacaksa, DbC daha kapsamlı bir şekilde kullanılacaktır.

Derleyici desteği olmadan, "DbC" yalnızca "değişmeyenleri / varsayımları denetle ve ihlal edilirse istisna at" için kullanılan ilk addır.


Bu durma problemine girmiyor mu?
Ceasar Bautista

@ Sezar Bu bağlıdır. Bazı varsayımlar kontrol edilebilir, bazıları ise kontrol edilemez. Örneğin, boş bir listeyi argüman olarak iletmekten kaçınmayı ya da bir tane geri döndürmeyi mümkün kılan tip sistemleri vardır.
Ingo

Güzel nokta (+1), Bertrand Meyer’in “Programlamanın beyni” bölümünde yer almasına rağmen, aynı zamanda rasgele sınıf oluşturma sistemlerinden ve sözleşmelerin ihlali için kontrol edilme çağrısından bahsetti. Bu yüzden karışık bir derleme zamanı / çalışma zamanı yaklaşımı, ama bu tekniğin her durumda işe yaradığından şüpheliyim
Maksee

Bu, bir dereceye kadar geçerlidir, bununla birlikte, bir istisnadan çok feci bir başarısızlık olması gerekir (aşağıya bakınız). DBC'nin temel avantajı, aslında daha iyi tasarlanmış programlara yol açan metodoloji ve verilen herhangi bir yöntemin, iç mantığın çoğunu basitleştiren girişte yasal bir durumda olması gerektiğine dair güvencedir. Genel olarak, bir sözleşme ihlal edildiğinde istisnalar atma işinde olmamalısınız. Programın YASAL olarak ~ X durumunda olabileceği durumlar dışında istisnalar kullanılmalı ve müşteri kodu bunu yapmalıdır. Bir sözleşme diyecektir ki ~ X sadece yasa dışıdır.
Kaitain

1

Basit bir açıklama yaptım, çoğu insan (programcılar dahil), gerekli gördükleri sürece fazladan iş istemiyor. Güvenliğin çok önemli olduğu kabul edilen Aviyonik programlama, pek çok projeyi onsuz görmedim.

Ancak, web sitesi, masaüstü veya mobil programlama düşünüyorsanız - çökmeler ve beklenmedik davranışlar bazen kötülerin ve programcıların hataları bildirirken ve daha sonra bunları düzeltmenin yeterli olacağı kabul edildiğinde fazladan çalışmaktan kaçınacağı düşünülmez.

Bu muhtemelen Ada'nın havacılık programlama endüstrisinin dışına çıkmadığını düşünüyorum çünkü Ada harika bir dil olsa ve daha güvenilir bir sistem oluşturmak istiyorsanız, bu iş için en iyi dil (SPARK hariç) Ada'ya dayalı dil).

C # için sözleşme kütüphaneleri tarafından tasarlananlar Microsoft tarafından deneyseldir ve güvenilir yazılımlar oluşturmak için çok faydalıdırlar, ancak piyasada hiç bir zaman ivme kazanmazlardı, aksi halde onları şimdiye kadar çekirdek C # dilinin bir parçası olarak görürdünüz.

İddialar, post / post koşullar ve değişmeyenler için tamamen işlevsel bir destekle aynı değildir. Onları taklit etmeye çalışsa da, uygun desteği olan bir dil / derleyici 'soyut sözdizimi ağacı' analizini yapar ve basitçe iddia edemediği mantık hatalarını kontrol eder.

Düzenleme: Bir arama yaptım ve aşağıdakiler yararlı olabilecek bir tartışma konusu: https://stackoverflow.com/questions/4065001/are-there-any-provable-real-world-languages-scala


-2

Çoğunlukla sebepler aşağıdaki gibidir:

  1. Yalnızca popüler olmayan dillerde bulunur
  2. Mevcut programlama dillerinde aynı şeyleri gerçekten yapmak isteyen herhangi biri tarafından farklı şekilde yapılabildiğinden gereksizdir.
  3. Anlamak ve kullanmak zordur - doğru şekilde yapmak için özel bilgi gerektirir, bu yüzden bunu yapan az sayıda insan vardır.
  4. bunu yapmak için büyük miktarda kod gerektirir - programcılar yazdıkları karakter miktarını en aza indirmeyi tercih eder - uzun bir kod parçası alırsa, bununla ilgili bir sorun olması gerekir
  5. Avantajlar orada değil - sadece onu değerli kılmak için yeterli böcek bulamıyor

1
Cevabınız iyi tartışılmadı. Hiç bir avantajı olmadığını, çok miktarda kod gerektirdiğini ve mevcut dillerle yapılabileceğinden (bunun için özel olarak ele alınan OP!) Gereksiz olduğunu belirtiyorsunuz.
Andres F.

Ben iddiaları vb bunun yerine bir yedek olarak düşünmüyorum. Bu, onu mevcut dillerde yapmanın doğru bir yolu değil (yani henüz ele alınmadı)
tp1

@ tp1, eğer programcılar yazmayı en aza indirmeyi gerçekten isterlerse, asla Java gibi ayrıntılı ve anlamlı bir şeye girmeyeceklerdir. Ve evet, programlamanın kendisi "düzgün bir şekilde" yapmak için "uzmanlık bilgisi" gerektirir. Böyle bir bilgiye sahip olmayanların kodlamasına izin verilmemelidir.
SK-mantık

@ Sk-mantık: Görünüşe göre dünyanın yarısı OO'yu yanlış yapıyor, çünkü üye fonksiyonlardan veri üyelerine üye fonksiyonlara yönlendirme fonksiyonları yazmak istemiyorlar. Bu benim deneyimimde büyük bir sorun. Bu doğrudan yazılacak karakter sayısını en aza indirmekten kaynaklanır.
tp1

@ tp1, insanlar yazmayı gerçekten en aza indirmeyi isteselerdi, OO'ya bile hiç dokunmazlardı. OOP, Smalltalk gibi en iyi uygulamalarında bile doğal olarak belirgindir. Kötü bir özellik olduğunu söyleyemem, eloquence bazen yardımcı olur.
SK-mantık
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.