Niedawno odkryłem Design by Contract (DbC) i uważam, że jest to niezwykle interesujący sposób pisania kodu. Wydaje się, że oferuje między innymi:
- Lepsza dokumentacja. Ponieważ umowa jest dokumentacją, nie można być nieaktualnym. Ponadto, ponieważ umowa określa dokładnie, co robi procedura, pomaga w ponownym użyciu.
- Prostsze debugowanie. Ponieważ wykonywanie programu kończy się w momencie niepowodzenia umowy, błędy nie mogą się rozprzestrzeniać, a naruszone twierdzenie zostanie prawdopodobnie podświetlone. Zapewnia to wsparcie podczas projektowania i konserwacji.
- Lepsza analiza statyczna. DbC jest w zasadzie tylko implementacją logiki Hoare i powinny obowiązywać te same zasady.
W porównaniu koszty wydają się raczej niewielkie:
- Dodatkowe pisanie palcami. Ponieważ umowy muszą zostać określone.
- Trwa trochę szkolenia, aby poczuć się komfortowo z pisaniem umów.
Teraz, znając przede wszystkim Pythona, zdaję sobie sprawę, że w rzeczywistości możliwe jest napisanie warunków wstępnych (po prostu wyjątki dla nieodpowiednich danych wejściowych), a nawet możliwe jest użycie asercji do ponownego przetestowania pewnych warunków dodatkowych. Ale nie można symulować niektórych funkcji, takich jak „stary” lub „wynik” bez dodatkowej magii, która ostatecznie zostałaby uznana za nie-Pythonic. (Ponadto istnieje kilka bibliotek, które oferują wsparcie, ale ostatecznie mam wrażenie, że korzystanie z nich byłoby niewłaściwe, ponieważ większość programistów tego nie robi). Zakładam, że jest to podobny problem dla wszystkich innych języków (z wyjątkiem oczywiście , Eiffel).
Moja intuicja mówi mi, że brak wsparcia musi być wynikiem pewnego rodzaju odrzucenia praktyki, ale wyszukiwanie w Internecie nie było owocne. Zastanawiam się, czy ktoś może wyjaśnić, dlaczego większość współczesnych języków wydaje się tak mało wspierać? Czy DbC jest wadliwe lub zbyt drogie? A może jest to po prostu przestarzałe z powodu Extreme Programming i innych metodologii?
źródło
Odpowiedzi:
Prawdopodobnie są one obsługiwane w praktycznie każdym języku programowania.
Potrzebne są „twierdzenia”.
Można je łatwo zakodować jako instrukcje „jeśli”:
Dzięki temu możesz pisać kontrakty, umieszczając takie asercje u góry kodu dla ograniczeń wejściowych; te w punktach powrotu są ograniczeniami wyjściowymi. Możesz nawet dodawać niezmienniki w całym kodzie (chociaż tak naprawdę nie są częścią „projektu na podstawie umowy”).
Twierdzę więc, że nie są one rozpowszechnione, ponieważ programiści są zbyt leniwi, aby je kodować, a nie dlatego, że nie można tego zrobić.
Możesz uczynić je nieco bardziej wydajnymi w większości języków, definiując stałą logiczną podczas kompilacji „sprawdzanie” i nieco poprawiając instrukcje:
Jeśli nie podoba ci się składnia, możesz skorzystać z różnych technik abstrakcji języka, takich jak makra.
Niektóre współczesne języki dają ci niezłą składnię, i myślę, że to właśnie rozumiesz przez „wsparcie nowoczesnego języka”. To wsparcie, ale jest dość cienkie.
To, czego większość współczesnych języków nie daje, to twierdzenia „czasowe” (w stosunku do dowolnych poprzednich lub następnych stanów [operator czasowy „w końcu”], których potrzebujesz, jeśli chcesz napisać naprawdę interesujące umowy. JEŚLI instrukcje nie pomogą ty tutaj.
źródło
super
metodę i ewentualnie wyrzucić wyniki, jeśli chcesz sprawdzić kontrakty bez powielania. To naprawdę pomaga w implementacji czystego kodu zgodnego z LSP.Jak mówisz, Design by Contract to funkcja w Eiffel, która od dawna jest jednym z tych języków programowania, który jest powszechnie szanowany w społeczności, ale który nigdy się nie przyjął.
DbC nie jest w żadnym z najpopularniejszych języków, ponieważ stosunkowo niedawno społeczność programistów głównego nurtu przyjęła do wiadomości, że dodanie ograniczeń / oczekiwań do kodu jest „rozsądną” rzeczą, której można oczekiwać od programistów. Teraz programiści często rozumieją, jak cenne jest testowanie jednostkowe, co sprowadza się do tego, że programiści bardziej akceptują wprowadzanie kodu w celu weryfikacji swoich argumentów i dostrzegania korzyści. Ale dekadę temu zapewne większość programistów powiedziałaby „to tylko dodatkowa praca dla rzeczy, o których wiesz, że zawsze będą w porządku”.
Myślę, że gdybyś dzisiaj poszedł do przeciętnego programisty i porozmawiał o post-warunkach, entuzjastycznie skinąłby głową i powiedział: „OK, to jak testowanie jednostkowe”. A jeśli mówisz o warunkach wstępnych, powiedzą „OK, to jest jak sprawdzanie poprawności parametrów, co nie zawsze robimy, ale wiesz, myślę, że jest ok ...” A potem, jeśli mówisz o niezmiennikach , zaczęliby mówić: „Ojej, ile to narzutów? Ile jeszcze błędów będziemy łapać?” itp.
Myślę więc, że zanim DbC zostanie bardzo szeroko przyjęte, jest jeszcze wiele do zrobienia.
źródło
Fałszywe.
To praktyka projektowa . Może być wcielony jawnie w kodzie (styl Eiffla) lub pośrednio w kodzie (większość języków) lub w testach jednostkowych. Praktyka projektowania istnieje i działa dobrze. Obsługa języków jest dostępna na całej mapie. Jest jednak obecny w wielu językach w ramach testu jednostkowego.
To jest drogie I. Co ważniejsze, są pewne rzeczy, których nie można udowodnić w danym języku. Na przykład zakończenia pętli nie można udowodnić w języku programowania, wymaga ona zdolności sprawdzania „wyższego rzędu”. Tak więc niektóre rodzaje umów są technicznie niewyrażalne.
Nie.
Najczęściej stosujemy testy jednostkowe, aby wykazać, że DbC jest spełnione.
W przypadku Pythona, jak zauważyłeś, DbC działa w kilku miejscach.
Wyniki testu docstring i docstring.
Asercje potwierdzające dane wejściowe i wyjściowe.
Testy jednostkowe.
Dalej.
Możesz adoptować narzędzia w stylu programowania, aby pisać dokument, który zawiera informacje o DbC i który generuje czyste skrypty testu jednostkowego w języku Python plus. Umiejętne programowanie pozwala napisać niezłą literaturę, która zawiera umowy i kompletne źródło.
źródło
there are some things which cannot be proven
. Formalna weryfikacja może być świetna, ale nie wszystko jest weryfikowalne! Ta funkcja faktycznie ogranicza możliwości języka programowania!Tylko zgaduję. Być może po części nie jest tak popularny, ponieważ „Design by Contract” jest znakiem towarowym firmy Eiffel.
źródło
Jedna hipoteza jest taka, że w przypadku wystarczająco dużego złożonego programu, zwłaszcza z ruchomym celem, sama masa umów może stać się tak samo wadliwa i trudna do debugowania, a nawet bardziej, niż sam kod programu. Jak w przypadku każdego wzorca, użycie może być mniejsze niż w przeszłości, a także wyraźne zalety, gdy jest stosowany w bardziej ukierunkowany sposób.
Innym możliwym wnioskiem jest to, że popularność „języków zarządzanych” jest aktualnym dowodem wsparcia projektowania według umowy dla wybranych wybranych zarządzanych funkcji (ograniczenia tablic według umów itp.)
źródło
Powodem, dla którego większość popularnych języków nie ma funkcji DbC w języku jest stosunek kosztów do korzyści związanych z jego wdrożeniem, jest on zbyt wysoki dla implementatora języka.
jedna strona tego została już omówiona w innych odpowiedziach, testy jednostkowe i inne mechanizmy wykonawcze (lub nawet niektóre mechanizmy kompilacji czasu z szablonowym meta programowaniem) mogą już dać ci wiele z dobroci DbC. Dlatego, chociaż istnieje korzyść, prawdopodobnie jest postrzegana jako dość skromna.
Druga strona to koszt, retro dostosowanie DbC do istniejącego języka jest prawdopodobnie zbyt dużą przełomową zmianą i bardzo skomplikowane do uruchomienia. Wprowadzenie nowej składni w języku bez łamania starego kodu jest trudne. Aktualizacja istniejącej standardowej biblioteki w celu zastosowania tak daleko idącej zmiany byłaby kosztowna. Dlatego możemy stwierdzić, że wdrożenie funkcji DbC w istniejącym języku wiąże się z wysokimi kosztami.
Chciałbym również zauważyć, że koncepcje, które są prawie umowami na szablony, a zatem są nieco związane z DbC, zostały porzucone z najnowszego standardu C ++, ponieważ nawet po latach pracy nad nimi oszacowano, że wciąż potrzebowali lat pracy. Tego rodzaju duże, szerokie i rozległe zmiany w językach są po prostu zbyt trudne do wdrożenia.
źródło
DbC byłoby wykorzystywane w szerszym zakresie, gdyby kontrakty mogły być sprawdzane w czasie kompilacji, aby nie było możliwe uruchomienie programu, który naruszyłby jakąkolwiek umowę.
Bez obsługi kompilatora „DbC” to po prostu inna nazwa dla „sprawdzania niezmienników / założeń i zgłaszania wyjątku w przypadku naruszenia”.
źródło
Mam proste wyjaśnienie, większość ludzi (w tym programiści) nie chce dodatkowej pracy, chyba że uzna to za konieczne. Programowanie awioniki, w której bezpieczeństwo jest uważane za bardzo ważne Nie widziałem bez niego większości projektów.
Ale jeśli zastanawiasz się nad witryną, komputerem lub programowaniem mobilnym - awarie i nieoczekiwane zachowanie czasami nie jest uważane za złe, a programiści unikają dodatkowej pracy przy zgłaszaniu błędów, a później ich naprawianie jest uważane za wystarczające.
Jest to prawdopodobnie powód, dla którego myślę, że Ada nigdy nie wybrała się poza branżę programowania lotniczego, ponieważ wymaga więcej pracy przy kodowaniu, chociaż Ada jest niesamowitym językiem, a jeśli chcesz zbudować niezawodny system, jest to najlepszy język do pracy (z wyjątkiem SPARK, który jest zastrzeżony) język oparty na Adzie).
Biblioteki kontraktowe zaprojektowane dla C # były eksperymentalne przez Microsoft i są bardzo przydatne do budowy niezawodnego oprogramowania, ale nigdy nie nabrały rozpędu na rynku, w przeciwnym razie widzielibyście je teraz jako część podstawowego języka C #.
Twierdzenia to nie to samo, co w pełni funkcjonalne wsparcie dla warunków przed / po i niezmienne. Chociaż może próbować je emulować, ale język / kompilator z odpowiednią obsługą wykonuje analizę „abstrakcyjnego drzewa składni” i sprawdza błędy logiczne, których zwykłe twierdzenia nie potrafią.
Edycja: Przeprowadziłem wyszukiwanie, a następna związana jest dyskusja, która może być pomocna: https://stackoverflow.com/questions/4065001/are-there-any-provable-real-world-languages-scala
źródło
Przeważnie przyczyny są następujące:
źródło